@adhdev/daemon-core 0.9.19 → 0.9.21
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/cli-adapters/provider-cli-adapter.d.ts +22 -2
- package/dist/cli-adapters/provider-cli-shared.d.ts +13 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +371 -249
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +371 -249
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +13 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapters/provider-cli-adapter.ts +426 -268
- package/src/cli-adapters/provider-cli-shared.ts +8 -0
- package/src/commands/chat-commands.ts +9 -8
- package/src/index.d.ts +1 -1
- package/src/index.ts +1 -0
- package/src/shared-types.d.ts +13 -1
- package/src/shared-types.ts +15 -1
- package/src/status/builders.ts +8 -8
- package/src/status/reporter.ts +7 -11
- package/src/status/snapshot.ts +21 -5
package/dist/index.mjs
CHANGED
|
@@ -1958,6 +1958,7 @@ var init_provider_cli_runtime = __esm({
|
|
|
1958
1958
|
var provider_cli_adapter_exports = {};
|
|
1959
1959
|
__export(provider_cli_adapter_exports, {
|
|
1960
1960
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
1961
|
+
appendBoundedText: () => appendBoundedText,
|
|
1961
1962
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
1962
1963
|
});
|
|
1963
1964
|
import * as os10 from "os";
|
|
@@ -1991,6 +1992,14 @@ function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages
|
|
|
1991
1992
|
}
|
|
1992
1993
|
return false;
|
|
1993
1994
|
}
|
|
1995
|
+
function appendBoundedText(current, chunk, maxChars) {
|
|
1996
|
+
if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
|
|
1997
|
+
if (maxChars <= 0) return "";
|
|
1998
|
+
if (chunk.length >= maxChars) return chunk.slice(-maxChars);
|
|
1999
|
+
const keepFromCurrent = maxChars - chunk.length;
|
|
2000
|
+
if (current.length <= keepFromCurrent) return current + chunk;
|
|
2001
|
+
return current.slice(-keepFromCurrent) + chunk;
|
|
2002
|
+
}
|
|
1994
2003
|
var ProviderCliAdapter;
|
|
1995
2004
|
var init_provider_cli_adapter = __esm({
|
|
1996
2005
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
@@ -2067,15 +2076,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
2067
2076
|
startupFirstOutputAt = 0;
|
|
2068
2077
|
// PTY I/O
|
|
2069
2078
|
onPtyDataCallback = null;
|
|
2070
|
-
|
|
2079
|
+
pendingOutputParseChunks = [];
|
|
2071
2080
|
pendingOutputParseTimer = null;
|
|
2072
|
-
|
|
2081
|
+
ptyOutputChunks = [];
|
|
2073
2082
|
ptyOutputFlushTimer = null;
|
|
2074
2083
|
pendingTerminalQueryTail = "";
|
|
2075
2084
|
lastOutputAt = 0;
|
|
2076
2085
|
lastNonEmptyOutputAt = 0;
|
|
2077
2086
|
lastScreenChangeAt = 0;
|
|
2078
2087
|
lastScreenSnapshot = "";
|
|
2088
|
+
lastScreenText = "";
|
|
2089
|
+
lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2079
2090
|
// Server log forwarding
|
|
2080
2091
|
serverConn = null;
|
|
2081
2092
|
logBuffer = [];
|
|
@@ -2121,6 +2132,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2121
2132
|
traceSeq = 0;
|
|
2122
2133
|
traceSessionId = "";
|
|
2123
2134
|
parsedStatusCache = null;
|
|
2135
|
+
lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
|
|
2136
|
+
static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
|
|
2137
|
+
static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
|
|
2124
2138
|
static MAX_TRACE_ENTRIES = 250;
|
|
2125
2139
|
providerResolutionMeta;
|
|
2126
2140
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
@@ -2129,6 +2143,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
2129
2143
|
this.messages = [...this.committedMessages];
|
|
2130
2144
|
this.structuredMessages = [...this.committedMessages];
|
|
2131
2145
|
}
|
|
2146
|
+
readTerminalScreenText(now = Date.now()) {
|
|
2147
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2148
|
+
this.lastScreenText = screenText;
|
|
2149
|
+
this.lastScreenSnapshotReadAt = now;
|
|
2150
|
+
return screenText;
|
|
2151
|
+
}
|
|
2152
|
+
shouldReadTerminalScreenSnapshot(now) {
|
|
2153
|
+
if (!this.lastScreenText) return true;
|
|
2154
|
+
return now - this.lastScreenSnapshotReadAt >= _ProviderCliAdapter.SCREEN_SNAPSHOT_MIN_INTERVAL_MS;
|
|
2155
|
+
}
|
|
2156
|
+
resetTerminalScreen(rows, cols) {
|
|
2157
|
+
this.terminalScreen.reset(rows, cols);
|
|
2158
|
+
this.lastScreenText = "";
|
|
2159
|
+
this.lastScreenSnapshot = "";
|
|
2160
|
+
this.lastScreenChangeAt = 0;
|
|
2161
|
+
this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2162
|
+
}
|
|
2163
|
+
getFreshParsedStatusCache() {
|
|
2164
|
+
const cached = this.parsedStatusCache;
|
|
2165
|
+
if (cached && cached.committedMessagesRef === this.committedMessages && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBuffer === this.accumulatedRawBuffer && cached.screenText === this.lastScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName && cached.lastOutputAt === this.lastOutputAt) {
|
|
2166
|
+
return cached.result;
|
|
2167
|
+
}
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2132
2170
|
getIdleFinishConfirmMs() {
|
|
2133
2171
|
return this.timeouts.idleFinishConfirm;
|
|
2134
2172
|
}
|
|
@@ -2243,9 +2281,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2243
2281
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2244
2282
|
this.pendingOutputParseTimer = null;
|
|
2245
2283
|
}
|
|
2246
|
-
if (
|
|
2247
|
-
const rawData = this.
|
|
2248
|
-
this.
|
|
2284
|
+
if (this.pendingOutputParseChunks.length === 0) return;
|
|
2285
|
+
const rawData = this.pendingOutputParseChunks.join("");
|
|
2286
|
+
this.pendingOutputParseChunks = [];
|
|
2249
2287
|
this.handleOutput(rawData);
|
|
2250
2288
|
}
|
|
2251
2289
|
async spawn() {
|
|
@@ -2300,7 +2338,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2300
2338
|
terminalScreen: this.terminalScreen
|
|
2301
2339
|
});
|
|
2302
2340
|
}
|
|
2303
|
-
this.
|
|
2341
|
+
this.pendingOutputParseChunks.push(data);
|
|
2304
2342
|
if (!this.pendingOutputParseTimer) {
|
|
2305
2343
|
this.pendingOutputParseTimer = setTimeout(() => {
|
|
2306
2344
|
this.pendingOutputParseTimer = null;
|
|
@@ -2308,13 +2346,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
2308
2346
|
}, this.timeouts.ptyFlush);
|
|
2309
2347
|
}
|
|
2310
2348
|
if (this.onPtyDataCallback) {
|
|
2311
|
-
this.
|
|
2349
|
+
this.ptyOutputChunks.push(data);
|
|
2312
2350
|
if (!this.ptyOutputFlushTimer) {
|
|
2313
2351
|
this.ptyOutputFlushTimer = setTimeout(() => {
|
|
2314
|
-
if (this.
|
|
2315
|
-
this.onPtyDataCallback(this.
|
|
2352
|
+
if (this.ptyOutputChunks.length > 0 && this.onPtyDataCallback) {
|
|
2353
|
+
this.onPtyDataCallback(this.ptyOutputChunks.join(""));
|
|
2316
2354
|
}
|
|
2317
|
-
this.
|
|
2355
|
+
this.ptyOutputChunks = [];
|
|
2318
2356
|
this.ptyOutputFlushTimer = null;
|
|
2319
2357
|
}, this.timeouts.ptyFlush);
|
|
2320
2358
|
}
|
|
@@ -2339,7 +2377,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2339
2377
|
clearTimeout(this.startupSettleTimer);
|
|
2340
2378
|
this.startupSettleTimer = null;
|
|
2341
2379
|
}
|
|
2342
|
-
this.
|
|
2380
|
+
this.resetTerminalScreen(24, 80);
|
|
2343
2381
|
this.pendingTerminalQueryTail = "";
|
|
2344
2382
|
this.currentTurnScope = null;
|
|
2345
2383
|
this.finishRetryCount = 0;
|
|
@@ -2361,11 +2399,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
2361
2399
|
this.terminalScreen.write(rawData);
|
|
2362
2400
|
const cleanData = sanitizeTerminalText(rawData);
|
|
2363
2401
|
const now = Date.now();
|
|
2364
|
-
const
|
|
2365
|
-
const
|
|
2402
|
+
const shouldReadScreen = this.shouldReadTerminalScreenSnapshot(now);
|
|
2403
|
+
const screenText = shouldReadScreen ? this.readTerminalScreenText(now) : this.lastScreenText;
|
|
2404
|
+
const normalizedScreenSnapshot = shouldReadScreen ? normalizeScreenSnapshot(screenText) : this.lastScreenSnapshot;
|
|
2366
2405
|
this.lastOutputAt = now;
|
|
2367
2406
|
if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
|
|
2368
|
-
if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
2407
|
+
if (shouldReadScreen && normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
2369
2408
|
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
2370
2409
|
this.lastScreenChangeAt = now;
|
|
2371
2410
|
}
|
|
@@ -2387,7 +2426,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2387
2426
|
this.scheduleStartupSettleCheck();
|
|
2388
2427
|
}
|
|
2389
2428
|
if (this.isWaitingForResponse && cleanData) {
|
|
2390
|
-
this.responseBuffer = (this.responseBuffer
|
|
2429
|
+
this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
|
|
2391
2430
|
}
|
|
2392
2431
|
if (cleanData.trim()) {
|
|
2393
2432
|
if (this.serverConn) {
|
|
@@ -2396,11 +2435,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
2396
2435
|
this.logBuffer.push({ message: cleanData.trim(), level: "info" });
|
|
2397
2436
|
}
|
|
2398
2437
|
}
|
|
2399
|
-
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
2400
2438
|
const prevAccumulatedLen = this.accumulatedBuffer.length;
|
|
2401
2439
|
const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
|
|
2402
|
-
this.
|
|
2403
|
-
this.
|
|
2440
|
+
this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
|
|
2441
|
+
this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
2442
|
+
this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
2404
2443
|
if (this.currentTurnScope) {
|
|
2405
2444
|
const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
|
|
2406
2445
|
const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
|
|
@@ -2411,14 +2450,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
2411
2450
|
this.currentTurnScope.rawBufferStart = Math.max(0, this.currentTurnScope.rawBufferStart - droppedRaw);
|
|
2412
2451
|
}
|
|
2413
2452
|
}
|
|
2414
|
-
this.resolveStartupState("output");
|
|
2453
|
+
this.resolveStartupState("output", screenText, normalizedScreenSnapshot, now);
|
|
2415
2454
|
this.scheduleSettle();
|
|
2416
2455
|
}
|
|
2417
|
-
resolveStartupState(trigger) {
|
|
2456
|
+
resolveStartupState(trigger, screenTextOverride, normalizedScreenOverride, nowOverride) {
|
|
2418
2457
|
if (!this.startupParseGate) return;
|
|
2419
|
-
const now = Date.now();
|
|
2420
|
-
const screenText = this.
|
|
2421
|
-
const normalizedScreen = normalizeScreenSnapshot(screenText);
|
|
2458
|
+
const now = typeof nowOverride === "number" ? nowOverride : Date.now();
|
|
2459
|
+
const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.readTerminalScreenText();
|
|
2460
|
+
const normalizedScreen = typeof normalizedScreenOverride === "string" ? normalizedScreenOverride : normalizeScreenSnapshot(screenText);
|
|
2422
2461
|
const hasStartupOutput = !!this.startupFirstOutputAt || !!normalizedScreen.trim();
|
|
2423
2462
|
if (!hasStartupOutput) return;
|
|
2424
2463
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
@@ -2653,40 +2692,28 @@ var init_provider_cli_adapter = __esm({
|
|
|
2653
2692
|
}, delayTime);
|
|
2654
2693
|
return;
|
|
2655
2694
|
}
|
|
2656
|
-
const tail = this.settledBuffer;
|
|
2657
|
-
const screenText = this.terminalScreen.getText() || "";
|
|
2658
2695
|
this.resolveStartupState("settled");
|
|
2659
|
-
if (this.startupParseGate)
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
const
|
|
2663
|
-
|
|
2664
|
-
this.responseBuffer,
|
|
2665
|
-
this.currentTurnScope
|
|
2666
|
-
);
|
|
2667
|
-
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
|
|
2668
|
-
const modal = this.runParseApproval(tail) || parsedModal;
|
|
2669
|
-
const rawScriptStatus = this.runDetectStatus(tail);
|
|
2670
|
-
const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
|
|
2671
|
-
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
2696
|
+
if (this.startupParseGate) return;
|
|
2697
|
+
const session = this.runParseSession();
|
|
2698
|
+
if (!session) return;
|
|
2699
|
+
const { status, messages, modal, parsedStatus } = session;
|
|
2700
|
+
const parsedMessages = normalizeCliParsedMessages(messages, {
|
|
2672
2701
|
committedMessages: this.committedMessages,
|
|
2673
2702
|
scope: this.currentTurnScope,
|
|
2674
2703
|
lastOutputAt: this.lastOutputAt
|
|
2675
|
-
})
|
|
2676
|
-
if (this.maybeCommitVisibleIdleTranscript(
|
|
2677
|
-
|
|
2678
|
-
}
|
|
2679
|
-
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
2680
|
-
const parsedShowsLiveAssistantProgress = parsedTranscript?.status === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
|
|
2704
|
+
});
|
|
2705
|
+
if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
|
|
2706
|
+
const lastParsedAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant");
|
|
2681
2707
|
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
|
|
2708
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2682
2709
|
this.recordTrace("settled", {
|
|
2683
|
-
tail: summarizeCliTraceText(
|
|
2710
|
+
tail: summarizeCliTraceText(this.settledBuffer, 500),
|
|
2684
2711
|
screenText: summarizeCliTraceText(screenText, 1200),
|
|
2685
|
-
detectStatus:
|
|
2686
|
-
parsedStatus:
|
|
2712
|
+
detectStatus: status,
|
|
2713
|
+
parsedStatus: parsedStatus || null,
|
|
2687
2714
|
parsedMessageCount: parsedMessages.length,
|
|
2688
2715
|
parsedLastAssistant: lastParsedAssistant ? summarizeCliTraceText(lastParsedAssistant.content, 280) : "",
|
|
2689
|
-
parsedActiveModal:
|
|
2716
|
+
parsedActiveModal: modal,
|
|
2690
2717
|
approval: modal,
|
|
2691
2718
|
...buildCliTraceParseSnapshot({
|
|
2692
2719
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
@@ -2720,36 +2747,36 @@ var init_provider_cli_adapter = __esm({
|
|
|
2720
2747
|
`[${this.cliType}] Settled without assistant: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
|
|
2721
2748
|
);
|
|
2722
2749
|
}
|
|
2723
|
-
if (!
|
|
2750
|
+
if (!status) return;
|
|
2724
2751
|
const prevStatus = this.currentStatus;
|
|
2725
|
-
const ctx = { now,
|
|
2752
|
+
const ctx = { now, modal, status, parsedMessages, lastParsedAssistant, parsedStatus: parsedStatus || null, prevStatus };
|
|
2726
2753
|
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
2727
2754
|
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
2728
2755
|
LOG.info(
|
|
2729
2756
|
"CLI",
|
|
2730
|
-
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)}
|
|
2757
|
+
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)} status=${String(status || "")} parsedStatus=${String(parsedStatus || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
|
|
2731
2758
|
);
|
|
2732
|
-
const shouldHoldGenerating =
|
|
2759
|
+
const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
|
|
2733
2760
|
if (shouldHoldGenerating) {
|
|
2734
2761
|
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
2735
2762
|
return;
|
|
2736
2763
|
}
|
|
2737
|
-
if (
|
|
2764
|
+
if (status === "waiting_approval") {
|
|
2738
2765
|
this.applyWaitingApproval(ctx);
|
|
2739
2766
|
return;
|
|
2740
2767
|
}
|
|
2741
|
-
if (
|
|
2768
|
+
if (status === "generating") {
|
|
2742
2769
|
this.applyGenerating(ctx);
|
|
2743
2770
|
return;
|
|
2744
2771
|
}
|
|
2745
|
-
if (
|
|
2772
|
+
if (status === "idle") {
|
|
2746
2773
|
this.applyIdle(ctx, now);
|
|
2747
2774
|
}
|
|
2748
2775
|
}
|
|
2749
2776
|
// Returns false if the caller should bail out (debounce pending).
|
|
2750
2777
|
applyPendingScriptStatusDebounce(ctx) {
|
|
2751
|
-
const { now,
|
|
2752
|
-
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (
|
|
2778
|
+
const { now, status, prevStatus } = ctx;
|
|
2779
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (status === "generating" || status === "waiting_approval");
|
|
2753
2780
|
if (!shouldDebounce) {
|
|
2754
2781
|
this.pendingScriptStatus = null;
|
|
2755
2782
|
this.pendingScriptStatusSince = 0;
|
|
@@ -2767,8 +2794,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2767
2794
|
this.evaluateSettled();
|
|
2768
2795
|
}, delayMs);
|
|
2769
2796
|
};
|
|
2770
|
-
if (this.pendingScriptStatus !==
|
|
2771
|
-
this.pendingScriptStatus =
|
|
2797
|
+
if (this.pendingScriptStatus !== status) {
|
|
2798
|
+
this.pendingScriptStatus = status;
|
|
2772
2799
|
this.pendingScriptStatusSince = now;
|
|
2773
2800
|
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
2774
2801
|
return false;
|
|
@@ -2781,7 +2808,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2781
2808
|
return true;
|
|
2782
2809
|
}
|
|
2783
2810
|
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
2784
|
-
const {
|
|
2811
|
+
const { status } = ctx;
|
|
2785
2812
|
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
2786
2813
|
this.setStatus("generating", "recent_activity_hold");
|
|
2787
2814
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
@@ -2792,7 +2819,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2792
2819
|
}
|
|
2793
2820
|
}, this.timeouts.generatingIdle);
|
|
2794
2821
|
this.recordTrace("hold_generating_recent_activity", {
|
|
2795
|
-
scriptStatus,
|
|
2822
|
+
scriptStatus: status,
|
|
2796
2823
|
recentInteractiveActivity,
|
|
2797
2824
|
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
2798
2825
|
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
@@ -2846,11 +2873,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
2846
2873
|
}
|
|
2847
2874
|
}
|
|
2848
2875
|
applyGenerating(ctx) {
|
|
2849
|
-
const {
|
|
2876
|
+
const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
|
|
2850
2877
|
this.clearIdleFinishCandidate("generating");
|
|
2878
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2851
2879
|
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
2852
2880
|
const noActiveTurn = !this.currentTurnScope;
|
|
2853
2881
|
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText) || /accept edits on/i.test(effectiveScreenText) && (/Update available!/i.test(screenText) || /\/effort/i.test(screenText) || /^.*➜\s+\S+/m.test(effectiveScreenText));
|
|
2882
|
+
const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
|
|
2854
2883
|
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
2855
2884
|
return;
|
|
2856
2885
|
}
|
|
@@ -2877,7 +2906,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2877
2906
|
this.onStatusChange?.();
|
|
2878
2907
|
}
|
|
2879
2908
|
applyIdle(ctx, now) {
|
|
2880
|
-
const {
|
|
2909
|
+
const { modal, lastParsedAssistant, prevStatus } = ctx;
|
|
2881
2910
|
if (prevStatus === "waiting_approval") {
|
|
2882
2911
|
if (this.approvalExitTimeout) {
|
|
2883
2912
|
clearTimeout(this.approvalExitTimeout);
|
|
@@ -2999,20 +3028,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
2999
3028
|
this.setStatus("idle", "response_finished");
|
|
3000
3029
|
this.onStatusChange?.();
|
|
3001
3030
|
}
|
|
3002
|
-
maybeCommitVisibleIdleTranscript(
|
|
3031
|
+
maybeCommitVisibleIdleTranscript(session, parsedMessages) {
|
|
3003
3032
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
3004
3033
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
3005
|
-
if (!
|
|
3034
|
+
if (!session || session.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || session.modal) {
|
|
3006
3035
|
return false;
|
|
3007
3036
|
}
|
|
3008
|
-
const
|
|
3009
|
-
committedMessages: this.committedMessages,
|
|
3010
|
-
scope: this.currentTurnScope,
|
|
3011
|
-
lastOutputAt: this.lastOutputAt
|
|
3012
|
-
});
|
|
3013
|
-
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
3037
|
+
const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
|
|
3014
3038
|
if (!visibleAssistant) return false;
|
|
3015
|
-
this.committedMessages =
|
|
3039
|
+
this.committedMessages = parsedMessages;
|
|
3016
3040
|
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
3017
3041
|
this.clearAllTimers();
|
|
3018
3042
|
this.syncMessageViews();
|
|
@@ -3090,6 +3114,59 @@ var init_provider_cli_adapter = __esm({
|
|
|
3090
3114
|
};
|
|
3091
3115
|
}
|
|
3092
3116
|
// ─── Script Execution ──────────────────────────
|
|
3117
|
+
runParseSession() {
|
|
3118
|
+
if (typeof this.cliScripts?.parseSession === "function") {
|
|
3119
|
+
try {
|
|
3120
|
+
const screenText = this.terminalScreen.getText();
|
|
3121
|
+
const tail = this.recentOutputBuffer.slice(-500);
|
|
3122
|
+
const input = buildCliParseInput({
|
|
3123
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
3124
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3125
|
+
recentOutputBuffer: this.recentOutputBuffer,
|
|
3126
|
+
terminalScreenText: screenText,
|
|
3127
|
+
baseMessages: this.committedMessages,
|
|
3128
|
+
partialResponse: this.responseBuffer,
|
|
3129
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
3130
|
+
scope: this.currentTurnScope,
|
|
3131
|
+
runtimeSettings: this.runtimeSettings
|
|
3132
|
+
});
|
|
3133
|
+
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
3134
|
+
this.parseErrorMessage = null;
|
|
3135
|
+
return session && typeof session === "object" ? session : null;
|
|
3136
|
+
} catch (e) {
|
|
3137
|
+
const message = e?.message || String(e);
|
|
3138
|
+
this.parseErrorMessage = message;
|
|
3139
|
+
LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
|
|
3140
|
+
return null;
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
|
|
3144
|
+
try {
|
|
3145
|
+
const tail = this.settledBuffer;
|
|
3146
|
+
const parsedTranscript = this.parseCurrentTranscript(
|
|
3147
|
+
this.committedMessages,
|
|
3148
|
+
this.responseBuffer,
|
|
3149
|
+
this.currentTurnScope
|
|
3150
|
+
);
|
|
3151
|
+
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
|
|
3152
|
+
const approval = this.runParseApproval(tail);
|
|
3153
|
+
const modal = approval || parsedModal;
|
|
3154
|
+
const rawStatus = this.runDetectStatus(tail);
|
|
3155
|
+
const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
|
|
3156
|
+
const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
|
|
3157
|
+
return {
|
|
3158
|
+
status: effectiveStatus,
|
|
3159
|
+
messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
|
|
3160
|
+
modal,
|
|
3161
|
+
parsedStatus
|
|
3162
|
+
};
|
|
3163
|
+
} catch (e) {
|
|
3164
|
+
const message = e?.message || String(e);
|
|
3165
|
+
this.parseErrorMessage = message;
|
|
3166
|
+
LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
|
|
3167
|
+
return null;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3093
3170
|
runDetectStatus(text) {
|
|
3094
3171
|
if (!this.cliScripts?.detectStatus) return null;
|
|
3095
3172
|
try {
|
|
@@ -3163,14 +3240,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3163
3240
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3164
3241
|
let effectiveModal = startupModal || this.activeModal;
|
|
3165
3242
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
const
|
|
3169
|
-
if (
|
|
3170
|
-
|
|
3171
|
-
|
|
3243
|
+
let parsed = this.getFreshParsedStatusCache();
|
|
3244
|
+
if (!parsed && effectiveStatus !== "idle") {
|
|
3245
|
+
const now = Date.now();
|
|
3246
|
+
if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
|
|
3247
|
+
this.lastStatusHotPathParseAt = now;
|
|
3248
|
+
try {
|
|
3249
|
+
parsed = this.getScriptParsedStatus();
|
|
3250
|
+
} catch {
|
|
3251
|
+
}
|
|
3172
3252
|
}
|
|
3173
|
-
}
|
|
3253
|
+
}
|
|
3254
|
+
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3255
|
+
if (parsed?.status === "waiting_approval" && parsedModal) {
|
|
3256
|
+
effectiveStatus = "waiting_approval";
|
|
3257
|
+
effectiveModal = parsedModal;
|
|
3174
3258
|
}
|
|
3175
3259
|
}
|
|
3176
3260
|
return {
|
|
@@ -3202,7 +3286,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3202
3286
|
* Called by command handler / dashboard for rich content rendering.
|
|
3203
3287
|
*/
|
|
3204
3288
|
getScriptParsedStatus() {
|
|
3205
|
-
const screenText = this.
|
|
3289
|
+
const screenText = this.readTerminalScreenText();
|
|
3206
3290
|
const cached = this.parsedStatusCache;
|
|
3207
3291
|
if (cached && cached.committedMessagesRef === this.committedMessages && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBuffer === this.accumulatedRawBuffer && cached.screenText === screenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName && cached.lastOutputAt === this.lastOutputAt) {
|
|
3208
3292
|
return cached.result;
|
|
@@ -3222,8 +3306,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3222
3306
|
this.onStatusChange?.();
|
|
3223
3307
|
}
|
|
3224
3308
|
}
|
|
3225
|
-
if (
|
|
3226
|
-
|
|
3309
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
3310
|
+
const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
3311
|
+
committedMessages: this.committedMessages,
|
|
3312
|
+
scope: this.currentTurnScope,
|
|
3313
|
+
lastOutputAt: this.lastOutputAt
|
|
3314
|
+
});
|
|
3315
|
+
const fakeSession = {
|
|
3316
|
+
status: parsed.status || "idle",
|
|
3317
|
+
messages: parsed.messages,
|
|
3318
|
+
modal: parsedModal,
|
|
3319
|
+
parsedStatus: parsed.status || null
|
|
3320
|
+
};
|
|
3321
|
+
if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
|
|
3322
|
+
return this.getScriptParsedStatus();
|
|
3323
|
+
}
|
|
3227
3324
|
}
|
|
3228
3325
|
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
3229
3326
|
let result;
|
|
@@ -3405,6 +3502,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
3405
3502
|
}
|
|
3406
3503
|
await this.sendMessage(promptText);
|
|
3407
3504
|
}
|
|
3505
|
+
isSubmitStuck(normalizedPromptSnippet) {
|
|
3506
|
+
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return false;
|
|
3507
|
+
if (this.hasActionableApproval()) return false;
|
|
3508
|
+
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return false;
|
|
3509
|
+
const screenText = this.terminalScreen.getText();
|
|
3510
|
+
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return false;
|
|
3511
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
3512
|
+
if (liveApproval) return false;
|
|
3513
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3514
|
+
return liveStatus !== "generating" && liveStatus !== "waiting_approval";
|
|
3515
|
+
}
|
|
3408
3516
|
async writeToPty(data) {
|
|
3409
3517
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
3410
3518
|
await this.ptyProcess.write(data);
|
|
@@ -3428,6 +3536,121 @@ var init_provider_cli_adapter = __esm({
|
|
|
3428
3536
|
this.finishRetryTimer = null;
|
|
3429
3537
|
}
|
|
3430
3538
|
}
|
|
3539
|
+
commitSendUserTurn(state) {
|
|
3540
|
+
if (state.didCommitUserTurn) return;
|
|
3541
|
+
state.didCommitUserTurn = true;
|
|
3542
|
+
this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
|
|
3543
|
+
this.syncMessageViews();
|
|
3544
|
+
}
|
|
3545
|
+
armResponseTimeout() {
|
|
3546
|
+
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
3547
|
+
this.responseTimeout = setTimeout(() => {
|
|
3548
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
3549
|
+
}, this.timeouts.maxResponse);
|
|
3550
|
+
}
|
|
3551
|
+
writeSubmitKeyForRetry(mode) {
|
|
3552
|
+
void this.writeToPty(this.sendKey).catch((error) => {
|
|
3553
|
+
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
3554
|
+
});
|
|
3555
|
+
}
|
|
3556
|
+
retrySubmitIfStuck(state, attempt) {
|
|
3557
|
+
this.submitRetryTimer = null;
|
|
3558
|
+
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
3559
|
+
const screenText = this.terminalScreen.getText();
|
|
3560
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3561
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
3562
|
+
this.recordTrace("submit_write", {
|
|
3563
|
+
mode: "submit_retry",
|
|
3564
|
+
attempt,
|
|
3565
|
+
sendKey: this.sendKey,
|
|
3566
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3567
|
+
});
|
|
3568
|
+
this.writeSubmitKeyForRetry("submit_retry");
|
|
3569
|
+
if (attempt >= 3) {
|
|
3570
|
+
this.submitRetryUsed = true;
|
|
3571
|
+
return;
|
|
3572
|
+
}
|
|
3573
|
+
this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, attempt + 1), state.retryDelayMs);
|
|
3574
|
+
}
|
|
3575
|
+
retryImmediateSubmitIfStuck(state) {
|
|
3576
|
+
this.submitRetryTimer = null;
|
|
3577
|
+
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
3578
|
+
const screenText = this.terminalScreen.getText();
|
|
3579
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3580
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
3581
|
+
this.recordTrace("submit_write", {
|
|
3582
|
+
mode: "immediate_retry",
|
|
3583
|
+
attempt: 1,
|
|
3584
|
+
sendKey: this.sendKey,
|
|
3585
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3586
|
+
});
|
|
3587
|
+
this.writeSubmitKeyForRetry("immediate_retry");
|
|
3588
|
+
this.submitRetryUsed = true;
|
|
3589
|
+
}
|
|
3590
|
+
submitSendKey(state, completion) {
|
|
3591
|
+
if (!this.ptyProcess) {
|
|
3592
|
+
completion.resolveOnce();
|
|
3593
|
+
return;
|
|
3594
|
+
}
|
|
3595
|
+
this.submitPendingUntil = 0;
|
|
3596
|
+
const screenText = this.terminalScreen.getText();
|
|
3597
|
+
this.recordTrace("submit_write", {
|
|
3598
|
+
mode: "submit_key",
|
|
3599
|
+
sendKey: this.sendKey,
|
|
3600
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3601
|
+
});
|
|
3602
|
+
void this.writeToPty(this.sendKey).then(() => {
|
|
3603
|
+
this.commitSendUserTurn(state);
|
|
3604
|
+
this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, 1), state.retryDelayMs);
|
|
3605
|
+
this.armResponseTimeout();
|
|
3606
|
+
completion.resolveOnce();
|
|
3607
|
+
}, completion.rejectOnce);
|
|
3608
|
+
}
|
|
3609
|
+
submitImmediatePrompt(state, completion) {
|
|
3610
|
+
this.submitPendingUntil = 0;
|
|
3611
|
+
this.recordTrace("submit_write", {
|
|
3612
|
+
mode: "immediate",
|
|
3613
|
+
text: summarizeCliTraceText(state.text, 500),
|
|
3614
|
+
sendKey: this.sendKey,
|
|
3615
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3616
|
+
});
|
|
3617
|
+
void this.writeToPty(state.text + this.sendKey).then(() => {
|
|
3618
|
+
this.commitSendUserTurn(state);
|
|
3619
|
+
this.submitRetryTimer = setTimeout(() => this.retryImmediateSubmitIfStuck(state), state.retryDelayMs);
|
|
3620
|
+
this.armResponseTimeout();
|
|
3621
|
+
completion.resolveOnce();
|
|
3622
|
+
}, completion.rejectOnce);
|
|
3623
|
+
}
|
|
3624
|
+
waitForEchoAndSubmit(state, completion, submitStartedAt, lastNormalizedScreen = "", lastScreenChangeAt = submitStartedAt) {
|
|
3625
|
+
if (!this.ptyProcess) {
|
|
3626
|
+
completion.resolveOnce();
|
|
3627
|
+
return;
|
|
3628
|
+
}
|
|
3629
|
+
const now = Date.now();
|
|
3630
|
+
const elapsed = now - submitStartedAt;
|
|
3631
|
+
const screenText = this.terminalScreen.getText();
|
|
3632
|
+
const normalizedScreen = normalizePromptText(screenText);
|
|
3633
|
+
const nextScreenChangeAt = normalizedScreen !== lastNormalizedScreen ? now : lastScreenChangeAt;
|
|
3634
|
+
const echoVisible = !state.normalizedPromptSnippet || promptLikelyVisible(screenText, state.normalizedPromptSnippet);
|
|
3635
|
+
if (echoVisible) {
|
|
3636
|
+
const screenSettled = now - nextScreenChangeAt >= 500;
|
|
3637
|
+
if (elapsed >= state.submitDelayMs && screenSettled) {
|
|
3638
|
+
this.submitSendKey(state, completion);
|
|
3639
|
+
return;
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
if (elapsed >= state.maxEchoWaitMs) {
|
|
3643
|
+
this.submitSendKey(state, completion);
|
|
3644
|
+
return;
|
|
3645
|
+
}
|
|
3646
|
+
setTimeout(() => this.waitForEchoAndSubmit(
|
|
3647
|
+
state,
|
|
3648
|
+
completion,
|
|
3649
|
+
submitStartedAt,
|
|
3650
|
+
normalizedScreen,
|
|
3651
|
+
nextScreenChangeAt
|
|
3652
|
+
), 50);
|
|
3653
|
+
}
|
|
3431
3654
|
async sendMessage(text) {
|
|
3432
3655
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
3433
3656
|
const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
|
|
@@ -3503,12 +3726,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
3503
3726
|
const submitDelayMs = this.sendDelayMs + Math.min(2e3, Math.max(0, estimatedLines - 1) * 350);
|
|
3504
3727
|
const maxEchoWaitMs = submitDelayMs + Math.max(1500, Math.min(5e3, estimatedLines * 500));
|
|
3505
3728
|
const retryDelayMs = Math.max(350, Math.min(1500, Math.max(this.sendDelayMs, submitDelayMs)));
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3729
|
+
const sendState = {
|
|
3730
|
+
text,
|
|
3731
|
+
normalizedPromptSnippet,
|
|
3732
|
+
submitDelayMs,
|
|
3733
|
+
maxEchoWaitMs,
|
|
3734
|
+
retryDelayMs,
|
|
3735
|
+
didCommitUserTurn: false
|
|
3512
3736
|
};
|
|
3513
3737
|
if (this.settleTimer) {
|
|
3514
3738
|
clearTimeout(this.settleTimer);
|
|
@@ -3516,110 +3740,23 @@ var init_provider_cli_adapter = __esm({
|
|
|
3516
3740
|
}
|
|
3517
3741
|
this.responseEpoch += 1;
|
|
3518
3742
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
3519
|
-
const startResponseTimeout = () => {
|
|
3520
|
-
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
3521
|
-
this.responseTimeout = setTimeout(() => {
|
|
3522
|
-
if (this.isWaitingForResponse) this.finishResponse();
|
|
3523
|
-
}, this.timeouts.maxResponse);
|
|
3524
|
-
};
|
|
3525
3743
|
await new Promise((resolve12, reject) => {
|
|
3526
3744
|
let resolved = false;
|
|
3527
|
-
const
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
const writeRetryKey = (mode) => {
|
|
3539
|
-
void this.writeToPty(this.sendKey).catch((error) => {
|
|
3540
|
-
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
3541
|
-
});
|
|
3542
|
-
};
|
|
3543
|
-
const submit = () => {
|
|
3544
|
-
if (!this.ptyProcess) {
|
|
3545
|
-
resolveOnce();
|
|
3546
|
-
return;
|
|
3745
|
+
const completion = {
|
|
3746
|
+
resolveOnce: () => {
|
|
3747
|
+
if (resolved) return;
|
|
3748
|
+
resolved = true;
|
|
3749
|
+
resolve12();
|
|
3750
|
+
},
|
|
3751
|
+
rejectOnce: (error) => {
|
|
3752
|
+
if (resolved) return;
|
|
3753
|
+
this.resetPendingSendState("send_write_failed");
|
|
3754
|
+
resolved = true;
|
|
3755
|
+
reject(error);
|
|
3547
3756
|
}
|
|
3548
|
-
this.submitPendingUntil = 0;
|
|
3549
|
-
const screenText = this.terminalScreen.getText();
|
|
3550
|
-
this.recordTrace("submit_write", {
|
|
3551
|
-
mode: "submit_key",
|
|
3552
|
-
sendKey: this.sendKey,
|
|
3553
|
-
screenText: summarizeCliTraceText(screenText, 500)
|
|
3554
|
-
});
|
|
3555
|
-
const retrySubmitIfStuck = (attempt) => {
|
|
3556
|
-
this.submitRetryTimer = null;
|
|
3557
|
-
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3558
|
-
if (this.hasActionableApproval()) return;
|
|
3559
|
-
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3560
|
-
const screenText2 = this.terminalScreen.getText();
|
|
3561
|
-
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
3562
|
-
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
3563
|
-
if (liveApproval) return;
|
|
3564
|
-
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3565
|
-
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
3566
|
-
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3567
|
-
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
3568
|
-
this.recordTrace("submit_write", {
|
|
3569
|
-
mode: "submit_retry",
|
|
3570
|
-
attempt,
|
|
3571
|
-
sendKey: this.sendKey,
|
|
3572
|
-
screenText: summarizeCliTraceText(screenText2, 500)
|
|
3573
|
-
});
|
|
3574
|
-
writeRetryKey("submit_retry");
|
|
3575
|
-
if (attempt >= 3) {
|
|
3576
|
-
this.submitRetryUsed = true;
|
|
3577
|
-
return;
|
|
3578
|
-
}
|
|
3579
|
-
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
|
|
3580
|
-
};
|
|
3581
|
-
void this.writeToPty(this.sendKey).then(() => {
|
|
3582
|
-
commitUserTurn();
|
|
3583
|
-
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
|
|
3584
|
-
startResponseTimeout();
|
|
3585
|
-
resolveOnce();
|
|
3586
|
-
}, rejectOnce);
|
|
3587
3757
|
};
|
|
3588
3758
|
if (this.submitStrategy === "immediate") {
|
|
3589
|
-
this.
|
|
3590
|
-
this.recordTrace("submit_write", {
|
|
3591
|
-
mode: "immediate",
|
|
3592
|
-
text: summarizeCliTraceText(text, 500),
|
|
3593
|
-
sendKey: this.sendKey,
|
|
3594
|
-
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3595
|
-
});
|
|
3596
|
-
void this.writeToPty(text + this.sendKey).then(() => {
|
|
3597
|
-
commitUserTurn();
|
|
3598
|
-
this.submitRetryTimer = setTimeout(() => {
|
|
3599
|
-
this.submitRetryTimer = null;
|
|
3600
|
-
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3601
|
-
if (this.hasActionableApproval()) return;
|
|
3602
|
-
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3603
|
-
const screenText = this.terminalScreen.getText();
|
|
3604
|
-
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
3605
|
-
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
3606
|
-
if (liveApproval) return;
|
|
3607
|
-
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3608
|
-
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
3609
|
-
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
3610
|
-
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3611
|
-
this.recordTrace("submit_write", {
|
|
3612
|
-
mode: "immediate_retry",
|
|
3613
|
-
attempt: 1,
|
|
3614
|
-
sendKey: this.sendKey,
|
|
3615
|
-
screenText: summarizeCliTraceText(screenText, 500)
|
|
3616
|
-
});
|
|
3617
|
-
writeRetryKey("immediate_retry");
|
|
3618
|
-
this.submitRetryUsed = true;
|
|
3619
|
-
}, retryDelayMs);
|
|
3620
|
-
startResponseTimeout();
|
|
3621
|
-
resolveOnce();
|
|
3622
|
-
}, rejectOnce);
|
|
3759
|
+
this.submitImmediatePrompt(sendState, completion);
|
|
3623
3760
|
return;
|
|
3624
3761
|
}
|
|
3625
3762
|
if (submitDelayMs > 0) {
|
|
@@ -3632,36 +3769,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
3632
3769
|
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3633
3770
|
});
|
|
3634
3771
|
const submitStartedAt = Date.now();
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
resolveOnce();
|
|
3640
|
-
return;
|
|
3641
|
-
}
|
|
3642
|
-
const now = Date.now();
|
|
3643
|
-
const elapsed = now - submitStartedAt;
|
|
3644
|
-
const screenText = this.terminalScreen.getText();
|
|
3645
|
-
const normalizedScreen = normalizePromptText(screenText);
|
|
3646
|
-
if (normalizedScreen !== lastNormalizedScreen) {
|
|
3647
|
-
lastNormalizedScreen = normalizedScreen;
|
|
3648
|
-
lastScreenChangeAt = now;
|
|
3649
|
-
}
|
|
3650
|
-
const echoVisible = !normalizedPromptSnippet || promptLikelyVisible(screenText, normalizedPromptSnippet);
|
|
3651
|
-
if (echoVisible) {
|
|
3652
|
-
const screenSettled = now - lastScreenChangeAt >= 500;
|
|
3653
|
-
if (elapsed >= submitDelayMs && screenSettled) {
|
|
3654
|
-
submit();
|
|
3655
|
-
return;
|
|
3656
|
-
}
|
|
3657
|
-
}
|
|
3658
|
-
if (elapsed >= maxEchoWaitMs) {
|
|
3659
|
-
submit();
|
|
3660
|
-
return;
|
|
3661
|
-
}
|
|
3662
|
-
setTimeout(waitForEchoAndSubmit, 50);
|
|
3663
|
-
};
|
|
3664
|
-
void this.writeToPty(text).then(() => waitForEchoAndSubmit(), rejectOnce);
|
|
3772
|
+
void this.writeToPty(text).then(
|
|
3773
|
+
() => this.waitForEchoAndSubmit(sendState, completion, submitStartedAt),
|
|
3774
|
+
completion.rejectOnce
|
|
3775
|
+
);
|
|
3665
3776
|
});
|
|
3666
3777
|
}
|
|
3667
3778
|
getPartialResponse() {
|
|
@@ -3738,9 +3849,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3738
3849
|
shutdown() {
|
|
3739
3850
|
this.clearIdleFinishCandidate("shutdown");
|
|
3740
3851
|
this.clearAllTimers();
|
|
3741
|
-
this.
|
|
3852
|
+
this.pendingOutputParseChunks = [];
|
|
3742
3853
|
this.pendingTerminalQueryTail = "";
|
|
3743
|
-
this.
|
|
3854
|
+
this.ptyOutputChunks = [];
|
|
3744
3855
|
this.finishRetryCount = 0;
|
|
3745
3856
|
if (this.ptyProcess) {
|
|
3746
3857
|
this.ptyProcess.write("");
|
|
@@ -3761,9 +3872,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3761
3872
|
detach() {
|
|
3762
3873
|
this.clearIdleFinishCandidate("detach");
|
|
3763
3874
|
this.clearAllTimers();
|
|
3764
|
-
this.
|
|
3875
|
+
this.pendingOutputParseChunks = [];
|
|
3765
3876
|
this.pendingTerminalQueryTail = "";
|
|
3766
|
-
this.
|
|
3877
|
+
this.ptyOutputChunks = [];
|
|
3767
3878
|
this.finishRetryCount = 0;
|
|
3768
3879
|
if (this.ptyProcess) {
|
|
3769
3880
|
try {
|
|
@@ -3794,19 +3905,19 @@ var init_provider_cli_adapter = __esm({
|
|
|
3794
3905
|
clearTimeout(this.pendingOutputParseTimer);
|
|
3795
3906
|
this.pendingOutputParseTimer = null;
|
|
3796
3907
|
}
|
|
3797
|
-
this.
|
|
3908
|
+
this.pendingOutputParseChunks = [];
|
|
3798
3909
|
this.pendingTerminalQueryTail = "";
|
|
3799
3910
|
if (this.ptyOutputFlushTimer) {
|
|
3800
3911
|
clearTimeout(this.ptyOutputFlushTimer);
|
|
3801
3912
|
this.ptyOutputFlushTimer = null;
|
|
3802
3913
|
}
|
|
3803
|
-
this.
|
|
3914
|
+
this.ptyOutputChunks = [];
|
|
3804
3915
|
if (this.finishRetryTimer) {
|
|
3805
3916
|
clearTimeout(this.finishRetryTimer);
|
|
3806
3917
|
this.finishRetryTimer = null;
|
|
3807
3918
|
}
|
|
3808
3919
|
this.finishRetryCount = 0;
|
|
3809
|
-
this.
|
|
3920
|
+
this.resetTerminalScreen();
|
|
3810
3921
|
this.ptyProcess?.clearBuffer?.();
|
|
3811
3922
|
this.onStatusChange?.();
|
|
3812
3923
|
}
|
|
@@ -3923,7 +4034,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3923
4034
|
traceEntryCount: this.traceEntries.length,
|
|
3924
4035
|
statusHistory: this.statusHistory.slice(-30),
|
|
3925
4036
|
timeouts: this.timeouts,
|
|
3926
|
-
pendingOutputParseBufferLength: this.
|
|
4037
|
+
pendingOutputParseBufferLength: this.pendingOutputParseChunks.reduce((total, chunk) => total + chunk.length, 0),
|
|
3927
4038
|
pendingOutputParseScheduled: !!this.pendingOutputParseTimer,
|
|
3928
4039
|
ptyAlive: !!this.ptyProcess
|
|
3929
4040
|
};
|
|
@@ -9514,14 +9625,14 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
9514
9625
|
id: state.instanceId || state.type,
|
|
9515
9626
|
parentId: null,
|
|
9516
9627
|
providerType: state.type,
|
|
9517
|
-
|
|
9628
|
+
providerName: state.name,
|
|
9518
9629
|
kind: "workspace",
|
|
9519
9630
|
transport: "cdp-page",
|
|
9520
9631
|
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
9521
9632
|
activeModal: activeChat?.activeModal || null
|
|
9522
9633
|
}),
|
|
9523
9634
|
title,
|
|
9524
|
-
|
|
9635
|
+
workspace: state.workspace || null,
|
|
9525
9636
|
activeChat,
|
|
9526
9637
|
...summaryMetadata && { summaryMetadata },
|
|
9527
9638
|
...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
|
|
@@ -9546,7 +9657,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
9546
9657
|
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
9547
9658
|
parentId: parent.instanceId || parent.type,
|
|
9548
9659
|
providerType: ext.type,
|
|
9549
|
-
|
|
9660
|
+
providerName: ext.name,
|
|
9550
9661
|
providerSessionId: ext.providerSessionId,
|
|
9551
9662
|
kind: "agent",
|
|
9552
9663
|
transport: "cdp-webview",
|
|
@@ -9554,7 +9665,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
9554
9665
|
activeModal: activeChat?.activeModal || null
|
|
9555
9666
|
}),
|
|
9556
9667
|
title: activeChat?.title || ext.name,
|
|
9557
|
-
|
|
9668
|
+
workspace: parent.workspace || null,
|
|
9558
9669
|
activeChat,
|
|
9559
9670
|
...summaryMetadata && { summaryMetadata },
|
|
9560
9671
|
...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
|
|
@@ -9594,7 +9705,7 @@ function buildCliSession(state, options) {
|
|
|
9594
9705
|
id: state.instanceId,
|
|
9595
9706
|
parentId: null,
|
|
9596
9707
|
providerType: state.type,
|
|
9597
|
-
|
|
9708
|
+
providerName: state.name,
|
|
9598
9709
|
providerSessionId: state.providerSessionId,
|
|
9599
9710
|
kind: "agent",
|
|
9600
9711
|
transport: "pty",
|
|
@@ -9602,7 +9713,7 @@ function buildCliSession(state, options) {
|
|
|
9602
9713
|
activeModal: activeChat?.activeModal || null
|
|
9603
9714
|
}),
|
|
9604
9715
|
title: activeChat?.title || state.name,
|
|
9605
|
-
|
|
9716
|
+
workspace: state.workspace || null,
|
|
9606
9717
|
...includeRuntimeMetadata && {
|
|
9607
9718
|
runtimeKey: state.runtime?.runtimeKey,
|
|
9608
9719
|
runtimeDisplayName: state.runtime?.displayName,
|
|
@@ -9641,14 +9752,14 @@ function buildAcpSession(state, options) {
|
|
|
9641
9752
|
id: state.instanceId,
|
|
9642
9753
|
parentId: null,
|
|
9643
9754
|
providerType: state.type,
|
|
9644
|
-
|
|
9755
|
+
providerName: state.name,
|
|
9645
9756
|
kind: "agent",
|
|
9646
9757
|
transport: "acp",
|
|
9647
9758
|
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
9648
9759
|
activeModal: activeChat?.activeModal || null
|
|
9649
9760
|
}),
|
|
9650
9761
|
title: activeChat?.title || state.name,
|
|
9651
|
-
|
|
9762
|
+
workspace: state.workspace || null,
|
|
9652
9763
|
activeChat,
|
|
9653
9764
|
...summaryMetadata && { summaryMetadata },
|
|
9654
9765
|
...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
|
|
@@ -10095,26 +10206,26 @@ function buildReadChatReplayCollapseSignature(message) {
|
|
|
10095
10206
|
function shouldCollapseReadChatReplayDuplicate(message) {
|
|
10096
10207
|
if (!message) return false;
|
|
10097
10208
|
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
10098
|
-
|
|
10099
|
-
const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
|
|
10100
|
-
return kind === "tool" || kind === "terminal" || kind === "thought" || kind === "system";
|
|
10209
|
+
return role === "assistant" || role === "system";
|
|
10101
10210
|
}
|
|
10102
10211
|
function collapseReplayDuplicatesFromReadChat(messages) {
|
|
10103
10212
|
const collapsed = [];
|
|
10104
|
-
|
|
10213
|
+
const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
|
|
10105
10214
|
for (const message of messages) {
|
|
10215
|
+
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
10216
|
+
if (role === "user") {
|
|
10217
|
+
replaySignaturesInCurrentTurn.clear();
|
|
10218
|
+
}
|
|
10106
10219
|
const signature = buildReadChatReplayCollapseSignature(message);
|
|
10107
10220
|
const previous = collapsed[collapsed.length - 1];
|
|
10108
10221
|
const previousSignature = buildReadChatReplayCollapseSignature(previous);
|
|
10109
10222
|
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
10110
10223
|
if (previousSignature === signature) continue;
|
|
10111
|
-
if (
|
|
10224
|
+
if (replaySignaturesInCurrentTurn.has(signature)) continue;
|
|
10112
10225
|
}
|
|
10113
10226
|
collapsed.push(message);
|
|
10114
10227
|
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
10115
|
-
|
|
10116
|
-
} else if ((message.role || "").toLowerCase() === "user") {
|
|
10117
|
-
lastReplayTurnSignature = "";
|
|
10228
|
+
replaySignaturesInCurrentTurn.add(signature);
|
|
10118
10229
|
}
|
|
10119
10230
|
}
|
|
10120
10231
|
return collapsed;
|
|
@@ -17622,6 +17733,18 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
|
|
|
17622
17733
|
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
|
|
17623
17734
|
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
17624
17735
|
}
|
|
17736
|
+
function projectLiveSessionFromFull(session) {
|
|
17737
|
+
const {
|
|
17738
|
+
capabilities: _capabilities,
|
|
17739
|
+
controlValues: _controlValues,
|
|
17740
|
+
providerControls: _providerControls,
|
|
17741
|
+
...rest
|
|
17742
|
+
} = session;
|
|
17743
|
+
return {
|
|
17744
|
+
...rest,
|
|
17745
|
+
activeChat: normalizeActiveChatData(session.activeChat, LIVE_STATUS_ACTIVE_CHAT_OPTIONS)
|
|
17746
|
+
};
|
|
17747
|
+
}
|
|
17625
17748
|
function buildRecentLaunches(recentActivity) {
|
|
17626
17749
|
return recentActivity.map((item) => ({
|
|
17627
17750
|
id: item.id,
|
|
@@ -17646,7 +17769,7 @@ function buildStatusSnapshot(options) {
|
|
|
17646
17769
|
options.cdpManagers,
|
|
17647
17770
|
{ profile: "full" }
|
|
17648
17771
|
);
|
|
17649
|
-
const sessions = profile === "full" ? unreadSourceSessions : buildSessionEntries(
|
|
17772
|
+
const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
|
|
17650
17773
|
options.allStates,
|
|
17651
17774
|
options.cdpManagers,
|
|
17652
17775
|
{ profile }
|
|
@@ -18932,10 +19055,6 @@ var DaemonStatusReporter = class {
|
|
|
18932
19055
|
LOG.info("StatusReport", `\u2192${target} ${baseSummary}`);
|
|
18933
19056
|
}
|
|
18934
19057
|
}
|
|
18935
|
-
const sessions = buildSessionEntries(
|
|
18936
|
-
allStates,
|
|
18937
|
-
this.deps.cdpManagers
|
|
18938
|
-
);
|
|
18939
19058
|
const payload = {
|
|
18940
19059
|
...buildStatusSnapshot({
|
|
18941
19060
|
allStates,
|
|
@@ -18955,9 +19074,9 @@ var DaemonStatusReporter = class {
|
|
|
18955
19074
|
}),
|
|
18956
19075
|
screenshotUsage: this.deps.getScreenshotUsage?.() || null
|
|
18957
19076
|
};
|
|
18958
|
-
const payloadBytes = JSON.stringify(payload).length;
|
|
18959
19077
|
const p2pSent = this.sendP2PPayload(payload);
|
|
18960
19078
|
if (p2pSent) {
|
|
19079
|
+
const payloadBytes = JSON.stringify(payload).length;
|
|
18961
19080
|
LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
|
|
18962
19081
|
if (payloadBytes > 256 * 1024) {
|
|
18963
19082
|
LOG.warn(
|
|
@@ -18967,8 +19086,10 @@ var DaemonStatusReporter = class {
|
|
|
18967
19086
|
}
|
|
18968
19087
|
}
|
|
18969
19088
|
if (opts?.p2pOnly) return;
|
|
19089
|
+
if (!serverConnected || !serverConn) return;
|
|
19090
|
+
const payloadSessions = Array.isArray(payload.sessions) ? payload.sessions : [];
|
|
18970
19091
|
const wsPayload = {
|
|
18971
|
-
sessions:
|
|
19092
|
+
sessions: payloadSessions.map((session) => ({
|
|
18972
19093
|
id: session.id,
|
|
18973
19094
|
parentId: session.parentId,
|
|
18974
19095
|
providerType: session.providerType,
|
|
@@ -18994,8 +19115,9 @@ var DaemonStatusReporter = class {
|
|
|
18994
19115
|
return;
|
|
18995
19116
|
}
|
|
18996
19117
|
this.lastServerStatusHash = wsHash;
|
|
19118
|
+
const wsPayloadBytes = JSON.stringify(wsPayload).length;
|
|
18997
19119
|
serverConn.sendMessage("status_report", wsPayload);
|
|
18998
|
-
LOG.debug("Server", `sent status_report (${
|
|
19120
|
+
LOG.debug("Server", `sent status_report (${wsPayloadBytes} bytes)${opts?.reason ? ` [${opts.reason}]` : ""}`);
|
|
18999
19121
|
}
|
|
19000
19122
|
// ─── P2P ─────────────────────────────────────────
|
|
19001
19123
|
sendP2PPayload(payload) {
|