@adhdev/daemon-core 1.0.18-rc.9 → 1.0.19
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-shared.d.ts +33 -0
- package/dist/commands/cli-manager.d.ts +9 -0
- package/dist/commands/upgrade-helper.d.ts +1 -0
- package/dist/commands/windows-atomic-upgrade.d.ts +1 -0
- package/dist/config/mesh-json-config.d.ts +62 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2205 -657
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2173 -634
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-active-work.d.ts +1 -1
- package/dist/mesh/mesh-ledger.d.ts +1 -1
- package/dist/mesh/mesh-node-identity.d.ts +23 -0
- package/dist/mesh/mesh-refine-gates.d.ts +89 -0
- package/dist/mesh/mesh-remote-event-pull.d.ts +3 -0
- package/dist/mesh/mesh-work-queue.d.ts +24 -1
- package/dist/providers/auto-approve-modes.d.ts +14 -0
- package/dist/providers/chat-message-normalization.d.ts +22 -0
- package/dist/providers/cli-provider-instance-types.d.ts +2 -0
- package/dist/providers/cli-provider-instance.d.ts +76 -0
- package/dist/providers/contracts.d.ts +17 -0
- package/dist/providers/provider-schema.d.ts +1 -0
- package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +14 -0
- package/dist/providers/types/interactive-prompt.d.ts +18 -0
- package/dist/repo-mesh-types.d.ts +38 -6
- package/dist/shared-types.d.ts +4 -2
- package/package.json +3 -3
- package/src/cli-adapters/cli-state-engine.ts +17 -1
- package/src/cli-adapters/provider-cli-adapter.ts +2 -6
- package/src/cli-adapters/provider-cli-shared.ts +48 -0
- package/src/commands/cli-manager.ts +72 -8
- package/src/commands/high-family/mesh-events.ts +13 -2
- package/src/commands/med-family/mesh-crud.ts +155 -0
- package/src/commands/med-family/mesh-queue.ts +74 -1
- package/src/commands/router-refine.ts +71 -4
- package/src/commands/router.ts +8 -0
- package/src/commands/upgrade-helper.ts +50 -1
- package/src/commands/windows-atomic-upgrade.ts +88 -23
- package/src/config/mesh-json-config.ts +103 -0
- package/src/index.ts +21 -1
- package/src/mesh/coordinator-prompt.ts +2 -1
- package/src/mesh/mesh-active-work.ts +11 -1
- package/src/mesh/mesh-completion-synthesis.ts +12 -1
- package/src/mesh/mesh-event-classify.ts +19 -0
- package/src/mesh/mesh-event-forwarding.ts +64 -6
- package/src/mesh/mesh-events-utils.ts +42 -0
- package/src/mesh/mesh-ledger.ts +5 -0
- package/src/mesh/mesh-node-identity.ts +49 -0
- package/src/mesh/mesh-queue-assignment.ts +84 -10
- package/src/mesh/mesh-reconcile-loop.ts +257 -3
- package/src/mesh/mesh-refine-gates.ts +300 -0
- package/src/mesh/mesh-remote-event-pull.ts +68 -47
- package/src/mesh/mesh-work-queue.ts +85 -2
- package/src/providers/auto-approve-modes.ts +97 -0
- package/src/providers/chat-message-normalization.ts +53 -0
- package/src/providers/cli-provider-instance-types.ts +28 -0
- package/src/providers/cli-provider-instance.ts +394 -28
- package/src/providers/contracts.ts +25 -1
- package/src/providers/provider-schema.ts +83 -0
- package/src/providers/sdk/v1/builders/cli/detect-status.ts +23 -0
- package/src/providers/sdk/v1/builders/cli/parse-approval.ts +20 -0
- package/src/providers/sdk/v1/schemas/cli/provider.schema.json +44 -0
- package/src/providers/types/interactive-prompt.ts +77 -0
- package/src/repo-mesh-types.ts +112 -12
- package/src/shared-types.ts +9 -1
- package/src/status/reporter.ts +1 -0
- package/src/status/snapshot.ts +2 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MeshLedgerEntry } from './mesh-ledger.js';
|
|
2
2
|
import type { MeshWorkQueueEntry, DirectDispatchRecord } from './mesh-work-queue.js';
|
|
3
3
|
export type MeshActiveWorkSource = 'queue' | 'direct';
|
|
4
|
-
export type MeshActiveWorkStatus = 'pending' | 'assigned' | 'generating' | 'idle' | 'failed' | 'awaiting_approval';
|
|
4
|
+
export type MeshActiveWorkStatus = 'pending' | 'assigned' | 'generating' | 'idle' | 'failed' | 'awaiting_approval' | 'awaiting_choice';
|
|
5
5
|
export interface MeshActiveWorkRecord {
|
|
6
6
|
taskId: string;
|
|
7
7
|
source: MeshActiveWorkSource;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import { EventEmitter } from 'events';
|
|
16
16
|
import { MeshRuntimeStore } from './mesh-runtime-store.js';
|
|
17
17
|
import { type MeshLedgerOriginatingCoordinatorV2 } from './contracts.js';
|
|
18
|
-
export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'p2p_dispatch_failed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_joined' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled' | 'direct_fast_forward' | 'delivery_unroutable' | 'direct_dispatch_pruned' | 'event_held' | 'event_held_requeued' | 'task_reclaimed' | 'coordinator_operating_note' | 'coordinator_operating_note_tombstone' | 'mission_created' | 'mission_status_changed' | 'mission_goal_updated' | 'magi_dispatched' | 'magi_synthesis' | 'key_injection' | 'worktree_cleanup_candidate';
|
|
18
|
+
export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'task_question_pending' | 'p2p_dispatch_failed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_joined' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled' | 'direct_fast_forward' | 'delivery_unroutable' | 'direct_dispatch_pruned' | 'event_held' | 'event_held_requeued' | 'task_reclaimed' | 'coordinator_operating_note' | 'coordinator_operating_note_tombstone' | 'mission_created' | 'mission_status_changed' | 'mission_goal_updated' | 'magi_dispatched' | 'magi_synthesis' | 'key_injection' | 'worktree_cleanup_candidate';
|
|
19
19
|
export interface MeshLedgerEntry {
|
|
20
20
|
id: string;
|
|
21
21
|
meshId: string;
|
|
@@ -107,6 +107,29 @@ export declare function resolveEffectiveMeshNodeHealth(node: any): string;
|
|
|
107
107
|
* replica that can never run.
|
|
108
108
|
*/
|
|
109
109
|
export declare function isMeshNodeHealthLaunchable(node: any): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Launch FRESHNESS gate — distinct from the health gate above.
|
|
112
|
+
*
|
|
113
|
+
* `deriveMeshNodeHealthFromGit` reports a clean-tree node with `behind > 0` as
|
|
114
|
+
* 'online', so the health gate (isMeshNodeHealthLaunchable) happily lets a STALE
|
|
115
|
+
* node — one whose branch is N commits behind its upstream — win auto-launch fitness
|
|
116
|
+
* routing and run a fresh worker against out-of-date code. `behind` is deliberately
|
|
117
|
+
* NOT folded into deriveMeshNodeHealthFromGit because "behind" is not universally
|
|
118
|
+
* unhealthy (the MAGI planner and other callers share that resolver); it is only
|
|
119
|
+
* unhealthy for *spawning new work*. This gate encodes exactly that launch-time axis.
|
|
120
|
+
*
|
|
121
|
+
* Returns false (NOT fresh → skip / de-rank) only when git telemetry is PRESENT and
|
|
122
|
+
* proves staleness:
|
|
123
|
+
* - behind count exceeds `maxBehind` (default 0 — any behind blocks), OR
|
|
124
|
+
* - a submodule is out of sync (gitlink points off upstream — cannot be caught up
|
|
125
|
+
* by a simple worktree ff and would launch against a mismatched submodule).
|
|
126
|
+
*
|
|
127
|
+
* When telemetry is absent it returns true (fresh), preserving the online/unknown-pass
|
|
128
|
+
* philosophy: we never block on missing data, only on data that proves the node stale.
|
|
129
|
+
*/
|
|
130
|
+
export declare function isMeshNodeFreshEnoughToLaunch(node: any, opts?: {
|
|
131
|
+
maxBehind?: number;
|
|
132
|
+
}): boolean;
|
|
110
133
|
export declare function applyInlineMeshBranchConvergence(mesh: any, node: any, status: Record<string, unknown>): void;
|
|
111
134
|
export declare function summarizeInlineMeshBranchConvergence(nodes: Array<Record<string, unknown>>): Record<string, unknown>;
|
|
112
135
|
export declare function readCachedInlineMeshActiveSessions(node: any): string[];
|
|
@@ -504,6 +504,95 @@ type GitlinkTrivialFastForwardEvaluation = {
|
|
|
504
504
|
* gate.
|
|
505
505
|
*/
|
|
506
506
|
export declare function collectFastForwardGitlinkPaths(repoRoot: string, baseHead: string, branchHead: string): string[];
|
|
507
|
+
export type SubmoduleGitlinkConvergeResult = {
|
|
508
|
+
/** True when at least one diverged gitlink submodule was rebased onto its base-side commit. */
|
|
509
|
+
converged: boolean;
|
|
510
|
+
/**
|
|
511
|
+
* Set when convergence was declined/aborted (fail-safe → caller keeps the
|
|
512
|
+
* original defer→blocked_review path). One of:
|
|
513
|
+
* no_changed_gitlinks — no gitlink differs base↔branch
|
|
514
|
+
* not_diverged — the gitlink is ff/behind/equal (gate handles it)
|
|
515
|
+
* rebase_conflict — replaying branch-side onto base-side hit a real
|
|
516
|
+
* content conflict inside the submodule (aborted)
|
|
517
|
+
*/
|
|
518
|
+
reason?: string;
|
|
519
|
+
/**
|
|
520
|
+
* Converged gitlinks: path → the rebased submodule commit (SUBNEW) that the
|
|
521
|
+
* root rebase must resolve the gitlink conflict to. Only populated for paths
|
|
522
|
+
* whose submodule was successfully rebased (base-side is now a strict ancestor).
|
|
523
|
+
*/
|
|
524
|
+
resolutions: Array<{
|
|
525
|
+
path: string;
|
|
526
|
+
baseCommit: string;
|
|
527
|
+
branchCommit: string;
|
|
528
|
+
rebasedCommit: string;
|
|
529
|
+
}>;
|
|
530
|
+
/** Per-path outcome for observability/logging. */
|
|
531
|
+
gitlinks: Array<{
|
|
532
|
+
path: string;
|
|
533
|
+
baseCommit?: string;
|
|
534
|
+
branchCommit?: string;
|
|
535
|
+
rebasedCommit?: string;
|
|
536
|
+
action: 'rebased' | 'skipped_not_diverged' | 'rebase_conflict';
|
|
537
|
+
}>;
|
|
538
|
+
};
|
|
539
|
+
/**
|
|
540
|
+
* STEP 1 of auto-converging diverged oss-style submodule gitlinks: rebase the
|
|
541
|
+
* branch-side submodule commit(s) onto the base-side submodule commit INSIDE the
|
|
542
|
+
* worktree's submodule checkout (detached HEAD), so the base-side commit becomes a
|
|
543
|
+
* strict ancestor of the rebased tip. Returns the rebased commit per path so the
|
|
544
|
+
* caller's root rebase can resolve the gitlink conflict to it (STEP 2, see
|
|
545
|
+
* {@link rootRebaseResolvingGitlinks}). This automates the documented manual
|
|
546
|
+
* strict-fast-forward bypass and keeps the landed submodule history linear rather
|
|
547
|
+
* than masking a divergence.
|
|
548
|
+
*
|
|
549
|
+
* Fail-safe by construction: it only touches gitlinks that are a genuine sibling
|
|
550
|
+
* divergence (both commits local, neither an ancestor of the other, shared merge
|
|
551
|
+
* base). A submodule rebase content conflict aborts, restores the branch-side
|
|
552
|
+
* checkout, and returns `converged:false` (caller keeps defer→blocked_review). It
|
|
553
|
+
* never commits the root and NEVER pushes — remote publish is the merge/
|
|
554
|
+
* reachability stage's job; this stage is local reconciliation only.
|
|
555
|
+
*
|
|
556
|
+
* @param worktreeRoot the branch worktree root (its `<path>` submodule checkout is rebased)
|
|
557
|
+
* @param baseRepoRoot the source/base repo root (reads the base-side gitlink commit)
|
|
558
|
+
* @param baseHead the fetched base head (root ref) — source of base-side gitlink commits
|
|
559
|
+
* @param branchHead the worktree branch head (root ref) — source of branch-side gitlink commits
|
|
560
|
+
*/
|
|
561
|
+
export declare function convergeDivergedSubmoduleGitlinks(worktreeRoot: string, baseRepoRoot: string, baseHead: string, branchHead: string): SubmoduleGitlinkConvergeResult;
|
|
562
|
+
export type RootRebaseGitlinkResolveResult = {
|
|
563
|
+
/** True when the root rebase completed (with gitlink conflicts resolved to the converged commits). */
|
|
564
|
+
ok: boolean;
|
|
565
|
+
/** New root HEAD after the rebase (only meaningful when ok). */
|
|
566
|
+
branchHead?: string;
|
|
567
|
+
/**
|
|
568
|
+
* Set when the rebase was aborted (fail-safe). One of:
|
|
569
|
+
* non_gitlink_conflict — a conflict on a non-submodule path (genuine content conflict)
|
|
570
|
+
* unexpected_gitlink — a gitlink conflicted that we have no converged commit for
|
|
571
|
+
* rebase_error — the rebase failed for a non-conflict reason
|
|
572
|
+
*/
|
|
573
|
+
reason?: string;
|
|
574
|
+
/** The paths that conflicted at the point of abort (for diagnostics). */
|
|
575
|
+
conflictPaths?: string[];
|
|
576
|
+
};
|
|
577
|
+
/**
|
|
578
|
+
* STEP 2 of auto-converging diverged submodule gitlinks: rebase the worktree root
|
|
579
|
+
* branch onto `baseHead`, resolving each submodule-gitlink conflict to the
|
|
580
|
+
* pre-converged commit from {@link convergeDivergedSubmoduleGitlinks}. git's
|
|
581
|
+
* recursive merge refuses to auto-merge a diverged gitlink ("Recursive merging
|
|
582
|
+
* with submodules currently only supports trivial cases"), so we drive the rebase
|
|
583
|
+
* ourselves: on each stop, if the ONLY unmerged paths are gitlinks we have a
|
|
584
|
+
* converged commit for, we stage those to the converged commit and `--continue`.
|
|
585
|
+
* Any non-gitlink conflict (or a gitlink with no converged commit) aborts the
|
|
586
|
+
* rebase and returns `ok:false` → caller keeps the defer→blocked_review path.
|
|
587
|
+
*
|
|
588
|
+
* On success the base-side gitlink is a strict ancestor of the resolved branch-side
|
|
589
|
+
* commit, so the downstream patch-equivalence gate treats it as a trivial
|
|
590
|
+
* fast-forward and passes.
|
|
591
|
+
*/
|
|
592
|
+
export declare function rootRebaseResolvingGitlinks(worktreeRoot: string, baseHead: string, resolutions: Array<{
|
|
593
|
+
path: string;
|
|
594
|
+
rebasedCommit: string;
|
|
595
|
+
}>): RootRebaseGitlinkResolveResult;
|
|
507
596
|
/**
|
|
508
597
|
* Decide whether a merge-tree submodule conflict between base and branch is a
|
|
509
598
|
* trivial gitlink fast-forward (and nothing else).
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { DaemonComponents } from '../boot/daemon-lifecycle.js';
|
|
2
2
|
import type { LocalMeshEntry } from '../repo-mesh-types.js';
|
|
3
3
|
export declare function pullRemoteNodeQueues(components: DaemonComponents, mesh: LocalMeshEntry, localDaemonId: string | undefined, candidateDaemonIds: string[]): Promise<void>;
|
|
4
|
+
export declare function pullPendingEventsFromNode(components: DaemonComponents, meshId: string, node: {
|
|
5
|
+
daemonId?: string;
|
|
6
|
+
}, localDaemonId: string | undefined, candidateDaemonIds: string[], pulls: Array<Record<string, unknown>>): Promise<void>;
|
|
4
7
|
export declare function unwrapReadChatPayload(raw: unknown): Record<string, unknown> | null;
|
|
5
8
|
export declare function readChatPayloadStatus(payload: Record<string, unknown> | null): string;
|
|
6
9
|
export declare function realTerminalEmitPendingForTask(meshId: string, taskId: string): boolean;
|
|
@@ -337,7 +337,15 @@ export type DependencyFailurePolicy = 'block' | 'cancel';
|
|
|
337
337
|
* Update the status of a specific task.
|
|
338
338
|
* Used when a session completes, fails, or stalls.
|
|
339
339
|
*/
|
|
340
|
-
export declare function updateTaskStatus(meshId: string, taskId: string, status: MeshTaskStatus, opts?:
|
|
340
|
+
export declare function updateTaskStatus(meshId: string, taskId: string, status: MeshTaskStatus, opts?: {
|
|
341
|
+
/**
|
|
342
|
+
* CANCEL-STICKY-TERMINAL: operator/system override to permit a terminal→non-terminal
|
|
343
|
+
* transition (e.g. an explicit operator reopen). Without this, a write that would flip
|
|
344
|
+
* a `completed`/`failed`/`cancelled` row back to `pending`/`assigned` is refused as a
|
|
345
|
+
* no-op. Terminal→terminal and any transition FROM a non-terminal state are unaffected.
|
|
346
|
+
*/
|
|
347
|
+
force?: boolean;
|
|
348
|
+
} & MeshQueueMutationOptions): MeshWorkQueueEntry | null;
|
|
341
349
|
export declare function recordTaskAutoLaunch(meshId: string, taskId: string, autoLaunch: Omit<NonNullable<MeshWorkQueueEntry['autoLaunch']>, 'updatedAt'>): MeshWorkQueueEntry | null;
|
|
342
350
|
/**
|
|
343
351
|
* Mark a queue task as manually cancelled without deleting audit history.
|
|
@@ -345,6 +353,21 @@ export declare function recordTaskAutoLaunch(meshId: string, taskId: string, aut
|
|
|
345
353
|
export declare function cancelTask(meshId: string, taskId: string, opts?: {
|
|
346
354
|
reason?: string;
|
|
347
355
|
} & MeshQueueMutationOptions): MeshWorkQueueEntry | null;
|
|
356
|
+
/**
|
|
357
|
+
* CANCEL-STICKY-TERMINAL: the assignment a task carried at cancel time, handed to the cancel
|
|
358
|
+
* command handler so it can stop the bound worker. cancelTask runs in the pure queue-store
|
|
359
|
+
* module (no DaemonComponents), so it records the binding here and the handler drains it.
|
|
360
|
+
*/
|
|
361
|
+
export interface CancelledTaskAssignment {
|
|
362
|
+
sessionId: string;
|
|
363
|
+
nodeId?: string;
|
|
364
|
+
providerType?: string;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Read-and-clear the assignment a just-cancelled task was bound to. Returns undefined when the
|
|
368
|
+
* cancelled task had no live assignment (nothing to stop). One-shot: the entry is deleted on read.
|
|
369
|
+
*/
|
|
370
|
+
export declare function takeCancelledTaskAssignment(meshId: string, taskId: string): CancelledTaskAssignment | undefined;
|
|
348
371
|
/**
|
|
349
372
|
* Return a queue task to pending for retry. By default, dead session targeting
|
|
350
373
|
* and assigned ownership are cleared so stale assignments do not strand again.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AutoApproveMode, AutoApproveModeRisk, AutoApproveModeStrategy, ProviderModule } from './contracts.js';
|
|
2
|
+
export interface ResolvedAutoApproveMode {
|
|
3
|
+
active: boolean;
|
|
4
|
+
strategy: AutoApproveModeStrategy;
|
|
5
|
+
modeId: string;
|
|
6
|
+
}
|
|
7
|
+
/** Runtime defense-in-depth for provider definitions that bypass schema validation. */
|
|
8
|
+
export declare function deriveAutoApproveModeRisk(mode: Pick<AutoApproveMode, 'risk' | 'launchArgs'>): AutoApproveModeRisk;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve new mode settings before the legacy boolean. A stale/unknown explicit
|
|
11
|
+
* mode id fails closed instead of falling through to an enabled legacy setting.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveProviderAutoApproveMode(provider: ProviderModule, settings: Record<string, unknown> | undefined): ResolvedAutoApproveMode;
|
|
14
|
+
export declare function findProviderAutoApproveMode(provider: ProviderModule | undefined, modeId: string): AutoApproveMode | undefined;
|
|
@@ -58,6 +58,28 @@ export declare function extractFinalAssistantSummaryEvidence(messages: ChatMessa
|
|
|
58
58
|
* grace gate) on top of this structural check.
|
|
59
59
|
*/
|
|
60
60
|
export declare function selectFinalAssistantTurnEndMessage(messages: ChatMessage[] | null | undefined): ChatMessage | null;
|
|
61
|
+
/**
|
|
62
|
+
* EARLY-IDLE-COMPLETION-FALSE-POSITIVE — trailing tool/terminal activity detector.
|
|
63
|
+
*
|
|
64
|
+
* True when the transcript's LAST non-empty user-facing assistant bubble is followed
|
|
65
|
+
* by one or more TOOL / TERMINAL activity bubbles (a tool_use/command the assistant
|
|
66
|
+
* fired AFTER its text) — i.e. the assistant emitted a preamble ("Let me explore…"),
|
|
67
|
+
* then started running Read/Grep, so the turn is still executing and its answer has
|
|
68
|
+
* not landed. Callers that would otherwise promote that preamble to a turn-end summary
|
|
69
|
+
* off a momentary (startup-grace / inter-tool) idle read use this as a veto.
|
|
70
|
+
*
|
|
71
|
+
* Deliberately NARROW so the pure-PTY completion rescue is preserved:
|
|
72
|
+
* - Only TOOL/TERMINAL activity trailing the assistant vetoes. A trailing THOUGHT or
|
|
73
|
+
* status bubble does NOT (a finished turn can end on an internal thought), matching
|
|
74
|
+
* selectFinalAssistantTurnEndMessage's skip set minus the "still-working" signals.
|
|
75
|
+
* - A genuinely FINISHED worker (final assistant last, no trailing tool activity —
|
|
76
|
+
* the kimi pure-PTY continuous-idle shape) returns false, so its early completion
|
|
77
|
+
* is untouched.
|
|
78
|
+
*
|
|
79
|
+
* Returns false when there is no final assistant bubble at all (the caller's
|
|
80
|
+
* selectFinalAssistantTurnEndMessage already handles that as "not a turn end").
|
|
81
|
+
*/
|
|
82
|
+
export declare function hasTrailingToolActivityAfterFinalAssistant(messages: ChatMessage[] | null | undefined): boolean;
|
|
61
83
|
export declare const BUILTIN_CHAT_MESSAGE_KINDS: readonly ["standard", "thought", "tool", "terminal", "system"];
|
|
62
84
|
export type BuiltinChatMessageKind = typeof BUILTIN_CHAT_MESSAGE_KINDS[number];
|
|
63
85
|
export type ChatMessageKind = BuiltinChatMessageKind | (string & {});
|
|
@@ -19,6 +19,7 @@ export type CompletedFinalizationBlock = {
|
|
|
19
19
|
terminal?: boolean;
|
|
20
20
|
allowTimeout?: boolean;
|
|
21
21
|
holdForTranscript?: boolean;
|
|
22
|
+
noExternalTranscriptSource?: boolean;
|
|
22
23
|
};
|
|
23
24
|
export type CompletionFinalAssistantEvidence = {
|
|
24
25
|
present: boolean;
|
|
@@ -37,6 +38,7 @@ export type ExternalTranscriptProbe = {
|
|
|
37
38
|
};
|
|
38
39
|
export declare const COMPLETED_FINALIZATION_RETRY_MS = 1000;
|
|
39
40
|
export declare const COMPLETED_FINALIZATION_MAX_WAIT_MS = 30000;
|
|
41
|
+
export declare const CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS = 20000;
|
|
40
42
|
export declare const NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4000;
|
|
41
43
|
export declare const PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
|
|
42
44
|
export declare const ANTIGRAVITY_HOLD_QUIET_DWELL_MS = 3000;
|
|
@@ -192,6 +192,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
192
192
|
private meshStallEmittedForAnchor;
|
|
193
193
|
private meshStallTurnActiveLast;
|
|
194
194
|
private meshStallLastFiredAt;
|
|
195
|
+
private meshStallNativeTranscriptSample;
|
|
195
196
|
private busyEpoch;
|
|
196
197
|
private fastCollapseSynthesizedTaskId;
|
|
197
198
|
private startupGraceCollapseAt;
|
|
@@ -424,6 +425,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
424
425
|
* once at completion). Reset on the next turn's start.
|
|
425
426
|
*/
|
|
426
427
|
private lastCompletionSummary;
|
|
428
|
+
private lastEmittedCompletion;
|
|
427
429
|
private enforceFreshSessionLaunchIfNeeded;
|
|
428
430
|
/**
|
|
429
431
|
* BRAIN-ROUTING (runtime-control thinking axis): for a provider that selects
|
|
@@ -574,6 +576,76 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
574
576
|
* starts with a clean slate (a restart is not throttled by a prior stall).
|
|
575
577
|
*/
|
|
576
578
|
private resetMeshStallEpisode;
|
|
579
|
+
/**
|
|
580
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 1). For a native-source provider
|
|
581
|
+
* (transcriptAuthority=provider — its authoritative history is an on-disk
|
|
582
|
+
* transcript file, e.g. kimi's wire.jsonl), sample the transcript's current
|
|
583
|
+
* progress fingerprint (record count + source-file mtime) WITHOUT parsing the
|
|
584
|
+
* PTY. Used by the stall watchdog to distinguish "PTY render is quiet but the
|
|
585
|
+
* worker is still doing long tool work (transcript growing)" from a genuine
|
|
586
|
+
* wedge. Returns null for a pure-PTY provider (no native source) or when the
|
|
587
|
+
* source cannot be resolved this tick — the caller then falls back to the
|
|
588
|
+
* unchanged lastOutputAt-only judgment.
|
|
589
|
+
*
|
|
590
|
+
* Generalized on the provider's native-source flag, NOT a hardcoded provider
|
|
591
|
+
* type, so every current and future pure-PTY long-tool native-source provider
|
|
592
|
+
* benefits. Cheap enough for the stall path: it runs only at the stall threshold
|
|
593
|
+
* (≥180s of PTY stasis), never on the routine 5s tick.
|
|
594
|
+
*/
|
|
595
|
+
private sampleNativeTranscriptProgress;
|
|
596
|
+
/**
|
|
597
|
+
* KIMI-MESH-COMPLETION-EMIT (axis 2). Last-chance completion emit for a mesh
|
|
598
|
+
* DELEGATED worker whose PTY has already exited (e.g. killed by a false stall)
|
|
599
|
+
* and is about to be auto-cleaned (cli-manager.startCliExitMonitor →
|
|
600
|
+
* removeInstance closes the event-emit window forever). If the worker actually
|
|
601
|
+
* FINISHED its assigned turn — its authoritative native transcript holds a final
|
|
602
|
+
* assistant message for the injected task — but the completion event never fired
|
|
603
|
+
* (the stall-kill happened before the FSM's idle transition), emit it now so the
|
|
604
|
+
* coordinator learns the task completed instead of waiting ~180s for the reconcile
|
|
605
|
+
* transcript-poll to reclaim it.
|
|
606
|
+
*
|
|
607
|
+
* Scope & guards (must all hold to emit):
|
|
608
|
+
* • mesh worker session only — a normal standalone session's ordinary exit is
|
|
609
|
+
* never synthesized (isMeshWorkerSession()).
|
|
610
|
+
* • DOUBLE-EMIT guard — refuse if this turn's completion already fired
|
|
611
|
+
* (lastEmittedCompletion matches the current taskId). A worker that completed
|
|
612
|
+
* cleanly and is merely being cleaned up never double-emits.
|
|
613
|
+
* • evidence gate — reuse the same final-assistant/turn-scoped summary machinery
|
|
614
|
+
* as the normal completion path (completionFinalSummary over the native
|
|
615
|
+
* transcript). No in-turn assistant summary ⇒ no proof of completion ⇒ leave
|
|
616
|
+
* the reclaim path to handle a genuinely-unfinished worker.
|
|
617
|
+
*
|
|
618
|
+
* Returns true when a synthetic completion was emitted, false otherwise. Safe to
|
|
619
|
+
* call unconditionally from the cleanup path.
|
|
620
|
+
*/
|
|
621
|
+
flushMeshCompletionBeforeCleanup(): boolean;
|
|
622
|
+
/**
|
|
623
|
+
* KIMI-PURE-PTY-COMPLETION-EMIT (Fix 3): stall-path completion reconcile for the
|
|
624
|
+
* PURE-PTY transcript class (kimi and kin — no native transcript, no provider
|
|
625
|
+
* authority; see isPurePtyTranscriptProvider). Such a worker whose
|
|
626
|
+
* generating_completed never emitted (the onTurnStarted idle→idle collapse Fix 1
|
|
627
|
+
* fixes at the source) sits at a STATIC idle prompt: its PTY output stops the
|
|
628
|
+
* instant the answer is rendered, so the status-agnostic no-progress watchdog
|
|
629
|
+
* (checkMeshWorkerStall) reads the finished-but-quiet session as a stall and would
|
|
630
|
+
* false-fire monitor:no_progress. The native-transcript reconcile
|
|
631
|
+
* (sampleNativeTranscriptProgress) does NOT cover this class (no native source →
|
|
632
|
+
* null sample), so the stall path needs its own guard.
|
|
633
|
+
*
|
|
634
|
+
* Called from checkMeshWorkerStall just before the fire. Returns true when the
|
|
635
|
+
* session is a finished pure-PTY turn — idle, no pending response, and a PTY-parsed
|
|
636
|
+
* in-turn final assistant summary — in which case it emits the missing
|
|
637
|
+
* generating_completed (idempotent: a real/late emit writes the terminal ledger and
|
|
638
|
+
* the coordinator's reconcile makes any duplicate a no-op) and the caller SUPPRESSES
|
|
639
|
+
* the stall. Returns false for every other class/state (native-source provider, a
|
|
640
|
+
* genuinely mid-turn or wedged worker with no final assistant), so a real stall still
|
|
641
|
+
* fires unchanged.
|
|
642
|
+
*
|
|
643
|
+
* Evidence bar is identical to flushMeshCompletionBeforeCleanup: injected task's turn
|
|
644
|
+
* genuinely started + an in-turn final assistant summary. Conservative by
|
|
645
|
+
* construction — no summary ⇒ no proof of completion ⇒ return false and let the real
|
|
646
|
+
* stall fire.
|
|
647
|
+
*/
|
|
648
|
+
private tryReconcilePurePtyCompletionForStall;
|
|
577
649
|
/**
|
|
578
650
|
* AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
|
|
579
651
|
* persist before the in-progress settle gate is torn down. For a delegated
|
|
@@ -738,7 +810,11 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
738
810
|
getAdapter(): ProviderCliAdapter;
|
|
739
811
|
get cliType(): string;
|
|
740
812
|
get cliName(): string;
|
|
813
|
+
private resolveAutoApproveMode;
|
|
814
|
+
/** Legacy boolean view retained for internal/test compatibility. */
|
|
741
815
|
private shouldAutoApprove;
|
|
816
|
+
private shouldUsePtyAutoApprove;
|
|
817
|
+
private resetPtyAutoApproveState;
|
|
742
818
|
/** @see ProviderInstance.noteManualInteraction */
|
|
743
819
|
noteManualInteraction(now?: number, opts?: {
|
|
744
820
|
passive?: boolean;
|
|
@@ -389,6 +389,21 @@ export interface ProviderCompatibilityEntry {
|
|
|
389
389
|
ideVersion: string;
|
|
390
390
|
scriptDir: string;
|
|
391
391
|
}
|
|
392
|
+
export type AutoApproveModeStrategy = 'pty-parse-default' | 'launch-args' | 'post-boot-command';
|
|
393
|
+
export type AutoApproveModeRisk = 'safe' | 'caution' | 'dangerous';
|
|
394
|
+
export interface AutoApproveMode {
|
|
395
|
+
id: string;
|
|
396
|
+
label: string;
|
|
397
|
+
strategy: AutoApproveModeStrategy;
|
|
398
|
+
risk: AutoApproveModeRisk;
|
|
399
|
+
warning?: string;
|
|
400
|
+
launchArgs?: string[];
|
|
401
|
+
removeArgs?: string[];
|
|
402
|
+
}
|
|
403
|
+
export interface AutoApproveModesConfig {
|
|
404
|
+
default: string;
|
|
405
|
+
modes: AutoApproveMode[];
|
|
406
|
+
}
|
|
392
407
|
export interface ProviderModule {
|
|
393
408
|
/** Unique identifier (e.g. 'cline', 'cursor', 'gemini-cli') */
|
|
394
409
|
type: string;
|
|
@@ -418,6 +433,8 @@ export interface ProviderModule {
|
|
|
418
433
|
status?: string;
|
|
419
434
|
/** Inventory/support detail string maintained in adhdev-providers */
|
|
420
435
|
details?: string;
|
|
436
|
+
/** Provider-specific auto-approve choices and their launch/runtime strategy. */
|
|
437
|
+
autoApproveModes?: AutoApproveModesConfig;
|
|
421
438
|
/** Install instructions (shown when command is missing) */
|
|
422
439
|
install?: string;
|
|
423
440
|
/** Custom version detection command (e.g. 'cursor --version', 'claude -v') */
|
|
@@ -75,6 +75,20 @@ export interface DetectStatusTuiSpec {
|
|
|
75
75
|
declare function scopeText(input: CliStatusInput, scope: SpinnerSpec['scope'] | SettledPromptSpec['scope'], windowLines: number | undefined): string;
|
|
76
76
|
declare function spinnerMatches(spec: SpinnerSpec, input: CliStatusInput): boolean;
|
|
77
77
|
declare function settledPromptMatches(spec: SettledPromptSpec, input: CliStatusInput): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* APPROVAL-PICKER-MISROUTE (mission f1d25e11) defense-in-depth: an
|
|
80
|
+
* AskUserQuestion multi-choice picker is NOT an approval modal. Its option rows
|
|
81
|
+
* ("❯ 1. label") can otherwise satisfy the approval button cue and get
|
|
82
|
+
* mis-classified as `waiting_approval`, so the worker's question is surfaced to
|
|
83
|
+
* the coordinator as a task_approval_needed (→ mesh_approve, which cannot answer
|
|
84
|
+
* it). The picker carries a distinctive signature the approval FSM never does:
|
|
85
|
+
* the claude TUI select footer ("Enter to select … Esc to cancel") together with
|
|
86
|
+
* the freeform escape hatch ("Type something" / "Chat about this"). When both are
|
|
87
|
+
* present the screen is a question picker — surfaced separately as
|
|
88
|
+
* waiting_choice — so the approval matchers must yield. Mirrors the legacy
|
|
89
|
+
* looksLikeSelectionPicker guard (cli-provider-instance.ts) ported to SDK-v1.
|
|
90
|
+
*/
|
|
91
|
+
export declare function isAskUserQuestionPickerSignature(text: string): boolean;
|
|
78
92
|
declare function modalMatches(spec: ModalSpec, input: CliStatusInput): boolean;
|
|
79
93
|
export declare function buildDetectStatusFromTui(spec: DetectStatusTuiSpec): CliDetectStatusFn;
|
|
80
94
|
export declare const __internal: {
|
|
@@ -28,6 +28,24 @@ export interface InteractiveAnswer {
|
|
|
28
28
|
}
|
|
29
29
|
export declare function normalizeInteractivePrompt(raw: unknown): InteractivePrompt | null;
|
|
30
30
|
export declare function normalizeInteractivePromptResponse(raw: unknown): InteractivePromptResponse;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a coordinator-friendly answer form into the strict, questionId-keyed
|
|
33
|
+
* InteractivePromptResponse the TUI/answer machinery consumes (mission f1d25e11).
|
|
34
|
+
*
|
|
35
|
+
* mesh_answer_question lets the coordinator answer against the option LABELS or
|
|
36
|
+
* 1-based INDEXES it saw in the agent:waiting_choice event, without having to
|
|
37
|
+
* reconstruct the exact questionId → selectedLabels map. This resolves that
|
|
38
|
+
* ergonomic form against the AUTHORITATIVE active prompt (the daemon holds it),
|
|
39
|
+
* so index/label resolution and question ordering are correct by construction.
|
|
40
|
+
*
|
|
41
|
+
* Accepted `raw` shapes:
|
|
42
|
+
* - The strict form ({ promptId, answers: { [questionId]: { selectedLabels } } })
|
|
43
|
+
* — passed straight to normalizeInteractivePromptResponse (back-compat).
|
|
44
|
+
* - The friendly form ({ promptId, answers: [ { questionId?, select?, freeform? } ] })
|
|
45
|
+
* — entries map to questions by questionId, else by array position. `select`
|
|
46
|
+
* is a label (string) / 1-based index (number) / array of either.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveInteractivePromptResponse(prompt: InteractivePrompt, raw: unknown): InteractivePromptResponse;
|
|
31
49
|
export declare function buildClaudeInteractiveToolResult(response: InteractivePromptResponse): string;
|
|
32
50
|
export interface ClaudeInteractiveTuiPage {
|
|
33
51
|
screenText: string;
|
|
@@ -14,6 +14,8 @@ import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
|
14
14
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
15
15
|
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
16
16
|
import type { MagiKindPanelMap, DifficultyBrainMap, NodeCapabilitySlot } from '@adhdev/mesh-shared';
|
|
17
|
+
import type { ProviderModule } from './providers/contracts.js';
|
|
18
|
+
import type { RepoMeshDeclarativeConfig } from './config/mesh-json-config.js';
|
|
17
19
|
export interface RepoMesh {
|
|
18
20
|
id: string;
|
|
19
21
|
name: string;
|
|
@@ -255,6 +257,8 @@ export interface RepoMeshPolicy {
|
|
|
255
257
|
* A node policy may override this per-node (RepoMeshNodePolicy.delegatedWorkerAutoApprove).
|
|
256
258
|
*/
|
|
257
259
|
delegatedWorkerAutoApprove?: boolean;
|
|
260
|
+
/** Explicit opt-in required before delegated workers may use a dangerous provider mode. */
|
|
261
|
+
delegatedWorkerDangerousModeAllow?: boolean;
|
|
258
262
|
/**
|
|
259
263
|
* MESH-SEND-KEYS (feature 3): opt-in to allow the coordinator to inject
|
|
260
264
|
* DESTRUCTIVE keys (CTRL_C / ESC) into a worker PTY via mesh_send_keys. These
|
|
@@ -406,6 +410,8 @@ export interface RepoMeshNodePolicy {
|
|
|
406
410
|
* precedence over the mesh-level policy for worker sessions launched onto this node.
|
|
407
411
|
*/
|
|
408
412
|
delegatedWorkerAutoApprove?: boolean;
|
|
413
|
+
/** Per-node override for dangerous delegated worker mode authorization. */
|
|
414
|
+
delegatedWorkerDangerousModeAllow?: boolean;
|
|
409
415
|
/**
|
|
410
416
|
* MESH-SEND-KEYS (feature 3): per-node override for
|
|
411
417
|
* RepoMeshPolicy.allowSendKeysDestructive.
|
|
@@ -524,13 +530,39 @@ export declare function normalizeAutoFastForwardPolicy(value: unknown): NonNulla
|
|
|
524
530
|
*/
|
|
525
531
|
export declare function mergeAndNormalizePolicy(base: RepoMeshPolicy | undefined, patch: Partial<RepoMeshPolicy> | undefined): RepoMeshPolicy;
|
|
526
532
|
/**
|
|
527
|
-
* Resolve
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
533
|
+
* Resolve delegated worker auto-approve. Legacy providers return a boolean. Providers
|
|
534
|
+
* with modes return a mode id, except a dangerous mode is downgraded to a
|
|
535
|
+
* non-dangerous PTY mode unless mesh/node policy explicitly opts in.
|
|
536
|
+
*
|
|
537
|
+
* THREE EXPLICIT STAGES — do not collapse them; the ordering is a hard MAGI
|
|
538
|
+
* invariant:
|
|
539
|
+
*
|
|
540
|
+
* ① ENABLE gate (machine-local policy only): node boolean > mesh boolean.
|
|
541
|
+
* `enabled=false` returns `false` IMMEDIATELY, BEFORE any mode selection.
|
|
542
|
+
* The repo `mesh.json` providerDefaults has ZERO influence here — a
|
|
543
|
+
* node/mesh opt-out is never overridden by a repo-declared requested mode.
|
|
544
|
+
*
|
|
545
|
+
* ② MODE selection (only when enabled === true):
|
|
546
|
+
* task override [FUTURE — param reserved below, not yet wired] >
|
|
547
|
+
* repo mesh.json providerDefaults.autoApproveModes[providerType] >
|
|
548
|
+
* provider spec autoApproveModes.default.
|
|
549
|
+
* A repo-requested mode ID is adopted ONLY when it exists in the provider's
|
|
550
|
+
* own `autoApproveModes.modes`; an unknown/stale/typo'd ID is IGNORED and we
|
|
551
|
+
* fall back to the provider default (fail-closed: never coerce into a
|
|
552
|
+
* dangerous mode via a bad ID).
|
|
553
|
+
*
|
|
554
|
+
* ③ DANGEROUS gate: whichever mode stage ② picked, if it is dangerous and the
|
|
555
|
+
* machine-local delegatedWorkerDangerousModeAllow is not set, downgrade to a
|
|
556
|
+
* non-dangerous PTY-parse mode (or `false` if none exists).
|
|
532
557
|
*/
|
|
533
|
-
export declare function resolveDelegatedWorkerAutoApprove(meshPolicy?: Pick<RepoMeshPolicy, 'delegatedWorkerAutoApprove'> | null, nodePolicy?: Pick<RepoMeshNodePolicy, 'delegatedWorkerAutoApprove'> | null): boolean;
|
|
558
|
+
export declare function resolveDelegatedWorkerAutoApprove(meshPolicy?: Pick<RepoMeshPolicy, 'delegatedWorkerAutoApprove' | 'delegatedWorkerDangerousModeAllow'> | null, nodePolicy?: Pick<RepoMeshNodePolicy, 'delegatedWorkerAutoApprove' | 'delegatedWorkerDangerousModeAllow'> | null, provider?: Pick<ProviderModule, 'autoApproveModes'> | null, repoConfig?: RepoMeshDeclarativeConfig | null, providerType?: string | null): boolean | string;
|
|
559
|
+
export declare function resolveDelegatedWorkerDangerousModeAllow(meshPolicy?: Pick<RepoMeshPolicy, 'delegatedWorkerDangerousModeAllow'> | null, nodePolicy?: Pick<RepoMeshNodePolicy, 'delegatedWorkerDangerousModeAllow'> | null): boolean;
|
|
560
|
+
/** Shape a boolean-or-mode resolution for the settings precedence contract. */
|
|
561
|
+
export declare function delegatedWorkerAutoApproveSettings(meshPolicy?: Pick<RepoMeshPolicy, 'delegatedWorkerAutoApprove' | 'delegatedWorkerDangerousModeAllow'> | null, nodePolicy?: Pick<RepoMeshNodePolicy, 'delegatedWorkerAutoApprove' | 'delegatedWorkerDangerousModeAllow'> | null, provider?: Pick<ProviderModule, 'autoApproveModes'> | null, repoConfig?: RepoMeshDeclarativeConfig | null, providerType?: string | null): {
|
|
562
|
+
autoApprove: boolean | undefined;
|
|
563
|
+
autoApproveMode: string | undefined;
|
|
564
|
+
delegatedWorkerDangerousModeAllow: boolean;
|
|
565
|
+
};
|
|
534
566
|
/**
|
|
535
567
|
* MESH-SEND-KEYS (feature 3): resolve whether DESTRUCTIVE key injection
|
|
536
568
|
* (CTRL_C/ESC via mesh_send_keys) is permitted for a node. Node policy overrides
|
package/dist/shared-types.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type { ProviderState, ProviderStatus, ActiveChatData, IdeProviderState, C
|
|
|
13
13
|
export type { ProviderErrorReason } from './providers/provider-instance.js';
|
|
14
14
|
import type { ActiveChatData as _ActiveChatData, ProviderErrorReason as _ProviderErrorReason } from './providers/provider-instance.js';
|
|
15
15
|
import type { WorkspaceEntry } from './config/workspaces.js';
|
|
16
|
-
import type { ProviderMeshCoordinatorConfig, ProviderResumeCapability } from './providers/contracts.js';
|
|
16
|
+
import type { AutoApproveModesConfig, ProviderMeshCoordinatorConfig, ProviderResumeCapability } from './providers/contracts.js';
|
|
17
17
|
import type { GitCompactSummary, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams } from './git/git-types.js';
|
|
18
18
|
import type { InteractivePrompt } from './providers/types/interactive-prompt.js';
|
|
19
19
|
export type { GitCommandName, GitCompactSummary, GitDiffSummary, GitFailureReason, GitFileChange, GitFileChangeStatus, GitRepoIdentity, GitRepoStatus, GitSnapshot, GitSnapshotCompareSummary, GitSnapshotReason, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams, } from './git/git-types.js';
|
|
@@ -428,6 +428,8 @@ export interface AvailableProviderInfo {
|
|
|
428
428
|
lastVerification?: MachineProviderCheckResult;
|
|
429
429
|
/** Provider-declared Repo Mesh coordinator/MCP behavior. */
|
|
430
430
|
meshCoordinator?: ProviderMeshCoordinatorConfig;
|
|
431
|
+
/** Provider-declared auto-approve choices shown by session launch UIs. */
|
|
432
|
+
autoApproveModes?: AutoApproveModesConfig;
|
|
431
433
|
/** BRAIN-ROUTING: suggested model values for the new-session model dropdown. */
|
|
432
434
|
modelOptions?: string[];
|
|
433
435
|
/** BRAIN-ROUTING: reasoning-effort values for the new-session thinking dropdown. */
|
|
@@ -624,7 +626,7 @@ export interface DashboardBootstrapDaemonEntry extends Partial<CloudDaemonSummar
|
|
|
624
626
|
p2p?: StatusReportPayload['p2p'];
|
|
625
627
|
timestamp?: number;
|
|
626
628
|
}
|
|
627
|
-
export type DaemonStatusEventName = 'agent:generating_started' | 'agent:waiting_approval' | 'agent:generating_completed' | 'agent:stopped' | 'monitor:no_progress' | 'monitor:long_generating';
|
|
629
|
+
export type DaemonStatusEventName = 'agent:generating_started' | 'agent:waiting_approval' | 'agent:waiting_choice' | 'agent:generating_completed' | 'agent:stopped' | 'monitor:no_progress' | 'monitor:long_generating';
|
|
628
630
|
/** Minimal daemon-originated event payload relayed through the server. */
|
|
629
631
|
export interface DaemonStatusEventPayload {
|
|
630
632
|
event: DaemonStatusEventName;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
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",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"author": "vilmire",
|
|
48
48
|
"license": "AGPL-3.0-or-later",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@adhdev/mesh-shared": "
|
|
51
|
-
"@adhdev/session-host-core": "
|
|
50
|
+
"@adhdev/mesh-shared": "*",
|
|
51
|
+
"@adhdev/session-host-core": "*",
|
|
52
52
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
53
53
|
"ajv": "^8.20.0",
|
|
54
54
|
"ajv-formats": "^3.0.1",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
buildCliScreenSnapshot,
|
|
17
17
|
compactPromptText,
|
|
18
|
+
isPurePtyTranscriptProvider,
|
|
18
19
|
normalizePromptText,
|
|
19
20
|
promptLikelyVisible,
|
|
20
21
|
type CliChatMessage,
|
|
@@ -361,7 +362,22 @@ export class CliStateEngine {
|
|
|
361
362
|
// idle transition, unchanged. Scoped to transcriptAuthority:'provider'
|
|
362
363
|
// only, so PTY-authoritative providers (whose spinner/settled parsing
|
|
363
364
|
// already drives generating promptly) are unaffected.
|
|
364
|
-
|
|
365
|
+
//
|
|
366
|
+
// (fix: kimi pure-PTY completion-emit) The pure-PTY full-buffer class
|
|
367
|
+
// (kimi and kin — see isPurePtyTranscriptProvider) is NOT
|
|
368
|
+
// transcriptAuthority:'provider', so without this it stays idle when a
|
|
369
|
+
// prompt is submitted from idle: the FSM never crosses generating→idle,
|
|
370
|
+
// detectStatusTransition's generating|waiting_approval→idle arm never
|
|
371
|
+
// runs, and agent:generating_completed is never emitted — the mesh
|
|
372
|
+
// coordinator leaves the task 'assigned' and the status-agnostic stall
|
|
373
|
+
// watchdog then false-fires task_stalled on the finished-but-idle
|
|
374
|
+
// session. Promoting this class to generating on turn-start makes the
|
|
375
|
+
// existing PTY-parsed final-assistant idle gate produce a real
|
|
376
|
+
// generating→idle completion edge. Same idle safety as above: applyIdle
|
|
377
|
+
// / finishResponse still own the actual idle transition.
|
|
378
|
+
const promoteOnTurnStart = this.provider.transcriptAuthority === 'provider'
|
|
379
|
+
|| isPurePtyTranscriptProvider(this.provider);
|
|
380
|
+
if (promoteOnTurnStart && this.currentStatus !== 'waiting_approval') {
|
|
365
381
|
this.setStatus('generating', 'turn_started');
|
|
366
382
|
this.callbacks.onStatusChange();
|
|
367
383
|
}
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
compactPromptText,
|
|
40
40
|
estimatePromptDisplayLines,
|
|
41
41
|
extractPromptRetrySnippet,
|
|
42
|
+
isPurePtyTranscriptProvider,
|
|
42
43
|
listCliScriptNames,
|
|
43
44
|
normalizePromptText,
|
|
44
45
|
normalizeScreenSnapshot,
|
|
@@ -456,12 +457,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
456
457
|
* provider-owned) so no other provider's turn-scoped parse changes.
|
|
457
458
|
*/
|
|
458
459
|
private parsesFullPtyTranscriptFromBuffer(): boolean {
|
|
459
|
-
|
|
460
|
-
// nativeHistory is a top-level provider field not surfaced on
|
|
461
|
-
// CliProviderModule; read it via the same structural cast used for `tui`.
|
|
462
|
-
if ((this.provider as { nativeHistory?: unknown }).nativeHistory) return false;
|
|
463
|
-
const transcriptPty = (this.provider.tui as { transcriptPty?: { scope?: unknown } } | undefined)?.transcriptPty;
|
|
464
|
-
return transcriptPty?.scope === 'buffer';
|
|
460
|
+
return isPurePtyTranscriptProvider(this.provider);
|
|
465
461
|
}
|
|
466
462
|
|
|
467
463
|
/**
|