@adhdev/daemon-core 1.0.18-rc.12 → 1.0.18-rc.13
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/dist/index.js +145 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +145 -4
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +45 -0
- package/package.json +3 -3
- package/src/commands/cli-manager.ts +18 -0
- package/src/providers/cli-provider-instance.ts +167 -0
|
@@ -192,6 +192,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
192
192
|
private meshStallEmittedForAnchor;
|
|
193
193
|
private meshStallTurnActiveLast;
|
|
194
194
|
private meshStallLastFiredAt;
|
|
195
|
+
private meshStallNativeTranscriptSample;
|
|
195
196
|
private busyEpoch;
|
|
196
197
|
private fastCollapseSynthesizedTaskId;
|
|
197
198
|
private startupGraceCollapseAt;
|
|
@@ -424,6 +425,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
424
425
|
* once at completion). Reset on the next turn's start.
|
|
425
426
|
*/
|
|
426
427
|
private lastCompletionSummary;
|
|
428
|
+
private lastEmittedCompletion;
|
|
427
429
|
private enforceFreshSessionLaunchIfNeeded;
|
|
428
430
|
/**
|
|
429
431
|
* BRAIN-ROUTING (runtime-control thinking axis): for a provider that selects
|
|
@@ -574,6 +576,49 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
574
576
|
* starts with a clean slate (a restart is not throttled by a prior stall).
|
|
575
577
|
*/
|
|
576
578
|
private resetMeshStallEpisode;
|
|
579
|
+
/**
|
|
580
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 1). For a native-source provider
|
|
581
|
+
* (transcriptAuthority=provider — its authoritative history is an on-disk
|
|
582
|
+
* transcript file, e.g. kimi's wire.jsonl), sample the transcript's current
|
|
583
|
+
* progress fingerprint (record count + source-file mtime) WITHOUT parsing the
|
|
584
|
+
* PTY. Used by the stall watchdog to distinguish "PTY render is quiet but the
|
|
585
|
+
* worker is still doing long tool work (transcript growing)" from a genuine
|
|
586
|
+
* wedge. Returns null for a pure-PTY provider (no native source) or when the
|
|
587
|
+
* source cannot be resolved this tick — the caller then falls back to the
|
|
588
|
+
* unchanged lastOutputAt-only judgment.
|
|
589
|
+
*
|
|
590
|
+
* Generalized on the provider's native-source flag, NOT a hardcoded provider
|
|
591
|
+
* type, so every current and future pure-PTY long-tool native-source provider
|
|
592
|
+
* benefits. Cheap enough for the stall path: it runs only at the stall threshold
|
|
593
|
+
* (≥180s of PTY stasis), never on the routine 5s tick.
|
|
594
|
+
*/
|
|
595
|
+
private sampleNativeTranscriptProgress;
|
|
596
|
+
/**
|
|
597
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 2). Last-chance completion emit for a mesh
|
|
598
|
+
* DELEGATED worker whose PTY has already exited (e.g. killed by a false stall)
|
|
599
|
+
* and is about to be auto-cleaned (cli-manager.startCliExitMonitor →
|
|
600
|
+
* removeInstance closes the event-emit window forever). If the worker actually
|
|
601
|
+
* FINISHED its assigned turn — its authoritative native transcript holds a final
|
|
602
|
+
* assistant message for the injected task — but the completion event never fired
|
|
603
|
+
* (the stall-kill happened before the FSM's idle transition), emit it now so the
|
|
604
|
+
* coordinator learns the task completed instead of waiting ~180s for the reconcile
|
|
605
|
+
* transcript-poll to reclaim it.
|
|
606
|
+
*
|
|
607
|
+
* Scope & guards (must all hold to emit):
|
|
608
|
+
* • mesh worker session only — a normal standalone session's ordinary exit is
|
|
609
|
+
* never synthesized (isMeshWorkerSession()).
|
|
610
|
+
* • DOUBLE-EMIT guard — refuse if this turn's completion already fired
|
|
611
|
+
* (lastEmittedCompletion matches the current taskId). A worker that completed
|
|
612
|
+
* cleanly and is merely being cleaned up never double-emits.
|
|
613
|
+
* • evidence gate — reuse the same final-assistant/turn-scoped summary machinery
|
|
614
|
+
* as the normal completion path (completionFinalSummary over the native
|
|
615
|
+
* transcript). No in-turn assistant summary ⇒ no proof of completion ⇒ leave
|
|
616
|
+
* the reclaim path to handle a genuinely-unfinished worker.
|
|
617
|
+
*
|
|
618
|
+
* Returns true when a synthetic completion was emitted, false otherwise. Safe to
|
|
619
|
+
* call unconditionally from the cleanup path.
|
|
620
|
+
*/
|
|
621
|
+
flushMeshCompletionBeforeCleanup(): boolean;
|
|
577
622
|
/**
|
|
578
623
|
* AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
|
|
579
624
|
* persist before the in-progress settle gate is torn down. For a delegated
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "1.0.18-rc.
|
|
3
|
+
"version": "1.0.18-rc.13",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"author": "vilmire",
|
|
48
48
|
"license": "AGPL-3.0-or-later",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@adhdev/mesh-shared": "1.0.18-rc.
|
|
51
|
-
"@adhdev/session-host-core": "1.0.18-rc.
|
|
50
|
+
"@adhdev/mesh-shared": "1.0.18-rc.13",
|
|
51
|
+
"@adhdev/session-host-core": "1.0.18-rc.13",
|
|
52
52
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
53
53
|
"ajv": "^8.20.0",
|
|
54
54
|
"ajv-formats": "^3.0.1",
|
|
@@ -707,6 +707,24 @@ export class DaemonCliManager {
|
|
|
707
707
|
clearInterval(checkStopped);
|
|
708
708
|
setTimeout(() => {
|
|
709
709
|
if (this.adapters.has(key)) {
|
|
710
|
+
// KIMI-MESH-COMPLETION-EMIT (axis 2): before removeInstance closes the
|
|
711
|
+
// event-emit window, give a mesh DELEGATED worker one last chance to emit
|
|
712
|
+
// its completion. A native-source worker (e.g. kimi) can have its PTY
|
|
713
|
+
// killed by a false stall AFTER it finished the task (transcript written)
|
|
714
|
+
// but BEFORE the FSM's idle→completed event fired — the instance is the
|
|
715
|
+
// only thing that can emit that event, and it is about to be removed. The
|
|
716
|
+
// instance-side method is a no-op for a non-mesh session or when the
|
|
717
|
+
// turn's completion already fired (double-emit guard) or when there is no
|
|
718
|
+
// transcript evidence of a finished turn. Best-effort — never blocks cleanup.
|
|
719
|
+
try {
|
|
720
|
+
const inst = instanceManager?.getInstance(key) as (ProviderInstance & { flushMeshCompletionBeforeCleanup?: () => boolean }) | undefined;
|
|
721
|
+
if (typeof inst?.flushMeshCompletionBeforeCleanup === 'function') {
|
|
722
|
+
const emitted = inst.flushMeshCompletionBeforeCleanup();
|
|
723
|
+
if (emitted) LOG.info('CLI', `Emitted pre-cleanup mesh completion for ${cliType} session ${key} before auto-clean`);
|
|
724
|
+
}
|
|
725
|
+
} catch (e) {
|
|
726
|
+
LOG.warn('CLI', `pre-cleanup mesh completion flush failed for ${key}: ${(e as Error)?.message || e}`);
|
|
727
|
+
}
|
|
710
728
|
this.adapters.delete(key);
|
|
711
729
|
this.deps.removeAgentTracking(key);
|
|
712
730
|
sessionRegistry?.unregisterByInstanceKey(key);
|
|
@@ -332,6 +332,18 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
332
332
|
// MESH_WORKER_STALL_REFIRE_COOLDOWN_MS between successive emissions across
|
|
333
333
|
// anchor re-arms (the per-anchor guard only covers a single continuous stall).
|
|
334
334
|
private meshStallLastFiredAt = -1;
|
|
335
|
+
// KIMI-MESH-COMPLETION-EMIT (axis 1): the native-source transcript progress
|
|
336
|
+
// fingerprint (record count + source mtime) observed the LAST time the stall
|
|
337
|
+
// watchdog checked a native-source provider (transcriptAuthority=provider — e.g.
|
|
338
|
+
// kimi wire.jsonl). A pure-PTY native-source worker running a long, screen-quiet
|
|
339
|
+
// tool (no viewport bytes for minutes) looks stalled by the lastOutputAt clock
|
|
340
|
+
// even though its transcript file is still growing. Before firing the stall, we
|
|
341
|
+
// compare the current transcript fingerprint against this snapshot; if the
|
|
342
|
+
// transcript advanced, the "stall" is a false positive of PTY-render stasis, so
|
|
343
|
+
// we re-arm the anchor instead of paging the coordinator (whose no_progress
|
|
344
|
+
// handling can lead to the worker being stopped mid-work → completion never
|
|
345
|
+
// emitted). null = not yet sampled for this session/anchor.
|
|
346
|
+
private meshStallNativeTranscriptSample: { msgCount: number; sourceMtimeMs: number } | null = null;
|
|
335
347
|
// FALSE-IDLE continuity epoch: monotonically bumped on EVERY entry into a busy
|
|
336
348
|
// phase (→generating or →waiting_approval). The completedDebouncePending snapshots
|
|
337
349
|
// this value at arm time (busyEpochAtArm); the flush guard requires it UNCHANGED
|
|
@@ -1418,6 +1430,15 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1418
1430
|
*/
|
|
1419
1431
|
private lastCompletionSummary: { content: string; receivedAt: number; sourceTimestampMs?: number } | null = null;
|
|
1420
1432
|
|
|
1433
|
+
// KIMI-MESH-COMPLETION-EMIT (axis 2, double-emit guard): the (taskId, wall-clock)
|
|
1434
|
+
// of the most recent agent:generating_completed this instance emitted, stamped by
|
|
1435
|
+
// emitGeneratingCompleted. The pre-cleanup completion flush
|
|
1436
|
+
// (flushMeshCompletionBeforeCleanup, driven by cli-manager's exit monitor) reads
|
|
1437
|
+
// this to refuse a SECOND completion for a turn whose completion already fired —
|
|
1438
|
+
// so a worker that finished cleanly and is simply being auto-cleaned never emits a
|
|
1439
|
+
// duplicate. taskId '' covers an ad-hoc (no-task) turn. null = none emitted yet.
|
|
1440
|
+
private lastEmittedCompletion: { taskId: string; at: number } | null = null;
|
|
1441
|
+
|
|
1421
1442
|
private async enforceFreshSessionLaunchIfNeeded(): Promise<void> {
|
|
1422
1443
|
const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
|
|
1423
1444
|
if (!scriptName) return;
|
|
@@ -2404,6 +2425,38 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2404
2425
|
const stalledMs = now - this.meshStallAnchorAt;
|
|
2405
2426
|
if (stalledMs < threshold) return;
|
|
2406
2427
|
|
|
2428
|
+
// KIMI-MESH-COMPLETION-EMIT (axis 1): transcript-aware stall for native-source
|
|
2429
|
+
// providers. A pure-PTY native-source worker (transcriptAuthority=provider,
|
|
2430
|
+
// e.g. kimi) running a long, screen-quiet tool emits no viewport bytes for
|
|
2431
|
+
// minutes, so the lastOutputAt clock above reads it as stalled — but its
|
|
2432
|
+
// authoritative transcript (wire.jsonl) is still being appended. Firing
|
|
2433
|
+
// monitor:no_progress here surfaces a false stall to the coordinator whose
|
|
2434
|
+
// downstream handling can stop the worker mid-work, killing the emit window
|
|
2435
|
+
// before the real completion propagates. So before firing, sample the native
|
|
2436
|
+
// transcript's progress fingerprint: if it advanced (more records OR a fresher
|
|
2437
|
+
// source mtime) since the last sample, the worker is demonstrably alive — treat
|
|
2438
|
+
// it as progress. Re-arm the anchor to `now` and reset the episode so the clock
|
|
2439
|
+
// restarts from this proven-live moment; only a transcript that is ALSO static
|
|
2440
|
+
// falls through to the genuine-stall fire below. No-op for pure-PTY providers
|
|
2441
|
+
// (sample is null → unchanged behavior).
|
|
2442
|
+
const nativeSample = this.sampleNativeTranscriptProgress();
|
|
2443
|
+
if (nativeSample) {
|
|
2444
|
+
const prev = this.meshStallNativeTranscriptSample;
|
|
2445
|
+
const advanced = !prev
|
|
2446
|
+
|| nativeSample.msgCount > prev.msgCount
|
|
2447
|
+
|| nativeSample.sourceMtimeMs > prev.sourceMtimeMs;
|
|
2448
|
+
this.meshStallNativeTranscriptSample = nativeSample;
|
|
2449
|
+
if (advanced) {
|
|
2450
|
+
if (this.isMeshWorkerSession()) {
|
|
2451
|
+
traceMeshEventDrop('mesh_worker_stall_transcript_advancing', this.meshTraceCtx('monitor:no_progress'),
|
|
2452
|
+
`msgCount=${nativeSample.msgCount} sourceMtime=${nativeSample.sourceMtimeMs} (PTY quiet ${Math.round(stalledMs / 1000)}s but transcript advancing)`);
|
|
2453
|
+
}
|
|
2454
|
+
this.meshStallAnchorAt = now;
|
|
2455
|
+
this.meshStallEmittedForAnchor = false;
|
|
2456
|
+
return;
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2407
2460
|
// FALSE-STALL-WATCHDOG-OVERFIRE (fix E): per-session refire cooldown. Mark
|
|
2408
2461
|
// this anchor emitted regardless so a still-static anchor does not re-check
|
|
2409
2462
|
// every tick, but suppress the actual coordinator notification (and the
|
|
@@ -2454,6 +2507,116 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2454
2507
|
this.meshStallEmittedForAnchor = false;
|
|
2455
2508
|
this.meshStallTurnActiveLast = undefined;
|
|
2456
2509
|
this.meshStallLastFiredAt = -1;
|
|
2510
|
+
this.meshStallNativeTranscriptSample = null;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
/**
|
|
2514
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 1). For a native-source provider
|
|
2515
|
+
* (transcriptAuthority=provider — its authoritative history is an on-disk
|
|
2516
|
+
* transcript file, e.g. kimi's wire.jsonl), sample the transcript's current
|
|
2517
|
+
* progress fingerprint (record count + source-file mtime) WITHOUT parsing the
|
|
2518
|
+
* PTY. Used by the stall watchdog to distinguish "PTY render is quiet but the
|
|
2519
|
+
* worker is still doing long tool work (transcript growing)" from a genuine
|
|
2520
|
+
* wedge. Returns null for a pure-PTY provider (no native source) or when the
|
|
2521
|
+
* source cannot be resolved this tick — the caller then falls back to the
|
|
2522
|
+
* unchanged lastOutputAt-only judgment.
|
|
2523
|
+
*
|
|
2524
|
+
* Generalized on the provider's native-source flag, NOT a hardcoded provider
|
|
2525
|
+
* type, so every current and future pure-PTY long-tool native-source provider
|
|
2526
|
+
* benefits. Cheap enough for the stall path: it runs only at the stall threshold
|
|
2527
|
+
* (≥180s of PTY stasis), never on the routine 5s tick.
|
|
2528
|
+
*/
|
|
2529
|
+
private sampleNativeTranscriptProgress(): { msgCount: number; sourceMtimeMs: number } | null {
|
|
2530
|
+
if (!isNativeSourceCanonicalHistory(this.provider?.nativeHistory)) return null;
|
|
2531
|
+
// readExternalCompletionMessages resolves this session's OWN native-source
|
|
2532
|
+
// conversation (providerSessionId / persisted pin / floor claim) and, as a
|
|
2533
|
+
// side effect, refreshes this.lastExternalCompletionProbe with the source
|
|
2534
|
+
// path, mtime, and message count. Reusing it keeps the resolution logic in
|
|
2535
|
+
// one place and immune to the antigravity-style session-id quirks.
|
|
2536
|
+
let messages: unknown[] | null = null;
|
|
2537
|
+
try {
|
|
2538
|
+
messages = this.readExternalCompletionMessages();
|
|
2539
|
+
} catch {
|
|
2540
|
+
return null; // best-effort: an unresolved transcript → fall back to PTY clock
|
|
2541
|
+
}
|
|
2542
|
+
const probe = this.lastExternalCompletionProbe;
|
|
2543
|
+
if (!probe) return null;
|
|
2544
|
+
return {
|
|
2545
|
+
msgCount: typeof probe.msgCount === 'number' ? probe.msgCount : (Array.isArray(messages) ? messages.length : 0),
|
|
2546
|
+
sourceMtimeMs: typeof probe.sourceMtimeMs === 'number' ? probe.sourceMtimeMs : 0,
|
|
2547
|
+
};
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
/**
|
|
2551
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 2). Last-chance completion emit for a mesh
|
|
2552
|
+
* DELEGATED worker whose PTY has already exited (e.g. killed by a false stall)
|
|
2553
|
+
* and is about to be auto-cleaned (cli-manager.startCliExitMonitor →
|
|
2554
|
+
* removeInstance closes the event-emit window forever). If the worker actually
|
|
2555
|
+
* FINISHED its assigned turn — its authoritative native transcript holds a final
|
|
2556
|
+
* assistant message for the injected task — but the completion event never fired
|
|
2557
|
+
* (the stall-kill happened before the FSM's idle transition), emit it now so the
|
|
2558
|
+
* coordinator learns the task completed instead of waiting ~180s for the reconcile
|
|
2559
|
+
* transcript-poll to reclaim it.
|
|
2560
|
+
*
|
|
2561
|
+
* Scope & guards (must all hold to emit):
|
|
2562
|
+
* • mesh worker session only — a normal standalone session's ordinary exit is
|
|
2563
|
+
* never synthesized (isMeshWorkerSession()).
|
|
2564
|
+
* • DOUBLE-EMIT guard — refuse if this turn's completion already fired
|
|
2565
|
+
* (lastEmittedCompletion matches the current taskId). A worker that completed
|
|
2566
|
+
* cleanly and is merely being cleaned up never double-emits.
|
|
2567
|
+
* • evidence gate — reuse the same final-assistant/turn-scoped summary machinery
|
|
2568
|
+
* as the normal completion path (completionFinalSummary over the native
|
|
2569
|
+
* transcript). No in-turn assistant summary ⇒ no proof of completion ⇒ leave
|
|
2570
|
+
* the reclaim path to handle a genuinely-unfinished worker.
|
|
2571
|
+
*
|
|
2572
|
+
* Returns true when a synthetic completion was emitted, false otherwise. Safe to
|
|
2573
|
+
* call unconditionally from the cleanup path.
|
|
2574
|
+
*/
|
|
2575
|
+
flushMeshCompletionBeforeCleanup(): boolean {
|
|
2576
|
+
if (!this.isMeshWorkerSession()) return false;
|
|
2577
|
+
const taskId = this.completingTurnTaskId();
|
|
2578
|
+
|
|
2579
|
+
// DOUBLE-EMIT guard: this turn's completion already fired — never re-emit.
|
|
2580
|
+
if (this.lastEmittedCompletion && this.lastEmittedCompletion.taskId === (taskId ?? '')) {
|
|
2581
|
+
return false;
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// Evidence gate: the injected task's own turn must have genuinely started
|
|
2585
|
+
// (guards against synthesizing a completion off a reused session's stale tail
|
|
2586
|
+
// before this task ran) and the native transcript must hold an in-turn final
|
|
2587
|
+
// assistant summary. turnStartedAt anchors the turn-scoped read.
|
|
2588
|
+
if (!this.injectedTaskHasStartedGenerating()) return false;
|
|
2589
|
+
const turnStartedAt = typeof (this.adapter as any)?.currentTurnStartedAt === 'number'
|
|
2590
|
+
? (this.adapter as any).currentTurnStartedAt as number
|
|
2591
|
+
: this.meshTaskInjectedAt || undefined;
|
|
2592
|
+
let parsedMessages: unknown;
|
|
2593
|
+
try {
|
|
2594
|
+
parsedMessages = this.adapter?.getScriptParsedStatus?.()?.messages;
|
|
2595
|
+
} catch { parsedMessages = undefined; }
|
|
2596
|
+
let finalSummary: string | undefined;
|
|
2597
|
+
try {
|
|
2598
|
+
finalSummary = this.completionFinalSummary(parsedMessages, turnStartedAt);
|
|
2599
|
+
} catch { finalSummary = undefined; }
|
|
2600
|
+
// No in-turn final assistant evidence → not a proven turn-end. Defer to the
|
|
2601
|
+
// coordinator's reclaim/reconcile path rather than fabricate a completion.
|
|
2602
|
+
if (!finalSummary) return false;
|
|
2603
|
+
|
|
2604
|
+
LOG.warn('CLI', `[${this.type}] emitting pre-cleanup mesh completion for session ${this.instanceId} `
|
|
2605
|
+
+ `task=${taskId ?? '(none)'} — PTY exited before the completion event fired but the native transcript `
|
|
2606
|
+
+ `shows a finished turn; synthesizing completion so the coordinator is not left waiting for reclaim.`);
|
|
2607
|
+
if (this.isMeshWorkerSession()) {
|
|
2608
|
+
traceMeshEventStage('fired', this.meshTraceCtx(), 'pre_cleanup_transcript_completion');
|
|
2609
|
+
}
|
|
2610
|
+
this.emitGeneratingCompleted({
|
|
2611
|
+
chatTitle: '',
|
|
2612
|
+
duration: undefined,
|
|
2613
|
+
timestamp: Date.now(),
|
|
2614
|
+
taskId,
|
|
2615
|
+
finalSummary,
|
|
2616
|
+
evidenceLevel: 'transcript',
|
|
2617
|
+
completionDiagnostic: { source: 'pre_cleanup_transcript_completion' },
|
|
2618
|
+
});
|
|
2619
|
+
return true;
|
|
2457
2620
|
}
|
|
2458
2621
|
|
|
2459
2622
|
/**
|
|
@@ -2997,6 +3160,10 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
2997
3160
|
if (summary) {
|
|
2998
3161
|
this.lastCompletionSummary = { content: summary, receivedAt: opts.timestamp };
|
|
2999
3162
|
}
|
|
3163
|
+
// KIMI-MESH-COMPLETION-EMIT (axis 2, double-emit guard): record that THIS turn's
|
|
3164
|
+
// completion has now been emitted, keyed by its taskId, so the pre-cleanup
|
|
3165
|
+
// completion flush never fires a duplicate for the same turn.
|
|
3166
|
+
this.lastEmittedCompletion = { taskId: typeof opts.taskId === 'string' ? opts.taskId : '', at: Date.now() };
|
|
3000
3167
|
this.pushEvent({
|
|
3001
3168
|
event: 'agent:generating_completed',
|
|
3002
3169
|
chatTitle: opts.chatTitle,
|