@adhdev/daemon-core 0.9.82-rc.29 → 0.9.82-rc.290

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.
Files changed (281) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +8 -0
  2. package/dist/boot/process-hardening.d.ts +50 -0
  3. package/dist/build-info.d.ts +37 -0
  4. package/dist/chat/source-machine.d.ts +166 -0
  5. package/dist/chat/source-resolver.d.ts +104 -0
  6. package/dist/chat/subscription-updates.d.ts +1 -0
  7. package/dist/cli-adapter-types.d.ts +23 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +198 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +106 -63
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +4 -0
  12. package/dist/cli-adapters/provider-cli-shared.d.ts +38 -0
  13. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  14. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  15. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  16. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  17. package/dist/commands/cli-manager.d.ts +2 -1
  18. package/dist/commands/handler.d.ts +110 -0
  19. package/dist/commands/mesh-coordinator.d.ts +85 -1
  20. package/dist/commands/router.d.ts +160 -1
  21. package/dist/config/chat-history.d.ts +9 -0
  22. package/dist/config/config.d.ts +5 -0
  23. package/dist/config/mesh-config.d.ts +72 -1
  24. package/dist/git/git-commands.d.ts +9 -1
  25. package/dist/git/git-diff.d.ts +6 -0
  26. package/dist/git/git-status.d.ts +7 -0
  27. package/dist/git/git-types.d.ts +2 -50
  28. package/dist/index.d.ts +51 -12
  29. package/dist/index.js +34510 -12948
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +38172 -16711
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/installer.d.ts +1 -4
  34. package/dist/ipc/local-ipc-server.d.ts +91 -0
  35. package/dist/launch.d.ts +1 -1
  36. package/dist/logging/async-batch-writer.d.ts +10 -0
  37. package/dist/mesh/contracts.d.ts +164 -0
  38. package/dist/mesh/coordinator-prompt.d.ts +36 -0
  39. package/dist/mesh/coordinator-registry.d.ts +59 -0
  40. package/dist/mesh/mesh-active-work.d.ts +108 -0
  41. package/dist/mesh/mesh-delivery-policy.d.ts +131 -0
  42. package/dist/mesh/mesh-events-coordinator.d.ts +133 -0
  43. package/dist/mesh/mesh-events-pending.d.ts +45 -0
  44. package/dist/mesh/mesh-events-stale.d.ts +40 -0
  45. package/dist/mesh/mesh-events-utils.d.ts +47 -0
  46. package/dist/mesh/mesh-events.d.ts +6 -49
  47. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  48. package/dist/mesh/mesh-host-ownership.d.ts +9 -0
  49. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -3
  50. package/dist/mesh/mesh-ledger.d.ts +77 -1
  51. package/dist/mesh/mesh-missions.d.ts +68 -0
  52. package/dist/mesh/mesh-reconcile-loop.d.ts +7 -0
  53. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  54. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  55. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  56. package/dist/mesh/mesh-routing.d.ts +70 -0
  57. package/dist/mesh/mesh-runtime-store.d.ts +345 -0
  58. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  59. package/dist/mesh/mesh-work-queue.d.ts +166 -5
  60. package/dist/mesh/preview-freshness.d.ts +18 -0
  61. package/dist/mesh/refine-config.d.ts +215 -0
  62. package/dist/mesh/worktree-bootstrap-config.d.ts +135 -0
  63. package/dist/providers/acp-provider-instance.d.ts +2 -0
  64. package/dist/providers/approval-utils.d.ts +13 -0
  65. package/dist/providers/cli-provider-instance.d.ts +61 -3
  66. package/dist/providers/contracts.d.ts +130 -6
  67. package/dist/providers/external-sources.d.ts +71 -0
  68. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +100 -0
  69. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  70. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  71. package/dist/providers/native-history/dispatcher.d.ts +27 -0
  72. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  73. package/dist/providers/native-history/index.d.ts +13 -0
  74. package/dist/providers/provider-instance-manager.d.ts +13 -0
  75. package/dist/providers/provider-instance.d.ts +13 -1
  76. package/dist/providers/provider-loader.d.ts +26 -4
  77. package/dist/providers/provider-trust.d.ts +31 -0
  78. package/dist/providers/read-chat-contract.d.ts +29 -0
  79. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  80. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +85 -0
  81. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  82. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  83. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  84. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  85. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  86. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  87. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  88. package/dist/providers/sdk/v1/index.d.ts +30 -0
  89. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  90. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  91. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  92. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  93. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  94. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  95. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  96. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  97. package/dist/providers/spec/adapter.d.ts +59 -0
  98. package/dist/providers/spec/cli-adapter.d.ts +140 -0
  99. package/dist/providers/spec/evaluator.d.ts +23 -0
  100. package/dist/providers/spec/fsm-driver.d.ts +278 -0
  101. package/dist/providers/spec/fsm-evaluator.d.ts +72 -0
  102. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  103. package/dist/providers/spec/fsm-types.d.ts +128 -0
  104. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  105. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  106. package/dist/providers/spec/route.d.ts +4 -0
  107. package/dist/providers/spec/types.d.ts +144 -0
  108. package/dist/providers/transcript-v2.d.ts +176 -0
  109. package/dist/providers/types/interactive-prompt.d.ts +48 -0
  110. package/dist/repo-mesh-types.d.ts +148 -13
  111. package/dist/sessions/registry.d.ts +6 -0
  112. package/dist/shared-types-extra.d.ts +2 -4
  113. package/dist/shared-types.d.ts +42 -1
  114. package/dist/status/normalize.d.ts +1 -1
  115. package/dist/status/normalize.js +1 -0
  116. package/dist/status/normalize.js.map +1 -1
  117. package/dist/status/normalize.mjs +1 -0
  118. package/dist/status/normalize.mjs.map +1 -1
  119. package/dist/status/reporter.d.ts +2 -0
  120. package/dist/status/snapshot.d.ts +1 -0
  121. package/dist/types.d.ts +5 -0
  122. package/package.json +7 -3
  123. package/src/agent-stream/poller.ts +2 -3
  124. package/src/boot/daemon-lifecycle.ts +55 -12
  125. package/src/boot/process-hardening.ts +89 -0
  126. package/src/build-info.ts +73 -0
  127. package/src/chat/source-machine.ts +534 -0
  128. package/src/chat/source-resolver.ts +0 -0
  129. package/src/chat/subscription-updates.ts +20 -1
  130. package/src/cli-adapter-types.d.ts +1 -0
  131. package/src/cli-adapter-types.ts +22 -2
  132. package/src/cli-adapters/cli-script-runner.ts +421 -0
  133. package/src/cli-adapters/cli-state-engine.ts +1215 -0
  134. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  135. package/src/cli-adapters/provider-cli-adapter.ts +674 -1139
  136. package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
  137. package/src/cli-adapters/provider-cli-parse.ts +13 -0
  138. package/src/cli-adapters/provider-cli-runtime.ts +3 -1
  139. package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
  140. package/src/cli-adapters/provider-cli-shared.ts +68 -11
  141. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  142. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +53 -29
  143. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  144. package/src/cli-adapters/terminal-screen.ts +16 -81
  145. package/src/commands/chat-commands.ts +1813 -60
  146. package/src/commands/cli-manager.ts +286 -14
  147. package/src/commands/handler.ts +809 -2
  148. package/src/commands/mesh-coordinator.ts +332 -122
  149. package/src/commands/router.ts +5721 -546
  150. package/src/config/chat-history.ts +229 -24
  151. package/src/config/config.ts +12 -0
  152. package/src/config/mesh-config.ts +303 -3
  153. package/src/config/recent-activity.ts +8 -2
  154. package/src/daemon/dev-auto-implement.ts +3 -2
  155. package/src/daemon/dev-cli-debug.ts +10 -1
  156. package/src/detection/ide-detector.ts +26 -16
  157. package/src/git/git-commands.ts +42 -12
  158. package/src/git/git-diff.ts +53 -0
  159. package/src/git/git-status.ts +198 -7
  160. package/src/git/git-types.ts +14 -62
  161. package/src/git/git-worktree.ts +8 -1
  162. package/src/index.ts +131 -11
  163. package/src/installer.d.ts +1 -1
  164. package/src/installer.ts +8 -6
  165. package/src/ipc/local-ipc-server.ts +278 -0
  166. package/src/launch.d.ts +1 -1
  167. package/src/launch.ts +37 -28
  168. package/src/logging/async-batch-writer.ts +55 -0
  169. package/src/logging/logger.ts +2 -1
  170. package/src/mesh/contracts.ts +329 -0
  171. package/src/mesh/coordinator-prompt.ts +219 -31
  172. package/src/mesh/coordinator-registry.ts +121 -0
  173. package/src/mesh/mesh-active-work.ts +468 -0
  174. package/src/mesh/mesh-delivery-policy.ts +315 -0
  175. package/src/mesh/mesh-events-coordinator.ts +1679 -0
  176. package/src/mesh/mesh-events-pending.ts +508 -0
  177. package/src/mesh/mesh-events-stale.ts +283 -0
  178. package/src/mesh/mesh-events-utils.ts +254 -0
  179. package/src/mesh/mesh-events.ts +30 -1035
  180. package/src/mesh/mesh-fast-forward.ts +839 -0
  181. package/src/mesh/mesh-host-ownership.ts +73 -0
  182. package/src/mesh/mesh-ledger-reconciliation.ts +12 -5
  183. package/src/mesh/mesh-ledger.ts +589 -102
  184. package/src/mesh/mesh-missions.ts +172 -0
  185. package/src/mesh/mesh-reconcile-loop.ts +411 -0
  186. package/src/mesh/mesh-refine-batch.ts +197 -0
  187. package/src/mesh/mesh-refine-status.ts +231 -0
  188. package/src/mesh/mesh-review-inbox.ts +307 -0
  189. package/src/mesh/mesh-routing.ts +275 -0
  190. package/src/mesh/mesh-runtime-store.ts +1399 -0
  191. package/src/mesh/mesh-task-stats.ts +154 -0
  192. package/src/mesh/mesh-work-queue.ts +586 -145
  193. package/src/mesh/preview-freshness.ts +118 -0
  194. package/src/mesh/refine-config.ts +403 -0
  195. package/src/mesh/worktree-bootstrap-config.ts +326 -0
  196. package/src/providers/acp-provider-instance.ts +15 -1
  197. package/src/providers/approval-utils.d.ts +4 -0
  198. package/src/providers/approval-utils.ts +47 -5
  199. package/src/providers/chat-message-normalization.ts +4 -11
  200. package/src/providers/cli-provider-instance.ts +920 -81
  201. package/src/providers/contracts.d.ts +55 -0
  202. package/src/providers/contracts.ts +141 -6
  203. package/src/providers/external-sources.ts +218 -0
  204. package/src/providers/ide-provider-instance.ts +19 -5
  205. package/src/providers/native-history/antigravity-cli-transcript.ts +643 -0
  206. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  207. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  208. package/src/providers/native-history/dispatcher.ts +340 -0
  209. package/src/providers/native-history/hermes-cli-transcript.ts +230 -0
  210. package/src/providers/native-history/index.ts +30 -0
  211. package/src/providers/provider-instance-manager.ts +30 -0
  212. package/src/providers/provider-instance.ts +10 -1
  213. package/src/providers/provider-loader.ts +584 -50
  214. package/src/providers/provider-schema.ts +87 -14
  215. package/src/providers/provider-trust.ts +114 -0
  216. package/src/providers/read-chat-contract.ts +76 -16
  217. package/src/providers/sdk/README.md +49 -0
  218. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  219. package/src/providers/sdk/v1/builders/cli/detect-status.ts +262 -0
  220. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  221. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +250 -0
  222. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  223. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  224. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  225. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  226. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  227. package/src/providers/sdk/v1/index.ts +152 -0
  228. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  229. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  230. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  231. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +504 -0
  232. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  233. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  234. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  235. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  236. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  237. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  238. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  239. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  240. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  241. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  242. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  243. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  244. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  245. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  246. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  247. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  248. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  249. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  250. package/src/providers/sdk/v1/validators/index.ts +19 -0
  251. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  252. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  253. package/src/providers/spec/adapter.ts +155 -0
  254. package/src/providers/spec/cli-adapter.ts +730 -0
  255. package/src/providers/spec/evaluator.ts +345 -0
  256. package/src/providers/spec/fsm-driver.ts +875 -0
  257. package/src/providers/spec/fsm-evaluator.ts +255 -0
  258. package/src/providers/spec/fsm-loader.ts +112 -0
  259. package/src/providers/spec/fsm-types.ts +222 -0
  260. package/src/providers/spec/native-history-executor.ts +943 -0
  261. package/src/providers/spec/pre-launch-trust.ts +104 -0
  262. package/src/providers/spec/route.ts +51 -0
  263. package/src/providers/spec/types.ts +189 -0
  264. package/src/providers/transcript-v2.ts +567 -0
  265. package/src/providers/types/interactive-prompt.ts +488 -0
  266. package/src/providers/version-archive.ts +38 -20
  267. package/src/repo-mesh-types.ts +177 -13
  268. package/src/sessions/registry.ts +6 -0
  269. package/src/shared-types-extra.ts +2 -4
  270. package/src/shared-types.ts +45 -1
  271. package/src/status/builders.ts +26 -6
  272. package/src/status/normalize.ts +2 -0
  273. package/src/status/reporter.ts +15 -0
  274. package/src/status/snapshot.ts +84 -25
  275. package/src/system/host-memory.ts +29 -12
  276. package/src/types.ts +5 -0
  277. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  278. package/dist/mesh/mesh-sync.d.ts +0 -53
  279. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  280. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  281. package/src/mesh/mesh-sync.ts +0 -111
@@ -11,6 +11,7 @@
11
11
  * IMPORTANT: This file must remain runtime-free (types only).
12
12
  */
13
13
  import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
14
+ import type { MeshMissionSummary } from './mesh/mesh-missions.js';
14
15
  export interface RepoMesh {
15
16
  id: string;
16
17
  name: string;
@@ -19,10 +20,37 @@ export interface RepoMesh {
19
20
  defaultBranch?: string;
20
21
  policy: RepoMeshPolicy;
21
22
  coordinator: RepoMeshCoordinatorConfig;
23
+ meshHost?: RepoMeshHostMetadata;
22
24
  projectContext: ProjectContextSnapshot;
23
25
  nodes: RepoMeshNode[];
24
26
  status: 'active' | 'archived' | 'deleted';
25
27
  }
28
+ export type RepoMeshDaemonRole = 'host' | 'member';
29
+ export interface RepoMeshHostPairingMetadata {
30
+ status: 'not_configured' | 'pairing' | 'paired' | 'rejected' | 'revoked';
31
+ tokenId?: string;
32
+ joinedAt?: string;
33
+ lastPairedAt?: string;
34
+ lastRejectedAt?: string;
35
+ expiresAt?: string;
36
+ }
37
+ export interface RepoMeshHostMetadata {
38
+ /** Local daemon role for this mesh. Missing metadata defaults to host for standalone compatibility. */
39
+ role: RepoMeshDaemonRole;
40
+ /** Daemon that owns mesh truth/status/git/queue/session/ledger/coordinator ownership. */
41
+ hostDaemonId?: string;
42
+ /** Mesh node that represents the host daemon, when known. */
43
+ hostNodeId?: string;
44
+ /** Future standalone manual pairing endpoint entered by member daemons. */
45
+ hostAddress?: string;
46
+ /** Redacted pairing state only; raw join tokens must not be persisted here. */
47
+ pairing?: RepoMeshHostPairingMetadata;
48
+ }
49
+ export interface RepoMeshHostStatus extends RepoMeshHostMetadata {
50
+ canOwnCoordinator: boolean;
51
+ canOwnQueue: boolean;
52
+ defaulted: boolean;
53
+ }
26
54
  export interface RepoMeshNode {
27
55
  id: string;
28
56
  daemonId: string;
@@ -37,15 +65,31 @@ export interface RepoMeshNode {
37
65
  effectiveCapabilities: RepoMeshNodeCapabilities;
38
66
  policy: RepoMeshNodePolicy;
39
67
  health: RepoMeshNodeHealth;
68
+ role?: RepoMeshDaemonRole;
40
69
  status: 'enabled' | 'disabled' | 'removed';
41
70
  }
42
71
  export type RepoMeshNodeHealth = 'online' | 'offline' | 'degraded' | 'dirty' | 'wrong_branch' | 'unknown';
43
72
  export type RepoMeshSessionCleanupMode = 'preserve' | 'stop' | 'delete_stopped' | 'stop_and_delete';
44
73
  export type RepoMeshSpawnedSessionVisibility = 'visible' | 'hidden';
74
+ export interface RepoMeshAutoFastForwardPolicy {
75
+ /** Defaults to true. Set false to disable daemon-initiated idle fast-forwards. */
76
+ enabled: boolean;
77
+ /** Maximum behind count eligible for automatic fast-forward. Missing means no limit. */
78
+ maxBehind?: number;
79
+ /** Defaults to true. Require submodule status to be clean before automatic fast-forward. */
80
+ requireCleanSubmodules?: boolean;
81
+ }
45
82
  export interface RepoMeshPolicy {
46
83
  requirePreTaskCheckpoint: boolean;
47
84
  requirePostTaskCheckpoint: boolean;
48
85
  requireApprovalForPush: boolean;
86
+ /**
87
+ * Narrow Refinery opt-in: when validation and patch-equivalence have passed,
88
+ * allow Refinery to publish submodule gitlink commits to each submodule's
89
+ * configured remote main branch with a non-force push, then verify reachability.
90
+ * Defaults to false; root branch pushes/merges are not affected.
91
+ */
92
+ allowAutoPublishSubmoduleMainCommits?: boolean;
49
93
  requireApprovalForDestructiveGit: boolean;
50
94
  dirtyWorkspaceBehavior: 'block' | 'warn' | 'checkpoint_then_continue';
51
95
  maxParallelTasks: number;
@@ -56,12 +100,28 @@ export interface RepoMeshPolicy {
56
100
  * watch-the-agents behavior; hidden sessions remain discoverable and manually openable.
57
101
  */
58
102
  spawnedSessionVisibility?: RepoMeshSpawnedSessionVisibility;
103
+ /**
104
+ * Whether worker sessions the coordinator dispatches should auto-approve agent
105
+ * approval modals (tool/command prompts) without firing a user-facing approval
106
+ * notification. Delegated workers are coordinator-driven, so a human should not
107
+ * have to approve each one; defaults to true. Set to false to make delegated
108
+ * worker sessions stop at approval modals like an interactive session.
109
+ * Stamped into the worker launch settings envelope as `autoApprove`, which wins
110
+ * over the global per-provider-type autoApprove config via the settings merge.
111
+ * A node policy may override this per-node (RepoMeshNodePolicy.delegatedWorkerAutoApprove).
112
+ */
113
+ delegatedWorkerAutoApprove?: boolean;
59
114
  /**
60
115
  * What to do with delegated session-host records for a node when it is removed.
61
116
  * Defaults to 'preserve' so completed work can be reviewed later and live
62
117
  * runtimes are never stopped/deleted unless the mesh owner opts in.
63
118
  */
64
119
  sessionCleanupOnNodeRemove?: RepoMeshSessionCleanupMode;
120
+ /**
121
+ * Daemon-initiated fast-forward for idle clean nodes that are only behind
122
+ * their tracked upstream. Defaults to enabled.
123
+ */
124
+ autoFastForward?: RepoMeshAutoFastForwardPolicy;
65
125
  /**
66
126
  * Maximum number of automatic retry recommendations for a failed task on the
67
127
  * same node before the daemon advises the coordinator to escalate or reassign.
@@ -81,6 +141,11 @@ export interface RepoMeshNodePolicy {
81
141
  maxConcurrentSessions?: number;
82
142
  /** Ordered provider preference used when mesh_launch_session omits an explicit type. */
83
143
  providerPriority?: string[];
144
+ /**
145
+ * Per-node override for RepoMeshPolicy.delegatedWorkerAutoApprove. When set, takes
146
+ * precedence over the mesh-level policy for worker sessions launched onto this node.
147
+ */
148
+ delegatedWorkerAutoApprove?: boolean;
84
149
  /**
85
150
  * Optional associated/external repos that must be checked alongside this node.
86
151
  * These are explicit policy/config entries only; Repo Mesh does not auto-discover
@@ -104,6 +169,14 @@ export interface RepoMeshNodePolicy {
104
169
  initSubmodulesOnClone?: boolean;
105
170
  }
106
171
  export declare const DEFAULT_MESH_POLICY: RepoMeshPolicy;
172
+ /**
173
+ * Resolve whether a delegated worker session launched onto `nodePolicy` (within a mesh
174
+ * governed by `meshPolicy`) should auto-approve. Precedence: node override → mesh policy
175
+ * → default true. The result is stamped into the worker launch settings envelope as
176
+ * `autoApprove`; it wins over the global per-provider-type autoApprove config because the
177
+ * launch path merges the envelope as a settingsOverride on top of the provider defaults.
178
+ */
179
+ export declare function resolveDelegatedWorkerAutoApprove(meshPolicy?: Pick<RepoMeshPolicy, 'delegatedWorkerAutoApprove'> | null, nodePolicy?: Pick<RepoMeshNodePolicy, 'delegatedWorkerAutoApprove'> | null): boolean;
107
180
  export interface RepoMeshNodeCapabilities {
108
181
  platform?: string;
109
182
  packageManagers?: string[];
@@ -167,7 +240,28 @@ export interface RepoMeshCoordinatorConfig {
167
240
  providerType?: string;
168
241
  /** Preferred node to run coordinator on (null = auto) */
169
242
  preferredNodeId?: string;
170
- /** Additional system prompt context for coordinator */
243
+ /**
244
+ * Full mesh-level override for the coordinator system prompt. When set,
245
+ * replaces the daemon's rendered default and any user-file override
246
+ * (~/.adhdev/coordinator-prompts/<cli>.md). The per-launch
247
+ * extraSystemPrompt still composes on top — it always lands last as
248
+ * Additional Context. Supports the same {{placeholders}} the daemon's
249
+ * default template uses ({{meshName}}, {{repo}}, {{nodes}}, …).
250
+ */
251
+ systemPromptOverride?: string;
252
+ /**
253
+ * Mesh-level append. Composes after whichever base prompt won
254
+ * (override → user-file override → daemon default). Use this when you
255
+ * want extra rules for THIS mesh but otherwise the standard prompt is
256
+ * fine. Stacks with the user-file append (`<cli>.append.md`) — both
257
+ * apply if both are set.
258
+ */
259
+ systemPromptAppend?: string;
260
+ /**
261
+ * @deprecated Use systemPromptAppend. Kept as a fallback alias so
262
+ * existing meshes.json files keep working without a migration step;
263
+ * the daemon prefers systemPromptAppend when both are present.
264
+ */
171
265
  systemPromptSuffix?: string;
172
266
  }
173
267
  /**
@@ -185,6 +279,7 @@ export interface LocalMeshEntry {
185
279
  defaultBranch?: string;
186
280
  policy: RepoMeshPolicy;
187
281
  coordinator: RepoMeshCoordinatorConfig;
282
+ meshHost?: RepoMeshHostMetadata;
188
283
  nodes: LocalMeshNodeEntry[];
189
284
  createdAt: string;
190
285
  updatedAt: string;
@@ -196,16 +291,42 @@ export interface LocalMeshNodeEntry {
196
291
  daemonId?: string;
197
292
  /** Machine registry ID that owns this workspace, when known. */
198
293
  machineId?: string;
294
+ /** Operator-defined capability tags used by mesh queue matching. */
295
+ capabilities?: string[];
199
296
  userOverrides: Partial<RepoMeshNodeCapabilities>;
200
297
  policy: RepoMeshNodePolicy;
298
+ /**
299
+ * Per-node instruction surfaced in the coordinator prompt so the LLM
300
+ * knows what each node is for (e.g. "this is the staging mirror — run
301
+ * only smoke tests here", or "use opus on this node, sonnet elsewhere").
302
+ * Empty/missing: omitted silently from the rendered prompt, no rule
303
+ * line about it gets added. The coordinator forwards/honors it when
304
+ * delegating; we don't enforce it at the daemon level.
305
+ */
306
+ systemPrompt?: string;
201
307
  /** For single-machine mesh: same daemon, different worktree */
202
308
  isLocalWorktree?: boolean;
203
309
  /** Branch this worktree tracks (set when created via clone_mesh_node) */
204
310
  worktreeBranch?: string;
205
311
  /** Node ID this worktree was cloned from */
206
312
  clonedFromNodeId?: string;
313
+ /** Repo-local preparation result for ADHDev-created worktree nodes. */
314
+ worktreeBootstrap?: {
315
+ status: 'ready' | 'running' | 'failed' | 'not_configured' | 'disabled' | 'stale';
316
+ required?: boolean;
317
+ configSource?: string;
318
+ configSourceType?: string;
319
+ startedAt?: string;
320
+ completedAt?: string;
321
+ lastCommand?: string;
322
+ exitCode?: number | null;
323
+ error?: string;
324
+ commandsRun?: Array<Record<string, unknown>>;
325
+ staleInputs?: string[];
326
+ };
207
327
  /** Optional associated/external repos configured as node metadata. */
208
328
  relatedRepos?: RepoMeshRelatedRepo[];
329
+ role?: RepoMeshDaemonRole;
209
330
  }
210
331
  export interface RepoMeshStatus {
211
332
  meshId: string;
@@ -213,22 +334,20 @@ export interface RepoMeshStatus {
213
334
  repoIdentity: string;
214
335
  defaultBranch?: string;
215
336
  refreshedAt: string;
337
+ meshHost?: RepoMeshHostStatus;
216
338
  nodes: RepoMeshNodeStatus[];
217
339
  queue?: RepoMeshQueueStatus;
218
340
  ledger?: RepoMeshLedgerStatus;
341
+ /**
342
+ * Mission summaries for the dashboard overview. Active/paused missions plus a
343
+ * capped, newest-first slice of completed/abandoned history. Omitted by older
344
+ * daemons — the dashboard must treat this as optional and render an empty
345
+ * state when absent. Split on each entry's `status` for live vs. history.
346
+ */
347
+ missions?: MeshMissionSummary[];
219
348
  }
220
- export interface RepoMeshSessionStatus {
221
- sessionId: string;
222
- providerType?: string;
223
- state?: string;
224
- lifecycle?: 'starting' | 'running' | 'stopping' | 'stopped' | 'failed' | 'interrupted';
225
- surfaceKind?: 'live_runtime' | 'recovery_snapshot' | 'inactive_record';
226
- recoveryState?: string | null;
227
- workspace?: string | null;
228
- title?: string | null;
229
- lastActivityAt?: string | null;
230
- isCached?: boolean;
231
- }
349
+ export type { RepoMeshSessionStatus } from '@adhdev/mesh-shared';
350
+ import type { RepoMeshSessionStatus } from '@adhdev/mesh-shared';
232
351
  export type RepoMeshPeerConnectionState = 'self' | 'connected' | 'connecting' | 'disconnected' | 'failed' | 'closed' | 'unknown';
233
352
  export type RepoMeshPeerConnectionTransport = 'local' | 'direct' | 'relay' | 'unknown';
234
353
  export interface RepoMeshPeerConnectionStatus {
@@ -249,9 +368,12 @@ export interface RepoMeshNodeStatus {
249
368
  repoRoot?: string;
250
369
  daemonId?: string;
251
370
  machineId?: string;
371
+ role?: RepoMeshDaemonRole;
252
372
  machineStatus?: string;
253
373
  isLocalWorktree?: boolean;
254
374
  worktreeBranch?: string;
375
+ /** Mirrored from LocalMeshNodeEntry.systemPrompt for coordinator-prompt rendering. */
376
+ systemPrompt?: string;
255
377
  health: RepoMeshNodeHealth;
256
378
  git?: GitRepoStatus;
257
379
  /**
@@ -265,6 +387,14 @@ export interface RepoMeshNodeStatus {
265
387
  activeSessionDetails?: RepoMeshSessionStatus[];
266
388
  providerPriority?: string[];
267
389
  launchReady?: boolean;
390
+ /** True when the node is clean, ahead=0, behind>0, and safe for fast-forward consideration. */
391
+ autoFastForwardEligible?: boolean;
392
+ /** Coordinator-facing suggestion for obvious clean catch-up work. */
393
+ suggestedAction?: 'auto_fast_forward';
394
+ worktreeBootstrap?: LocalMeshNodeEntry['worktreeBootstrap'];
395
+ launchBlockedReason?: string;
396
+ launchBlockedMessage?: string;
397
+ recoveryHint?: string;
268
398
  lastSeenAt?: string;
269
399
  updatedAt?: string;
270
400
  connection?: RepoMeshPeerConnectionStatus;
@@ -352,3 +482,8 @@ export interface RepoMeshLedgerStatus {
352
482
  entries: RepoMeshLedgerEntryStatus[];
353
483
  summary: RepoMeshLedgerSummaryStatus;
354
484
  }
485
+ export interface MeshAsyncJobLifecycle {
486
+ startedAt?: string;
487
+ completedAt?: string;
488
+ error?: string;
489
+ }
@@ -7,6 +7,12 @@ export interface SessionRuntimeTarget {
7
7
  cdpManagerKey?: string;
8
8
  adapterKey?: string;
9
9
  instanceKey?: string;
10
+ /** Working directory for CLI/ACP sessions. Used by read_chat to resolve
11
+ * native history when there is no live adapter (e.g. subscription path). */
12
+ workspace?: string;
13
+ /** Wall clock at register time. native-history readers use it as a
14
+ * cutoff so a fresh session can't show records from a prior one. */
15
+ spawnedAtMs?: number;
10
16
  }
11
17
  export declare class SessionRegistry {
12
18
  private readonly bySessionId;
@@ -18,12 +18,10 @@ export interface RuntimeAttachedClient {
18
18
  readOnly: boolean;
19
19
  }
20
20
  /** Session status union (used by SessionEntry.status, legacy recent-launch metadata, etc.) */
21
- export type SessionStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
21
+ export type SessionStatus = 'idle' | 'generating' | 'waiting_approval' | 'waiting_choice' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
22
22
  /** Inbox bucket categories for recent sessions */
23
23
  export type RecentSessionBucket = 'needs_attention' | 'working' | 'task_complete' | 'idle';
24
24
  /** Terminal backend status */
25
25
  export interface TerminalBackendStatus {
26
- backend: 'xterm' | 'ghostty-vt';
27
- preference: 'auto' | 'xterm' | 'ghostty-vt';
28
- ghosttyAvailable: boolean;
26
+ backend: 'ghostty-vt';
29
27
  }
@@ -14,6 +14,7 @@ import type { ActiveChatData as _ActiveChatData, ProviderErrorReason as _Provide
14
14
  import type { WorkspaceEntry } from './config/workspaces.js';
15
15
  import type { ProviderMeshCoordinatorConfig, ProviderResumeCapability } from './providers/contracts.js';
16
16
  import type { GitCompactSummary, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams } from './git/git-types.js';
17
+ import type { InteractivePrompt } from './providers/types/interactive-prompt.js';
17
18
  export type { GitCommandName, GitCompactSummary, GitDiffSummary, GitFailureReason, GitFileChange, GitFileChangeStatus, GitRepoIdentity, GitRepoStatus, GitSnapshot, GitSnapshotCompareSummary, GitSnapshotReason, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams, } from './git/git-types.js';
18
19
  export interface SessionActiveChatData extends Omit<_ActiveChatData, 'messages'> {
19
20
  messages?: _ActiveChatData['messages'];
@@ -49,6 +50,14 @@ export interface ReadChatSyncResult {
49
50
  message: string;
50
51
  buttons: string[];
51
52
  } | null;
53
+ activeInteractivePrompt?: InteractivePrompt | null;
54
+ /**
55
+ * Chat source provenance from ChatSourceMachine (A2). Carries the
56
+ * selected source, transition cause, lock state, and legacy
57
+ * fallbackReason — opaque to the daemon-core, consumed by web-core
58
+ * for the source debug badge and SourceTimeline (A3).
59
+ */
60
+ messageSource?: Record<string, unknown>;
52
61
  }
53
62
  export interface ProviderSummaryItem {
54
63
  id: string;
@@ -268,6 +277,7 @@ export interface SessionEntry {
268
277
  runtimeRecoveryState?: string | null;
269
278
  resume?: ProviderResumeCapability;
270
279
  activeChat: SessionActiveChatData | null;
280
+ activeInteractivePrompt?: InteractivePrompt | null;
271
281
  capabilities?: SessionCapability[];
272
282
  /** Effective message input/media support for this session. Defaults fail-closed to text-only. */
273
283
  messageInput?: MessageInputSupport;
@@ -292,6 +302,11 @@ export interface SessionEntry {
292
302
  seenCompletionMarker?: string;
293
303
  surfaceHidden?: boolean;
294
304
  settings?: Record<string, any>;
305
+ /** Set when this session is acting as a mesh coordinator for the given mesh. */
306
+ coordinator?: {
307
+ meshId: string;
308
+ role: 'coordinator';
309
+ };
295
310
  meshQueueStats?: {
296
311
  total?: number;
297
312
  active?: number;
@@ -410,7 +425,33 @@ export interface AvailableProviderInfo {
410
425
  lastVerification?: MachineProviderCheckResult;
411
426
  /** Provider-declared Repo Mesh coordinator/MCP behavior. */
412
427
  meshCoordinator?: ProviderMeshCoordinatorConfig;
413
- }
428
+ /**
429
+ * Provider trust classification — derived from the on-disk layer the
430
+ * manifest came from and the shape of the manifest. Dashboards use
431
+ * this to render a trust badge and gate activation of
432
+ * `external-untrusted` providers behind a confirm modal.
433
+ */
434
+ trust?: ProviderTrust;
435
+ /** Daemon-side human-readable description of the trust value. */
436
+ trustDescription?: string;
437
+ /** True when activation needs a user-side confirmation step. */
438
+ requiresConfirmation?: boolean;
439
+ /** Which on-disk layer the manifest lives in. */
440
+ sourceLayer?: 'user' | 'upstream' | 'external';
441
+ /** For external providers, the source-name namespace it came from. */
442
+ sourceName?: string | null;
443
+ /** Manifest-declared version, e.g. "1.2.1". */
444
+ providerVersion?: string;
445
+ /** Underlying executable name (CLI/binary providers). */
446
+ binary?: string;
447
+ /** Lifecycle label from the manifest: "Stable", "Beta", … */
448
+ status?: string;
449
+ /** One-line provider description from the manifest. */
450
+ details?: string;
451
+ /** Manifest-declared links: homepage, docs, repo, … */
452
+ links?: Record<string, string>;
453
+ }
454
+ export type ProviderTrust = 'user-custom' | 'trusted' | 'trusted-with-scripts' | 'external-safe' | 'external-untrusted';
414
455
  export interface MachineProviderCheckResult {
415
456
  ok: boolean;
416
457
  stage?: 'detection' | 'runnable' | 'verification';
@@ -1,6 +1,6 @@
1
1
  import type { ActiveChatData } from '../providers/provider-instance.js';
2
2
  import type { SessionActiveChatData } from '../shared-types.js';
3
- export type ManagedStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
3
+ export type ManagedStatus = 'idle' | 'generating' | 'waiting_approval' | 'waiting_choice' | 'error' | 'stopped' | 'starting' | 'panel_hidden' | 'not_monitored' | 'disconnected';
4
4
  export interface NormalizeActiveChatOptions {
5
5
  includeMessages?: boolean;
6
6
  includeInputContent?: boolean;
@@ -119,6 +119,7 @@ function normalizeManagedStatus(status, opts) {
119
119
  if (hasApprovalButtons(opts?.activeModal)) return "waiting_approval";
120
120
  const normalized = String(status || "idle").trim().toLowerCase();
121
121
  if (normalized === "waiting_approval") return "waiting_approval";
122
+ if (normalized === "waiting_choice") return "waiting_choice";
122
123
  if (WORKING_STATUSES.has(normalized)) return "generating";
123
124
  if (normalized === "error") return "error";
124
125
  if (normalized === "stopped") return "stopped";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\nimport type { SessionActiveChatData } from '../shared-types.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nexport interface NormalizeActiveChatOptions {\n includeMessages?: boolean;\n includeInputContent?: boolean;\n includeActiveModal?: boolean;\n messageLimit?: number;\n totalBytesLimit?: number;\n stringLimit?: number;\n fallbackStringLimit?: number;\n}\n\n// Full snapshots are still capped, but can carry recent chat context for API/inspection use.\nconst FULL_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: true,\n includeInputContent: true,\n includeActiveModal: true,\n messageLimit: 60,\n totalBytesLimit: 96 * 1024,\n stringLimit: 4 * 1024,\n fallbackStringLimit: 1024,\n};\n\n// Live/metadata snapshots only need routing + UI summary. Current chat text is loaded\n// on demand via `read_chat`, and older history via `chat_history`.\nexport const LIVE_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: false,\n includeInputContent: false,\n includeActiveModal: false,\n messageLimit: 0,\n totalBytesLimit: 0,\n stringLimit: 512,\n fallbackStringLimit: 256,\n};\n\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\n/**\n * Collapse timestamp / createdAt into receivedAt so downstream consumers\n * only ever need to read a single canonical time field.\n */\nfunction normalizeMessageTime(message: unknown): unknown {\n if (!message || typeof message !== 'object') return message;\n const msg = message as Record<string, unknown>;\n if (msg.receivedAt == null) {\n const fallback = msg.timestamp ?? msg.createdAt;\n if (fallback != null) {\n const ts = typeof fallback === 'string' ? Date.parse(fallback as string) : Number(fallback);\n if (Number.isFinite(ts) && ts > 0) msg.receivedAt = ts;\n }\n }\n return msg;\n}\n\nfunction trimMessagesForStatus(\n messages: unknown[] | null | undefined,\n options: Required<NormalizeActiveChatOptions>,\n): unknown[] {\n if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-options.messageLimit);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));\n let size = estimateBytes(normalized);\n\n if (size > options.totalBytesLimit) {\n normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > options.totalBytesLimit) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n options: NormalizeActiveChatOptions = FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n): T extends null | undefined ? T : SessionActiveChatData {\n if (!activeChat) return activeChat as T extends null | undefined ? T : SessionActiveChatData;\n const resolvedOptions: Required<NormalizeActiveChatOptions> = {\n ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n ...options,\n };\n const {\n messages: _messages,\n ...rest\n } = activeChat;\n const normalized: SessionActiveChatData = {\n ...rest,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : null,\n inputContent: resolvedOptions.includeInputContent && activeChat.inputContent\n ? truncateString(activeChat.inputContent, 2 * 1024)\n : undefined,\n };\n if (resolvedOptions.includeMessages) {\n normalized.messages = trimMessagesForStatus(activeChat.messages, resolvedOptions) as SessionActiveChatData['messages'];\n }\n return normalized as T extends null | undefined ? T : SessionActiveChatData;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\nimport type { SessionActiveChatData } from '../shared-types.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'waiting_choice'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nexport interface NormalizeActiveChatOptions {\n includeMessages?: boolean;\n includeInputContent?: boolean;\n includeActiveModal?: boolean;\n messageLimit?: number;\n totalBytesLimit?: number;\n stringLimit?: number;\n fallbackStringLimit?: number;\n}\n\n// Full snapshots are still capped, but can carry recent chat context for API/inspection use.\nconst FULL_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: true,\n includeInputContent: true,\n includeActiveModal: true,\n messageLimit: 60,\n totalBytesLimit: 96 * 1024,\n stringLimit: 4 * 1024,\n fallbackStringLimit: 1024,\n};\n\n// Live/metadata snapshots only need routing + UI summary. Current chat text is loaded\n// on demand via `read_chat`, and older history via `chat_history`.\nexport const LIVE_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: false,\n includeInputContent: false,\n includeActiveModal: false,\n messageLimit: 0,\n totalBytesLimit: 0,\n stringLimit: 512,\n fallbackStringLimit: 256,\n};\n\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\n/**\n * Collapse timestamp / createdAt into receivedAt so downstream consumers\n * only ever need to read a single canonical time field.\n */\nfunction normalizeMessageTime(message: unknown): unknown {\n if (!message || typeof message !== 'object') return message;\n const msg = message as Record<string, unknown>;\n if (msg.receivedAt == null) {\n const fallback = msg.timestamp ?? msg.createdAt;\n if (fallback != null) {\n const ts = typeof fallback === 'string' ? Date.parse(fallback as string) : Number(fallback);\n if (Number.isFinite(ts) && ts > 0) msg.receivedAt = ts;\n }\n }\n return msg;\n}\n\nfunction trimMessagesForStatus(\n messages: unknown[] | null | undefined,\n options: Required<NormalizeActiveChatOptions>,\n): unknown[] {\n if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-options.messageLimit);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));\n let size = estimateBytes(normalized);\n\n if (size > options.totalBytesLimit) {\n normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > options.totalBytesLimit) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (normalized === 'waiting_choice') return 'waiting_choice';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n options: NormalizeActiveChatOptions = FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n): T extends null | undefined ? T : SessionActiveChatData {\n if (!activeChat) return activeChat as T extends null | undefined ? T : SessionActiveChatData;\n const resolvedOptions: Required<NormalizeActiveChatOptions> = {\n ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n ...options,\n };\n const {\n messages: _messages,\n ...rest\n } = activeChat;\n const normalized: SessionActiveChatData = {\n ...rest,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : null,\n inputContent: resolvedOptions.includeInputContent && activeChat.inputContent\n ? truncateString(activeChat.inputContent, 2 * 1024)\n : undefined,\n };\n if (resolvedOptions.includeMessages) {\n normalized.messages = trimMessagesForStatus(activeChat.messages, resolvedOptions) as SessionActiveChatData['messages'];\n }\n return normalized as T extends null | undefined ? T : SessionActiveChatData;\n}\n"],"mappings":"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","names":[]}
@@ -91,6 +91,7 @@ function normalizeManagedStatus(status, opts) {
91
91
  if (hasApprovalButtons(opts?.activeModal)) return "waiting_approval";
92
92
  const normalized = String(status || "idle").trim().toLowerCase();
93
93
  if (normalized === "waiting_approval") return "waiting_approval";
94
+ if (normalized === "waiting_choice") return "waiting_choice";
94
95
  if (WORKING_STATUSES.has(normalized)) return "generating";
95
96
  if (normalized === "error") return "error";
96
97
  if (normalized === "stopped") return "stopped";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\nimport type { SessionActiveChatData } from '../shared-types.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nexport interface NormalizeActiveChatOptions {\n includeMessages?: boolean;\n includeInputContent?: boolean;\n includeActiveModal?: boolean;\n messageLimit?: number;\n totalBytesLimit?: number;\n stringLimit?: number;\n fallbackStringLimit?: number;\n}\n\n// Full snapshots are still capped, but can carry recent chat context for API/inspection use.\nconst FULL_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: true,\n includeInputContent: true,\n includeActiveModal: true,\n messageLimit: 60,\n totalBytesLimit: 96 * 1024,\n stringLimit: 4 * 1024,\n fallbackStringLimit: 1024,\n};\n\n// Live/metadata snapshots only need routing + UI summary. Current chat text is loaded\n// on demand via `read_chat`, and older history via `chat_history`.\nexport const LIVE_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: false,\n includeInputContent: false,\n includeActiveModal: false,\n messageLimit: 0,\n totalBytesLimit: 0,\n stringLimit: 512,\n fallbackStringLimit: 256,\n};\n\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\n/**\n * Collapse timestamp / createdAt into receivedAt so downstream consumers\n * only ever need to read a single canonical time field.\n */\nfunction normalizeMessageTime(message: unknown): unknown {\n if (!message || typeof message !== 'object') return message;\n const msg = message as Record<string, unknown>;\n if (msg.receivedAt == null) {\n const fallback = msg.timestamp ?? msg.createdAt;\n if (fallback != null) {\n const ts = typeof fallback === 'string' ? Date.parse(fallback as string) : Number(fallback);\n if (Number.isFinite(ts) && ts > 0) msg.receivedAt = ts;\n }\n }\n return msg;\n}\n\nfunction trimMessagesForStatus(\n messages: unknown[] | null | undefined,\n options: Required<NormalizeActiveChatOptions>,\n): unknown[] {\n if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-options.messageLimit);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));\n let size = estimateBytes(normalized);\n\n if (size > options.totalBytesLimit) {\n normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > options.totalBytesLimit) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n options: NormalizeActiveChatOptions = FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n): T extends null | undefined ? T : SessionActiveChatData {\n if (!activeChat) return activeChat as T extends null | undefined ? T : SessionActiveChatData;\n const resolvedOptions: Required<NormalizeActiveChatOptions> = {\n ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n ...options,\n };\n const {\n messages: _messages,\n ...rest\n } = activeChat;\n const normalized: SessionActiveChatData = {\n ...rest,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : null,\n inputContent: resolvedOptions.includeInputContent && activeChat.inputContent\n ? truncateString(activeChat.inputContent, 2 * 1024)\n : undefined,\n };\n if (resolvedOptions.includeMessages) {\n normalized.messages = trimMessagesForStatus(activeChat.messages, resolvedOptions) as SessionActiveChatData['messages'];\n }\n return normalized as T extends null | undefined ? T : SessionActiveChatData;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/status/normalize.ts"],"sourcesContent":["import type { ActiveChatData } from '../providers/provider-instance.js';\nimport type { SessionActiveChatData } from '../shared-types.js';\n\nexport type ManagedStatus =\n | 'idle'\n | 'generating'\n | 'waiting_approval'\n | 'waiting_choice'\n | 'error'\n | 'stopped'\n | 'starting'\n | 'panel_hidden'\n | 'not_monitored'\n | 'disconnected';\n\nconst WORKING_STATUSES = new Set([\n 'generating',\n 'streaming',\n 'loading',\n 'loading_reference',\n 'thinking',\n 'active',\n]);\n\nexport interface NormalizeActiveChatOptions {\n includeMessages?: boolean;\n includeInputContent?: boolean;\n includeActiveModal?: boolean;\n messageLimit?: number;\n totalBytesLimit?: number;\n stringLimit?: number;\n fallbackStringLimit?: number;\n}\n\n// Full snapshots are still capped, but can carry recent chat context for API/inspection use.\nconst FULL_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: true,\n includeInputContent: true,\n includeActiveModal: true,\n messageLimit: 60,\n totalBytesLimit: 96 * 1024,\n stringLimit: 4 * 1024,\n fallbackStringLimit: 1024,\n};\n\n// Live/metadata snapshots only need routing + UI summary. Current chat text is loaded\n// on demand via `read_chat`, and older history via `chat_history`.\nexport const LIVE_STATUS_ACTIVE_CHAT_OPTIONS: Required<NormalizeActiveChatOptions> = {\n includeMessages: false,\n includeInputContent: false,\n includeActiveModal: false,\n messageLimit: 0,\n totalBytesLimit: 0,\n stringLimit: 512,\n fallbackStringLimit: 256,\n};\n\nconst STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;\nconst STATUS_MODAL_BUTTON_LIMIT = 120;\n\nfunction truncateString(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(0, Math.max(0, maxChars));\n return `${value.slice(0, maxChars - 12)}...[truncated]`;\n}\n\nfunction truncateStringTail(value: string, maxChars: number): string {\n if (value.length <= maxChars) return value;\n if (maxChars <= 12) return value.slice(value.length - Math.max(0, maxChars));\n return `...[truncated]${value.slice(value.length - (maxChars - 12))}`;\n}\n\nfunction trimStructuredStrings(value: unknown, maxChars: number): unknown {\n if (typeof value === 'string') return truncateString(value, maxChars);\n if (Array.isArray(value)) return value.map((item) => trimStructuredStrings(item, maxChars));\n if (!value || typeof value !== 'object') return value;\n return Object.fromEntries(\n Object.entries(value).map(([key, nested]) => [key, trimStructuredStrings(nested, maxChars)]),\n );\n}\n\nfunction estimateBytes(value: unknown): number {\n try {\n return JSON.stringify(value).length;\n } catch {\n return String(value ?? '').length;\n }\n}\n\nfunction trimMessageForStatus(message: unknown, stringLimit: number): unknown {\n if (!message || typeof message !== 'object') return message;\n return trimStructuredStrings(message, stringLimit);\n}\n\n/**\n * Collapse timestamp / createdAt into receivedAt so downstream consumers\n * only ever need to read a single canonical time field.\n */\nfunction normalizeMessageTime(message: unknown): unknown {\n if (!message || typeof message !== 'object') return message;\n const msg = message as Record<string, unknown>;\n if (msg.receivedAt == null) {\n const fallback = msg.timestamp ?? msg.createdAt;\n if (fallback != null) {\n const ts = typeof fallback === 'string' ? Date.parse(fallback as string) : Number(fallback);\n if (Number.isFinite(ts) && ts > 0) msg.receivedAt = ts;\n }\n }\n return msg;\n}\n\nfunction trimMessagesForStatus(\n messages: unknown[] | null | undefined,\n options: Required<NormalizeActiveChatOptions>,\n): unknown[] {\n if (!options.includeMessages || options.messageLimit <= 0 || options.totalBytesLimit <= 0) return [];\n if (!Array.isArray(messages) || messages.length === 0) return [];\n\n const recent = messages.slice(-options.messageLimit);\n const kept: unknown[] = [];\n let totalBytes = 0;\n\n for (let i = recent.length - 1; i >= 0; i -= 1) {\n let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.stringLimit));\n let size = estimateBytes(normalized);\n\n if (size > options.totalBytesLimit) {\n normalized = normalizeMessageTime(trimMessageForStatus(recent[i], options.fallbackStringLimit));\n size = estimateBytes(normalized);\n }\n\n if (kept.length > 0 && (totalBytes + size) > options.totalBytesLimit) {\n continue;\n }\n\n kept.push(normalized);\n totalBytes += size;\n }\n\n return kept.reverse();\n}\n\nfunction hasApprovalButtons(activeModal?: { buttons?: unknown[] | null } | null): boolean {\n return (activeModal?.buttons?.length ?? 0) > 0;\n}\n\nexport function normalizeManagedStatus(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): ManagedStatus {\n if (hasApprovalButtons(opts?.activeModal)) return 'waiting_approval';\n\n const normalized = String(status || 'idle').trim().toLowerCase();\n if (normalized === 'waiting_approval') return 'waiting_approval';\n if (normalized === 'waiting_choice') return 'waiting_choice';\n if (WORKING_STATUSES.has(normalized)) return 'generating';\n if (normalized === 'error') return 'error';\n if (normalized === 'stopped') return 'stopped';\n if (normalized === 'starting') return 'starting';\n if (normalized === 'panel_hidden') return 'panel_hidden';\n if (normalized === 'not_monitored') return 'not_monitored';\n if (normalized === 'disconnected') return 'disconnected';\n return 'idle';\n}\n\nexport function isManagedStatusWorking(status?: string | null): boolean {\n return normalizeManagedStatus(status) === 'generating';\n}\n\nexport function isManagedStatusWaiting(\n status?: string | null,\n opts?: { activeModal?: { buttons?: unknown[] | null } | null },\n): boolean {\n return normalizeManagedStatus(status, opts) === 'waiting_approval';\n}\n\nexport function normalizeActiveChatData<T extends ActiveChatData | null | undefined>(\n activeChat: T,\n options: NormalizeActiveChatOptions = FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n): T extends null | undefined ? T : SessionActiveChatData {\n if (!activeChat) return activeChat as T extends null | undefined ? T : SessionActiveChatData;\n const resolvedOptions: Required<NormalizeActiveChatOptions> = {\n ...FULL_STATUS_ACTIVE_CHAT_OPTIONS,\n ...options,\n };\n const {\n messages: _messages,\n ...rest\n } = activeChat;\n const normalized: SessionActiveChatData = {\n ...rest,\n status: normalizeManagedStatus(activeChat.status, { activeModal: activeChat.activeModal }),\n activeModal: resolvedOptions.includeActiveModal && activeChat.activeModal ? {\n message: truncateString(activeChat.activeModal.message || '', STATUS_MODAL_MESSAGE_LIMIT),\n buttons: (activeChat.activeModal.buttons || []).map((button) =>\n truncateString(String(button || ''), STATUS_MODAL_BUTTON_LIMIT)\n ),\n } : null,\n inputContent: resolvedOptions.includeInputContent && activeChat.inputContent\n ? truncateString(activeChat.inputContent, 2 * 1024)\n : undefined,\n };\n if (resolvedOptions.includeMessages) {\n normalized.messages = trimMessagesForStatus(activeChat.messages, resolvedOptions) as SessionActiveChatData['messages'];\n }\n return normalized as T extends null | undefined ? T : SessionActiveChatData;\n}\n"],"mappings":";AAeA,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAaD,IAAM,kCAAwE;AAAA,EAC1E,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,iBAAiB,KAAK;AAAA,EACtB,aAAa,IAAI;AAAA,EACjB,qBAAqB;AACzB;AAIO,IAAM,kCAAwE;AAAA,EACjF,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,qBAAqB;AACzB;AAEA,IAAM,6BAA6B,IAAI;AACvC,IAAM,4BAA4B;AAElC,SAAS,eAAe,OAAe,UAA0B;AAC7D,MAAI,MAAM,UAAU,SAAU,QAAO;AACrC,MAAI,YAAY,GAAI,QAAO,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;AAC/D,SAAO,GAAG,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;AAC3C;AAQA,SAAS,sBAAsB,OAAgB,UAA2B;AACtE,MAAI,OAAO,UAAU,SAAU,QAAO,eAAe,OAAO,QAAQ;AACpE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,CAAC,SAAS,sBAAsB,MAAM,QAAQ,CAAC;AAC1F,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,SAAO,OAAO;AAAA,IACV,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,sBAAsB,QAAQ,QAAQ,CAAC,CAAC;AAAA,EAC/F;AACJ;AAEA,SAAS,cAAc,OAAwB;AAC3C,MAAI;AACA,WAAO,KAAK,UAAU,KAAK,EAAE;AAAA,EACjC,QAAQ;AACJ,WAAO,OAAO,SAAS,EAAE,EAAE;AAAA,EAC/B;AACJ;AAEA,SAAS,qBAAqB,SAAkB,aAA8B;AAC1E,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,SAAO,sBAAsB,SAAS,WAAW;AACrD;AAMA,SAAS,qBAAqB,SAA2B;AACrD,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,MAAM;AACZ,MAAI,IAAI,cAAc,MAAM;AACxB,UAAM,WAAW,IAAI,aAAa,IAAI;AACtC,QAAI,YAAY,MAAM;AAClB,YAAM,KAAK,OAAO,aAAa,WAAW,KAAK,MAAM,QAAkB,IAAI,OAAO,QAAQ;AAC1F,UAAI,OAAO,SAAS,EAAE,KAAK,KAAK,EAAG,KAAI,aAAa;AAAA,IACxD;AAAA,EACJ;AACA,SAAO;AACX;AAEA,SAAS,sBACL,UACA,SACS;AACT,MAAI,CAAC,QAAQ,mBAAmB,QAAQ,gBAAgB,KAAK,QAAQ,mBAAmB,EAAG,QAAO,CAAC;AACnG,MAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,SAAS,WAAW,EAAG,QAAO,CAAC;AAE/D,QAAM,SAAS,SAAS,MAAM,CAAC,QAAQ,YAAY;AACnD,QAAM,OAAkB,CAAC;AACzB,MAAI,aAAa;AAEjB,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;AAC5C,QAAI,aAAa,qBAAqB,qBAAqB,OAAO,CAAC,GAAG,QAAQ,WAAW,CAAC;AAC1F,QAAI,OAAO,cAAc,UAAU;AAEnC,QAAI,OAAO,QAAQ,iBAAiB;AAChC,mBAAa,qBAAqB,qBAAqB,OAAO,CAAC,GAAG,QAAQ,mBAAmB,CAAC;AAC9F,aAAO,cAAc,UAAU;AAAA,IACnC;AAEA,QAAI,KAAK,SAAS,KAAM,aAAa,OAAQ,QAAQ,iBAAiB;AAClE;AAAA,IACJ;AAEA,SAAK,KAAK,UAAU;AACpB,kBAAc;AAAA,EAClB;AAEA,SAAO,KAAK,QAAQ;AACxB;AAEA,SAAS,mBAAmB,aAA8D;AACtF,UAAQ,aAAa,SAAS,UAAU,KAAK;AACjD;AAEO,SAAS,uBACZ,QACA,MACa;AACb,MAAI,mBAAmB,MAAM,WAAW,EAAG,QAAO;AAElD,QAAM,aAAa,OAAO,UAAU,MAAM,EAAE,KAAK,EAAE,YAAY;AAC/D,MAAI,eAAe,mBAAoB,QAAO;AAC9C,MAAI,eAAe,iBAAkB,QAAO;AAC5C,MAAI,iBAAiB,IAAI,UAAU,EAAG,QAAO;AAC7C,MAAI,eAAe,QAAS,QAAO;AACnC,MAAI,eAAe,UAAW,QAAO;AACrC,MAAI,eAAe,WAAY,QAAO;AACtC,MAAI,eAAe,eAAgB,QAAO;AAC1C,MAAI,eAAe,gBAAiB,QAAO;AAC3C,MAAI,eAAe,eAAgB,QAAO;AAC1C,SAAO;AACX;AAEO,SAAS,uBAAuB,QAAiC;AACpE,SAAO,uBAAuB,MAAM,MAAM;AAC9C;AAEO,SAAS,uBACZ,QACA,MACO;AACP,SAAO,uBAAuB,QAAQ,IAAI,MAAM;AACpD;AAEO,SAAS,wBACZ,YACA,UAAsC,iCACgB;AACtD,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,kBAAwD;AAAA,IAC1D,GAAG;AAAA,IACH,GAAG;AAAA,EACP;AACA,QAAM;AAAA,IACF,UAAU;AAAA,IACV,GAAG;AAAA,EACP,IAAI;AACJ,QAAM,aAAoC;AAAA,IACtC,GAAG;AAAA,IACH,QAAQ,uBAAuB,WAAW,QAAQ,EAAE,aAAa,WAAW,YAAY,CAAC;AAAA,IACzF,aAAa,gBAAgB,sBAAsB,WAAW,cAAc;AAAA,MACxE,SAAS,eAAe,WAAW,YAAY,WAAW,IAAI,0BAA0B;AAAA,MACxF,UAAU,WAAW,YAAY,WAAW,CAAC,GAAG;AAAA,QAAI,CAAC,WACjD,eAAe,OAAO,UAAU,EAAE,GAAG,yBAAyB;AAAA,MAClE;AAAA,IACJ,IAAI;AAAA,IACJ,cAAc,gBAAgB,uBAAuB,WAAW,eAC1D,eAAe,WAAW,cAAc,IAAI,IAAI,IAChD;AAAA,EACV;AACA,MAAI,gBAAgB,iBAAiB;AACjC,eAAW,WAAW,sBAAsB,WAAW,UAAU,eAAe;AAAA,EACpF;AACA,SAAO;AACX;","names":[]}
@@ -46,6 +46,8 @@ export declare class DaemonStatusReporter {
46
46
  private lastStatusSentAt;
47
47
  private statusPendingThrottle;
48
48
  private lastP2PStatusHash;
49
+ private lastP2PStatusSentAt;
50
+ private p2pDebounceTimer;
49
51
  private lastServerStatusHash;
50
52
  private lastStatusSummary;
51
53
  private statusTimer;
@@ -75,6 +75,7 @@ export declare function getSessionCompletionMarker(session: {
75
75
  receivedAt?: number | string;
76
76
  timestamp?: number | string;
77
77
  _turnKey?: string;
78
+ kind?: string;
78
79
  }> | null;
79
80
  } | null;
80
81
  }): string;
package/dist/types.d.ts CHANGED
@@ -36,6 +36,11 @@ export interface ChatMessage {
36
36
  index?: number;
37
37
  timestamp?: number;
38
38
  receivedAt?: number;
39
+ /** (A2.3) Monotonic sequence number per (session, source). Producer-asserted
40
+ * when emitted by v2-aware providers (transcript v2 schema); otherwise
41
+ * derived by the daemon from receivedAt/timestamp/index. ChatSourceMachine
42
+ * uses this as the native peak watermark for regression detection. */
43
+ sequence?: number;
39
44
  _turnKey?: string;
40
45
  /** Tool calls associated with this message */
41
46
  toolCalls?: ToolCallInfo[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.29",
3
+ "version": "0.9.82-rc.290",
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",
@@ -27,7 +27,7 @@
27
27
  "scripts": {
28
28
  "build": "tsup && npm run build:types",
29
29
  "build:types": "tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap false",
30
- "dev": "tsup --watch",
30
+ "dev": "tsup --watch --no-clean",
31
31
  "test": "vitest run",
32
32
  "test:watch": "vitest",
33
33
  "typecheck": "tsc --noEmit -p tsconfig.json"
@@ -46,9 +46,12 @@
46
46
  "author": "vilmire",
47
47
  "license": "AGPL-3.0-or-later",
48
48
  "dependencies": {
49
+ "@adhdev/mesh-shared": "0.9.82-rc.290",
49
50
  "@adhdev/session-host-core": "*",
50
51
  "@agentclientprotocol/sdk": "^0.16.1",
51
- "@xterm/xterm": "^6.0.0",
52
+ "ajv": "^8.20.0",
53
+ "ajv-formats": "^3.0.1",
54
+ "better-sqlite3": "^12.10.0",
52
55
  "chalk": "^5.3.0",
53
56
  "chokidar": "^4.0.3",
54
57
  "conf": "^13.0.0",
@@ -60,6 +63,7 @@
60
63
  "@adhdev/ghostty-vt-node": "*"
61
64
  },
62
65
  "devDependencies": {
66
+ "@types/better-sqlite3": "^7.6.13",
63
67
  "@types/js-yaml": "^4.0.9",
64
68
  "@types/node": "^22.0.0",
65
69
  "@types/ws": "^8.18.1",
@@ -19,7 +19,7 @@ import type { SessionRegistry } from '../sessions/registry.js';
19
19
  import { reconcileIdeRuntimeSessions } from '../sessions/reconcile.js';
20
20
  import { LOG } from '../logging/logger.js';
21
21
  import type { AgentStreamState } from './types.js';
22
- import { formatAutoApprovalMessage, pickApprovalButton } from '../providers/approval-utils.js';
22
+ import { formatAutoApprovalMessage, pickAutoApprovalButton } from '../providers/approval-utils.js';
23
23
  import type { ProviderModule } from '../providers/contracts.js';
24
24
  import { buildRuntimeSystemChatMessage } from '../providers/chat-message-normalization.js';
25
25
 
@@ -210,8 +210,7 @@ export class AgentStreamPoller {
210
210
  if (stream?.status === 'waiting_approval') {
211
211
  const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
212
212
  if (autoApprove && resolvedActiveSessionId) {
213
- const provider = providerLoader.getMeta(stream.agentType);
214
- const { label: buttonLabel } = pickApprovalButton(stream.activeModal?.buttons, provider);
213
+ const { label: buttonLabel } = pickAutoApprovalButton(stream.activeModal?.buttons);
215
214
  const approved = await agentStreamManager.resolveSessionAction(cdp, resolvedActiveSessionId, 'approve', buttonLabel);
216
215
  if (approved) {
217
216
  const effectId = [