@adhdev/daemon-core 0.8.84 → 0.8.85
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 +3 -0
- package/dist/cli-adapters/session-host-transport.d.ts +2 -1
- package/dist/index.js +253 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +253 -22
- package/dist/index.mjs.map +1 -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 +252 -21
- package/src/cli-adapters/session-host-transport.ts +9 -1
- package/src/commands/chat-commands.ts +35 -2
- package/src/providers/cli-provider-instance.ts +3 -1
- package/src/session-host/startup-restore-policy.js +2 -0
- package/src/session-host/startup-restore-policy.ts +2 -0
|
@@ -138,8 +138,11 @@ export declare class ProviderCliAdapter implements CliAdapter {
|
|
|
138
138
|
private getStartupConfirmationModal;
|
|
139
139
|
private shouldResolveModalWithEnter;
|
|
140
140
|
private waitForInteractivePrompt;
|
|
141
|
+
private clearStaleIdleResponseGuard;
|
|
142
|
+
private hasMeaningfulResponseBuffer;
|
|
141
143
|
private evaluateSettled;
|
|
142
144
|
private finishResponse;
|
|
145
|
+
private maybeCommitVisibleIdleTranscript;
|
|
143
146
|
private commitCurrentTranscript;
|
|
144
147
|
private runDetectStatus;
|
|
145
148
|
private runParseApproval;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SessionHostEndpoint, type SessionHostCategory } from '@adhdev/session-host-core';
|
|
1
|
+
import { type SessionHostEndpoint, type SessionHostCategory, type SessionHostRecord } from '@adhdev/session-host-core';
|
|
2
2
|
import type { PtyRuntimeTransport, PtySpawnOptions, PtyTransportFactory } from './pty-transport.js';
|
|
3
3
|
interface SessionHostPtyTransportFactoryOptions {
|
|
4
4
|
endpoint?: SessionHostEndpoint;
|
|
@@ -12,6 +12,7 @@ interface SessionHostPtyTransportFactoryOptions {
|
|
|
12
12
|
meta?: Record<string, unknown>;
|
|
13
13
|
attachExisting?: boolean;
|
|
14
14
|
}
|
|
15
|
+
export declare function shouldResumeAttachedSession(record: SessionHostRecord | null | undefined): boolean;
|
|
15
16
|
export declare class SessionHostPtyTransportFactory implements PtyTransportFactory {
|
|
16
17
|
private readonly options;
|
|
17
18
|
constructor(options: SessionHostPtyTransportFactoryOptions);
|
package/dist/index.js
CHANGED
|
@@ -2501,6 +2501,58 @@ var init_provider_cli_adapter = __esm({
|
|
|
2501
2501
|
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
2502
2502
|
);
|
|
2503
2503
|
}
|
|
2504
|
+
clearStaleIdleResponseGuard(reason) {
|
|
2505
|
+
const screenText = this.terminalScreen.getText() || "";
|
|
2506
|
+
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
2507
|
+
const blockingModal = this.activeModal || this.getStartupConfirmationModal(screenText);
|
|
2508
|
+
if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !visibleIdlePrompt || !!blockingModal) {
|
|
2509
|
+
return false;
|
|
2510
|
+
}
|
|
2511
|
+
if (this.responseTimeout) {
|
|
2512
|
+
clearTimeout(this.responseTimeout);
|
|
2513
|
+
this.responseTimeout = null;
|
|
2514
|
+
}
|
|
2515
|
+
if (this.idleTimeout) {
|
|
2516
|
+
clearTimeout(this.idleTimeout);
|
|
2517
|
+
this.idleTimeout = null;
|
|
2518
|
+
}
|
|
2519
|
+
if (this.approvalExitTimeout) {
|
|
2520
|
+
clearTimeout(this.approvalExitTimeout);
|
|
2521
|
+
this.approvalExitTimeout = null;
|
|
2522
|
+
}
|
|
2523
|
+
if (this.finishRetryTimer) {
|
|
2524
|
+
clearTimeout(this.finishRetryTimer);
|
|
2525
|
+
this.finishRetryTimer = null;
|
|
2526
|
+
}
|
|
2527
|
+
this.clearIdleFinishCandidate(reason);
|
|
2528
|
+
this.responseBuffer = "";
|
|
2529
|
+
this.isWaitingForResponse = false;
|
|
2530
|
+
this.responseSettleIgnoreUntil = 0;
|
|
2531
|
+
this.submitRetryUsed = false;
|
|
2532
|
+
this.submitRetryPromptSnippet = "";
|
|
2533
|
+
this.finishRetryCount = 0;
|
|
2534
|
+
this.currentTurnScope = null;
|
|
2535
|
+
this.activeModal = null;
|
|
2536
|
+
this.recordTrace("stale_idle_response_cleared", {
|
|
2537
|
+
reason,
|
|
2538
|
+
screenText: summarizeCliTraceText(screenText, 240)
|
|
2539
|
+
});
|
|
2540
|
+
return true;
|
|
2541
|
+
}
|
|
2542
|
+
hasMeaningfulResponseBuffer(promptSnippet) {
|
|
2543
|
+
const raw = String(this.responseBuffer || "").trim();
|
|
2544
|
+
if (!raw) return false;
|
|
2545
|
+
const normalizedPrompt = compactPromptText(promptSnippet);
|
|
2546
|
+
if (!normalizedPrompt) return true;
|
|
2547
|
+
const normalizedBuffer = compactPromptText(raw);
|
|
2548
|
+
if (!normalizedBuffer) return false;
|
|
2549
|
+
if (normalizedBuffer === normalizedPrompt) return false;
|
|
2550
|
+
if (normalizedBuffer.startsWith(normalizedPrompt)) {
|
|
2551
|
+
const remainder = normalizedBuffer.slice(normalizedPrompt.length).replace(/[─═\-]+/g, "").replace(/⏵⏵accepteditson\([^)]*\)/gi, "").replace(/accepteditson\([^)]*\)/gi, "").replace(/(?:◐|◑|◒|◓|◔|◕|◉|●|·)?(?:x?high|medium|low|max)·?\/effort/gi, "").replace(/updateavailable!run:[a-z0-9:._\-/]+/gi, "").replace(/esctointerrupt/gi, "").replace(/❯/g, "").replace(/^[\s\-–—:;,.!/?]+/, "").trim();
|
|
2552
|
+
return remainder.length > 0;
|
|
2553
|
+
}
|
|
2554
|
+
return true;
|
|
2555
|
+
}
|
|
2504
2556
|
evaluateSettled() {
|
|
2505
2557
|
const now = Date.now();
|
|
2506
2558
|
if (this.submitPendingUntil > now || this.responseSettleIgnoreUntil > now) {
|
|
@@ -2533,7 +2585,11 @@ var init_provider_cli_adapter = __esm({
|
|
|
2533
2585
|
scope: this.currentTurnScope,
|
|
2534
2586
|
lastOutputAt: this.lastOutputAt
|
|
2535
2587
|
}) : [];
|
|
2588
|
+
if (this.maybeCommitVisibleIdleTranscript(parsedTranscript)) {
|
|
2589
|
+
return;
|
|
2590
|
+
}
|
|
2536
2591
|
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
2592
|
+
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
|
|
2537
2593
|
this.recordTrace("settled", {
|
|
2538
2594
|
tail: summarizeCliTraceText(tail, 500),
|
|
2539
2595
|
screenText: summarizeCliTraceText(screenText, 1200),
|
|
@@ -2551,6 +2607,24 @@ var init_provider_cli_adapter = __esm({
|
|
|
2551
2607
|
scope: this.currentTurnScope
|
|
2552
2608
|
})
|
|
2553
2609
|
});
|
|
2610
|
+
if (this.currentTurnScope && !lastParsedAssistant && !this.submitRetryUsed && this.ptyProcess && this.currentStatus !== "waiting_approval" && promptLikelyVisible(screenText, normalizedPromptSnippet) && !this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) {
|
|
2611
|
+
this.submitRetryUsed = true;
|
|
2612
|
+
this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
2613
|
+
LOG.info("CLI", `[${this.cliType}] Retrying submit key from settled parser (no assistant yet)`);
|
|
2614
|
+
this.recordTrace("submit_write", {
|
|
2615
|
+
mode: "settled_retry",
|
|
2616
|
+
sendKey: this.sendKey,
|
|
2617
|
+
screenText: summarizeCliTraceText(screenText, 500)
|
|
2618
|
+
});
|
|
2619
|
+
this.ptyProcess.write(this.sendKey);
|
|
2620
|
+
if (this.settleTimer) clearTimeout(this.settleTimer);
|
|
2621
|
+
this.settleTimer = setTimeout(() => {
|
|
2622
|
+
this.settleTimer = null;
|
|
2623
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
2624
|
+
this.evaluateSettled();
|
|
2625
|
+
}, this.timeouts.outputSettle + 150);
|
|
2626
|
+
return;
|
|
2627
|
+
}
|
|
2554
2628
|
if (this.currentTurnScope && !lastParsedAssistant) {
|
|
2555
2629
|
LOG.info(
|
|
2556
2630
|
"CLI",
|
|
@@ -2593,7 +2667,15 @@ var init_provider_cli_adapter = __esm({
|
|
|
2593
2667
|
}
|
|
2594
2668
|
const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
|
|
2595
2669
|
const statusActivityHoldMs = this.getStatusActivityHoldMs();
|
|
2596
|
-
const
|
|
2670
|
+
const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
|
|
2671
|
+
const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
|
|
2672
|
+
if (this.currentTurnScope && this.cliType === "claude-cli") {
|
|
2673
|
+
LOG.info(
|
|
2674
|
+
"CLI",
|
|
2675
|
+
`[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} scriptStatus=${String(scriptStatus || "")} parsedStatus=${String(parsedTranscript?.status || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} visibleIdlePrompt=${String(visibleIdlePrompt)} visibleAssistantCandidate=${String(visibleAssistantCandidate)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
|
|
2676
|
+
);
|
|
2677
|
+
}
|
|
2678
|
+
const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(visibleIdlePrompt && visibleAssistantCandidate);
|
|
2597
2679
|
if (shouldHoldGenerating) {
|
|
2598
2680
|
this.clearIdleFinishCandidate("hold_generating_recent_activity");
|
|
2599
2681
|
this.setStatus("generating", "recent_activity_hold");
|
|
@@ -2624,8 +2706,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2624
2706
|
if (scriptStatus === "waiting_approval") {
|
|
2625
2707
|
this.clearIdleFinishCandidate("waiting_approval");
|
|
2626
2708
|
const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
2627
|
-
const
|
|
2628
|
-
if ((inCooldown ||
|
|
2709
|
+
const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
|
|
2710
|
+
if ((inCooldown || visibleIdlePrompt2) && !modal) {
|
|
2629
2711
|
if (this.approvalExitTimeout) {
|
|
2630
2712
|
clearTimeout(this.approvalExitTimeout);
|
|
2631
2713
|
this.approvalExitTimeout = null;
|
|
@@ -2697,7 +2779,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2697
2779
|
this.lastApprovalResolvedAt = Date.now();
|
|
2698
2780
|
}
|
|
2699
2781
|
if (this.isWaitingForResponse) {
|
|
2700
|
-
const
|
|
2782
|
+
const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
|
|
2701
2783
|
const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
|
|
2702
2784
|
const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
2703
2785
|
const hasAssistantTurn = !!lastParsedAssistant;
|
|
@@ -2705,12 +2787,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
2705
2787
|
const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
|
|
2706
2788
|
const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
|
|
2707
2789
|
const idleStableThresholdMs = idleFinishConfirmMs;
|
|
2708
|
-
const idleReady =
|
|
2790
|
+
const idleReady = visibleIdlePrompt2 && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
|
|
2709
2791
|
const candidate = this.idleFinishCandidate;
|
|
2710
2792
|
const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
|
|
2711
2793
|
const canFinishImmediately = idleReady && candidateQuiet;
|
|
2712
2794
|
this.recordTrace("idle_decision", {
|
|
2713
|
-
visibleIdlePrompt,
|
|
2795
|
+
visibleIdlePrompt: visibleIdlePrompt2,
|
|
2714
2796
|
quietForMs,
|
|
2715
2797
|
screenStableMs,
|
|
2716
2798
|
hasAssistantTurn,
|
|
@@ -2830,6 +2912,70 @@ var init_provider_cli_adapter = __esm({
|
|
|
2830
2912
|
this.setStatus("idle", "response_finished");
|
|
2831
2913
|
this.onStatusChange?.();
|
|
2832
2914
|
}
|
|
2915
|
+
maybeCommitVisibleIdleTranscript(parsed, options) {
|
|
2916
|
+
const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
|
|
2917
|
+
if (!allowImmediateScriptIdleCommit) return false;
|
|
2918
|
+
if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
|
|
2919
|
+
return false;
|
|
2920
|
+
}
|
|
2921
|
+
if (options?.requireVisibleAssistantCandidate) {
|
|
2922
|
+
const candidateText = options.screenText || this.terminalScreen.getText() || "";
|
|
2923
|
+
if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
|
|
2924
|
+
return false;
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
2928
|
+
committedMessages: this.committedMessages,
|
|
2929
|
+
scope: this.currentTurnScope,
|
|
2930
|
+
lastOutputAt: this.lastOutputAt
|
|
2931
|
+
});
|
|
2932
|
+
const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
2933
|
+
if (!visibleAssistant) return false;
|
|
2934
|
+
this.committedMessages = hydratedForIdleCommit;
|
|
2935
|
+
const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
|
|
2936
|
+
if (promptForTrim) {
|
|
2937
|
+
const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
2938
|
+
if (lastAssistantForTrim) {
|
|
2939
|
+
lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
if (this.responseTimeout) {
|
|
2943
|
+
clearTimeout(this.responseTimeout);
|
|
2944
|
+
this.responseTimeout = null;
|
|
2945
|
+
}
|
|
2946
|
+
if (this.idleTimeout) {
|
|
2947
|
+
clearTimeout(this.idleTimeout);
|
|
2948
|
+
this.idleTimeout = null;
|
|
2949
|
+
}
|
|
2950
|
+
if (this.approvalExitTimeout) {
|
|
2951
|
+
clearTimeout(this.approvalExitTimeout);
|
|
2952
|
+
this.approvalExitTimeout = null;
|
|
2953
|
+
}
|
|
2954
|
+
if (this.submitRetryTimer) {
|
|
2955
|
+
clearTimeout(this.submitRetryTimer);
|
|
2956
|
+
this.submitRetryTimer = null;
|
|
2957
|
+
}
|
|
2958
|
+
if (this.finishRetryTimer) {
|
|
2959
|
+
clearTimeout(this.finishRetryTimer);
|
|
2960
|
+
this.finishRetryTimer = null;
|
|
2961
|
+
}
|
|
2962
|
+
this.syncMessageViews();
|
|
2963
|
+
this.responseBuffer = "";
|
|
2964
|
+
this.isWaitingForResponse = false;
|
|
2965
|
+
this.responseSettleIgnoreUntil = 0;
|
|
2966
|
+
this.submitRetryUsed = false;
|
|
2967
|
+
this.submitRetryPromptSnippet = "";
|
|
2968
|
+
this.finishRetryCount = 0;
|
|
2969
|
+
this.currentTurnScope = null;
|
|
2970
|
+
this.activeModal = null;
|
|
2971
|
+
this.setStatus("idle", "script_idle_commit");
|
|
2972
|
+
this.onStatusChange?.();
|
|
2973
|
+
this.recordTrace("script_idle_commit", {
|
|
2974
|
+
messageCount: this.committedMessages.length,
|
|
2975
|
+
lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
|
|
2976
|
+
});
|
|
2977
|
+
return true;
|
|
2978
|
+
}
|
|
2833
2979
|
commitCurrentTranscript() {
|
|
2834
2980
|
const parsed = this.parseCurrentTranscript(
|
|
2835
2981
|
this.committedMessages,
|
|
@@ -2851,6 +2997,12 @@ var init_provider_cli_adapter = __esm({
|
|
|
2851
2997
|
}
|
|
2852
2998
|
this.syncMessageViews();
|
|
2853
2999
|
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
3000
|
+
if (this.currentTurnScope) {
|
|
3001
|
+
LOG.info(
|
|
3002
|
+
"CLI",
|
|
3003
|
+
`[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
|
|
3004
|
+
);
|
|
3005
|
+
}
|
|
2854
3006
|
this.recordTrace("commit_transcript", {
|
|
2855
3007
|
parsedStatus: parsed.status || null,
|
|
2856
3008
|
messageCount: this.committedMessages.length,
|
|
@@ -2870,11 +3022,18 @@ var init_provider_cli_adapter = __esm({
|
|
|
2870
3022
|
`[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
|
|
2871
3023
|
);
|
|
2872
3024
|
}
|
|
3025
|
+
const hasAssistant = !!lastAssistant;
|
|
2873
3026
|
return {
|
|
2874
|
-
hasAssistant
|
|
3027
|
+
hasAssistant,
|
|
2875
3028
|
assistantContent: lastAssistant?.content || ""
|
|
2876
3029
|
};
|
|
2877
3030
|
}
|
|
3031
|
+
if (this.currentTurnScope) {
|
|
3032
|
+
LOG.info(
|
|
3033
|
+
"CLI",
|
|
3034
|
+
`[${this.cliType}] commitCurrentTranscript parsed.messages=none responseBufferLen=${this.responseBuffer.length} accumulatedBufferLen=${this.accumulatedBuffer.length} parsedStatus=${parsed?.status || "-"} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
|
|
3035
|
+
);
|
|
3036
|
+
}
|
|
2878
3037
|
return {
|
|
2879
3038
|
hasAssistant: false,
|
|
2880
3039
|
assistantContent: ""
|
|
@@ -2960,19 +3119,25 @@ var init_provider_cli_adapter = __esm({
|
|
|
2960
3119
|
this.currentTurnScope,
|
|
2961
3120
|
screenText
|
|
2962
3121
|
);
|
|
2963
|
-
|
|
3122
|
+
if (this.maybeCommitVisibleIdleTranscript(parsed)) {
|
|
3123
|
+
return this.getScriptParsedStatus();
|
|
3124
|
+
}
|
|
3125
|
+
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
2964
3126
|
let result;
|
|
2965
3127
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
2966
|
-
const
|
|
2967
|
-
...message,
|
|
2968
|
-
id: message.id || `msg_${index}`,
|
|
2969
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
2970
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
2971
|
-
})) : hydrateCliParsedMessages(parsed.messages, {
|
|
3128
|
+
const parsedHydratedMessages = hydrateCliParsedMessages(parsed.messages, {
|
|
2972
3129
|
committedMessages: this.committedMessages,
|
|
2973
3130
|
scope: this.currentTurnScope,
|
|
2974
3131
|
lastOutputAt: this.lastOutputAt
|
|
2975
3132
|
});
|
|
3133
|
+
const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
|
|
3134
|
+
...message,
|
|
3135
|
+
id: message.id || `msg_${index}`,
|
|
3136
|
+
index: typeof message.index === "number" ? message.index : index,
|
|
3137
|
+
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3138
|
+
}));
|
|
3139
|
+
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && committedHydratedMessages.length > parsedHydratedMessages.length;
|
|
3140
|
+
const hydratedMessages = shouldPreferCommittedMessages || shouldPreferCommittedHistoryReplay ? committedHydratedMessages : parsedHydratedMessages;
|
|
2976
3141
|
result = {
|
|
2977
3142
|
id: parsed.id || "cli_session",
|
|
2978
3143
|
status: parsed.status || this.currentStatus,
|
|
@@ -2996,6 +3161,23 @@ var init_provider_cli_adapter = __esm({
|
|
|
2996
3161
|
activeModal: this.activeModal
|
|
2997
3162
|
};
|
|
2998
3163
|
}
|
|
3164
|
+
const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
|
|
3165
|
+
const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage;
|
|
3166
|
+
if (shouldClampStaleGeneratingToIdle) {
|
|
3167
|
+
result = {
|
|
3168
|
+
...result,
|
|
3169
|
+
status: "idle",
|
|
3170
|
+
messages: Array.isArray(result.messages) ? result.messages.map((message) => {
|
|
3171
|
+
if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
|
|
3172
|
+
const nextMeta = { ...message.meta || {} };
|
|
3173
|
+
delete nextMeta.streaming;
|
|
3174
|
+
return {
|
|
3175
|
+
...message,
|
|
3176
|
+
...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
|
|
3177
|
+
};
|
|
3178
|
+
}) : result.messages
|
|
3179
|
+
};
|
|
3180
|
+
}
|
|
2999
3181
|
this.parsedStatusCache = {
|
|
3000
3182
|
committedMessagesRef: this.committedMessages,
|
|
3001
3183
|
responseBuffer: this.responseBuffer,
|
|
@@ -3128,9 +3310,27 @@ ${data.message || ""}`.trim();
|
|
|
3128
3310
|
}
|
|
3129
3311
|
}
|
|
3130
3312
|
if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
|
|
3131
|
-
|
|
3313
|
+
const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
|
|
3314
|
+
try {
|
|
3315
|
+
return this.getScriptParsedStatus?.() || null;
|
|
3316
|
+
} catch {
|
|
3317
|
+
return null;
|
|
3318
|
+
}
|
|
3319
|
+
})() : null;
|
|
3320
|
+
const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
|
|
3321
|
+
const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
|
|
3322
|
+
const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
|
|
3323
|
+
if (shouldCommitParsedIdleBeforeSend) {
|
|
3324
|
+
this.commitCurrentTranscript();
|
|
3325
|
+
}
|
|
3326
|
+
if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
|
|
3132
3327
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
3133
3328
|
}
|
|
3329
|
+
if (this.isWaitingForResponse && !allowInputDuringGeneration) {
|
|
3330
|
+
if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
|
|
3331
|
+
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3134
3334
|
const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
|
|
3135
3335
|
if (blockingModal || this.currentStatus === "waiting_approval") {
|
|
3136
3336
|
throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
|
|
@@ -3210,7 +3410,7 @@ ${data.message || ""}`.trim();
|
|
|
3210
3410
|
this.submitRetryTimer = null;
|
|
3211
3411
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3212
3412
|
if (this.currentStatus === "waiting_approval") return;
|
|
3213
|
-
if (
|
|
3413
|
+
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3214
3414
|
const screenText2 = this.terminalScreen.getText();
|
|
3215
3415
|
if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
|
|
3216
3416
|
if (/Esc to interrupt|Do you want to proceed|This command requires approval|Allow Codex to|Approve and run now|Always approve this session|Running…|Running\.\.\./i.test(screenText2)) return;
|
|
@@ -3247,7 +3447,7 @@ ${data.message || ""}`.trim();
|
|
|
3247
3447
|
this.submitRetryTimer = null;
|
|
3248
3448
|
if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
|
|
3249
3449
|
if (this.currentStatus === "waiting_approval") return;
|
|
3250
|
-
if (
|
|
3450
|
+
if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
|
|
3251
3451
|
const screenText = this.terminalScreen.getText();
|
|
3252
3452
|
if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
|
|
3253
3453
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
@@ -9748,6 +9948,7 @@ function normalizeReadChatCommandStatus(status, activeModal) {
|
|
|
9748
9948
|
}
|
|
9749
9949
|
function buildReadChatCommandResult(payload, args) {
|
|
9750
9950
|
let validatedPayload;
|
|
9951
|
+
const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
|
|
9751
9952
|
try {
|
|
9752
9953
|
validatedPayload = validateReadChatResultPayload({
|
|
9753
9954
|
...payload,
|
|
@@ -9768,7 +9969,8 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
9768
9969
|
syncMode: "full",
|
|
9769
9970
|
replaceFrom: 0,
|
|
9770
9971
|
totalMessages: messages.length,
|
|
9771
|
-
lastMessageSignature
|
|
9972
|
+
lastMessageSignature,
|
|
9973
|
+
...debugReadChat ? { debugReadChat } : {}
|
|
9772
9974
|
};
|
|
9773
9975
|
}
|
|
9774
9976
|
const sync = computeReadChatSync(messages, cursor);
|
|
@@ -9779,7 +9981,8 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
9779
9981
|
syncMode: sync.syncMode,
|
|
9780
9982
|
replaceFrom: sync.replaceFrom,
|
|
9781
9983
|
totalMessages: sync.totalMessages,
|
|
9782
|
-
lastMessageSignature: sync.lastMessageSignature
|
|
9984
|
+
lastMessageSignature: sync.lastMessageSignature,
|
|
9985
|
+
...debugReadChat ? { debugReadChat } : {}
|
|
9783
9986
|
};
|
|
9784
9987
|
}
|
|
9785
9988
|
function didProviderConfirmSend(result) {
|
|
@@ -9870,14 +10073,33 @@ async function handleReadChat(h, args) {
|
|
|
9870
10073
|
}
|
|
9871
10074
|
}
|
|
9872
10075
|
const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
|
|
9873
|
-
const
|
|
10076
|
+
const adapterStatus = adapter.getStatus();
|
|
10077
|
+
const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
|
|
10078
|
+
const status = parsedRecord ? {
|
|
10079
|
+
...parsedRecord,
|
|
10080
|
+
messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
|
|
10081
|
+
status: adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
|
|
10082
|
+
activeModal: parsedRecord.activeModal || adapterStatus.activeModal
|
|
10083
|
+
} : adapterStatus;
|
|
9874
10084
|
const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
|
|
9875
10085
|
const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
|
|
9876
10086
|
if (status) {
|
|
10087
|
+
LOG.info("Command", `[read_chat] cli-like resolved provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord?.status || "")} shouldPreferAdapterMessages=${String(shouldPreferAdapterMessages)} adapterMsgCount=${Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0} parsedMsgCount=${Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0} returnedMsgCount=${Array.isArray(status.messages) ? status.messages.length : 0}`);
|
|
9877
10088
|
return buildReadChatCommandResult({
|
|
9878
10089
|
messages: status.messages || [],
|
|
9879
10090
|
status: status.status,
|
|
9880
10091
|
activeModal: status.activeModal,
|
|
10092
|
+
debugReadChat: {
|
|
10093
|
+
provider: adapter.cliType,
|
|
10094
|
+
targetSessionId: String(args?.targetSessionId || ""),
|
|
10095
|
+
adapterStatus: String(adapterStatus.status || ""),
|
|
10096
|
+
parsedStatus: String(parsedRecord?.status || ""),
|
|
10097
|
+
returnedStatus: String(status.status || ""),
|
|
10098
|
+
shouldPreferAdapterMessages,
|
|
10099
|
+
adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
|
|
10100
|
+
parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
|
|
10101
|
+
returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
|
|
10102
|
+
},
|
|
9881
10103
|
...title ? { title } : {},
|
|
9882
10104
|
...providerSessionId ? { providerSessionId } : {}
|
|
9883
10105
|
}, args);
|
|
@@ -12436,7 +12658,7 @@ var CliProviderInstance = class {
|
|
|
12436
12658
|
activeChat: {
|
|
12437
12659
|
id: `${this.type}_${this.workingDir}`,
|
|
12438
12660
|
title: parsedStatus?.title || dirName,
|
|
12439
|
-
status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
|
|
12661
|
+
status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : adapterStatus.status !== "idle" ? visibleStatus : parsedStatus?.status || visibleStatus,
|
|
12440
12662
|
messages: mergedMessages,
|
|
12441
12663
|
activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
|
|
12442
12664
|
inputContent: ""
|
|
@@ -24876,6 +25098,13 @@ init_pty_transport();
|
|
|
24876
25098
|
// src/cli-adapters/session-host-transport.ts
|
|
24877
25099
|
var import_session_host_core2 = require("@adhdev/session-host-core");
|
|
24878
25100
|
init_logger();
|
|
25101
|
+
function shouldResumeAttachedSession(record) {
|
|
25102
|
+
if (!record) return false;
|
|
25103
|
+
if (record.lifecycle === "interrupted") return true;
|
|
25104
|
+
if (record.lifecycle !== "stopped") return false;
|
|
25105
|
+
if (record.meta?.restoredFromStorage === true) return true;
|
|
25106
|
+
return typeof record.meta?.runtimeRecoveryState === "string" && String(record.meta.runtimeRecoveryState).trim().length > 0;
|
|
25107
|
+
}
|
|
24879
25108
|
var SessionHostRuntimeTransport = class {
|
|
24880
25109
|
constructor(options) {
|
|
24881
25110
|
this.options = options;
|
|
@@ -25049,7 +25278,7 @@ var SessionHostRuntimeTransport = class {
|
|
|
25049
25278
|
payload: {}
|
|
25050
25279
|
});
|
|
25051
25280
|
const existingRecord = existingRecords.success && existingRecords.result ? existingRecords.result.find((item) => item.sessionId === this.options.runtimeId) || null : null;
|
|
25052
|
-
if (existingRecord
|
|
25281
|
+
if (shouldResumeAttachedSession(existingRecord)) {
|
|
25053
25282
|
const resumeResponse = await this.client.request({
|
|
25054
25283
|
type: "resume_session",
|
|
25055
25284
|
payload: {
|
|
@@ -25345,6 +25574,8 @@ async function listHostedCliRuntimes(endpoint) {
|
|
|
25345
25574
|
// src/session-host/startup-restore-policy.js
|
|
25346
25575
|
function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
|
|
25347
25576
|
const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
|
|
25577
|
+
if (!raw) return true;
|
|
25578
|
+
if (raw === "0" || raw === "false" || raw === "no") return false;
|
|
25348
25579
|
return raw === "1" || raw === "true" || raw === "yes";
|
|
25349
25580
|
}
|
|
25350
25581
|
|