@adhdev/daemon-core 1.0.28-rc.17 → 1.0.28-rc.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/cli-adapters/cli-state-engine.ts +19 -1
- package/src/commands/chat-commands-read.ts +33 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "1.0.28-rc.
|
|
3
|
+
"version": "1.0.28-rc.18",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"author": "vilmire",
|
|
50
50
|
"license": "AGPL-3.0-or-later",
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@adhdev/mesh-shared": "1.0.28-rc.
|
|
53
|
-
"@adhdev/session-host-core": "1.0.28-rc.
|
|
52
|
+
"@adhdev/mesh-shared": "1.0.28-rc.18",
|
|
53
|
+
"@adhdev/session-host-core": "1.0.28-rc.18",
|
|
54
54
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
55
55
|
"ajv": "^8.20.0",
|
|
56
56
|
"ajv-formats": "^3.0.1",
|
|
@@ -729,7 +729,25 @@ export class CliStateEngine {
|
|
|
729
729
|
if (!session) return;
|
|
730
730
|
|
|
731
731
|
const { status, messages } = session;
|
|
732
|
-
|
|
732
|
+
// RC17-APPROVAL-NO-MODAL: a provider's own detectStatus/parseSession script can
|
|
733
|
+
// report status='waiting_approval' with a modal object whose buttons array is
|
|
734
|
+
// empty (a half-rendered approval frame, or — as observed live on a Claude
|
|
735
|
+
// session with no actionable modal anywhere in the raw PTY — a bare status flip
|
|
736
|
+
// with no real prompt at all). Previously this raw modal was latched straight
|
|
737
|
+
// into this.activeModal and dispatched through applyWaitingApproval's
|
|
738
|
+
// ALREADY-actionable branch (line ~1042 below), which sets status +
|
|
739
|
+
// fires agent:waiting_approval unconditionally — the "!modal" hysteresis/warn
|
|
740
|
+
// path (the one place button-validity was actually enforced) only runs when the
|
|
741
|
+
// modal is null, not when it merely has no buttons. Treat a buttons-empty modal
|
|
742
|
+
// as no modal here so it flows into that same proven hysteresis: it warns, waits
|
|
743
|
+
// out approvalCooldown, and never fires an event unless a LATER settle pass
|
|
744
|
+
// observes a genuinely actionable modal. Mirrors hasNonEmptyCliModalButtons used
|
|
745
|
+
// elsewhere (resolveModal, stabilizeFlappingApprovalStatus) — same predicate,
|
|
746
|
+
// applied at the point the modal first enters the FSM.
|
|
747
|
+
const rawModal = (session as any).activeModal ?? session.modal ?? null;
|
|
748
|
+
const modal = rawModal && Array.isArray(rawModal.buttons) && rawModal.buttons.some(
|
|
749
|
+
(button: unknown) => typeof button === 'string' && button.trim().length > 0,
|
|
750
|
+
) ? rawModal : null;
|
|
733
751
|
const parsedStatus = (session as any).parsedStatus ?? null;
|
|
734
752
|
const parsedMessages = normalizeCliParsedMessages(messages, {
|
|
735
753
|
scope: null,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type ChatSourceTransitionCause,
|
|
25
25
|
} from '../chat/source-resolver.js';
|
|
26
26
|
import type { ChatMessage } from '../types.js';
|
|
27
|
-
import { filterUserFacingChatMessages, isActivityChatMessage, isUserFacingChatMessage, normalizeChatMessages } from '../providers/chat-message-normalization.js';
|
|
27
|
+
import { filterUserFacingChatMessages, isActivityChatMessage, isUserFacingChatMessage, normalizeChatMessages, hasTrailingToolActivityAfterFinalAssistant } from '../providers/chat-message-normalization.js';
|
|
28
28
|
import {
|
|
29
29
|
READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS,
|
|
30
30
|
type RuntimeChatMessageMerger,
|
|
@@ -2480,11 +2480,43 @@ export async function handleReadChat(h: CommandHelpers, args: any): Promise<Comm
|
|
|
2480
2480
|
});
|
|
2481
2481
|
}
|
|
2482
2482
|
}
|
|
2483
|
+
// RC17-NATIVE-FINAL-ASSISTANT-MIDTURN: hasFinalVisibleAssistantMessage only
|
|
2484
|
+
// checks that the LAST visible native-transcript message is a non-empty
|
|
2485
|
+
// assistant/model bubble — it has no notion of whether that bubble is
|
|
2486
|
+
// actually the end of the turn. A live Claude repro showed this reconciling
|
|
2487
|
+
// generating→idle on an INTERIM narration bubble ("Starting the collector
|
|
2488
|
+
// now, before the two-turn protocol.") emitted mid-turn, well before the
|
|
2489
|
+
// real two-turn protocol/tool work ran — exactly the false-completion class
|
|
2490
|
+
// rc.16 (9452bd03/6677a565) closed for the mesh-event ingress via
|
|
2491
|
+
// hasTrailingToolActivityAfterFinalAssistant + hasLiveTurnPendingEvidence.
|
|
2492
|
+
// This read_chat status ingress is a SEPARATE consumer of the same
|
|
2493
|
+
// native-final-assistant signal (it feeds the `status` field returned to
|
|
2494
|
+
// read_chat/dashboard, not the mesh agent:generating_completed event) and
|
|
2495
|
+
// never got the equivalent veto. This reconciliation exists precisely for a
|
|
2496
|
+
// PTY/adapter status detector that never transitions to idle on its own (see
|
|
2497
|
+
// read-chat-completed-session-fallback.test.ts's antigravity stuck-busy
|
|
2498
|
+
// case: isProcessing() stays true forever, empty PTY messages, and native
|
|
2499
|
+
// history is the only signal that ever resolves it) — so gating on the
|
|
2500
|
+
// adapter's own pending-response bit here would neuter this reconciliation
|
|
2501
|
+
// for that exact intended case. Apply only STRUCTURAL, evidence-based vetoes
|
|
2502
|
+
// instead, mirroring rc.16's hasLiveTurnPendingEvidence: trailing tool/
|
|
2503
|
+
// terminal activity after the final-looking assistant bubble, scanned in (a)
|
|
2504
|
+
// the native messages being judged — the transcript's own admission that its
|
|
2505
|
+
// "final" bubble kept going — and (b) the live PTY-parsed tail
|
|
2506
|
+
// (returnedMessages), which carries no native-transcript write-lag and is
|
|
2507
|
+
// exactly how a live Claude repro was caught: the native JSONL's last row was
|
|
2508
|
+
// still the interim narration bubble (no trailing tool row landed there yet),
|
|
2509
|
+
// but the PTY had already rendered the very next "Auto-approved: Yes\nBash
|
|
2510
|
+
// command" tool activity. The antigravity stuck-busy case has an EMPTY PTY
|
|
2511
|
+
// message list, so (b) is a no-op there (the function short-circuits false on
|
|
2512
|
+
// an empty/absent array) and the existing regression is unaffected.
|
|
2483
2513
|
if (
|
|
2484
2514
|
isGeneratingLikeStatus(selectedStatus)
|
|
2485
2515
|
&& selectedTranscriptAuthority === 'provider'
|
|
2486
2516
|
&& !hasNonEmptyModalButtons(activeModal)
|
|
2487
2517
|
&& hasFinalVisibleAssistantMessage(selectedMessages)
|
|
2518
|
+
&& !hasTrailingToolActivityAfterFinalAssistant(selectedMessages as any)
|
|
2519
|
+
&& !hasTrailingToolActivityAfterFinalAssistant(returnedMessages as any)
|
|
2488
2520
|
) {
|
|
2489
2521
|
selectedStatus = 'idle';
|
|
2490
2522
|
selectedMessages = finalizeStreamingMessagesWhenIdle(selectedMessages, selectedStatus);
|