channel-worker 2.3.5 → 2.4.0
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/lib/api-client.js +7 -0
- package/lib/command-poller.js +53 -3
- package/package.json +1 -1
package/lib/api-client.js
CHANGED
|
@@ -83,6 +83,13 @@ class ApiClient {
|
|
|
83
83
|
return this.request('GET', '/workers/scene-queue-count');
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// ChatGPT subscription dispatch — returns { count, profile_id } so the
|
|
87
|
+
// daemon knows whether to launch a dedicated capture profile (distinct
|
|
88
|
+
// from the Veo3/FlowKit renderers pool).
|
|
89
|
+
async getChatgptQueue() {
|
|
90
|
+
return this.request('GET', '/workers/chatgpt-queue-count');
|
|
91
|
+
}
|
|
92
|
+
|
|
86
93
|
async sceneDispatch(nstProfileId) {
|
|
87
94
|
return this.request('POST', '/workers/scene-dispatch', { nst_profile_id: nstProfileId });
|
|
88
95
|
}
|
package/lib/command-poller.js
CHANGED
|
@@ -31,14 +31,21 @@ class CommandPoller {
|
|
|
31
31
|
this._dispatchTimer = setInterval(() => this._dispatchScenes(), 5000);
|
|
32
32
|
this._dispatching = false;
|
|
33
33
|
|
|
34
|
-
//
|
|
35
|
-
|
|
34
|
+
// ChatGPT-subscription dispatcher — launches the configured profile when
|
|
35
|
+
// a thumbnail command is waiting, independent from the scene renderers pool.
|
|
36
|
+
console.log('[chatgpt-dispatch] Started (every 5s)');
|
|
37
|
+
this._chatgptDispatchTimer = setInterval(() => this._dispatchChatgpt(), 5000);
|
|
38
|
+
this._chatgptDispatching = false;
|
|
39
|
+
|
|
40
|
+
// Profile timeout — close idle profiles after 30s with no work
|
|
41
|
+
this._profileTimeoutTimer = setInterval(() => this._checkProfileTimeouts(), 10000);
|
|
36
42
|
this._profileLastActivity = {}; // { nst_profile_id: timestamp }
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
stop() {
|
|
40
46
|
if (this.timer) { clearInterval(this.timer); this.timer = null; }
|
|
41
47
|
if (this._dispatchTimer) { clearInterval(this._dispatchTimer); this._dispatchTimer = null; }
|
|
48
|
+
if (this._chatgptDispatchTimer) { clearInterval(this._chatgptDispatchTimer); this._chatgptDispatchTimer = null; }
|
|
42
49
|
if (this._profileTimeoutTimer) { clearInterval(this._profileTimeoutTimer); this._profileTimeoutTimer = null; }
|
|
43
50
|
}
|
|
44
51
|
|
|
@@ -1234,6 +1241,8 @@ class CommandPoller {
|
|
|
1234
1241
|
const excess = runningRenderers.length - parallelLimit;
|
|
1235
1242
|
const idleRenderers = [];
|
|
1236
1243
|
for (const r of runningRenderers) {
|
|
1244
|
+
// Only daemon-launched profiles are eligible — skip manual launches
|
|
1245
|
+
if (!this._profileLastActivity[r.nst_profile_id]) continue;
|
|
1237
1246
|
try {
|
|
1238
1247
|
const c = await this.api.rendererHasCommands(r.nst_profile_id);
|
|
1239
1248
|
if (c === 0) idleRenderers.push(r);
|
|
@@ -1341,6 +1350,47 @@ class CommandPoller {
|
|
|
1341
1350
|
await this.nst.launchProfile(renderer.nst_profile_id, { proxy: renderer.proxy || null, extensionPath, forceRelaunch: options.forceRelaunch });
|
|
1342
1351
|
}
|
|
1343
1352
|
|
|
1353
|
+
// ─── ChatGPT Subscription Dispatch ─────────────────────────────────────────
|
|
1354
|
+
// Separate dispatcher for the dedicated ChatGPT profile (configured via
|
|
1355
|
+
// Setting: chatgpt_sub_profile_id). Launches the profile on-demand when a
|
|
1356
|
+
// generate_thumbnail command is pending, so Veo3 renderers stay untouched.
|
|
1357
|
+
|
|
1358
|
+
async _dispatchChatgpt() {
|
|
1359
|
+
if (this._chatgptDispatching) return;
|
|
1360
|
+
this._chatgptDispatching = true;
|
|
1361
|
+
try {
|
|
1362
|
+
if (!this.nst) return;
|
|
1363
|
+
const queue = await this.api.getChatgptQueue().catch(() => null);
|
|
1364
|
+
if (!queue || !queue.profile_id || queue.count <= 0) return;
|
|
1365
|
+
|
|
1366
|
+
const profileId = queue.profile_id;
|
|
1367
|
+
// Skip launch if already running (check via Nstbrowser running list).
|
|
1368
|
+
let alreadyRunning = false;
|
|
1369
|
+
try {
|
|
1370
|
+
const running = await this.nst.getRunningBrowsers();
|
|
1371
|
+
alreadyRunning = running.some(b => b.profileId === profileId || (b.name && b.name.toLowerCase() === profileId.toLowerCase()));
|
|
1372
|
+
} catch {}
|
|
1373
|
+
if (alreadyRunning) {
|
|
1374
|
+
this._profileLastActivity[profileId] = Date.now();
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
console.log(`[chatgpt-dispatch] Launching ${profileId} (queue=${queue.count})`);
|
|
1379
|
+
try {
|
|
1380
|
+
// Reuse _launchRendererProfile contract — it just needs { nst_profile_id, os, proxy }.
|
|
1381
|
+
await this._launchRendererProfile({ nst_profile_id: profileId, os: 'windows', proxy: null });
|
|
1382
|
+
this._profileLastActivity[profileId] = Date.now();
|
|
1383
|
+
console.log(`[chatgpt-dispatch] ${profileId} launched`);
|
|
1384
|
+
} catch (err) {
|
|
1385
|
+
console.error(`[chatgpt-dispatch] Failed to launch ${profileId}: ${err.message}`);
|
|
1386
|
+
}
|
|
1387
|
+
} catch (err) {
|
|
1388
|
+
console.error(`[chatgpt-dispatch] Error: ${err.message}`);
|
|
1389
|
+
} finally {
|
|
1390
|
+
this._chatgptDispatching = false;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1344
1394
|
// ─── Profile Timeout ───────────────────────────────────────────────────────
|
|
1345
1395
|
// Close profiles that have been idle (no commands assigned) for too long.
|
|
1346
1396
|
|
|
@@ -1348,7 +1398,7 @@ class CommandPoller {
|
|
|
1348
1398
|
try {
|
|
1349
1399
|
if (!this.nst) return;
|
|
1350
1400
|
|
|
1351
|
-
const IDLE_TIMEOUT =
|
|
1401
|
+
const IDLE_TIMEOUT = 30 * 1000; // 30s — matches old extension-side behavior
|
|
1352
1402
|
const now = Date.now();
|
|
1353
1403
|
const running = await this.nst.getRunningBrowsers();
|
|
1354
1404
|
if (running.length === 0) return;
|