vg-coder-cli 2.0.54 → 2.0.56
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/INTEGRATION.md +61 -5
- package/bugs/bug1.md +370 -0
- package/dist/vg-coder-bundle.js +1 -1
- package/package.json +1 -1
- package/src/server/api-server.js +13 -0
- package/src/server/task-queue.js +8 -2
- package/src/server/views/js/features/task-worker.js +18 -7
package/package.json
CHANGED
package/src/server/api-server.js
CHANGED
|
@@ -699,6 +699,19 @@ class ApiServer {
|
|
|
699
699
|
const body = req.body || {};
|
|
700
700
|
const opts = body.workerLabel ? { workerLabel: body.workerLabel } : {};
|
|
701
701
|
const payload = { url: body.url, model: body.model, active: body.active };
|
|
702
|
+
// Pin model cho worker (theo email) — _recycleWorkerTab sau task done
|
|
703
|
+
// sẽ reopen tab với cùng model, giữ lock qua nhiều task. Nếu caller
|
|
704
|
+
// không truyền workerLabel, pin cho TẤT CẢ launcher email hiện tại
|
|
705
|
+
// (single-tenant case phổ biến: 1 container = 1 worker).
|
|
706
|
+
if (body.model) {
|
|
707
|
+
if (body.workerLabel) {
|
|
708
|
+
taskQueue._pinnedModelByEmail.set(body.workerLabel, body.model);
|
|
709
|
+
} else {
|
|
710
|
+
for (const l of taskQueue.launchers.values()) {
|
|
711
|
+
if (l.email) taskQueue._pinnedModelByEmail.set(l.email, body.model);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
702
715
|
// Timeout 15s vì worker đợi tab status="complete" + 1.5s render delay
|
|
703
716
|
// để bắt AI Studio fallback. Worker-side timeout cũng là 8s — server
|
|
704
717
|
// phải lớn hơn để có response thay vì error.
|
package/src/server/task-queue.js
CHANGED
|
@@ -38,6 +38,10 @@ class TaskQueue {
|
|
|
38
38
|
// AI Studio tab (free CPU). Cancelled when a new task arrives or a worker
|
|
39
39
|
// recycles for that email.
|
|
40
40
|
this._idleCloseTimers = new Map();
|
|
41
|
+
// workerEmail → model string. Set qua /api/launcher/open-tab body.model;
|
|
42
|
+
// recycle dùng để reopen tab với cùng model (giữ pin qua nhiều task).
|
|
43
|
+
// Default null → recycle dùng AISTUDIO_DEFAULT_MODEL của extension.
|
|
44
|
+
this._pinnedModelByEmail = new Map();
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
attachIO(io) {
|
|
@@ -488,8 +492,10 @@ class TaskQueue {
|
|
|
488
492
|
return;
|
|
489
493
|
}
|
|
490
494
|
await new Promise(r => setTimeout(r, 400));
|
|
491
|
-
|
|
492
|
-
|
|
495
|
+
const pinned = this._pinnedModelByEmail.get(workerEmail);
|
|
496
|
+
const openPayload = pinned ? { model: pinned } : {};
|
|
497
|
+
await this.requestLauncher('launcher:open_tab', openPayload, { workerLabel: workerEmail }, 8_000);
|
|
498
|
+
console.log(chalk.cyan(`[TaskQueue] Recycled tab for ${workerEmail}${pinned ? ` (model=${pinned})` : ''}`));
|
|
493
499
|
// Schedule idle close. If new task arrives before TTL, enqueue() will
|
|
494
500
|
// cancel this timer.
|
|
495
501
|
this._scheduleIdleClose(workerEmail);
|
|
@@ -209,21 +209,32 @@ function throwIfRateLimited(stage = '') {
|
|
|
209
209
|
// đầu. Không throw — fail thì return null, caller chấp nhận `actualModel: null`.
|
|
210
210
|
async function readActualModel() {
|
|
211
211
|
try {
|
|
212
|
+
const url0 = location.href;
|
|
212
213
|
// Fast path: panel đã mở (worker tab đã chạy task → AI Studio thường giữ panel open)
|
|
213
214
|
let selector = document.querySelector('ms-model-selector');
|
|
214
215
|
if (selector) {
|
|
215
216
|
const name = selector.querySelector('[data-test-id="model-name"]')?.innerText?.trim();
|
|
216
|
-
if (name)
|
|
217
|
+
if (name) {
|
|
218
|
+
console.log('[ReadModel] FAST', { url: url0, name });
|
|
219
|
+
return name;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Panel đóng — toggle mở (aria-label sẽ là "Toggle run settings panel" khi đóng,
|
|
223
|
+
// "Close run settings panel" khi mở. Match cả 2 để robust).
|
|
224
|
+
const toggle = document.querySelector('[aria-label="Toggle run settings panel"]')
|
|
225
|
+
|| document.querySelector('[aria-label="Open run settings panel"]');
|
|
226
|
+
if (!toggle) {
|
|
227
|
+
console.warn('[ReadModel] NO_TOGGLE', { url: url0 });
|
|
228
|
+
return null;
|
|
217
229
|
}
|
|
218
|
-
// Slow path: toggle panel mở. Lưu state để restore sau khi đọc xong.
|
|
219
|
-
const toggle = document.querySelector('[aria-label="Toggle run settings panel"]');
|
|
220
|
-
if (!toggle) return null;
|
|
221
230
|
toggle.click();
|
|
222
|
-
await new Promise(r => setTimeout(r,
|
|
231
|
+
await new Promise(r => setTimeout(r, 1200));
|
|
223
232
|
selector = document.querySelector('ms-model-selector');
|
|
224
233
|
const name = selector?.querySelector('[data-test-id="model-name"]')?.innerText?.trim() || null;
|
|
225
|
-
|
|
226
|
-
|
|
234
|
+
console.log('[ReadModel] SLOW', { url: url0, urlNow: location.href, name });
|
|
235
|
+
// Đóng panel lại để không thay đổi UX (label sau khi mở thành "Close...")
|
|
236
|
+
const closeBtn = document.querySelector('[aria-label="Close run settings panel"]');
|
|
237
|
+
if (closeBtn) closeBtn.click();
|
|
227
238
|
return name;
|
|
228
239
|
} catch (err) {
|
|
229
240
|
console.warn('[TaskWorker] readActualModel failed:', err?.message);
|