@adhdev/daemon-core 0.8.89 → 0.8.91
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 +1 -0
- package/dist/index.js +32 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -15
- 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 +28 -11
- package/src/cli-adapters/provider-cli-parse.ts +4 -4
- package/src/commands/chat-commands.ts +7 -3
- package/src/status/reporter.ts +10 -2
package/package.json
CHANGED
|
@@ -677,6 +677,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
677
677
|
private looksLikeClaudeGeneratingLine(line: string): boolean {
|
|
678
678
|
const trimmed = String(line || '').trim();
|
|
679
679
|
if (!trimmed) return false;
|
|
680
|
+
if (/^⏵⏵\s+accept edits on/i.test(trimmed)) return false;
|
|
680
681
|
if (/esc to (cancel|interrupt|stop)/i.test(trimmed)) return true;
|
|
681
682
|
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+\S+.*\b(?:thinking|thought for \d+s?)\b/i.test(trimmed)) return true;
|
|
682
683
|
if (/^[✻✶✳✢✽⠂⠐⠒⠓⠦⠴⠶⠷⠿]+\s+[A-Z][A-Za-z-]{3,}ing\b.*(?:…|\.{3})/u.test(trimmed)) return true;
|
|
@@ -922,15 +923,22 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
922
923
|
return;
|
|
923
924
|
}
|
|
924
925
|
const startupModal = this.getStartupConfirmationModal(screenText);
|
|
925
|
-
const modal = this.runParseApproval(tail) || startupModal;
|
|
926
|
-
const rawScriptStatus = this.runDetectStatus(tail);
|
|
927
|
-
// detectStatus is the sole authority for status. parseApproval only enriches modal info.
|
|
928
|
-
const scriptStatus = startupModal ? 'waiting_approval' : rawScriptStatus;
|
|
929
926
|
const parsedTranscript = this.parseCurrentTranscript(
|
|
930
927
|
this.committedMessages,
|
|
931
928
|
this.responseBuffer,
|
|
932
929
|
this.currentTurnScope,
|
|
933
930
|
);
|
|
931
|
+
const parsedModal = parsedTranscript?.activeModal && Array.isArray(parsedTranscript.activeModal.buttons) && parsedTranscript.activeModal.buttons.some((button: any) => typeof button === 'string' && button.trim())
|
|
932
|
+
? parsedTranscript.activeModal
|
|
933
|
+
: null;
|
|
934
|
+
const modal = this.runParseApproval(tail) || parsedModal || startupModal;
|
|
935
|
+
const rawScriptStatus = this.runDetectStatus(tail);
|
|
936
|
+
// detectStatus is the primary authority for status, but if the parsed transcript
|
|
937
|
+
// already surfaced actionable approval buttons, promote that state so runtime
|
|
938
|
+
// status and resolve_action stay aligned with the visible prompt.
|
|
939
|
+
const scriptStatus = startupModal
|
|
940
|
+
? 'waiting_approval'
|
|
941
|
+
: (parsedModal && parsedTranscript?.status === 'waiting_approval' ? 'waiting_approval' : rawScriptStatus);
|
|
934
942
|
const parsedMessages = Array.isArray(parsedTranscript?.messages)
|
|
935
943
|
? normalizeCliParsedMessages(parsedTranscript.messages, {
|
|
936
944
|
committedMessages: this.committedMessages,
|
|
@@ -942,6 +950,9 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
942
950
|
return;
|
|
943
951
|
}
|
|
944
952
|
const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === 'assistant');
|
|
953
|
+
const parsedShowsLiveAssistantProgress = parsedTranscript?.status === 'generating'
|
|
954
|
+
&& !!lastParsedAssistant
|
|
955
|
+
&& parsedMessages.length > this.committedMessages.length;
|
|
945
956
|
const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || '');
|
|
946
957
|
this.recordTrace('settled', {
|
|
947
958
|
tail: summarizeCliTraceText(tail, 500),
|
|
@@ -1049,7 +1060,8 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1049
1060
|
&& this.isWaitingForResponse
|
|
1050
1061
|
&& !modal
|
|
1051
1062
|
&& recentInteractiveActivity
|
|
1052
|
-
&& !(visibleIdlePrompt && visibleAssistantCandidate)
|
|
1063
|
+
&& !(visibleIdlePrompt && visibleAssistantCandidate)
|
|
1064
|
+
&& !(parsedTranscript?.status === 'idle' && !!lastParsedAssistant);
|
|
1053
1065
|
|
|
1054
1066
|
if (shouldHoldGenerating) {
|
|
1055
1067
|
this.clearIdleFinishCandidate('hold_generating_recent_activity');
|
|
@@ -1124,7 +1136,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1124
1136
|
&& (/Update available!/i.test(screenText)
|
|
1125
1137
|
|| /\/effort/i.test(screenText)
|
|
1126
1138
|
|| /^.*➜\s+\S+/m.test(effectiveScreenText)));
|
|
1127
|
-
if (prevStatus === 'idle' && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome) {
|
|
1139
|
+
if (prevStatus === 'idle' && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
1128
1140
|
return;
|
|
1129
1141
|
}
|
|
1130
1142
|
if (prevStatus === 'waiting_approval') {
|
|
@@ -1461,14 +1473,19 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1461
1473
|
}
|
|
1462
1474
|
}
|
|
1463
1475
|
|
|
1476
|
+
private projectEffectiveStatus(startupModal: { message: string; buttons: string[] } | null = null): CliSessionStatus['status'] {
|
|
1477
|
+
if (this.parseErrorMessage) return 'error';
|
|
1478
|
+
if (startupModal) return 'waiting_approval';
|
|
1479
|
+
if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus === 'idle') return 'generating';
|
|
1480
|
+
return this.currentStatus;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1464
1483
|
// ─── Public API (CliAdapter) ───────────────────
|
|
1465
1484
|
|
|
1466
1485
|
getStatus(): CliSessionStatus {
|
|
1467
1486
|
const screenText = this.terminalScreen.getText() || '';
|
|
1468
1487
|
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
1469
|
-
const effectiveStatus = this.
|
|
1470
|
-
? 'error'
|
|
1471
|
-
: (startupModal ? 'waiting_approval' : this.currentStatus);
|
|
1488
|
+
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
1472
1489
|
return {
|
|
1473
1490
|
status: effectiveStatus,
|
|
1474
1491
|
messages: [...this.committedMessages],
|
|
@@ -2201,7 +2218,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
2201
2218
|
}
|
|
2202
2219
|
this.setStatus('generating', 'approval_resolved');
|
|
2203
2220
|
this.onStatusChange?.();
|
|
2204
|
-
const startupTrustModal = /Quick safety check|project trust|trust (?:this project|the contents of this directory|the files in this folder)/i.test(String(modal?.message || ''));
|
|
2221
|
+
const startupTrustModal = /Quick safety check|project trust|Confirm Claude Code project trust|trust (?:this project|the contents of this directory|the files in this folder)/i.test(String(modal?.message || ''));
|
|
2205
2222
|
if (startupTrustModal && buttonIndex in this.approvalKeys) {
|
|
2206
2223
|
this.ptyProcess.write(`${this.approvalKeys[buttonIndex]}\r`);
|
|
2207
2224
|
} else if (this.shouldResolveModalWithEnter(modal, buttonIndex)) {
|
|
@@ -2228,7 +2245,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
2228
2245
|
getDebugState(): Record<string, any> {
|
|
2229
2246
|
const screenText = sanitizeTerminalText(this.terminalScreen.getText());
|
|
2230
2247
|
const startupModal = this.startupParseGate ? this.getStartupConfirmationModal(screenText) : null;
|
|
2231
|
-
const effectiveStatus =
|
|
2248
|
+
const effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
2232
2249
|
const effectiveReady = this.ready || !!startupModal;
|
|
2233
2250
|
return {
|
|
2234
2251
|
type: this.cliType,
|
|
@@ -139,10 +139,10 @@ export function buildCliParseInput(options: {
|
|
|
139
139
|
runtimeSettings,
|
|
140
140
|
} = options;
|
|
141
141
|
const buffer = scope
|
|
142
|
-
?
|
|
142
|
+
? sliceFromOffset(accumulatedBuffer, scope.bufferStart)
|
|
143
143
|
: accumulatedBuffer;
|
|
144
144
|
const rawBuffer = scope
|
|
145
|
-
?
|
|
145
|
+
? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart)
|
|
146
146
|
: accumulatedRawBuffer;
|
|
147
147
|
const screenText = terminalScreenText;
|
|
148
148
|
const recentBuffer = buffer.slice(-1000) || recentOutputBuffer;
|
|
@@ -189,10 +189,10 @@ export function buildCliTraceParseSnapshot(options: {
|
|
|
189
189
|
}): Record<string, any> {
|
|
190
190
|
const { accumulatedBuffer, accumulatedRawBuffer, responseBuffer, partialResponse, scope } = options;
|
|
191
191
|
const scopedBuffer = scope
|
|
192
|
-
?
|
|
192
|
+
? sliceFromOffset(accumulatedBuffer, scope.bufferStart)
|
|
193
193
|
: accumulatedBuffer;
|
|
194
194
|
const scopedRawBuffer = scope
|
|
195
|
-
?
|
|
195
|
+
? sliceFromOffset(accumulatedRawBuffer, scope.rawBufferStart)
|
|
196
196
|
: accumulatedRawBuffer;
|
|
197
197
|
return {
|
|
198
198
|
currentTurnScope: scope || null,
|
|
@@ -491,13 +491,17 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
491
491
|
&& adapterStatus.messages.length > 0
|
|
492
492
|
&& Array.isArray(parsedRecord?.messages)
|
|
493
493
|
&& adapterStatus.messages.length > parsedRecord.messages.length;
|
|
494
|
+
const parsedShowsApproval = hasNonEmptyModalButtons(parsedRecord?.activeModal)
|
|
495
|
+
&& parsedRecord?.status === 'waiting_approval';
|
|
494
496
|
const status = parsedRecord
|
|
495
497
|
? {
|
|
496
498
|
...parsedRecord,
|
|
497
499
|
messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
|
|
498
|
-
status:
|
|
499
|
-
?
|
|
500
|
-
: (
|
|
500
|
+
status: parsedShowsApproval
|
|
501
|
+
? parsedRecord.status
|
|
502
|
+
: (adapterStatus.status !== 'idle'
|
|
503
|
+
? adapterStatus.status
|
|
504
|
+
: (parsedRecord.status || adapterStatus.status)),
|
|
501
505
|
activeModal: parsedRecord.activeModal || adapterStatus.activeModal,
|
|
502
506
|
}
|
|
503
507
|
: adapterStatus;
|
package/src/status/reporter.ts
CHANGED
|
@@ -91,6 +91,11 @@ export class DaemonStatusReporter {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
onStatusChange(): void {
|
|
94
|
+
if (this.deps.p2p?.isConnected) {
|
|
95
|
+
this.resetP2PHash();
|
|
96
|
+
this.sendUnifiedStatusReport({ p2pOnly: true, reason: 'status-change' })
|
|
97
|
+
.catch(e => LOG.warn('Status', `Immediate P2P status send failed: ${e?.message}`));
|
|
98
|
+
}
|
|
94
99
|
this.throttledReport();
|
|
95
100
|
}
|
|
96
101
|
|
|
@@ -215,10 +220,12 @@ export class DaemonStatusReporter {
|
|
|
215
220
|
|
|
216
221
|
async sendUnifiedStatusReport(opts?: { p2pOnly?: boolean; forceServer?: boolean; reason?: string }): Promise<void> {
|
|
217
222
|
const { serverConn, p2p } = this.deps;
|
|
218
|
-
|
|
223
|
+
const serverConnected = !!serverConn?.isConnected();
|
|
224
|
+
const p2pConnected = !!p2p?.isConnected;
|
|
225
|
+
if (!serverConnected && !p2pConnected) return;
|
|
219
226
|
this.lastStatusSentAt = Date.now();
|
|
220
227
|
const now = this.lastStatusSentAt;
|
|
221
|
-
const target = opts?.p2pOnly ? 'P2P' : 'P2P+Server';
|
|
228
|
+
const target = opts?.p2pOnly ? 'P2P' : (serverConnected ? 'P2P+Server' : 'P2P');
|
|
222
229
|
|
|
223
230
|
const allStates = this.deps.instanceManager.collectAllStates();
|
|
224
231
|
const ideStates = allStates.filter((s): s is IdeProviderState => s.category === 'ide');
|
|
@@ -316,6 +323,7 @@ export class DaemonStatusReporter {
|
|
|
316
323
|
...wsPayload,
|
|
317
324
|
timestamp: undefined,
|
|
318
325
|
}));
|
|
326
|
+
if (!serverConnected || !serverConn) return;
|
|
319
327
|
if (!opts?.forceServer && wsHash === this.lastServerStatusHash) {
|
|
320
328
|
LOG.debug('Server', `skip duplicate status_report${opts?.reason ? ` (${opts.reason})` : ''}`);
|
|
321
329
|
return;
|