vg-coder-cli 2.0.69 → 2.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/server/api-server.js
CHANGED
|
@@ -848,6 +848,51 @@ class ApiServer {
|
|
|
848
848
|
} catch (e) { res.status(launcherErr(e)).json({ error: e.message }); }
|
|
849
849
|
});
|
|
850
850
|
|
|
851
|
+
// Proxy a chrome.* command through a worker (content-script → SW
|
|
852
|
+
// message bridge). Use when the launcher SW socket is offline but the
|
|
853
|
+
// worker socket is alive — sending the message also wakes the SW.
|
|
854
|
+
// Body: { chromeId? | workerLabel?, cmd, args?, timeoutMs? }
|
|
855
|
+
// Available cmds (mirror of launcher.exec, run via SW message):
|
|
856
|
+
// tabs.query | tabs.remove | tabs.update | tabs.reload
|
|
857
|
+
// storage.sync.get | storage.local.get | runtime.reload | wake
|
|
858
|
+
this.app.post('/api/worker/exec', async (req, res) => {
|
|
859
|
+
try {
|
|
860
|
+
const body = req.body || {};
|
|
861
|
+
if (!body.cmd) return res.status(400).json({ error: 'cmd required' });
|
|
862
|
+
const opts = workerOpts(req); // accepts label/workerLabel/chromeId via req
|
|
863
|
+
// workerOpts only reads label/workerLabel — pass chromeId via opts
|
|
864
|
+
// directly when body has it (workers are addressed by socket, not
|
|
865
|
+
// chromeId, so we resolve chromeId → workerLabel client-side here).
|
|
866
|
+
if (body.chromeId && !opts.workerLabel) {
|
|
867
|
+
// Find any worker matching chromeId; route via its socketId.
|
|
868
|
+
const w = [...taskQueue.workers.values()].find(w => w.chromeId === body.chromeId);
|
|
869
|
+
if (w) opts.socketId = w.id;
|
|
870
|
+
else return res.status(404).json({ error: 'worker_not_found', chromeId: body.chromeId });
|
|
871
|
+
}
|
|
872
|
+
const timeoutMs = Math.min(Math.max(parseInt(body.timeoutMs, 10) || 10_000, 1_000), 30_000);
|
|
873
|
+
const result = await taskQueue.requestWorker('worker:exec', { cmd: body.cmd, args: body.args }, opts, timeoutMs);
|
|
874
|
+
res.json(result);
|
|
875
|
+
} catch (e) { res.status(503).json({ error: e.message }); }
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
// Dump extension metadata (id, version, install type, permissions) via
|
|
879
|
+
// the worker → SW message bridge. Useful when multiple installs of the
|
|
880
|
+
// same extension exist (Web Store + Load Unpacked) and we need to know
|
|
881
|
+
// which one is actually running.
|
|
882
|
+
this.app.get('/api/worker/extension-info', async (req, res) => {
|
|
883
|
+
try {
|
|
884
|
+
const opts = workerOpts(req);
|
|
885
|
+
const chromeIdQuery = (req.query?.chromeId || '').toString().trim();
|
|
886
|
+
if (chromeIdQuery && !opts.workerLabel) {
|
|
887
|
+
const w = [...taskQueue.workers.values()].find(w => w.chromeId === chromeIdQuery);
|
|
888
|
+
if (w) opts.socketId = w.id;
|
|
889
|
+
else return res.status(404).json({ error: 'worker_not_found', chromeId: chromeIdQuery });
|
|
890
|
+
}
|
|
891
|
+
const result = await taskQueue.requestWorker('worker:ext-info', {}, opts, 5_000);
|
|
892
|
+
res.json(result);
|
|
893
|
+
} catch (e) { res.status(503).json({ error: e.message }); }
|
|
894
|
+
});
|
|
895
|
+
|
|
851
896
|
this.app.get('/api/worker/status', (req, res) => {
|
|
852
897
|
const label = (req.query?.label || req.query?.workerLabel || '').toString().toLowerCase().trim();
|
|
853
898
|
res.json(taskQueue.workerStatus(label || undefined));
|
|
@@ -496,6 +496,59 @@ function connect() {
|
|
|
496
496
|
} catch (e) { ack && ack({ ok: false, error: e.message, stack: e.stack }); }
|
|
497
497
|
});
|
|
498
498
|
|
|
499
|
+
// Proxy chrome.* commands to the extension background SW via runtime
|
|
500
|
+
// message passing. Receiving the message also wakes the SW if it was
|
|
501
|
+
// evicted — that's the recovery path for "launcher offline" cases
|
|
502
|
+
// where the launcher socket is dead but the content-script socket
|
|
503
|
+
// (this worker) is alive.
|
|
504
|
+
socket.on('worker:exec', async ({ cmd, args } = {}, ack) => {
|
|
505
|
+
try {
|
|
506
|
+
if (!cmd) return ack && ack({ ok: false, error: 'cmd_required' });
|
|
507
|
+
if (typeof chrome === 'undefined' || !chrome.runtime?.sendMessage) {
|
|
508
|
+
return ack && ack({ ok: false, error: 'no_chrome_runtime' });
|
|
509
|
+
}
|
|
510
|
+
const reply = await new Promise((resolve) => {
|
|
511
|
+
try {
|
|
512
|
+
chrome.runtime.sendMessage({ action: 'WORKER_EXEC', cmd, args: args || {} }, (resp) => {
|
|
513
|
+
if (chrome.runtime.lastError) {
|
|
514
|
+
resolve({ ok: false, error: chrome.runtime.lastError.message });
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
resolve(resp || { ok: false, error: 'no_response' });
|
|
518
|
+
});
|
|
519
|
+
} catch (err) {
|
|
520
|
+
resolve({ ok: false, error: err?.message || String(err) });
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
ack && ack(reply);
|
|
524
|
+
} catch (e) { ack && ack({ ok: false, error: e.message }); }
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// Dump extension metadata via SW message — version, installType, ID,
|
|
528
|
+
// permissions. Useful when the user has multiple extension installs
|
|
529
|
+
// (Web Store + Load Unpacked) and we need to know which is live.
|
|
530
|
+
socket.on('worker:ext-info', async (_payload, ack) => {
|
|
531
|
+
try {
|
|
532
|
+
if (typeof chrome === 'undefined' || !chrome.runtime?.sendMessage) {
|
|
533
|
+
return ack && ack({ ok: false, error: 'no_chrome_runtime' });
|
|
534
|
+
}
|
|
535
|
+
const reply = await new Promise((resolve) => {
|
|
536
|
+
try {
|
|
537
|
+
chrome.runtime.sendMessage({ action: 'WORKER_EXT_INFO' }, (resp) => {
|
|
538
|
+
if (chrome.runtime.lastError) {
|
|
539
|
+
resolve({ ok: false, error: chrome.runtime.lastError.message });
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
resolve(resp || { ok: false, error: 'no_response' });
|
|
543
|
+
});
|
|
544
|
+
} catch (err) {
|
|
545
|
+
resolve({ ok: false, error: err?.message || String(err) });
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
ack && ack({ ok: true, info: reply });
|
|
549
|
+
} catch (e) { ack && ack({ ok: false, error: e.message }); }
|
|
550
|
+
});
|
|
551
|
+
|
|
499
552
|
socket.on('debug:logs', ({ since = 0, level = null, limit = 100, clear = false } = {}, ack) => {
|
|
500
553
|
try {
|
|
501
554
|
let logs = logBuffer.filter(e => e.at > Number(since || 0));
|