fix(bridge): renderer script debugging — async fetch, install path fix, product.json checksums
- Replace sync XHR tryPing() with async fetch tryPingAsync() for port discovery - Add ag-sdk JS file to product.json checksums in updateProductChecksums() - Revert to inline script approach for jetski HTML (vscode-file:// blocks custom .js) - Remove old external script tag cleanup, add inline markers - Update known-issues with 3 new findings - Add devlog entry #16
This commit is contained in:
@@ -289,24 +289,27 @@ async function setupApprovalObserver() {
|
||||
logToFile('[OBSERVER] workbench.html patched (needs reload)');
|
||||
}
|
||||
// Also patch workbench-jetski-agent.html (Antigravity's actual entry point!)
|
||||
// IMPORTANT: vscode-file:// protocol does NOT serve custom .js files,
|
||||
// so we INLINE the script content directly into the HTML.
|
||||
// IMPORTANT: vscode-file:// does NOT serve custom .js files (silent 404),
|
||||
// so we MUST inline the script directly into the HTML.
|
||||
const scriptDir = path.dirname(scriptPath);
|
||||
const jetskiHtml = path.join(scriptDir, 'workbench-jetski-agent.html');
|
||||
try {
|
||||
if (fs.existsSync(jetskiHtml)) {
|
||||
let html = fs.readFileSync(jetskiHtml, 'utf8');
|
||||
// Remove old external script tag if present (from previous versions)
|
||||
const oldScriptBasename = path.basename(scriptPath);
|
||||
if (html.includes(`src="./${oldScriptBasename}"`)) {
|
||||
html = html.replace(/\n?<!-- AG SDK \[variet-gravity-bridge\] -->\n?<script src="[^"]*"><\/script>\n?<!-- \/AG SDK \[variet-gravity-bridge\] -->\n?/, '');
|
||||
logToFile('[OBSERVER] removed old external <script src> tag from jetski HTML');
|
||||
// Remove old external script tag if present
|
||||
const extMarkerStart = '<!-- AG SDK [variet-gravity-bridge] -->';
|
||||
const extMarkerEnd = '<!-- /AG SDK [variet-gravity-bridge] -->';
|
||||
if (html.includes(extMarkerStart)) {
|
||||
const extRe = new RegExp('\\n?' + extMarkerStart.replace(/[[\]]/g, '\\$&') +
|
||||
'[\\s\\S]*?' +
|
||||
extMarkerEnd.replace(/[[\]]/g, '\\$&') + '\\n?');
|
||||
html = html.replace(extRe, '');
|
||||
logToFile('[OBSERVER] removed external script tag from jetski HTML');
|
||||
}
|
||||
// Insert or update inline script
|
||||
const inlineMarkerStart = '<!-- AG SDK INLINE [variet-gravity-bridge] -->';
|
||||
const inlineMarkerEnd = '<!-- /AG SDK INLINE [variet-gravity-bridge] -->';
|
||||
if (html.includes(inlineMarkerStart)) {
|
||||
// Replace existing inline script with updated content
|
||||
const re = new RegExp(inlineMarkerStart.replace(/[[\]]/g, '\\$&') +
|
||||
'[\\s\\S]*?' +
|
||||
inlineMarkerEnd.replace(/[[\]]/g, '\\$&'));
|
||||
@@ -314,7 +317,6 @@ async function setupApprovalObserver() {
|
||||
logToFile('[OBSERVER] jetski HTML inline script UPDATED');
|
||||
}
|
||||
else {
|
||||
// First time: insert before </html>
|
||||
html = html.replace('</html>', `\n${inlineMarkerStart}\n<script>\n${combinedScript}\n</script>\n${inlineMarkerEnd}\n</html>`);
|
||||
logToFile('[OBSERVER] jetski HTML inline script INSERTED');
|
||||
}
|
||||
@@ -372,15 +374,16 @@ function updateProductChecksums() {
|
||||
logToFile('[CHECKSUM] no checksums section in product.json');
|
||||
return;
|
||||
}
|
||||
// Files we may modify (relative key in product.json → absolute path)
|
||||
// Files we may modify or create (relative key in product.json → absolute path)
|
||||
// CRITICAL: vscode-file:// only serves files with valid checksums in product.json.
|
||||
// Custom JS files MUST be added here or they'll silently 404.
|
||||
const filesToCheck = {
|
||||
'vs/code/electron-browser/workbench/workbench.html': path.join(workbenchDir, 'workbench.html'),
|
||||
'vs/code/electron-browser/workbench/workbench-jetski-agent.html': path.join(workbenchDir, 'workbench-jetski-agent.html'),
|
||||
'vs/code/electron-browser/workbench/ag-sdk-variet-gravity-bridge.js': path.join(workbenchDir, 'ag-sdk-variet-gravity-bridge.js'),
|
||||
};
|
||||
let updated = false;
|
||||
for (const [key, filePath] of Object.entries(filesToCheck)) {
|
||||
if (!product.checksums[key])
|
||||
continue; // not in checksums, skip
|
||||
if (!fs.existsSync(filePath))
|
||||
continue;
|
||||
const fileBytes = fs.readFileSync(filePath);
|
||||
@@ -564,65 +567,29 @@ function generateApprovalObserverScript(_port) {
|
||||
function log(m){console.log('[GB Observer] '+m);}
|
||||
log('v2 Script loaded — discovering bridge port...');
|
||||
|
||||
// ── Port Discovery: try hardcoded port FIRST, then JSON fallback ──
|
||||
// vscode-file:// protocol blocks .json files, so XHR to ag-bridge-ports.json
|
||||
// returns 404. The extension embeds the known port at script generation time.
|
||||
// ── Port Discovery: async fetch()-based (sync XHR blocked in Electron renderer) ──
|
||||
var HARDCODED_PORT=${_port};
|
||||
|
||||
function tryPing(port,cb){
|
||||
try{
|
||||
var xhr=new XMLHttpRequest();
|
||||
xhr.open('GET','http://127.0.0.1:'+port+'/ping?t='+Date.now(),false);
|
||||
xhr.timeout=2000;
|
||||
xhr.send();
|
||||
if(xhr.status===200&&xhr.responseText==='pong'){cb(true);return;}
|
||||
}catch(e){}
|
||||
cb(false);
|
||||
function tryPingAsync(port){
|
||||
return fetch('http://127.0.0.1:'+port+'/ping?t='+Date.now(),{signal:AbortSignal.timeout(2000)})
|
||||
.then(function(r){return r.text();})
|
||||
.then(function(t){return t==='pong';})
|
||||
.catch(function(){return false;});
|
||||
}
|
||||
|
||||
function discoverPort(cb){
|
||||
// Strategy 1: Try hardcoded port immediately
|
||||
log('Trying hardcoded port '+HARDCODED_PORT+'...');
|
||||
tryPing(HARDCODED_PORT,function(ok){
|
||||
tryPingAsync(HARDCODED_PORT).then(function(ok){
|
||||
if(ok){log('Port discovered (hardcoded): '+HARDCODED_PORT);cb(HARDCODED_PORT);return;}
|
||||
log('Hardcoded port failed, falling back to JSON + port scan...');
|
||||
log('Hardcoded port failed, retrying with backoff...');
|
||||
|
||||
// Strategy 2: JSON file fallback + port scan
|
||||
var attempts=0;
|
||||
var timer=setInterval(function(){
|
||||
attempts++;
|
||||
if(attempts>60){clearInterval(timer);log('Port discovery timeout after 2min');return;}
|
||||
// Try hardcoded port again (server may start late)
|
||||
tryPing(HARDCODED_PORT,function(ok2){
|
||||
if(ok2){clearInterval(timer);log('Port discovered (hardcoded retry): '+HARDCODED_PORT);cb(HARDCODED_PORT);return;}
|
||||
tryPingAsync(HARDCODED_PORT).then(function(ok2){
|
||||
if(ok2){clearInterval(timer);log('Port discovered (retry #'+attempts+'): '+HARDCODED_PORT);cb(HARDCODED_PORT);}
|
||||
});
|
||||
// Try JSON file (may work in future Electron versions)
|
||||
try{
|
||||
var xhr=new XMLHttpRequest();
|
||||
xhr.open('GET','./ag-bridge-ports.json?t='+Date.now(),false);
|
||||
xhr.send();
|
||||
if(xhr.status===200){
|
||||
var ports=JSON.parse(xhr.responseText);
|
||||
var keys=Object.keys(ports);
|
||||
for(var i=0;i<keys.length;i++){
|
||||
var port=ports[keys[i]];
|
||||
if(port>0&&port<65536){
|
||||
try{
|
||||
var xhr2=new XMLHttpRequest();
|
||||
xhr2.open('GET','http://127.0.0.1:'+port+'/ping?t='+Date.now(),false);
|
||||
xhr2.timeout=1000;
|
||||
xhr2.send();
|
||||
if(xhr2.status===200&&xhr2.responseText==='pong'){
|
||||
clearInterval(timer);
|
||||
log('Port discovered (JSON): '+port+' (project='+keys[i]+')');
|
||||
cb(port);
|
||||
return;
|
||||
}
|
||||
}catch(e2){}
|
||||
}
|
||||
}
|
||||
}
|
||||
}catch(e){}
|
||||
},2000);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user