vg-coder-cli 2.0.66 → 2.0.67

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 CHANGED
@@ -217,6 +217,8 @@ Server có thể chủ động list / đóng / mở tab AI Studio trong từng p
217
217
  | `GET` | `/api/launcher/tabs` | `?chromeId=<uuid>` \| `?label=<email>` (optional) | List tabs trong profile (hoặc all profiles nếu bỏ pin) |
218
218
  | `POST` | `/api/launcher/close-tab` | `{ chromeId? \| workerLabel?, tabId?, all? }` | Đóng tab cụ thể, hoặc tất cả tab AI Studio nếu bỏ `tabId` |
219
219
  | `POST` | `/api/launcher/open-tab` | `{ chromeId? \| workerLabel?, model?, url?, active? }` | Mở tab mới. `model` mặc định `gemini-3-flash-preview`. Response v2.0.52+ kèm `requested_model` / `actual_model` / `fallback_occurred` (URL-based, **không reliable** với AI Studio versions mới — xem note) |
220
+ | `GET` | `/api/launcher/debug` | `?chromeId=<uuid>` \| `?workerLabel=<email>` (optional) | Dump launcher SW state: `swChromeId`, `syncStorage`, `localStorage`, AI Studio tabs, windows count, runtime info. Bỏ pin → broadcast all launchers. (v2.0.65+) |
221
+ | `POST` | `/api/launcher/exec` | `{ chromeId? \| workerLabel? \| all?, cmd, args?, timeoutMs? }` | Chạy 1 lệnh `chrome.*` đã định nghĩa sẵn trong launcher SW. (v2.0.66+, thay cho `eval` bị Manifest V3 CSP chặn) |
220
222
 
221
223
  **Pin precedence**: `chromeId` > `workerLabel` > default. `chromeId` chỉ exact-match một
222
224
  launcher cụ thể — dùng để address **profile chưa bind email** (mới cài extension,
@@ -243,6 +245,98 @@ curl -X POST -d '{"workerLabel":"alice@gmail.com","model":"gemini-3-flash-previe
243
245
  -H 'Content-Type: application/json' http://127.0.0.1:6868/api/launcher/open-tab
244
246
  ```
245
247
 
248
+ ### Remote launcher debug (v2.0.65+)
249
+
250
+ Hai endpoint dùng để inspect / điều khiển launcher SW từ xa thay vì phải mở
251
+ DevTools trong từng Chrome profile:
252
+
253
+ **`GET /api/launcher/debug`** — dump state cố định:
254
+
255
+ ```bash
256
+ # Một launcher cụ thể
257
+ curl -s "http://127.0.0.1:6868/api/launcher/debug?chromeId=6b420bac-..." | jq
258
+
259
+ # Broadcast 5 launchers (bỏ pin)
260
+ curl -s http://127.0.0.1:6868/api/launcher/debug | jq
261
+ ```
262
+
263
+ Response per launcher:
264
+
265
+ ```json
266
+ {
267
+ "ok": true,
268
+ "data": {
269
+ "swChromeId": "6b420bac-...",
270
+ "runtimeId": "comfeilpfnlaoijgndaikpniioglmonf",
271
+ "extVersion": "1.0.0",
272
+ "extName": "VetGo Pro",
273
+ "syncStorage": { "id": "6b420bac-..." },
274
+ "localStorage": {},
275
+ "profileInfo": null,
276
+ "socketId": "KFh5YmiCbYTGBmAzAAAB",
277
+ "serverUrl": "http://127.0.0.1:6868",
278
+ "tabs": {
279
+ "aistudio": [{ "id": 437926431, "url": "...", "status": "complete", "active": true }],
280
+ "totalCount": 12
281
+ },
282
+ "windows": 2,
283
+ "userAgent": "Mozilla/5.0 ..."
284
+ }
285
+ }
286
+ ```
287
+
288
+ Dùng để verify chromeId pipeline (launcher SW chromeId == `chrome.storage.sync.id`),
289
+ phát hiện profile có nhiều cửa sổ / quá nhiều tab, debug AI Studio tab missing.
290
+
291
+ **`POST /api/launcher/exec`** — chạy 1 lệnh đã định nghĩa sẵn trong launcher SW.
292
+ Manifest V3 cấm `new Function()` nên không có eval tự do — đây là tập 10 lệnh
293
+ chrome.* được whitelist, mỗi lệnh có schema args cố định:
294
+
295
+ | `cmd` | `args` | Trả về |
296
+ |---|---|---|
297
+ | `tabs.query` | `chrome.tabs.QueryInfo` (`{ url?, active?, ... }`) | Mảng tab info `{ id, windowId, url, title, status, active, ... }` |
298
+ | `tabs.get` | `{ tabId: number }` | 1 tab info |
299
+ | `tabs.update` | `{ tabId: number, ...props }` (`url`, `active`, `pinned`, ...) | `{ id, url, active }` |
300
+ | `tabs.reload` | `{ tabId: number, bypassCache?: bool }` | `{ ok: true, tabId }` |
301
+ | `storage.sync.get` | `{ keys?: string \| string[] \| null }` (null = all) | `Record<string, unknown>` |
302
+ | `storage.sync.set` | `{ items: Record<string, unknown> }` | `{ ok: true }` |
303
+ | `storage.local.get` | `{ keys?: ... }` | `Record<string, unknown>` |
304
+ | `runtime.reload` | — | `{ ok: true, scheduled: true }` (extension reload sau ~50ms; ack có thể không tới do SW chết) |
305
+ | `windows.list` | — | Mảng window info `{ id, focused, type, state, incognito }` |
306
+ | `cookies.get` | `{ url: string, name?: string }` | 1 cookie nếu `name`, mảng cookies nếu chỉ `url`. Mỗi cookie: `{ name, value, domain, path, expirationDate, secure, httpOnly }` |
307
+
308
+ Unknown `cmd` → `{ ok: false, error: "unknown_cmd", available: [...] }` (discovery).
309
+
310
+ Ví dụ:
311
+
312
+ ```bash
313
+ # Phải có chromeId nào sync với storage UUID không?
314
+ curl -s -X POST -H 'Content-Type: application/json' \
315
+ -d '{"chromeId":"6b420bac-...","cmd":"storage.sync.get"}' \
316
+ http://127.0.0.1:6868/api/launcher/exec | jq '.value'
317
+ # → { "id": "6b420bac-..." }
318
+
319
+ # Profile login Google chưa?
320
+ curl -s -X POST -H 'Content-Type: application/json' \
321
+ -d '{"chromeId":"6b420bac-...","cmd":"cookies.get","args":{"url":"https://accounts.google.com","name":"SID"}}' \
322
+ http://127.0.0.1:6868/api/launcher/exec | jq '.value'
323
+ # → { "name": "SID", "value": "...", ... } nếu đã login, null nếu chưa
324
+
325
+ # Reload extension (debug last resort)
326
+ curl -s -X POST -H 'Content-Type: application/json' \
327
+ -d '{"chromeId":"6b420bac-...","cmd":"runtime.reload"}' \
328
+ http://127.0.0.1:6868/api/launcher/exec
329
+
330
+ # Broadcast: tab AI Studio đang mở ở profile nào?
331
+ curl -s -X POST -H 'Content-Type: application/json' \
332
+ -d '{"all":true,"cmd":"tabs.query","args":{"url":"*://aistudio.google.com/*"}}' \
333
+ http://127.0.0.1:6868/api/launcher/exec \
334
+ | jq '.[] | { chromeId: .launcher.chromeId, tabs: (.value | length) }'
335
+ ```
336
+
337
+ **Thêm command mới** → sửa `execCommands` map trong [vetgo-auto/chrome/src/launcher.ts](vetgo-auto/chrome/src/launcher.ts),
338
+ rebuild + bump version + reload extension trong từng Chrome profile.
339
+
246
340
  `open-tab` response (v2.0.52+):
247
341
 
248
342
  ```json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vg-coder-cli",
3
- "version": "2.0.66",
3
+ "version": "2.0.67",
4
4
  "description": "🚀 CLI tool to analyze projects, concatenate source files, count tokens, and export HTML with syntax highlighting and copy functionality",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -818,13 +818,23 @@ class TaskQueue {
818
818
  }
819
819
 
820
820
  async _dispatch(task, worker) {
821
+ // Mark worker busy synchronously BEFORE any await so that concurrent
822
+ // _drain() ticks (each enqueue schedules its own setImmediate(_drain))
823
+ // don't both observe the same worker as idle and dispatch two tasks to
824
+ // it. Previously `worker.status = 'busy'` happened after `await
825
+ // store.saveTask` — the await yielded, a second drain saw worker idle,
826
+ // and a second task was dispatched onto the same worker. The worker can
827
+ // only run one task at a time, so the second one would hang in cache
828
+ // status='running' forever (worker.currentTaskId was overwritten and
829
+ // onWorkerComplete's `worker.currentTaskId !== taskId` guard rejected
830
+ // the late completion as stale).
821
831
  task.status = 'running';
822
832
  task.timing.startedAt = Date.now();
823
833
  task.worker = { socketId: worker.id, email: worker.email, ...(worker.meta || {}) };
824
- await store.saveTask(task);
825
834
  this.cache.set(task.id, task);
826
835
  worker.currentTaskId = task.id;
827
836
  worker.status = 'busy';
837
+ await store.saveTask(task);
828
838
 
829
839
  const port = this.io?.httpServer?.address?.()?.port || 6868;
830
840
  const baseUrl = `http://127.0.0.1:${port}`;