@adhdev/daemon-core 0.9.18 → 0.9.20
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.js
CHANGED
|
@@ -1961,6 +1961,7 @@ var init_provider_cli_runtime = __esm({
|
|
|
1961
1961
|
var provider_cli_adapter_exports = {};
|
|
1962
1962
|
__export(provider_cli_adapter_exports, {
|
|
1963
1963
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
1964
|
+
appendBoundedText: () => appendBoundedText,
|
|
1964
1965
|
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
1965
1966
|
});
|
|
1966
1967
|
function normalizeComparableTranscriptText(value) {
|
|
@@ -1993,6 +1994,14 @@ function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages
|
|
|
1993
1994
|
}
|
|
1994
1995
|
return false;
|
|
1995
1996
|
}
|
|
1997
|
+
function appendBoundedText(current, chunk, maxChars) {
|
|
1998
|
+
if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
|
|
1999
|
+
if (maxChars <= 0) return "";
|
|
2000
|
+
if (chunk.length >= maxChars) return chunk.slice(-maxChars);
|
|
2001
|
+
const keepFromCurrent = maxChars - chunk.length;
|
|
2002
|
+
if (current.length <= keepFromCurrent) return current + chunk;
|
|
2003
|
+
return current.slice(-keepFromCurrent) + chunk;
|
|
2004
|
+
}
|
|
1996
2005
|
var os10, ProviderCliAdapter;
|
|
1997
2006
|
var init_provider_cli_adapter = __esm({
|
|
1998
2007
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
@@ -2070,15 +2079,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
2070
2079
|
startupFirstOutputAt = 0;
|
|
2071
2080
|
// PTY I/O
|
|
2072
2081
|
onPtyDataCallback = null;
|
|
2073
|
-
|
|
2082
|
+
pendingOutputParseChunks = [];
|
|
2074
2083
|
pendingOutputParseTimer = null;
|
|
2075
|
-
|
|
2084
|
+
ptyOutputChunks = [];
|
|
2076
2085
|
ptyOutputFlushTimer = null;
|
|
2077
2086
|
pendingTerminalQueryTail = "";
|
|
2078
2087
|
lastOutputAt = 0;
|
|
2079
2088
|
lastNonEmptyOutputAt = 0;
|
|
2080
2089
|
lastScreenChangeAt = 0;
|
|
2081
2090
|
lastScreenSnapshot = "";
|
|
2091
|
+
lastScreenText = "";
|
|
2092
|
+
lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2082
2093
|
// Server log forwarding
|
|
2083
2094
|
serverConn = null;
|
|
2084
2095
|
logBuffer = [];
|
|
@@ -2124,6 +2135,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2124
2135
|
traceSeq = 0;
|
|
2125
2136
|
traceSessionId = "";
|
|
2126
2137
|
parsedStatusCache = null;
|
|
2138
|
+
lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
|
|
2139
|
+
static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
|
|
2140
|
+
static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
|
|
2127
2141
|
static MAX_TRACE_ENTRIES = 250;
|
|
2128
2142
|
providerResolutionMeta;
|
|
2129
2143
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
@@ -2132,6 +2146,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
2132
2146
|
this.messages = [...this.committedMessages];
|
|
2133
2147
|
this.structuredMessages = [...this.committedMessages];
|
|
2134
2148
|
}
|
|
2149
|
+
readTerminalScreenText(now = Date.now()) {
|
|
2150
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2151
|
+
this.lastScreenText = screenText;
|
|
2152
|
+
this.lastScreenSnapshotReadAt = now;
|
|
2153
|
+
return screenText;
|
|
2154
|
+
}
|
|
2155
|
+
shouldReadTerminalScreenSnapshot(now) {
|
|
2156
|
+
if (!this.lastScreenText) return true;
|
|
2157
|
+
return now - this.lastScreenSnapshotReadAt >= _ProviderCliAdapter.SCREEN_SNAPSHOT_MIN_INTERVAL_MS;
|
|
2158
|
+
}
|
|
2159
|
+
resetTerminalScreen(rows, cols) {
|
|
2160
|
+
this.terminalScreen.reset(rows, cols);
|
|
2161
|
+
this.lastScreenText = "";
|
|
2162
|
+
this.lastScreenSnapshot = "";
|
|
2163
|
+
this.lastScreenChangeAt = 0;
|
|
2164
|
+
this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2165
|
+
}
|
|
2166
|
+
getFreshParsedStatusCache() {
|
|
2167
|
+
const cached = this.parsedStatusCache;
|
|
2168
|
+
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) {
|
|
2169
|
+
return cached.result;
|
|
2170
|
+
}
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2135
2173
|
getIdleFinishConfirmMs() {
|
|
2136
2174
|
return this.timeouts.idleFinishConfirm;
|
|
2137
2175
|
}
|
|
@@ -2246,9 +2284,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2246
2284
|
clearTimeout(this.pendingOutputParseTimer);
|
|
2247
2285
|
this.pendingOutputParseTimer = null;
|
|
2248
2286
|
}
|
|
2249
|
-
if (
|
|
2250
|
-
const rawData = this.
|
|
2251
|
-
this.
|
|
2287
|
+
if (this.pendingOutputParseChunks.length === 0) return;
|
|
2288
|
+
const rawData = this.pendingOutputParseChunks.join("");
|
|
2289
|
+
this.pendingOutputParseChunks = [];
|
|
2252
2290
|
this.handleOutput(rawData);
|
|
2253
2291
|
}
|
|
2254
2292
|
async spawn() {
|
|
@@ -2303,7 +2341,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2303
2341
|
terminalScreen: this.terminalScreen
|
|
2304
2342
|
});
|
|
2305
2343
|
}
|
|
2306
|
-
this.
|
|
2344
|
+
this.pendingOutputParseChunks.push(data);
|
|
2307
2345
|
if (!this.pendingOutputParseTimer) {
|
|
2308
2346
|
this.pendingOutputParseTimer = setTimeout(() => {
|
|
2309
2347
|
this.pendingOutputParseTimer = null;
|
|
@@ -2311,13 +2349,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
2311
2349
|
}, this.timeouts.ptyFlush);
|
|
2312
2350
|
}
|
|
2313
2351
|
if (this.onPtyDataCallback) {
|
|
2314
|
-
this.
|
|
2352
|
+
this.ptyOutputChunks.push(data);
|
|
2315
2353
|
if (!this.ptyOutputFlushTimer) {
|
|
2316
2354
|
this.ptyOutputFlushTimer = setTimeout(() => {
|
|
2317
|
-
if (this.
|
|
2318
|
-
this.onPtyDataCallback(this.
|
|
2355
|
+
if (this.ptyOutputChunks.length > 0 && this.onPtyDataCallback) {
|
|
2356
|
+
this.onPtyDataCallback(this.ptyOutputChunks.join(""));
|
|
2319
2357
|
}
|
|
2320
|
-
this.
|
|
2358
|
+
this.ptyOutputChunks = [];
|
|
2321
2359
|
this.ptyOutputFlushTimer = null;
|
|
2322
2360
|
}, this.timeouts.ptyFlush);
|
|
2323
2361
|
}
|
|
@@ -2342,7 +2380,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2342
2380
|
clearTimeout(this.startupSettleTimer);
|
|
2343
2381
|
this.startupSettleTimer = null;
|
|
2344
2382
|
}
|
|
2345
|
-
this.
|
|
2383
|
+
this.resetTerminalScreen(24, 80);
|
|
2346
2384
|
this.pendingTerminalQueryTail = "";
|
|
2347
2385
|
this.currentTurnScope = null;
|
|
2348
2386
|
this.finishRetryCount = 0;
|
|
@@ -2364,11 +2402,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
2364
2402
|
this.terminalScreen.write(rawData);
|
|
2365
2403
|
const cleanData = sanitizeTerminalText(rawData);
|
|
2366
2404
|
const now = Date.now();
|
|
2367
|
-
const
|
|
2368
|
-
const
|
|
2405
|
+
const shouldReadScreen = this.shouldReadTerminalScreenSnapshot(now);
|
|
2406
|
+
const screenText = shouldReadScreen ? this.readTerminalScreenText(now) : this.lastScreenText;
|
|
2407
|
+
const normalizedScreenSnapshot = shouldReadScreen ? normalizeScreenSnapshot(screenText) : this.lastScreenSnapshot;
|
|
2369
2408
|
this.lastOutputAt = now;
|
|
2370
2409
|
if (cleanData.trim()) this.lastNonEmptyOutputAt = now;
|
|
2371
|
-
if (normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
2410
|
+
if (shouldReadScreen && normalizedScreenSnapshot !== this.lastScreenSnapshot) {
|
|
2372
2411
|
this.lastScreenSnapshot = normalizedScreenSnapshot;
|
|
2373
2412
|
this.lastScreenChangeAt = now;
|
|
2374
2413
|
}
|
|
@@ -2390,7 +2429,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2390
2429
|
this.scheduleStartupSettleCheck();
|
|
2391
2430
|
}
|
|
2392
2431
|
if (this.isWaitingForResponse && cleanData) {
|
|
2393
|
-
this.responseBuffer = (this.responseBuffer
|
|
2432
|
+
this.responseBuffer = appendBoundedText(this.responseBuffer, cleanData, 8e3);
|
|
2394
2433
|
}
|
|
2395
2434
|
if (cleanData.trim()) {
|
|
2396
2435
|
if (this.serverConn) {
|
|
@@ -2399,11 +2438,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
2399
2438
|
this.logBuffer.push({ message: cleanData.trim(), level: "info" });
|
|
2400
2439
|
}
|
|
2401
2440
|
}
|
|
2402
|
-
this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
|
|
2403
2441
|
const prevAccumulatedLen = this.accumulatedBuffer.length;
|
|
2404
2442
|
const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
|
|
2405
|
-
this.
|
|
2406
|
-
this.
|
|
2443
|
+
this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, 1e3);
|
|
2444
|
+
this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
2445
|
+
this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
|
|
2407
2446
|
if (this.currentTurnScope) {
|
|
2408
2447
|
const droppedClean = prevAccumulatedLen + cleanData.length - this.accumulatedBuffer.length;
|
|
2409
2448
|
const droppedRaw = prevAccumulatedRawLen + rawData.length - this.accumulatedRawBuffer.length;
|
|
@@ -2414,14 +2453,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
2414
2453
|
this.currentTurnScope.rawBufferStart = Math.max(0, this.currentTurnScope.rawBufferStart - droppedRaw);
|
|
2415
2454
|
}
|
|
2416
2455
|
}
|
|
2417
|
-
this.resolveStartupState("output");
|
|
2456
|
+
this.resolveStartupState("output", screenText, normalizedScreenSnapshot, now);
|
|
2418
2457
|
this.scheduleSettle();
|
|
2419
2458
|
}
|
|
2420
|
-
resolveStartupState(trigger) {
|
|
2459
|
+
resolveStartupState(trigger, screenTextOverride, normalizedScreenOverride, nowOverride) {
|
|
2421
2460
|
if (!this.startupParseGate) return;
|
|
2422
|
-
const now = Date.now();
|
|
2423
|
-
const screenText = this.
|
|
2424
|
-
const normalizedScreen = normalizeScreenSnapshot(screenText);
|
|
2461
|
+
const now = typeof nowOverride === "number" ? nowOverride : Date.now();
|
|
2462
|
+
const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.readTerminalScreenText();
|
|
2463
|
+
const normalizedScreen = typeof normalizedScreenOverride === "string" ? normalizedScreenOverride : normalizeScreenSnapshot(screenText);
|
|
2425
2464
|
const hasStartupOutput = !!this.startupFirstOutputAt || !!normalizedScreen.trim();
|
|
2426
2465
|
if (!hasStartupOutput) return;
|
|
2427
2466
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
@@ -2656,40 +2695,28 @@ var init_provider_cli_adapter = __esm({
|
|
|
2656
2695
|
}, delayTime);
|
|
2657
2696
|
return;
|
|
2658
2697
|
}
|
|
2659
|
-
const tail = this.settledBuffer;
|
|
2660
|
-
const screenText = this.terminalScreen.getText() || "";
|
|
2661
2698
|
this.resolveStartupState("settled");
|
|
2662
|
-
if (this.startupParseGate)
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
const
|
|
2666
|
-
|
|
2667
|
-
this.responseBuffer,
|
|
2668
|
-
this.currentTurnScope
|
|
2669
|
-
);
|
|
2670
|
-
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsedTranscript.activeModal : null;
|
|
2671
|
-
const modal = this.runParseApproval(tail) || parsedModal;
|
|
2672
|
-
const rawScriptStatus = this.runDetectStatus(tail);
|
|
2673
|
-
const scriptStatus = parsedTranscript?.status === "waiting_approval" && modal ? "waiting_approval" : rawScriptStatus;
|
|
2674
|
-
const parsedMessages = Array.isArray(parsedTranscript?.messages) ? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
2699
|
+
if (this.startupParseGate) return;
|
|
2700
|
+
const session = this.runParseSession();
|
|
2701
|
+
if (!session) return;
|
|
2702
|
+
const { status, messages, modal, parsedStatus } = session;
|
|
2703
|
+
const parsedMessages = normalizeCliParsedMessages(messages, {
|
|
2675
2704
|
committedMessages: this.committedMessages,
|
|
2676
2705
|
scope: this.currentTurnScope,
|
|
2677
2706
|
lastOutputAt: this.lastOutputAt
|
|
2678
|
-
})
|
|
2679
|
-
if (this.maybeCommitVisibleIdleTranscript(
|
|
2680
|
-
|
|
2681
|
-
}
|
|
2682
|
-
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
2683
|
-
const parsedShowsLiveAssistantProgress = parsedTranscript?.status === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
|
|
2707
|
+
});
|
|
2708
|
+
if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
|
|
2709
|
+
const lastParsedAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant");
|
|
2684
2710
|
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
|
|
2711
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2685
2712
|
this.recordTrace("settled", {
|
|
2686
|
-
tail: summarizeCliTraceText(
|
|
2713
|
+
tail: summarizeCliTraceText(this.settledBuffer, 500),
|
|
2687
2714
|
screenText: summarizeCliTraceText(screenText, 1200),
|
|
2688
|
-
detectStatus:
|
|
2689
|
-
parsedStatus:
|
|
2715
|
+
detectStatus: status,
|
|
2716
|
+
parsedStatus: parsedStatus || null,
|
|
2690
2717
|
parsedMessageCount: parsedMessages.length,
|
|
2691
2718
|
parsedLastAssistant: lastParsedAssistant ? summarizeCliTraceText(lastParsedAssistant.content, 280) : "",
|
|
2692
|
-
parsedActiveModal:
|
|
2719
|
+
parsedActiveModal: modal,
|
|
2693
2720
|
approval: modal,
|
|
2694
2721
|
...buildCliTraceParseSnapshot({
|
|
2695
2722
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
@@ -2723,36 +2750,36 @@ var init_provider_cli_adapter = __esm({
|
|
|
2723
2750
|
`[${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 || "-"}`
|
|
2724
2751
|
);
|
|
2725
2752
|
}
|
|
2726
|
-
if (!
|
|
2753
|
+
if (!status) return;
|
|
2727
2754
|
const prevStatus = this.currentStatus;
|
|
2728
|
-
const ctx = { now,
|
|
2755
|
+
const ctx = { now, modal, status, parsedMessages, lastParsedAssistant, parsedStatus: parsedStatus || null, prevStatus };
|
|
2729
2756
|
if (!this.applyPendingScriptStatusDebounce(ctx)) return;
|
|
2730
2757
|
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
2731
2758
|
LOG.info(
|
|
2732
2759
|
"CLI",
|
|
2733
|
-
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope?.prompt || "").slice(0, 140)}
|
|
2760
|
+
`[${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)}`
|
|
2734
2761
|
);
|
|
2735
|
-
const shouldHoldGenerating =
|
|
2762
|
+
const shouldHoldGenerating = status === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(parsedStatus === "idle" && !!lastParsedAssistant);
|
|
2736
2763
|
if (shouldHoldGenerating) {
|
|
2737
2764
|
this.applyHoldGenerating(ctx, recentInteractiveActivity);
|
|
2738
2765
|
return;
|
|
2739
2766
|
}
|
|
2740
|
-
if (
|
|
2767
|
+
if (status === "waiting_approval") {
|
|
2741
2768
|
this.applyWaitingApproval(ctx);
|
|
2742
2769
|
return;
|
|
2743
2770
|
}
|
|
2744
|
-
if (
|
|
2771
|
+
if (status === "generating") {
|
|
2745
2772
|
this.applyGenerating(ctx);
|
|
2746
2773
|
return;
|
|
2747
2774
|
}
|
|
2748
|
-
if (
|
|
2775
|
+
if (status === "idle") {
|
|
2749
2776
|
this.applyIdle(ctx, now);
|
|
2750
2777
|
}
|
|
2751
2778
|
}
|
|
2752
2779
|
// Returns false if the caller should bail out (debounce pending).
|
|
2753
2780
|
applyPendingScriptStatusDebounce(ctx) {
|
|
2754
|
-
const { now,
|
|
2755
|
-
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (
|
|
2781
|
+
const { now, status, prevStatus } = ctx;
|
|
2782
|
+
const shouldDebounce = prevStatus === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && (status === "generating" || status === "waiting_approval");
|
|
2756
2783
|
if (!shouldDebounce) {
|
|
2757
2784
|
this.pendingScriptStatus = null;
|
|
2758
2785
|
this.pendingScriptStatusSince = 0;
|
|
@@ -2770,8 +2797,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2770
2797
|
this.evaluateSettled();
|
|
2771
2798
|
}, delayMs);
|
|
2772
2799
|
};
|
|
2773
|
-
if (this.pendingScriptStatus !==
|
|
2774
|
-
this.pendingScriptStatus =
|
|
2800
|
+
if (this.pendingScriptStatus !== status) {
|
|
2801
|
+
this.pendingScriptStatus = status;
|
|
2775
2802
|
this.pendingScriptStatusSince = now;
|
|
2776
2803
|
armPending(_ProviderCliAdapter.SCRIPT_STATUS_DEBOUNCE_MS);
|
|
2777
2804
|
return false;
|
|
@@ -2784,7 +2811,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2784
2811
|
return true;
|
|
2785
2812
|
}
|
|
2786
2813
|
applyHoldGenerating(ctx, recentInteractiveActivity) {
|
|
2787
|
-
const {
|
|
2814
|
+
const { status } = ctx;
|
|
2788
2815
|
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
2789
2816
|
this.setStatus("generating", "recent_activity_hold");
|
|
2790
2817
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
@@ -2795,7 +2822,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2795
2822
|
}
|
|
2796
2823
|
}, this.timeouts.generatingIdle);
|
|
2797
2824
|
this.recordTrace("hold_generating_recent_activity", {
|
|
2798
|
-
scriptStatus,
|
|
2825
|
+
scriptStatus: status,
|
|
2799
2826
|
recentInteractiveActivity,
|
|
2800
2827
|
lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
|
|
2801
2828
|
lastScreenChangeAt: this.lastScreenChangeAt,
|
|
@@ -2849,11 +2876,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
2849
2876
|
}
|
|
2850
2877
|
}
|
|
2851
2878
|
applyGenerating(ctx) {
|
|
2852
|
-
const {
|
|
2879
|
+
const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
|
|
2853
2880
|
this.clearIdleFinishCandidate("generating");
|
|
2881
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2854
2882
|
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
2855
2883
|
const noActiveTurn = !this.currentTurnScope;
|
|
2856
2884
|
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));
|
|
2885
|
+
const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant && parsedMessages.length > this.committedMessages.length;
|
|
2857
2886
|
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
2858
2887
|
return;
|
|
2859
2888
|
}
|
|
@@ -2880,7 +2909,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2880
2909
|
this.onStatusChange?.();
|
|
2881
2910
|
}
|
|
2882
2911
|
applyIdle(ctx, now) {
|
|
2883
|
-
const {
|
|
2912
|
+
const { modal, lastParsedAssistant, prevStatus } = ctx;
|
|
2884
2913
|
if (prevStatus === "waiting_approval") {
|
|
2885
2914
|
if (this.approvalExitTimeout) {
|
|
2886
2915
|
clearTimeout(this.approvalExitTimeout);
|
|
@@ -3002,20 +3031,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
3002
3031
|
this.setStatus("idle", "response_finished");
|
|
3003
3032
|
this.onStatusChange?.();
|
|
3004
3033
|
}
|
|
3005
|
-
maybeCommitVisibleIdleTranscript(
|
|
3034
|
+
maybeCommitVisibleIdleTranscript(session, parsedMessages) {
|
|
3006
3035
|
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
3007
3036
|
if (!allowImmediateScriptIdleCommit) return false;
|
|
3008
|
-
if (!
|
|
3037
|
+
if (!session || session.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || session.modal) {
|
|
3009
3038
|
return false;
|
|
3010
3039
|
}
|
|
3011
|
-
const
|
|
3012
|
-
committedMessages: this.committedMessages,
|
|
3013
|
-
scope: this.currentTurnScope,
|
|
3014
|
-
lastOutputAt: this.lastOutputAt
|
|
3015
|
-
});
|
|
3016
|
-
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
3040
|
+
const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
|
|
3017
3041
|
if (!visibleAssistant) return false;
|
|
3018
|
-
this.committedMessages =
|
|
3042
|
+
this.committedMessages = parsedMessages;
|
|
3019
3043
|
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
3020
3044
|
this.clearAllTimers();
|
|
3021
3045
|
this.syncMessageViews();
|
|
@@ -3093,6 +3117,59 @@ var init_provider_cli_adapter = __esm({
|
|
|
3093
3117
|
};
|
|
3094
3118
|
}
|
|
3095
3119
|
// ─── Script Execution ──────────────────────────
|
|
3120
|
+
runParseSession() {
|
|
3121
|
+
if (typeof this.cliScripts?.parseSession === "function") {
|
|
3122
|
+
try {
|
|
3123
|
+
const screenText = this.terminalScreen.getText();
|
|
3124
|
+
const tail = this.recentOutputBuffer.slice(-500);
|
|
3125
|
+
const input = buildCliParseInput({
|
|
3126
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
3127
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3128
|
+
recentOutputBuffer: this.recentOutputBuffer,
|
|
3129
|
+
terminalScreenText: screenText,
|
|
3130
|
+
baseMessages: this.committedMessages,
|
|
3131
|
+
partialResponse: this.responseBuffer,
|
|
3132
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
3133
|
+
scope: this.currentTurnScope,
|
|
3134
|
+
runtimeSettings: this.runtimeSettings
|
|
3135
|
+
});
|
|
3136
|
+
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
3137
|
+
this.parseErrorMessage = null;
|
|
3138
|
+
return session && typeof session === "object" ? session : null;
|
|
3139
|
+
} catch (e) {
|
|
3140
|
+
const message = e?.message || String(e);
|
|
3141
|
+
this.parseErrorMessage = message;
|
|
3142
|
+
LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
|
|
3143
|
+
return null;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
|
|
3147
|
+
try {
|
|
3148
|
+
const tail = this.settledBuffer;
|
|
3149
|
+
const parsedTranscript = this.parseCurrentTranscript(
|
|
3150
|
+
this.committedMessages,
|
|
3151
|
+
this.responseBuffer,
|
|
3152
|
+
this.currentTurnScope
|
|
3153
|
+
);
|
|
3154
|
+
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((b) => typeof b === "string" && b.trim()) ? parsedTranscript.activeModal : null;
|
|
3155
|
+
const approval = this.runParseApproval(tail);
|
|
3156
|
+
const modal = approval || parsedModal;
|
|
3157
|
+
const rawStatus = this.runDetectStatus(tail);
|
|
3158
|
+
const parsedStatus = typeof parsedTranscript?.status === "string" ? parsedTranscript.status : null;
|
|
3159
|
+
const effectiveStatus = parsedStatus === "waiting_approval" && modal ? "waiting_approval" : rawStatus || parsedStatus || "idle";
|
|
3160
|
+
return {
|
|
3161
|
+
status: effectiveStatus,
|
|
3162
|
+
messages: Array.isArray(parsedTranscript?.messages) ? parsedTranscript.messages : [],
|
|
3163
|
+
modal,
|
|
3164
|
+
parsedStatus
|
|
3165
|
+
};
|
|
3166
|
+
} catch (e) {
|
|
3167
|
+
const message = e?.message || String(e);
|
|
3168
|
+
this.parseErrorMessage = message;
|
|
3169
|
+
LOG.warn("CLI", `[${this.cliType}] parseSession fallback error: ${message}`);
|
|
3170
|
+
return null;
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3096
3173
|
runDetectStatus(text) {
|
|
3097
3174
|
if (!this.cliScripts?.detectStatus) return null;
|
|
3098
3175
|
try {
|
|
@@ -3166,14 +3243,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3166
3243
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3167
3244
|
let effectiveModal = startupModal || this.activeModal;
|
|
3168
3245
|
if (!startupModal && !effectiveModal && typeof this.cliScripts?.parseOutput === "function") {
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
const
|
|
3172
|
-
if (
|
|
3173
|
-
|
|
3174
|
-
|
|
3246
|
+
let parsed = this.getFreshParsedStatusCache();
|
|
3247
|
+
if (!parsed && effectiveStatus !== "idle") {
|
|
3248
|
+
const now = Date.now();
|
|
3249
|
+
if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
|
|
3250
|
+
this.lastStatusHotPathParseAt = now;
|
|
3251
|
+
try {
|
|
3252
|
+
parsed = this.getScriptParsedStatus();
|
|
3253
|
+
} catch {
|
|
3254
|
+
}
|
|
3175
3255
|
}
|
|
3176
|
-
}
|
|
3256
|
+
}
|
|
3257
|
+
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3258
|
+
if (parsed?.status === "waiting_approval" && parsedModal) {
|
|
3259
|
+
effectiveStatus = "waiting_approval";
|
|
3260
|
+
effectiveModal = parsedModal;
|
|
3177
3261
|
}
|
|
3178
3262
|
}
|
|
3179
3263
|
return {
|
|
@@ -3205,7 +3289,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3205
3289
|
* Called by command handler / dashboard for rich content rendering.
|
|
3206
3290
|
*/
|
|
3207
3291
|
getScriptParsedStatus() {
|
|
3208
|
-
const screenText = this.
|
|
3292
|
+
const screenText = this.readTerminalScreenText();
|
|
3209
3293
|
const cached = this.parsedStatusCache;
|
|
3210
3294
|
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) {
|
|
3211
3295
|
return cached.result;
|
|
@@ -3225,8 +3309,21 @@ var init_provider_cli_adapter = __esm({
|
|
|
3225
3309
|
this.onStatusChange?.();
|
|
3226
3310
|
}
|
|
3227
3311
|
}
|
|
3228
|
-
if (
|
|
3229
|
-
|
|
3312
|
+
if (parsed && Array.isArray(parsed.messages)) {
|
|
3313
|
+
const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
3314
|
+
committedMessages: this.committedMessages,
|
|
3315
|
+
scope: this.currentTurnScope,
|
|
3316
|
+
lastOutputAt: this.lastOutputAt
|
|
3317
|
+
});
|
|
3318
|
+
const fakeSession = {
|
|
3319
|
+
status: parsed.status || "idle",
|
|
3320
|
+
messages: parsed.messages,
|
|
3321
|
+
modal: parsedModal,
|
|
3322
|
+
parsedStatus: parsed.status || null
|
|
3323
|
+
};
|
|
3324
|
+
if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
|
|
3325
|
+
return this.getScriptParsedStatus();
|
|
3326
|
+
}
|
|
3230
3327
|
}
|
|
3231
3328
|
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
3232
3329
|
let result;
|
|
@@ -3408,6 +3505,17 @@ var init_provider_cli_adapter = __esm({
|
|
|
3408
3505
|
}
|
|
3409
3506
|
await this.sendMessage(promptText);
|
|
3410
3507
|
}
|
|
3508
|
+
isSubmitStuck(normalizedPromptSnippet) {
|
|
3509
|
+
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return false;
|
|
3510
|
+
if (this.hasActionableApproval()) return false;
|
|
3511
|
+
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return false;
|
|
3512
|
+
const screenText = this.terminalScreen.getText();
|
|
3513
|
+
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return false;
|
|
3514
|
+
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
3515
|
+
if (liveApproval) return false;
|
|
3516
|
+
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3517
|
+
return liveStatus !== "generating" && liveStatus !== "waiting_approval";
|
|
3518
|
+
}
|
|
3411
3519
|
async writeToPty(data) {
|
|
3412
3520
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
3413
3521
|
await this.ptyProcess.write(data);
|
|
@@ -3431,6 +3539,121 @@ var init_provider_cli_adapter = __esm({
|
|
|
3431
3539
|
this.finishRetryTimer = null;
|
|
3432
3540
|
}
|
|
3433
3541
|
}
|
|
3542
|
+
commitSendUserTurn(state) {
|
|
3543
|
+
if (state.didCommitUserTurn) return;
|
|
3544
|
+
state.didCommitUserTurn = true;
|
|
3545
|
+
this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
|
|
3546
|
+
this.syncMessageViews();
|
|
3547
|
+
}
|
|
3548
|
+
armResponseTimeout() {
|
|
3549
|
+
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
3550
|
+
this.responseTimeout = setTimeout(() => {
|
|
3551
|
+
if (this.isWaitingForResponse) this.finishResponse();
|
|
3552
|
+
}, this.timeouts.maxResponse);
|
|
3553
|
+
}
|
|
3554
|
+
writeSubmitKeyForRetry(mode) {
|
|
3555
|
+
void this.writeToPty(this.sendKey).catch((error) => {
|
|
3556
|
+
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
retrySubmitIfStuck(state, attempt) {
|
|
3560
|
+
this.submitRetryTimer = null;
|
|
3561
|
+
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
3562
|
+
const screenText = this.terminalScreen.getText();
|
|
3563
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3564
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
3565
|
+
this.recordTrace("submit_write", {
|
|
3566
|
+
mode: "submit_retry",
|
|
3567
|
+
attempt,
|
|
3568
|
+
sendKey: this.sendKey,
|
|
3569
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3570
|
+
});
|
|
3571
|
+
this.writeSubmitKeyForRetry("submit_retry");
|
|
3572
|
+
if (attempt >= 3) {
|
|
3573
|
+
this.submitRetryUsed = true;
|
|
3574
|
+
return;
|
|
3575
|
+
}
|
|
3576
|
+
this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, attempt + 1), state.retryDelayMs);
|
|
3577
|
+
}
|
|
3578
|
+
retryImmediateSubmitIfStuck(state) {
|
|
3579
|
+
this.submitRetryTimer = null;
|
|
3580
|
+
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
3581
|
+
const screenText = this.terminalScreen.getText();
|
|
3582
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3583
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
3584
|
+
this.recordTrace("submit_write", {
|
|
3585
|
+
mode: "immediate_retry",
|
|
3586
|
+
attempt: 1,
|
|
3587
|
+
sendKey: this.sendKey,
|
|
3588
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3589
|
+
});
|
|
3590
|
+
this.writeSubmitKeyForRetry("immediate_retry");
|
|
3591
|
+
this.submitRetryUsed = true;
|
|
3592
|
+
}
|
|
3593
|
+
submitSendKey(state, completion) {
|
|
3594
|
+
if (!this.ptyProcess) {
|
|
3595
|
+
completion.resolveOnce();
|
|
3596
|
+
return;
|
|
3597
|
+
}
|
|
3598
|
+
this.submitPendingUntil = 0;
|
|
3599
|
+
const screenText = this.terminalScreen.getText();
|
|
3600
|
+
this.recordTrace("submit_write", {
|
|
3601
|
+
mode: "submit_key",
|
|
3602
|
+
sendKey: this.sendKey,
|
|
3603
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
3604
|
+
});
|
|
3605
|
+
void this.writeToPty(this.sendKey).then(() => {
|
|
3606
|
+
this.commitSendUserTurn(state);
|
|
3607
|
+
this.submitRetryTimer = setTimeout(() => this.retrySubmitIfStuck(state, 1), state.retryDelayMs);
|
|
3608
|
+
this.armResponseTimeout();
|
|
3609
|
+
completion.resolveOnce();
|
|
3610
|
+
}, completion.rejectOnce);
|
|
3611
|
+
}
|
|
3612
|
+
submitImmediatePrompt(state, completion) {
|
|
3613
|
+
this.submitPendingUntil = 0;
|
|
3614
|
+
this.recordTrace("submit_write", {
|
|
3615
|
+
mode: "immediate",
|
|
3616
|
+
text: summarizeCliTraceText(state.text, 500),
|
|
3617
|
+
sendKey: this.sendKey,
|
|
3618
|
+
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3619
|
+
});
|
|
3620
|
+
void this.writeToPty(state.text + this.sendKey).then(() => {
|
|
3621
|
+
this.commitSendUserTurn(state);
|
|
3622
|
+
this.submitRetryTimer = setTimeout(() => this.retryImmediateSubmitIfStuck(state), state.retryDelayMs);
|
|
3623
|
+
this.armResponseTimeout();
|
|
3624
|
+
completion.resolveOnce();
|
|
3625
|
+
}, completion.rejectOnce);
|
|
3626
|
+
}
|
|
3627
|
+
waitForEchoAndSubmit(state, completion, submitStartedAt, lastNormalizedScreen = "", lastScreenChangeAt = submitStartedAt) {
|
|
3628
|
+
if (!this.ptyProcess) {
|
|
3629
|
+
completion.resolveOnce();
|
|
3630
|
+
return;
|
|
3631
|
+
}
|
|
3632
|
+
const now = Date.now();
|
|
3633
|
+
const elapsed = now - submitStartedAt;
|
|
3634
|
+
const screenText = this.terminalScreen.getText();
|
|
3635
|
+
const normalizedScreen = normalizePromptText(screenText);
|
|
3636
|
+
const nextScreenChangeAt = normalizedScreen !== lastNormalizedScreen ? now : lastScreenChangeAt;
|
|
3637
|
+
const echoVisible = !state.normalizedPromptSnippet || promptLikelyVisible(screenText, state.normalizedPromptSnippet);
|
|
3638
|
+
if (echoVisible) {
|
|
3639
|
+
const screenSettled = now - nextScreenChangeAt >= 500;
|
|
3640
|
+
if (elapsed >= state.submitDelayMs && screenSettled) {
|
|
3641
|
+
this.submitSendKey(state, completion);
|
|
3642
|
+
return;
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
if (elapsed >= state.maxEchoWaitMs) {
|
|
3646
|
+
this.submitSendKey(state, completion);
|
|
3647
|
+
return;
|
|
3648
|
+
}
|
|
3649
|
+
setTimeout(() => this.waitForEchoAndSubmit(
|
|
3650
|
+
state,
|
|
3651
|
+
completion,
|
|
3652
|
+
submitStartedAt,
|
|
3653
|
+
normalizedScreen,
|
|
3654
|
+
nextScreenChangeAt
|
|
3655
|
+
), 50);
|
|
3656
|
+
}
|
|
3434
3657
|
async sendMessage(text) {
|
|
3435
3658
|
if (!this.ptyProcess) throw new Error(`${this.cliName} is not running`);
|
|
3436
3659
|
const allowInputDuringGeneration = this.provider.allowInputDuringGeneration === true;
|
|
@@ -3506,12 +3729,13 @@ var init_provider_cli_adapter = __esm({
|
|
|
3506
3729
|
const submitDelayMs = this.sendDelayMs + Math.min(2e3, Math.max(0, estimatedLines - 1) * 350);
|
|
3507
3730
|
const maxEchoWaitMs = submitDelayMs + Math.max(1500, Math.min(5e3, estimatedLines * 500));
|
|
3508
3731
|
const retryDelayMs = Math.max(350, Math.min(1500, Math.max(this.sendDelayMs, submitDelayMs)));
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3732
|
+
const sendState = {
|
|
3733
|
+
text,
|
|
3734
|
+
normalizedPromptSnippet,
|
|
3735
|
+
submitDelayMs,
|
|
3736
|
+
maxEchoWaitMs,
|
|
3737
|
+
retryDelayMs,
|
|
3738
|
+
didCommitUserTurn: false
|
|
3515
3739
|
};
|
|
3516
3740
|
if (this.settleTimer) {
|
|
3517
3741
|
clearTimeout(this.settleTimer);
|
|
@@ -3519,110 +3743,23 @@ var init_provider_cli_adapter = __esm({
|
|
|
3519
3743
|
}
|
|
3520
3744
|
this.responseEpoch += 1;
|
|
3521
3745
|
this.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
3522
|
-
const startResponseTimeout = () => {
|
|
3523
|
-
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
3524
|
-
this.responseTimeout = setTimeout(() => {
|
|
3525
|
-
if (this.isWaitingForResponse) this.finishResponse();
|
|
3526
|
-
}, this.timeouts.maxResponse);
|
|
3527
|
-
};
|
|
3528
3746
|
await new Promise((resolve12, reject) => {
|
|
3529
3747
|
let resolved = false;
|
|
3530
|
-
const
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
const writeRetryKey = (mode) => {
|
|
3542
|
-
void this.writeToPty(this.sendKey).catch((error) => {
|
|
3543
|
-
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
3544
|
-
});
|
|
3545
|
-
};
|
|
3546
|
-
const submit = () => {
|
|
3547
|
-
if (!this.ptyProcess) {
|
|
3548
|
-
resolveOnce();
|
|
3549
|
-
return;
|
|
3748
|
+
const completion = {
|
|
3749
|
+
resolveOnce: () => {
|
|
3750
|
+
if (resolved) return;
|
|
3751
|
+
resolved = true;
|
|
3752
|
+
resolve12();
|
|
3753
|
+
},
|
|
3754
|
+
rejectOnce: (error) => {
|
|
3755
|
+
if (resolved) return;
|
|
3756
|
+
this.resetPendingSendState("send_write_failed");
|
|
3757
|
+
resolved = true;
|
|
3758
|
+
reject(error);
|
|
3550
3759
|
}
|
|
3551
|
-
this.submitPendingUntil = 0;
|
|
3552
|
-
const screenText = this.terminalScreen.getText();
|
|
3553
|
-
this.recordTrace("submit_write", {
|
|
3554
|
-
mode: "submit_key",
|
|
3555
|
-
sendKey: this.sendKey,
|
|
3556
|
-
screenText: summarizeCliTraceText(screenText, 500)
|
|
3557
|
-
});
|
|
3558
|
-
const retrySubmitIfStuck = (attempt) => {
|
|
3559
|
-
this.submitRetryTimer = null;
|
|
3560
|
-
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3561
|
-
if (this.hasActionableApproval()) return;
|
|
3562
|
-
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3563
|
-
const screenText2 = this.terminalScreen.getText();
|
|
3564
|
-
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
3565
|
-
const liveApproval = this.runParseApproval(screenText2) || this.runParseApproval(this.recentOutputBuffer);
|
|
3566
|
-
if (liveApproval) return;
|
|
3567
|
-
const liveStatus = this.runDetectStatus(screenText2) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3568
|
-
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
3569
|
-
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3570
|
-
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
3571
|
-
this.recordTrace("submit_write", {
|
|
3572
|
-
mode: "submit_retry",
|
|
3573
|
-
attempt,
|
|
3574
|
-
sendKey: this.sendKey,
|
|
3575
|
-
screenText: summarizeCliTraceText(screenText2, 500)
|
|
3576
|
-
});
|
|
3577
|
-
writeRetryKey("submit_retry");
|
|
3578
|
-
if (attempt >= 3) {
|
|
3579
|
-
this.submitRetryUsed = true;
|
|
3580
|
-
return;
|
|
3581
|
-
}
|
|
3582
|
-
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(attempt + 1), retryDelayMs);
|
|
3583
|
-
};
|
|
3584
|
-
void this.writeToPty(this.sendKey).then(() => {
|
|
3585
|
-
commitUserTurn();
|
|
3586
|
-
this.submitRetryTimer = setTimeout(() => retrySubmitIfStuck(1), retryDelayMs);
|
|
3587
|
-
startResponseTimeout();
|
|
3588
|
-
resolveOnce();
|
|
3589
|
-
}, rejectOnce);
|
|
3590
3760
|
};
|
|
3591
3761
|
if (this.submitStrategy === "immediate") {
|
|
3592
|
-
this.
|
|
3593
|
-
this.recordTrace("submit_write", {
|
|
3594
|
-
mode: "immediate",
|
|
3595
|
-
text: summarizeCliTraceText(text, 500),
|
|
3596
|
-
sendKey: this.sendKey,
|
|
3597
|
-
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3598
|
-
});
|
|
3599
|
-
void this.writeToPty(text + this.sendKey).then(() => {
|
|
3600
|
-
commitUserTurn();
|
|
3601
|
-
this.submitRetryTimer = setTimeout(() => {
|
|
3602
|
-
this.submitRetryTimer = null;
|
|
3603
|
-
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3604
|
-
if (this.hasActionableApproval()) return;
|
|
3605
|
-
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3606
|
-
const screenText = this.terminalScreen.getText();
|
|
3607
|
-
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
3608
|
-
const liveApproval = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
|
|
3609
|
-
if (liveApproval) return;
|
|
3610
|
-
const liveStatus = this.runDetectStatus(screenText) || this.runDetectStatus(this.recentOutputBuffer);
|
|
3611
|
-
if (liveStatus === "generating" || liveStatus === "waiting_approval") return;
|
|
3612
|
-
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
3613
|
-
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
3614
|
-
this.recordTrace("submit_write", {
|
|
3615
|
-
mode: "immediate_retry",
|
|
3616
|
-
attempt: 1,
|
|
3617
|
-
sendKey: this.sendKey,
|
|
3618
|
-
screenText: summarizeCliTraceText(screenText, 500)
|
|
3619
|
-
});
|
|
3620
|
-
writeRetryKey("immediate_retry");
|
|
3621
|
-
this.submitRetryUsed = true;
|
|
3622
|
-
}, retryDelayMs);
|
|
3623
|
-
startResponseTimeout();
|
|
3624
|
-
resolveOnce();
|
|
3625
|
-
}, rejectOnce);
|
|
3762
|
+
this.submitImmediatePrompt(sendState, completion);
|
|
3626
3763
|
return;
|
|
3627
3764
|
}
|
|
3628
3765
|
if (submitDelayMs > 0) {
|
|
@@ -3635,36 +3772,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
3635
3772
|
screenText: summarizeCliTraceText(this.terminalScreen.getText(), 500)
|
|
3636
3773
|
});
|
|
3637
3774
|
const submitStartedAt = Date.now();
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
resolveOnce();
|
|
3643
|
-
return;
|
|
3644
|
-
}
|
|
3645
|
-
const now = Date.now();
|
|
3646
|
-
const elapsed = now - submitStartedAt;
|
|
3647
|
-
const screenText = this.terminalScreen.getText();
|
|
3648
|
-
const normalizedScreen = normalizePromptText(screenText);
|
|
3649
|
-
if (normalizedScreen !== lastNormalizedScreen) {
|
|
3650
|
-
lastNormalizedScreen = normalizedScreen;
|
|
3651
|
-
lastScreenChangeAt = now;
|
|
3652
|
-
}
|
|
3653
|
-
const echoVisible = !normalizedPromptSnippet || promptLikelyVisible(screenText, normalizedPromptSnippet);
|
|
3654
|
-
if (echoVisible) {
|
|
3655
|
-
const screenSettled = now - lastScreenChangeAt >= 500;
|
|
3656
|
-
if (elapsed >= submitDelayMs && screenSettled) {
|
|
3657
|
-
submit();
|
|
3658
|
-
return;
|
|
3659
|
-
}
|
|
3660
|
-
}
|
|
3661
|
-
if (elapsed >= maxEchoWaitMs) {
|
|
3662
|
-
submit();
|
|
3663
|
-
return;
|
|
3664
|
-
}
|
|
3665
|
-
setTimeout(waitForEchoAndSubmit, 50);
|
|
3666
|
-
};
|
|
3667
|
-
void this.writeToPty(text).then(() => waitForEchoAndSubmit(), rejectOnce);
|
|
3775
|
+
void this.writeToPty(text).then(
|
|
3776
|
+
() => this.waitForEchoAndSubmit(sendState, completion, submitStartedAt),
|
|
3777
|
+
completion.rejectOnce
|
|
3778
|
+
);
|
|
3668
3779
|
});
|
|
3669
3780
|
}
|
|
3670
3781
|
getPartialResponse() {
|
|
@@ -3741,9 +3852,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3741
3852
|
shutdown() {
|
|
3742
3853
|
this.clearIdleFinishCandidate("shutdown");
|
|
3743
3854
|
this.clearAllTimers();
|
|
3744
|
-
this.
|
|
3855
|
+
this.pendingOutputParseChunks = [];
|
|
3745
3856
|
this.pendingTerminalQueryTail = "";
|
|
3746
|
-
this.
|
|
3857
|
+
this.ptyOutputChunks = [];
|
|
3747
3858
|
this.finishRetryCount = 0;
|
|
3748
3859
|
if (this.ptyProcess) {
|
|
3749
3860
|
this.ptyProcess.write("");
|
|
@@ -3764,9 +3875,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
3764
3875
|
detach() {
|
|
3765
3876
|
this.clearIdleFinishCandidate("detach");
|
|
3766
3877
|
this.clearAllTimers();
|
|
3767
|
-
this.
|
|
3878
|
+
this.pendingOutputParseChunks = [];
|
|
3768
3879
|
this.pendingTerminalQueryTail = "";
|
|
3769
|
-
this.
|
|
3880
|
+
this.ptyOutputChunks = [];
|
|
3770
3881
|
this.finishRetryCount = 0;
|
|
3771
3882
|
if (this.ptyProcess) {
|
|
3772
3883
|
try {
|
|
@@ -3797,19 +3908,19 @@ var init_provider_cli_adapter = __esm({
|
|
|
3797
3908
|
clearTimeout(this.pendingOutputParseTimer);
|
|
3798
3909
|
this.pendingOutputParseTimer = null;
|
|
3799
3910
|
}
|
|
3800
|
-
this.
|
|
3911
|
+
this.pendingOutputParseChunks = [];
|
|
3801
3912
|
this.pendingTerminalQueryTail = "";
|
|
3802
3913
|
if (this.ptyOutputFlushTimer) {
|
|
3803
3914
|
clearTimeout(this.ptyOutputFlushTimer);
|
|
3804
3915
|
this.ptyOutputFlushTimer = null;
|
|
3805
3916
|
}
|
|
3806
|
-
this.
|
|
3917
|
+
this.ptyOutputChunks = [];
|
|
3807
3918
|
if (this.finishRetryTimer) {
|
|
3808
3919
|
clearTimeout(this.finishRetryTimer);
|
|
3809
3920
|
this.finishRetryTimer = null;
|
|
3810
3921
|
}
|
|
3811
3922
|
this.finishRetryCount = 0;
|
|
3812
|
-
this.
|
|
3923
|
+
this.resetTerminalScreen();
|
|
3813
3924
|
this.ptyProcess?.clearBuffer?.();
|
|
3814
3925
|
this.onStatusChange?.();
|
|
3815
3926
|
}
|
|
@@ -3926,7 +4037,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3926
4037
|
traceEntryCount: this.traceEntries.length,
|
|
3927
4038
|
statusHistory: this.statusHistory.slice(-30),
|
|
3928
4039
|
timeouts: this.timeouts,
|
|
3929
|
-
pendingOutputParseBufferLength: this.
|
|
4040
|
+
pendingOutputParseBufferLength: this.pendingOutputParseChunks.reduce((total, chunk) => total + chunk.length, 0),
|
|
3930
4041
|
pendingOutputParseScheduled: !!this.pendingOutputParseTimer,
|
|
3931
4042
|
ptyAlive: !!this.ptyProcess
|
|
3932
4043
|
};
|
|
@@ -9667,14 +9778,14 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
9667
9778
|
id: state.instanceId || state.type,
|
|
9668
9779
|
parentId: null,
|
|
9669
9780
|
providerType: state.type,
|
|
9670
|
-
|
|
9781
|
+
providerName: state.name,
|
|
9671
9782
|
kind: "workspace",
|
|
9672
9783
|
transport: "cdp-page",
|
|
9673
9784
|
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
9674
9785
|
activeModal: activeChat?.activeModal || null
|
|
9675
9786
|
}),
|
|
9676
9787
|
title,
|
|
9677
|
-
|
|
9788
|
+
workspace: state.workspace || null,
|
|
9678
9789
|
activeChat,
|
|
9679
9790
|
...summaryMetadata && { summaryMetadata },
|
|
9680
9791
|
...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
|
|
@@ -9699,7 +9810,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
9699
9810
|
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
9700
9811
|
parentId: parent.instanceId || parent.type,
|
|
9701
9812
|
providerType: ext.type,
|
|
9702
|
-
|
|
9813
|
+
providerName: ext.name,
|
|
9703
9814
|
providerSessionId: ext.providerSessionId,
|
|
9704
9815
|
kind: "agent",
|
|
9705
9816
|
transport: "cdp-webview",
|
|
@@ -9707,7 +9818,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
9707
9818
|
activeModal: activeChat?.activeModal || null
|
|
9708
9819
|
}),
|
|
9709
9820
|
title: activeChat?.title || ext.name,
|
|
9710
|
-
|
|
9821
|
+
workspace: parent.workspace || null,
|
|
9711
9822
|
activeChat,
|
|
9712
9823
|
...summaryMetadata && { summaryMetadata },
|
|
9713
9824
|
...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
|
|
@@ -9747,7 +9858,7 @@ function buildCliSession(state, options) {
|
|
|
9747
9858
|
id: state.instanceId,
|
|
9748
9859
|
parentId: null,
|
|
9749
9860
|
providerType: state.type,
|
|
9750
|
-
|
|
9861
|
+
providerName: state.name,
|
|
9751
9862
|
providerSessionId: state.providerSessionId,
|
|
9752
9863
|
kind: "agent",
|
|
9753
9864
|
transport: "pty",
|
|
@@ -9755,7 +9866,7 @@ function buildCliSession(state, options) {
|
|
|
9755
9866
|
activeModal: activeChat?.activeModal || null
|
|
9756
9867
|
}),
|
|
9757
9868
|
title: activeChat?.title || state.name,
|
|
9758
|
-
|
|
9869
|
+
workspace: state.workspace || null,
|
|
9759
9870
|
...includeRuntimeMetadata && {
|
|
9760
9871
|
runtimeKey: state.runtime?.runtimeKey,
|
|
9761
9872
|
runtimeDisplayName: state.runtime?.displayName,
|
|
@@ -9794,14 +9905,14 @@ function buildAcpSession(state, options) {
|
|
|
9794
9905
|
id: state.instanceId,
|
|
9795
9906
|
parentId: null,
|
|
9796
9907
|
providerType: state.type,
|
|
9797
|
-
|
|
9908
|
+
providerName: state.name,
|
|
9798
9909
|
kind: "agent",
|
|
9799
9910
|
transport: "acp",
|
|
9800
9911
|
status: normalizeManagedStatus(activeChat?.status || state.status, {
|
|
9801
9912
|
activeModal: activeChat?.activeModal || null
|
|
9802
9913
|
}),
|
|
9803
9914
|
title: activeChat?.title || state.name,
|
|
9804
|
-
|
|
9915
|
+
workspace: state.workspace || null,
|
|
9805
9916
|
activeChat,
|
|
9806
9917
|
...summaryMetadata && { summaryMetadata },
|
|
9807
9918
|
...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
|
|
@@ -10248,26 +10359,26 @@ function buildReadChatReplayCollapseSignature(message) {
|
|
|
10248
10359
|
function shouldCollapseReadChatReplayDuplicate(message) {
|
|
10249
10360
|
if (!message) return false;
|
|
10250
10361
|
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
10251
|
-
|
|
10252
|
-
const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
|
|
10253
|
-
return kind === "tool" || kind === "terminal" || kind === "thought" || kind === "system";
|
|
10362
|
+
return role === "assistant" || role === "system";
|
|
10254
10363
|
}
|
|
10255
10364
|
function collapseReplayDuplicatesFromReadChat(messages) {
|
|
10256
10365
|
const collapsed = [];
|
|
10257
|
-
|
|
10366
|
+
const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
|
|
10258
10367
|
for (const message of messages) {
|
|
10368
|
+
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
10369
|
+
if (role === "user") {
|
|
10370
|
+
replaySignaturesInCurrentTurn.clear();
|
|
10371
|
+
}
|
|
10259
10372
|
const signature = buildReadChatReplayCollapseSignature(message);
|
|
10260
10373
|
const previous = collapsed[collapsed.length - 1];
|
|
10261
10374
|
const previousSignature = buildReadChatReplayCollapseSignature(previous);
|
|
10262
10375
|
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
10263
10376
|
if (previousSignature === signature) continue;
|
|
10264
|
-
if (
|
|
10377
|
+
if (replaySignaturesInCurrentTurn.has(signature)) continue;
|
|
10265
10378
|
}
|
|
10266
10379
|
collapsed.push(message);
|
|
10267
10380
|
if (shouldCollapseReadChatReplayDuplicate(message) && signature) {
|
|
10268
|
-
|
|
10269
|
-
} else if ((message.role || "").toLowerCase() === "user") {
|
|
10270
|
-
lastReplayTurnSignature = "";
|
|
10381
|
+
replaySignaturesInCurrentTurn.add(signature);
|
|
10271
10382
|
}
|
|
10272
10383
|
}
|
|
10273
10384
|
return collapsed;
|
|
@@ -17770,6 +17881,18 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
|
|
|
17770
17881
|
const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
|
|
17771
17882
|
return { unread, inboxBucket: unread ? "task_complete" : "idle" };
|
|
17772
17883
|
}
|
|
17884
|
+
function projectLiveSessionFromFull(session) {
|
|
17885
|
+
const {
|
|
17886
|
+
capabilities: _capabilities,
|
|
17887
|
+
controlValues: _controlValues,
|
|
17888
|
+
providerControls: _providerControls,
|
|
17889
|
+
...rest
|
|
17890
|
+
} = session;
|
|
17891
|
+
return {
|
|
17892
|
+
...rest,
|
|
17893
|
+
activeChat: normalizeActiveChatData(session.activeChat, LIVE_STATUS_ACTIVE_CHAT_OPTIONS)
|
|
17894
|
+
};
|
|
17895
|
+
}
|
|
17773
17896
|
function buildRecentLaunches(recentActivity) {
|
|
17774
17897
|
return recentActivity.map((item) => ({
|
|
17775
17898
|
id: item.id,
|
|
@@ -17794,7 +17917,7 @@ function buildStatusSnapshot(options) {
|
|
|
17794
17917
|
options.cdpManagers,
|
|
17795
17918
|
{ profile: "full" }
|
|
17796
17919
|
);
|
|
17797
|
-
const sessions = profile === "full" ? unreadSourceSessions : buildSessionEntries(
|
|
17920
|
+
const sessions = profile === "full" ? unreadSourceSessions : profile === "live" ? unreadSourceSessions.map(projectLiveSessionFromFull) : buildSessionEntries(
|
|
17798
17921
|
options.allStates,
|
|
17799
17922
|
options.cdpManagers,
|
|
17800
17923
|
{ profile }
|
|
@@ -19080,10 +19203,6 @@ var DaemonStatusReporter = class {
|
|
|
19080
19203
|
LOG.info("StatusReport", `\u2192${target} ${baseSummary}`);
|
|
19081
19204
|
}
|
|
19082
19205
|
}
|
|
19083
|
-
const sessions = buildSessionEntries(
|
|
19084
|
-
allStates,
|
|
19085
|
-
this.deps.cdpManagers
|
|
19086
|
-
);
|
|
19087
19206
|
const payload = {
|
|
19088
19207
|
...buildStatusSnapshot({
|
|
19089
19208
|
allStates,
|
|
@@ -19103,9 +19222,9 @@ var DaemonStatusReporter = class {
|
|
|
19103
19222
|
}),
|
|
19104
19223
|
screenshotUsage: this.deps.getScreenshotUsage?.() || null
|
|
19105
19224
|
};
|
|
19106
|
-
const payloadBytes = JSON.stringify(payload).length;
|
|
19107
19225
|
const p2pSent = this.sendP2PPayload(payload);
|
|
19108
19226
|
if (p2pSent) {
|
|
19227
|
+
const payloadBytes = JSON.stringify(payload).length;
|
|
19109
19228
|
LOG.debug("P2P", `sent (${payloadBytes} bytes)`);
|
|
19110
19229
|
if (payloadBytes > 256 * 1024) {
|
|
19111
19230
|
LOG.warn(
|
|
@@ -19115,8 +19234,10 @@ var DaemonStatusReporter = class {
|
|
|
19115
19234
|
}
|
|
19116
19235
|
}
|
|
19117
19236
|
if (opts?.p2pOnly) return;
|
|
19237
|
+
if (!serverConnected || !serverConn) return;
|
|
19238
|
+
const payloadSessions = Array.isArray(payload.sessions) ? payload.sessions : [];
|
|
19118
19239
|
const wsPayload = {
|
|
19119
|
-
sessions:
|
|
19240
|
+
sessions: payloadSessions.map((session) => ({
|
|
19120
19241
|
id: session.id,
|
|
19121
19242
|
parentId: session.parentId,
|
|
19122
19243
|
providerType: session.providerType,
|
|
@@ -19142,8 +19263,9 @@ var DaemonStatusReporter = class {
|
|
|
19142
19263
|
return;
|
|
19143
19264
|
}
|
|
19144
19265
|
this.lastServerStatusHash = wsHash;
|
|
19266
|
+
const wsPayloadBytes = JSON.stringify(wsPayload).length;
|
|
19145
19267
|
serverConn.sendMessage("status_report", wsPayload);
|
|
19146
|
-
LOG.debug("Server", `sent status_report (${
|
|
19268
|
+
LOG.debug("Server", `sent status_report (${wsPayloadBytes} bytes)${opts?.reason ? ` [${opts.reason}]` : ""}`);
|
|
19147
19269
|
}
|
|
19148
19270
|
// ─── P2P ─────────────────────────────────────────
|
|
19149
19271
|
sendP2PPayload(payload) {
|