@adhdev/daemon-core 0.9.82-rc.49 → 0.9.82-rc.490

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 (473) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +9 -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 +68 -2
  8. package/dist/cli-adapters/cli-script-runner.d.ts +117 -0
  9. package/dist/cli-adapters/cli-state-engine.d.ts +220 -0
  10. package/dist/cli-adapters/provider-cli-adapter.d.ts +137 -64
  11. package/dist/cli-adapters/provider-cli-parse.d.ts +5 -0
  12. package/dist/cli-adapters/provider-cli-runtime.d.ts +34 -0
  13. package/dist/cli-adapters/provider-cli-shared.d.ts +74 -0
  14. package/dist/cli-adapters/pty-write-chunking.d.ts +34 -0
  15. package/dist/cli-adapters/raw-terminal-io.d.ts +37 -0
  16. package/dist/cli-adapters/resolve-executable.d.ts +69 -0
  17. package/dist/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +6 -3
  18. package/dist/cli-adapters/terminal-backends/types.d.ts +10 -2
  19. package/dist/cli-adapters/terminal-screen.d.ts +4 -11
  20. package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
  21. package/dist/commands/chat-commands-read.d.ts +23 -0
  22. package/dist/commands/chat-commands-scope.d.ts +39 -0
  23. package/dist/commands/chat-commands-shared.d.ts +33 -0
  24. package/dist/commands/chat-commands-write.d.ts +14 -0
  25. package/dist/commands/chat-commands.d.ts +10 -23
  26. package/dist/commands/cli-manager.d.ts +71 -1
  27. package/dist/commands/handler.d.ts +125 -0
  28. package/dist/commands/high-family/index.d.ts +3 -0
  29. package/dist/commands/high-family/mesh-coordinator-launch.d.ts +2 -0
  30. package/dist/commands/high-family/mesh-events.d.ts +2 -0
  31. package/dist/commands/high-family/mesh-status.d.ts +2 -0
  32. package/dist/commands/high-family/types.d.ts +64 -0
  33. package/dist/commands/low-family/coordinator-prompt.d.ts +9 -0
  34. package/dist/commands/low-family/daemon-lifecycle.d.ts +2 -0
  35. package/dist/commands/low-family/diagnostics.d.ts +2 -0
  36. package/dist/commands/low-family/index.d.ts +3 -0
  37. package/dist/commands/low-family/mesh-ledger.d.ts +10 -0
  38. package/dist/commands/low-family/mesh-node-logs.d.ts +2 -0
  39. package/dist/commands/low-family/notification.d.ts +2 -0
  40. package/dist/commands/low-family/refine-config.d.ts +2 -0
  41. package/dist/commands/low-family/session-host.d.ts +2 -0
  42. package/dist/commands/low-family/spec-providerdev.d.ts +11 -0
  43. package/dist/commands/low-family/status-meta.d.ts +2 -0
  44. package/dist/commands/low-family/types.d.ts +33 -0
  45. package/dist/commands/med-family/cli-agent.d.ts +2 -0
  46. package/dist/commands/med-family/fast-forward.d.ts +2 -0
  47. package/dist/commands/med-family/ide.d.ts +10 -0
  48. package/dist/commands/med-family/index.d.ts +3 -0
  49. package/dist/commands/med-family/mesh-crud.d.ts +48 -0
  50. package/dist/commands/med-family/mesh-host-pairing.d.ts +2 -0
  51. package/dist/commands/med-family/mesh-queue.d.ts +2 -0
  52. package/dist/commands/med-family/mesh-restart.d.ts +2 -0
  53. package/dist/commands/med-family/types.d.ts +152 -0
  54. package/dist/commands/mesh-coordinator.d.ts +85 -1
  55. package/dist/commands/router-aggregate-status.d.ts +24 -0
  56. package/dist/commands/router-mesh-session-owner.d.ts +59 -0
  57. package/dist/commands/router-refine.d.ts +151 -0
  58. package/dist/commands/router-worktree-cleanup.d.ts +133 -0
  59. package/dist/commands/router.d.ts +203 -15
  60. package/dist/commands/upgrade-helper.d.ts +41 -1
  61. package/dist/config/chat-history.d.ts +11 -0
  62. package/dist/config/config.d.ts +19 -0
  63. package/dist/config/mesh-config.d.ts +65 -0
  64. package/dist/config/mesh-json-config.d.ts +199 -0
  65. package/dist/config/registry-resolver.d.ts +54 -0
  66. package/dist/config/repo-settings.d.ts +77 -0
  67. package/dist/config/state-store.d.ts +30 -0
  68. package/dist/daemon/dev-server.d.ts +0 -2
  69. package/dist/detection/cli-detector.d.ts +17 -0
  70. package/dist/detection/ide-detector.d.ts +13 -0
  71. package/dist/detection/win32-ide-version.d.ts +37 -0
  72. package/dist/git/change-impact-config.d.ts +159 -0
  73. package/dist/git/git-commands.d.ts +26 -2
  74. package/dist/git/git-diff.d.ts +6 -0
  75. package/dist/git/git-executor.d.ts +11 -0
  76. package/dist/git/git-status.d.ts +80 -0
  77. package/dist/git/git-types.d.ts +2 -50
  78. package/dist/git/git-worktree.d.ts +71 -1
  79. package/dist/git/index.d.ts +3 -1
  80. package/dist/index.d.ts +70 -17
  81. package/dist/index.js +53532 -19073
  82. package/dist/index.js.map +1 -1
  83. package/dist/index.mjs +53283 -18989
  84. package/dist/index.mjs.map +1 -1
  85. package/dist/installer.d.ts +1 -4
  86. package/dist/ipc/local-ipc-server.d.ts +91 -0
  87. package/dist/launch.d.ts +1 -1
  88. package/dist/logging/async-batch-writer.d.ts +10 -0
  89. package/dist/logging/debug-config.d.ts +16 -0
  90. package/dist/logging/log-redactor.d.ts +24 -0
  91. package/dist/logging/log-tail-reader.d.ts +81 -0
  92. package/dist/logging/logger.d.ts +1 -1
  93. package/dist/mesh/contracts.d.ts +256 -0
  94. package/dist/mesh/coordinator-prompt.d.ts +76 -0
  95. package/dist/mesh/coordinator-registry.d.ts +59 -0
  96. package/dist/mesh/mesh-active-work.d.ts +203 -0
  97. package/dist/mesh/mesh-clone-grace.d.ts +8 -0
  98. package/dist/mesh/mesh-completion-synthesis.d.ts +4 -0
  99. package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
  100. package/dist/mesh/mesh-delivery-policy.d.ts +104 -0
  101. package/dist/mesh/mesh-event-classify.d.ts +7 -0
  102. package/dist/mesh/mesh-event-forwarding.d.ts +58 -0
  103. package/dist/mesh/mesh-event-trace.d.ts +21 -0
  104. package/dist/mesh/mesh-events-coordinator.d.ts +4 -0
  105. package/dist/mesh/mesh-events-pending.d.ts +258 -0
  106. package/dist/mesh/mesh-events-stale.d.ts +61 -0
  107. package/dist/mesh/mesh-events-utils.d.ts +75 -0
  108. package/dist/mesh/mesh-events.d.ts +6 -49
  109. package/dist/mesh/mesh-fast-forward.d.ts +81 -0
  110. package/dist/mesh/mesh-host-ownership.d.ts +21 -1
  111. package/dist/mesh/mesh-init.d.ts +128 -0
  112. package/dist/mesh/mesh-ledger-reconciliation.d.ts +23 -4
  113. package/dist/mesh/mesh-ledger.d.ts +139 -1
  114. package/dist/mesh/mesh-magi-status.d.ts +63 -0
  115. package/dist/mesh/mesh-missions.d.ts +281 -0
  116. package/dist/mesh/mesh-node-identity.d.ts +310 -0
  117. package/dist/mesh/mesh-queue-assignment.d.ts +162 -0
  118. package/dist/mesh/mesh-reconcile-acked-hold.d.ts +17 -0
  119. package/dist/mesh/mesh-reconcile-config.d.ts +6 -0
  120. package/dist/mesh/mesh-reconcile-identity.d.ts +6 -0
  121. package/dist/mesh/mesh-reconcile-loop.d.ts +84 -0
  122. package/dist/mesh/mesh-reconcile-v2-backstop.d.ts +16 -0
  123. package/dist/mesh/mesh-refine-batch.d.ts +68 -0
  124. package/dist/mesh/mesh-refine-gates.d.ts +457 -0
  125. package/dist/mesh/mesh-refine-status.d.ts +62 -0
  126. package/dist/mesh/mesh-remote-event-pull.d.ts +15 -0
  127. package/dist/mesh/mesh-review-inbox.d.ts +90 -0
  128. package/dist/mesh/mesh-routing.d.ts +70 -0
  129. package/dist/mesh/mesh-runtime-store.d.ts +567 -0
  130. package/dist/mesh/mesh-scheduling-runtime.d.ts +78 -0
  131. package/dist/mesh/mesh-task-inflight.d.ts +46 -0
  132. package/dist/mesh/mesh-task-stats.d.ts +49 -0
  133. package/dist/mesh/mesh-unresolved-forward-outbox.d.ts +34 -0
  134. package/dist/mesh/mesh-warmup-deadline.d.ts +68 -0
  135. package/dist/mesh/mesh-work-queue.d.ts +392 -1
  136. package/dist/mesh/preview-freshness.d.ts +28 -0
  137. package/dist/mesh/refine-config.d.ts +97 -0
  138. package/dist/mesh/worktree-bootstrap-config.d.ts +219 -0
  139. package/dist/providers/acp-provider-instance.d.ts +5 -0
  140. package/dist/providers/approval-utils.d.ts +46 -0
  141. package/dist/providers/chat-message-normalization.d.ts +58 -1
  142. package/dist/providers/cli-provider-effect-format.d.ts +30 -0
  143. package/dist/providers/cli-provider-history-dedup.d.ts +17 -0
  144. package/dist/providers/cli-provider-input-prompt.d.ts +12 -0
  145. package/dist/providers/cli-provider-instance-types.d.ts +45 -0
  146. package/dist/providers/cli-provider-instance.d.ts +426 -30
  147. package/dist/providers/cli-provider-status-helpers.d.ts +46 -0
  148. package/dist/providers/cli-provider-transcript-merge.d.ts +7 -0
  149. package/dist/providers/contracts.d.ts +196 -6
  150. package/dist/providers/external-sources.d.ts +71 -0
  151. package/dist/providers/manual-attendance.d.ts +79 -0
  152. package/dist/providers/native-history/antigravity-claim-registry.d.ts +39 -0
  153. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +137 -0
  154. package/dist/providers/native-history/claude-cli-transcript.d.ts +70 -0
  155. package/dist/providers/native-history/codex-cli-transcript.d.ts +73 -0
  156. package/dist/providers/native-history/constants.d.ts +12 -0
  157. package/dist/providers/native-history/dispatcher.d.ts +44 -0
  158. package/dist/providers/native-history/hermes-cli-transcript.d.ts +30 -0
  159. package/dist/providers/native-history/index.d.ts +13 -0
  160. package/dist/providers/provider-instance-manager.d.ts +30 -0
  161. package/dist/providers/provider-instance.d.ts +31 -1
  162. package/dist/providers/provider-loader.d.ts +42 -5
  163. package/dist/providers/provider-trust.d.ts +31 -0
  164. package/dist/providers/read-chat-contract.d.ts +29 -0
  165. package/dist/providers/sdk/v1/builders/acp/detect-status.d.ts +68 -0
  166. package/dist/providers/sdk/v1/builders/cli/detect-status.d.ts +86 -0
  167. package/dist/providers/sdk/v1/builders/cli/parse-approval-squash.d.ts +59 -0
  168. package/dist/providers/sdk/v1/builders/cli/parse-approval.d.ts +65 -0
  169. package/dist/providers/sdk/v1/builders/cli/parse-session.d.ts +91 -0
  170. package/dist/providers/sdk/v1/builders/cli/visible-region.d.ts +42 -0
  171. package/dist/providers/sdk/v1/fixture-tooling/format.d.ts +126 -0
  172. package/dist/providers/sdk/v1/fixture-tooling/index.d.ts +8 -0
  173. package/dist/providers/sdk/v1/fixture-tooling/replay.d.ts +38 -0
  174. package/dist/providers/sdk/v1/index.d.ts +30 -0
  175. package/dist/providers/sdk/v1/sandbox/README-design.d.ts +193 -0
  176. package/dist/providers/sdk/v1/sandbox/require-whitelist.d.ts +74 -0
  177. package/dist/providers/sdk/v1/sandbox/script-runner.d.ts +98 -0
  178. package/dist/providers/sdk/v1/types/cli/index.d.ts +277 -0
  179. package/dist/providers/sdk/v1/types/common/index.d.ts +203 -0
  180. package/dist/providers/sdk/v1/validators/index.d.ts +5 -0
  181. package/dist/providers/sdk/v1/validators/manifest.d.ts +40 -0
  182. package/dist/providers/sdk/v1/validators/taint.d.ts +52 -0
  183. package/dist/providers/spec/adapter.d.ts +98 -0
  184. package/dist/providers/spec/cli-adapter.d.ts +223 -0
  185. package/dist/providers/spec/evaluator.d.ts +45 -0
  186. package/dist/providers/spec/fsm-driver.d.ts +449 -0
  187. package/dist/providers/spec/fsm-evaluator.d.ts +93 -0
  188. package/dist/providers/spec/fsm-loader.d.ts +14 -0
  189. package/dist/providers/spec/fsm-types.d.ts +202 -0
  190. package/dist/providers/spec/native-history-executor.d.ts +41 -0
  191. package/dist/providers/spec/pre-launch-trust.d.ts +16 -0
  192. package/dist/providers/spec/route.d.ts +4 -0
  193. package/dist/providers/spec/types.d.ts +244 -0
  194. package/dist/providers/status-monitor.d.ts +7 -7
  195. package/dist/providers/transcript-v2.d.ts +176 -0
  196. package/dist/providers/types/interactive-prompt.d.ts +84 -0
  197. package/dist/providers/working-dir.d.ts +17 -0
  198. package/dist/repo-mesh-types.d.ts +616 -12
  199. package/dist/runtime-defaults.d.ts +2 -0
  200. package/dist/session-host/managed-host.d.ts +64 -0
  201. package/dist/session-host/runtime-surface.d.ts +10 -16
  202. package/dist/sessions/registry.d.ts +26 -0
  203. package/dist/shared-types-extra.d.ts +2 -4
  204. package/dist/shared-types.d.ts +110 -55
  205. package/dist/status/chat-tail-hot-sessions.d.ts +40 -0
  206. package/dist/status/normalize.d.ts +1 -1
  207. package/dist/status/normalize.js +1 -0
  208. package/dist/status/normalize.js.map +1 -1
  209. package/dist/status/normalize.mjs +1 -0
  210. package/dist/status/normalize.mjs.map +1 -1
  211. package/dist/status/reporter.d.ts +2 -0
  212. package/dist/status/snapshot.d.ts +27 -0
  213. package/dist/system/hash.d.ts +8 -0
  214. package/dist/system/load-better-sqlite3.d.ts +21 -0
  215. package/dist/types.d.ts +20 -6
  216. package/package.json +11 -4
  217. package/src/agent-stream/poller.ts +2 -3
  218. package/src/agent-stream/provider-adapter.ts +1 -1
  219. package/src/boot/daemon-lifecycle.ts +80 -14
  220. package/src/boot/process-hardening.ts +89 -0
  221. package/src/build-info.ts +73 -0
  222. package/src/chat/source-machine.ts +534 -0
  223. package/src/chat/source-resolver.ts +0 -0
  224. package/src/chat/subscription-updates.ts +20 -1
  225. package/src/cli-adapter-types.d.ts +3 -1
  226. package/src/cli-adapter-types.ts +68 -2
  227. package/src/cli-adapters/cli-script-runner.ts +421 -0
  228. package/src/cli-adapters/cli-state-engine.ts +1282 -0
  229. package/src/cli-adapters/provider-cli-adapter.d.ts +1 -1
  230. package/src/cli-adapters/provider-cli-adapter.ts +1048 -1143
  231. package/src/cli-adapters/provider-cli-parse.d.ts +2 -0
  232. package/src/cli-adapters/provider-cli-parse.ts +19 -0
  233. package/src/cli-adapters/provider-cli-runtime.ts +56 -7
  234. package/src/cli-adapters/provider-cli-shared.d.ts +4 -0
  235. package/src/cli-adapters/provider-cli-shared.ts +121 -11
  236. package/src/cli-adapters/pty-transport.ts +2 -1
  237. package/src/cli-adapters/pty-write-chunking.ts +106 -0
  238. package/src/cli-adapters/raw-terminal-io.ts +252 -0
  239. package/src/cli-adapters/resolve-executable.ts +204 -0
  240. package/src/cli-adapters/session-host-transport.ts +2 -1
  241. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +63 -29
  242. package/src/cli-adapters/terminal-backends/types.ts +10 -3
  243. package/src/cli-adapters/terminal-screen.ts +16 -81
  244. package/src/commands/chat-commands-debug-bundle.ts +398 -0
  245. package/src/commands/chat-commands-read.ts +2788 -0
  246. package/src/commands/chat-commands-scope.ts +54 -0
  247. package/src/commands/chat-commands-shared.ts +114 -0
  248. package/src/commands/chat-commands-write.ts +891 -0
  249. package/src/commands/chat-commands.ts +19 -1841
  250. package/src/commands/cli-manager.d.ts +2 -0
  251. package/src/commands/cli-manager.ts +724 -27
  252. package/src/commands/handler.ts +865 -2
  253. package/src/commands/high-family/index.ts +28 -0
  254. package/src/commands/high-family/mesh-coordinator-launch.ts +696 -0
  255. package/src/commands/high-family/mesh-events.ts +102 -0
  256. package/src/commands/high-family/mesh-status.ts +857 -0
  257. package/src/commands/high-family/types.ts +80 -0
  258. package/src/commands/low-family/coordinator-prompt.ts +125 -0
  259. package/src/commands/low-family/daemon-lifecycle.ts +120 -0
  260. package/src/commands/low-family/diagnostics.ts +57 -0
  261. package/src/commands/low-family/index.ts +37 -0
  262. package/src/commands/low-family/mesh-ledger.ts +62 -0
  263. package/src/commands/low-family/mesh-node-logs.ts +87 -0
  264. package/src/commands/low-family/notification.ts +116 -0
  265. package/src/commands/low-family/refine-config.ts +106 -0
  266. package/src/commands/low-family/session-host.ts +282 -0
  267. package/src/commands/low-family/spec-providerdev.ts +217 -0
  268. package/src/commands/low-family/status-meta.ts +112 -0
  269. package/src/commands/low-family/types.ts +39 -0
  270. package/src/commands/med-family/cli-agent.ts +270 -0
  271. package/src/commands/med-family/fast-forward.ts +230 -0
  272. package/src/commands/med-family/ide.ts +163 -0
  273. package/src/commands/med-family/index.ts +37 -0
  274. package/src/commands/med-family/mesh-crud.ts +1268 -0
  275. package/src/commands/med-family/mesh-host-pairing.ts +234 -0
  276. package/src/commands/med-family/mesh-queue.ts +167 -0
  277. package/src/commands/med-family/mesh-restart.ts +92 -0
  278. package/src/commands/med-family/types.ts +153 -0
  279. package/src/commands/mesh-coordinator.ts +334 -124
  280. package/src/commands/router-aggregate-status.ts +209 -0
  281. package/src/commands/router-mesh-session-owner.ts +114 -0
  282. package/src/commands/router-refine.ts +1794 -0
  283. package/src/commands/router-worktree-cleanup.ts +870 -0
  284. package/src/commands/router.ts +567 -4149
  285. package/src/commands/stream-commands.ts +8 -0
  286. package/src/commands/upgrade-helper.ts +310 -45
  287. package/src/config/chat-history.ts +517 -24
  288. package/src/config/config.ts +30 -0
  289. package/src/config/mesh-config.ts +300 -24
  290. package/src/config/mesh-json-config.ts +376 -0
  291. package/src/config/recent-activity.ts +8 -2
  292. package/src/config/registry-resolver.ts +100 -0
  293. package/src/config/repo-settings.ts +111 -0
  294. package/src/config/state-store.ts +55 -0
  295. package/src/daemon/dev-auto-implement.ts +3 -2
  296. package/src/daemon/dev-cli-debug.ts +10 -1
  297. package/src/daemon/dev-server.ts +0 -541
  298. package/src/detection/cli-detector.ts +94 -9
  299. package/src/detection/ide-detector.ts +55 -16
  300. package/src/detection/win32-ide-version.ts +106 -0
  301. package/src/git/change-impact-config.ts +354 -0
  302. package/src/git/git-commands.ts +112 -16
  303. package/src/git/git-diff.ts +81 -11
  304. package/src/git/git-executor.ts +12 -0
  305. package/src/git/git-status.ts +822 -48
  306. package/src/git/git-types.ts +14 -62
  307. package/src/git/git-worktree.ts +261 -4
  308. package/src/git/index.ts +17 -0
  309. package/src/index.ts +190 -13
  310. package/src/installer.d.ts +1 -1
  311. package/src/installer.ts +8 -6
  312. package/src/ipc/local-ipc-server.ts +278 -0
  313. package/src/launch.d.ts +1 -1
  314. package/src/launch.ts +37 -28
  315. package/src/logging/async-batch-writer.ts +55 -0
  316. package/src/logging/command-log.ts +7 -5
  317. package/src/logging/debug-config.ts +25 -0
  318. package/src/logging/debug-trace.ts +7 -2
  319. package/src/logging/log-redactor.ts +100 -0
  320. package/src/logging/log-tail-reader.ts +341 -0
  321. package/src/logging/logger.ts +14 -7
  322. package/src/mesh/contracts.ts +510 -0
  323. package/src/mesh/coordinator-prompt.ts +627 -34
  324. package/src/mesh/coordinator-registry.ts +121 -0
  325. package/src/mesh/mesh-active-work.ts +706 -0
  326. package/src/mesh/mesh-clone-grace.ts +68 -0
  327. package/src/mesh/mesh-completion-synthesis.ts +416 -0
  328. package/src/mesh/mesh-coordinator-config.ts +97 -0
  329. package/src/mesh/mesh-delivery-policy.ts +284 -0
  330. package/src/mesh/mesh-event-classify.ts +78 -0
  331. package/src/mesh/mesh-event-forwarding.ts +2030 -0
  332. package/src/mesh/mesh-event-trace.ts +67 -0
  333. package/src/mesh/mesh-events-coordinator.ts +32 -0
  334. package/src/mesh/mesh-events-pending.ts +1548 -0
  335. package/src/mesh/mesh-events-stale.ts +452 -0
  336. package/src/mesh/mesh-events-utils.ts +443 -0
  337. package/src/mesh/mesh-events.ts +43 -1035
  338. package/src/mesh/mesh-fast-forward.ts +856 -0
  339. package/src/mesh/mesh-host-ownership.ts +41 -3
  340. package/src/mesh/mesh-init.ts +350 -0
  341. package/src/mesh/mesh-ledger-reconciliation.ts +12 -7
  342. package/src/mesh/mesh-ledger.ts +897 -102
  343. package/src/mesh/mesh-magi-status.ts +223 -0
  344. package/src/mesh/mesh-missions.ts +695 -0
  345. package/src/mesh/mesh-node-identity.ts +2065 -0
  346. package/src/mesh/mesh-queue-assignment.ts +2498 -0
  347. package/src/mesh/mesh-reconcile-acked-hold.ts +230 -0
  348. package/src/mesh/mesh-reconcile-config.ts +66 -0
  349. package/src/mesh/mesh-reconcile-identity.ts +103 -0
  350. package/src/mesh/mesh-reconcile-loop.ts +1696 -0
  351. package/src/mesh/mesh-reconcile-v2-backstop.ts +62 -0
  352. package/src/mesh/mesh-refine-batch.ts +205 -0
  353. package/src/mesh/mesh-refine-gates.ts +1792 -0
  354. package/src/mesh/mesh-refine-status.ts +231 -0
  355. package/src/mesh/mesh-remote-event-pull.ts +279 -0
  356. package/src/mesh/mesh-review-inbox.ts +308 -0
  357. package/src/mesh/mesh-routing.ts +291 -0
  358. package/src/mesh/mesh-runtime-store.ts +2292 -0
  359. package/src/mesh/mesh-scheduling-runtime.ts +198 -0
  360. package/src/mesh/mesh-task-inflight.ts +70 -0
  361. package/src/mesh/mesh-task-stats.ts +161 -0
  362. package/src/mesh/mesh-unresolved-forward-outbox.ts +215 -0
  363. package/src/mesh/mesh-warmup-deadline.ts +152 -0
  364. package/src/mesh/mesh-work-queue.ts +1489 -145
  365. package/src/mesh/preview-freshness.ts +163 -0
  366. package/src/mesh/refine-config.ts +129 -12
  367. package/src/mesh/worktree-bootstrap-config.ts +599 -0
  368. package/src/providers/acp-provider-instance.ts +43 -10
  369. package/src/providers/approval-utils.d.ts +5 -0
  370. package/src/providers/approval-utils.ts +100 -6
  371. package/src/providers/chat-message-normalization.ts +126 -4
  372. package/src/providers/cli-provider-effect-format.ts +53 -0
  373. package/src/providers/cli-provider-history-dedup.ts +75 -0
  374. package/src/providers/cli-provider-input-prompt.ts +133 -0
  375. package/src/providers/cli-provider-instance-types.ts +131 -0
  376. package/src/providers/cli-provider-instance.ts +2771 -499
  377. package/src/providers/cli-provider-status-helpers.ts +123 -0
  378. package/src/providers/cli-provider-transcript-merge.ts +114 -0
  379. package/src/providers/contracts.d.ts +55 -0
  380. package/src/providers/contracts.ts +207 -6
  381. package/src/providers/extension-provider-instance.ts +12 -7
  382. package/src/providers/external-sources.ts +218 -0
  383. package/src/providers/ide-provider-instance.ts +35 -12
  384. package/src/providers/manual-attendance.ts +105 -0
  385. package/src/providers/native-history/antigravity-claim-registry.ts +138 -0
  386. package/src/providers/native-history/antigravity-cli-transcript.ts +1275 -0
  387. package/src/providers/native-history/claude-cli-transcript.ts +396 -0
  388. package/src/providers/native-history/codex-cli-transcript.ts +479 -0
  389. package/src/providers/native-history/constants.ts +19 -0
  390. package/src/providers/native-history/dispatcher.ts +617 -0
  391. package/src/providers/native-history/hermes-cli-transcript.ts +312 -0
  392. package/src/providers/native-history/index.ts +30 -0
  393. package/src/providers/provider-instance-manager.ts +71 -0
  394. package/src/providers/provider-instance.ts +24 -1
  395. package/src/providers/provider-loader.ts +700 -55
  396. package/src/providers/provider-schema.ts +93 -14
  397. package/src/providers/provider-trust.ts +114 -0
  398. package/src/providers/read-chat-contract.ts +76 -16
  399. package/src/providers/sdk/README.md +49 -0
  400. package/src/providers/sdk/v1/builders/acp/detect-status.ts +144 -0
  401. package/src/providers/sdk/v1/builders/cli/detect-status.ts +313 -0
  402. package/src/providers/sdk/v1/builders/cli/parse-approval-squash.ts +158 -0
  403. package/src/providers/sdk/v1/builders/cli/parse-approval.ts +261 -0
  404. package/src/providers/sdk/v1/builders/cli/parse-session.ts +276 -0
  405. package/src/providers/sdk/v1/builders/cli/visible-region.ts +143 -0
  406. package/src/providers/sdk/v1/fixture-tooling/format.ts +130 -0
  407. package/src/providers/sdk/v1/fixture-tooling/index.ts +22 -0
  408. package/src/providers/sdk/v1/fixture-tooling/replay.ts +352 -0
  409. package/src/providers/sdk/v1/index.ts +152 -0
  410. package/src/providers/sdk/v1/sandbox/README-design.ts +195 -0
  411. package/src/providers/sdk/v1/sandbox/require-whitelist.ts +472 -0
  412. package/src/providers/sdk/v1/sandbox/script-runner.ts +150 -0
  413. package/src/providers/sdk/v1/schemas/cli/provider.schema.json +538 -0
  414. package/src/providers/sdk/v1/schemas/primitives/acp-session-protocol-v1.json +131 -0
  415. package/src/providers/sdk/v1/schemas/primitives/native-history-codex-rollout-v1.json +66 -0
  416. package/src/providers/sdk/v1/schemas/primitives/tui-approval-squash-v1.json +91 -0
  417. package/src/providers/sdk/v1/schemas/primitives/tui-assistant-block-v1.json +91 -0
  418. package/src/providers/sdk/v1/schemas/primitives/tui-cue-ordering-v1.json +47 -0
  419. package/src/providers/sdk/v1/schemas/primitives/tui-dispatch-order-v1.json +32 -0
  420. package/src/providers/sdk/v1/schemas/primitives/tui-footer-chrome-v1.json +42 -0
  421. package/src/providers/sdk/v1/schemas/primitives/tui-index-finder-v1.json +27 -0
  422. package/src/providers/sdk/v1/schemas/primitives/tui-modal-v1.json +125 -0
  423. package/src/providers/sdk/v1/schemas/primitives/tui-prompt-marker-v1.json +45 -0
  424. package/src/providers/sdk/v1/schemas/primitives/tui-session-id-extraction-v1.json +46 -0
  425. package/src/providers/sdk/v1/schemas/primitives/tui-settled-prompt-v1.json +71 -0
  426. package/src/providers/sdk/v1/schemas/primitives/tui-spinner-v1.json +83 -0
  427. package/src/providers/sdk/v1/schemas/primitives/tui-transcript-pty-v1.json +83 -0
  428. package/src/providers/sdk/v1/schemas/primitives/tui-visible-region-v1.json +57 -0
  429. package/src/providers/sdk/v1/schemas/primitives/tui-welcome-screen-v1.json +35 -0
  430. package/src/providers/sdk/v1/types/cli/index.ts +365 -0
  431. package/src/providers/sdk/v1/types/common/index.ts +229 -0
  432. package/src/providers/sdk/v1/validators/index.ts +19 -0
  433. package/src/providers/sdk/v1/validators/manifest.ts +110 -0
  434. package/src/providers/sdk/v1/validators/taint.ts +309 -0
  435. package/src/providers/spec/adapter.ts +246 -0
  436. package/src/providers/spec/cli-adapter.ts +1064 -0
  437. package/src/providers/spec/evaluator.ts +407 -0
  438. package/src/providers/spec/fsm-driver.ts +1528 -0
  439. package/src/providers/spec/fsm-evaluator.ts +290 -0
  440. package/src/providers/spec/fsm-loader.ts +128 -0
  441. package/src/providers/spec/fsm-types.ts +301 -0
  442. package/src/providers/spec/native-history-executor.ts +1241 -0
  443. package/src/providers/spec/pre-launch-trust.ts +104 -0
  444. package/src/providers/spec/route.ts +51 -0
  445. package/src/providers/spec/types.ts +284 -0
  446. package/src/providers/status-monitor.d.ts +7 -7
  447. package/src/providers/status-monitor.ts +37 -22
  448. package/src/providers/transcript-v2.ts +567 -0
  449. package/src/providers/types/interactive-prompt.ts +536 -0
  450. package/src/providers/version-archive.ts +64 -24
  451. package/src/providers/working-dir.ts +23 -0
  452. package/src/repo-mesh-types.ts +861 -14
  453. package/src/runtime-defaults.ts +39 -0
  454. package/src/session-host/managed-host.ts +218 -0
  455. package/src/session-host/runtime-surface.ts +20 -80
  456. package/src/sessions/registry.ts +44 -0
  457. package/src/shared-types-extra.ts +2 -4
  458. package/src/shared-types.d.ts +8 -0
  459. package/src/shared-types.ts +148 -55
  460. package/src/status/builders.ts +69 -6
  461. package/src/status/chat-tail-hot-sessions.ts +117 -2
  462. package/src/status/normalize.ts +2 -0
  463. package/src/status/reporter.ts +19 -1
  464. package/src/status/snapshot.ts +100 -27
  465. package/src/system/hash.ts +23 -0
  466. package/src/system/host-memory.ts +29 -12
  467. package/src/system/load-better-sqlite3.ts +68 -0
  468. package/src/types.ts +26 -6
  469. package/dist/cli-adapters/terminal-backends/xterm-backend.d.ts +0 -17
  470. package/dist/mesh/mesh-sync.d.ts +0 -53
  471. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +0 -16
  472. package/src/cli-adapters/terminal-backends/xterm-backend.ts +0 -97
  473. package/src/mesh/mesh-sync.ts +0 -111
@@ -0,0 +1,891 @@
1
+ /**
2
+ * Chat Commands — write side: handleSendChat, handleListChats, handleNewChat,
3
+ * handleSwitchChat, handleSetMode, handleChangeModel, handleSetThoughtLevel,
4
+ * handleResolveAction and the send/mode/model helpers they use.
5
+ */
6
+
7
+ import type { CommandResult, CommandHelpers } from './handler.js';
8
+ import type { CliAdapter } from '../cli-adapter-types.js';
9
+ import { normalizeInputEnvelope, type InputEnvelope, type ProviderModule, type ProviderScripts } from '../providers/contracts.js';
10
+ import { assertProviderSupportsDeclaredInput, assertTextOnlyInput } from '../providers/provider-input-support.js';
11
+ import { pickApprovalButton } from '../providers/approval-utils.js';
12
+ import { LOG } from '../logging/logger.js';
13
+ import {
14
+ READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS,
15
+ type RuntimeChatMessageMerger,
16
+ buildSendInputSignature,
17
+ getCurrentManagerKey,
18
+ getCurrentProviderType,
19
+ getTargetTransport,
20
+ getTargetedCliAdapter,
21
+ getTargetInstance,
22
+ isExtensionTransport,
23
+ parseMaybeJson,
24
+ } from './chat-commands-shared.js';
25
+
26
+ type LegacyStringScript = (params?: Record<string, unknown> | string) => string;
27
+
28
+ const RECENT_SEND_WINDOW_MS = 1200;
29
+ const HERMES_CLI_STARTING_SEND_SETTLE_MS = 2_000;
30
+ const recentSendByTarget = new Map<string, number>();
31
+
32
+ function buildRecentSendKey(h: CommandHelpers, args: any, provider: ProviderModule | undefined, signature: string): string {
33
+ const transport = getTargetTransport(h, provider) || 'unknown';
34
+ const target =
35
+ args?.targetSessionId
36
+ || args?.agentType
37
+ || h.currentSession?.providerType
38
+ || h.currentProviderType
39
+ || h.currentManagerKey
40
+ || 'unknown';
41
+ return `${transport}:${target}:${signature.trim()}`;
42
+ }
43
+
44
+ function getSendChatInputEnvelope(args: any): InputEnvelope {
45
+ return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
46
+ }
47
+
48
+ function sleep(ms: number): Promise<void> {
49
+ return new Promise((resolve) => setTimeout(resolve, ms));
50
+ }
51
+
52
+ async function waitOnceForFreshHermesCliStart(adapter: CliAdapter, log: (msg: string) => void): Promise<void> {
53
+ if (adapter.cliType !== 'hermes-cli') return;
54
+ const status = typeof adapter.getStatus === 'function' ? adapter.getStatus()?.status : undefined;
55
+ if (status !== 'starting') return;
56
+
57
+ log(`Hermes CLI is still starting; waiting ${HERMES_CLI_STARTING_SEND_SETTLE_MS}ms before first send`);
58
+ await sleep(HERMES_CLI_STARTING_SEND_SETTLE_MS);
59
+ }
60
+
61
+ function callLegacyTextScript(script: ProviderScripts[keyof ProviderScripts] | undefined, text: string): string | null {
62
+ if (typeof script !== 'function') return null;
63
+ return (script as LegacyStringScript)(text);
64
+ }
65
+
66
+ function isRecentDuplicateSend(key: string): boolean {
67
+ const now = Date.now();
68
+ for (const [candidate, ts] of recentSendByTarget.entries()) {
69
+ if (now - ts > RECENT_SEND_WINDOW_MS) recentSendByTarget.delete(candidate);
70
+ }
71
+ const previous = recentSendByTarget.get(key);
72
+ if (previous && (now - previous) <= RECENT_SEND_WINDOW_MS) return true;
73
+ recentSendByTarget.set(key, now);
74
+ return false;
75
+ }
76
+
77
+ function didProviderConfirmSend(result: any): boolean {
78
+ const parsed = parseMaybeJson(result);
79
+ if (parsed === true) return true;
80
+ if (typeof parsed === 'string') {
81
+ const normalized = parsed.trim().toLowerCase();
82
+ return normalized === 'ok' || normalized === 'sent' || normalized === 'success' || normalized === 'true';
83
+ }
84
+ if (!parsed || typeof parsed !== 'object') return false;
85
+
86
+ return parsed.sent === true
87
+ || parsed.success === true
88
+ || parsed.ok === true
89
+ || parsed.submitted === true
90
+ || parsed.dispatched === true;
91
+ }
92
+
93
+ async function readExtensionChatState(h: CommandHelpers): Promise<any | null> {
94
+ try {
95
+ const evalResult = await h.evaluateProviderScript('readChat', undefined, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS);
96
+ if (!evalResult?.result) return null;
97
+ const parsed = parseMaybeJson(evalResult.result);
98
+ return parsed && typeof parsed === 'object' ? parsed : null;
99
+ } catch {
100
+ return null;
101
+ }
102
+ }
103
+
104
+ function getStateMessageCount(state: any): number {
105
+ return Array.isArray(state?.messages) ? state.messages.length : 0;
106
+ }
107
+
108
+ function getStateLastSignature(state: any): string {
109
+ const messages = Array.isArray(state?.messages) ? state.messages : [];
110
+ const last = messages[messages.length - 1];
111
+ if (!last) return '';
112
+ return `${last.role || ''}:${String(last.content || '').replace(/\s+/g, ' ').trim()}`;
113
+ }
114
+
115
+ async function getStableExtensionBaseline(h: CommandHelpers): Promise<any | null> {
116
+ const first = await readExtensionChatState(h);
117
+ if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
118
+ await new Promise((resolve) => setTimeout(resolve, 150));
119
+ const second = await readExtensionChatState(h);
120
+ return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
121
+ }
122
+
123
+ async function verifyExtensionSendObserved(h: CommandHelpers, before: any): Promise<boolean> {
124
+ const beforeCount = getStateMessageCount(before);
125
+ const beforeSignature = getStateLastSignature(before);
126
+ for (let attempt = 0; attempt < 12; attempt += 1) {
127
+ await new Promise((resolve) => setTimeout(resolve, 250));
128
+ const state = await readExtensionChatState(h);
129
+ if (state?.status === 'waiting_approval') return true;
130
+ const afterCount = getStateMessageCount(state);
131
+ const afterSignature = getStateLastSignature(state);
132
+ if (afterCount > beforeCount) return true;
133
+ if (afterSignature && afterSignature !== beforeSignature) return true;
134
+ }
135
+ return false;
136
+ }
137
+
138
+ export async function handleSendChat(h: CommandHelpers, args: any): Promise<CommandResult> {
139
+ const input = getSendChatInputEnvelope(args);
140
+ const text = input.textFallback;
141
+ const hasInput = input.parts.length > 0 || (typeof text === 'string' && text.trim().length > 0);
142
+ if (!hasInput) return { success: false, error: 'input required' };
143
+ const _log = (msg: string) => LOG.debug('Command', `[send_chat] ${msg}`);
144
+ const provider = h.getProvider(args?.agentType);
145
+ const transport = getTargetTransport(h, provider);
146
+ const dedupeKey = buildRecentSendKey(h, args, provider, buildSendInputSignature(input));
147
+
148
+ const _logSendSuccess = (method: string, targetAgent?: string) => {
149
+ // Sending and transcript persistence are intentionally decoupled.
150
+ // User turns should reach history through read_chat/runtime transcript sync,
151
+ // not by eagerly appending the outgoing input here.
152
+ return { success: true, sent: true, method, targetAgent };
153
+ };
154
+
155
+ if (isRecentDuplicateSend(dedupeKey)) {
156
+ _log(`Suppressed duplicate send for ${dedupeKey}`);
157
+ return { success: true, sent: false, deduplicated: true };
158
+ }
159
+
160
+ if (transport === 'acp') {
161
+ const target = getTargetInstance(h, args);
162
+ if (!target || target.category !== 'acp') {
163
+ return { success: false, error: `ACP instance not found for ${provider?.type || args?.agentType || 'unknown'}` };
164
+ }
165
+ try {
166
+ assertProviderSupportsDeclaredInput(provider, input);
167
+ target.onEvent('send_message', { input });
168
+ return _logSendSuccess('acp-instance', target.type);
169
+ } catch (e: any) {
170
+ return { success: false, error: `acp send failed: ${e.message}` };
171
+ }
172
+ }
173
+
174
+ // PTY transport: route structured input through the provider instance so
175
+ // provider-specific CLI attachment strategies (for example Hermes file-path
176
+ // image prompts) are applied instead of collapsing everything to text.
177
+ if (transport === 'pty') {
178
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
179
+ if (adapter) {
180
+ _log(`${transport} adapter: ${adapter.cliType}`);
181
+ try {
182
+ const hasStructuredParts = input.parts.some((part) => part.type !== 'text');
183
+ if (hasStructuredParts) {
184
+ const target = getTargetInstance(h, args);
185
+ if (!target || target.category !== 'cli') {
186
+ return { success: false, error: `CLI instance not found for ${provider?.type || args?.agentType || 'unknown'}` };
187
+ }
188
+ assertProviderSupportsDeclaredInput(provider, input);
189
+ await waitOnceForFreshHermesCliStart(adapter, _log);
190
+ target.onEvent('send_message', { input });
191
+ return _logSendSuccess(`${transport}-instance`, target.type);
192
+ }
193
+ assertTextOnlyInput(provider, input);
194
+ if (!text) return { success: false, error: 'text required for PTY send' };
195
+ await waitOnceForFreshHermesCliStart(adapter, _log);
196
+ const forceSend = args?.force === true || args?.forceSend === true;
197
+ if (forceSend && typeof adapter.forceSendMessage === 'function') {
198
+ await adapter.forceSendMessage(text);
199
+ } else if (forceSend) {
200
+ await adapter.sendMessage(text, { force: true });
201
+ } else {
202
+ await adapter.sendMessage(text);
203
+ }
204
+ const target = getTargetInstance(h, args) as RuntimeChatMessageMerger | null;
205
+ if (target?.category === 'cli'
206
+ && target.type === adapter.cliType
207
+ && typeof target.recordAcknowledgedUserInput === 'function') {
208
+ target.recordAcknowledgedUserInput(input);
209
+ }
210
+ return {
211
+ ..._logSendSuccess(`${transport}-adapter`, adapter.cliType),
212
+ ...(forceSend ? { forceSent: true } : {}),
213
+ };
214
+ } catch (e: any) {
215
+ return { success: false, error: `${transport} send failed: ${e.message}` };
216
+ }
217
+ }
218
+ }
219
+
220
+ assertTextOnlyInput(provider, input);
221
+ if (!text) return { success: false, error: 'text required' };
222
+
223
+ // Extension transport: via AgentStreamManager
224
+ if (isExtensionTransport(transport)) {
225
+ _log(`Extension: ${provider?.type || 'unknown_extension'}`);
226
+ // Method 1: provider sendMessage script via evaluateInSession
227
+ try {
228
+ const beforeState = await getStableExtensionBaseline(h);
229
+ const evalResult = await h.evaluateProviderScript('sendMessage', { message: text }, 30000);
230
+ if (evalResult?.result) {
231
+ const parsed = parseMaybeJson(evalResult.result);
232
+ if (didProviderConfirmSend(parsed)) {
233
+ const observed = await verifyExtensionSendObserved(h, beforeState);
234
+ if (observed) {
235
+ _log(`Extension script sent OK`);
236
+ return _logSendSuccess('extension-script');
237
+ }
238
+ _log(`Extension script reported send but no chat-state change was observed`);
239
+ }
240
+ if (parsed?.needsTypeAndSend) {
241
+ _log(`Extension needsTypeAndSend → AgentStreamManager`);
242
+ }
243
+ }
244
+ } catch (e: any) {
245
+ _log(`Extension script error: ${e.message}`);
246
+ }
247
+ // Method 2: AgentStreamManager
248
+ const extensionSessionId = h.currentSession?.sessionId;
249
+ if (h.agentStream && h.getCdp() && extensionSessionId) {
250
+ const ok = await h.agentStream.sendToSession(h.getCdp()!, extensionSessionId, text);
251
+ if (ok) {
252
+ _log(`AgentStreamManager sent OK`);
253
+ return _logSendSuccess('agent-stream');
254
+ }
255
+ }
256
+ return { success: false, error: `Extension '${provider?.type || 'unknown_extension'}' send failed` };
257
+ }
258
+
259
+ // IDE category (default): provider sendMessage script is authoritative when present.
260
+ const targetCdp = h.getCdp();
261
+ if (!targetCdp?.isConnected) {
262
+ const managerKey = getCurrentManagerKey(h);
263
+ _log(`No CDP for ${managerKey}`);
264
+ return { success: false, error: `CDP for ${managerKey || 'unknown'} not connected` };
265
+ }
266
+
267
+ _log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
268
+ const sendScript = h.getProviderScript('sendMessage', { message: text });
269
+ if (sendScript) {
270
+ try {
271
+ const result = await targetCdp.evaluate(sendScript, 30000);
272
+ const parsed: any = parseMaybeJson(result);
273
+ if (didProviderConfirmSend(parsed)) {
274
+ _log(`sendMessage script OK`);
275
+ return _logSendSuccess('script');
276
+ }
277
+ if (parsed?.needsTypeAndSend && parsed?.selector) {
278
+ try {
279
+ const sent = await targetCdp.typeAndSend(parsed.selector, text);
280
+ if (sent) {
281
+ _log(`typeAndSend(script.selector=${parsed.selector}) success`);
282
+ return _logSendSuccess('typeAndSend-script');
283
+ }
284
+ } catch (e: any) {
285
+ _log(`typeAndSend(script.selector) failed: ${e.message}`);
286
+ }
287
+ }
288
+ if (parsed?.needsTypeAndSend && parsed?.clickCoords) {
289
+ try {
290
+ const { x, y } = parsed.clickCoords;
291
+ const sent = await targetCdp.typeAndSendAt(x, y, text);
292
+ if (sent) {
293
+ _log(`typeAndSendAt(${x},${y}) success`);
294
+ return _logSendSuccess('typeAndSendAt-script');
295
+ }
296
+ } catch (e: any) {
297
+ _log(`typeAndSendAt failed: ${e.message}`);
298
+ }
299
+ }
300
+ if (parsed?.needsTypeAndSend && provider?.inputMethod === 'cdp-type-and-send' && provider.inputSelector) {
301
+ try {
302
+ const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
303
+ if (sent) {
304
+ _log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
305
+ return _logSendSuccess('typeAndSend-provider');
306
+ }
307
+ } catch (e: any) {
308
+ _log(`typeAndSend(provider) failed: ${e.message}`);
309
+ }
310
+ }
311
+ if (parsed?.needsTypeAndSend && provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
312
+ try {
313
+ const webviewScript = callLegacyTextScript(provider.scripts.webviewSendMessage, text);
314
+ if (webviewScript && targetCdp.evaluateInWebviewFrame) {
315
+ const matchText = provider.webviewMatchText;
316
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
317
+ const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
318
+ const wvParsed: any = parseMaybeJson(wvResult);
319
+ if (didProviderConfirmSend(wvParsed)) {
320
+ _log(`webviewSendMessage OK`);
321
+ return _logSendSuccess('webview-script');
322
+ }
323
+ }
324
+ } catch (e: any) {
325
+ _log(`webviewSendMessage failed: ${e.message}`);
326
+ }
327
+ }
328
+ return { success: false, error: parsed?.error || 'Provider sendMessage did not confirm send' };
329
+ } catch (e: any) {
330
+ _log(`sendMessage script failed: ${e.message}`);
331
+ return { success: false, error: `Provider sendMessage failed: ${e.message}` };
332
+ }
333
+ }
334
+
335
+ if (provider?.webviewMatchText && provider?.scripts?.webviewSendMessage) {
336
+ try {
337
+ const webviewScript = callLegacyTextScript(provider.scripts.webviewSendMessage, text);
338
+ if (webviewScript && targetCdp.evaluateInWebviewFrame) {
339
+ const matchText = provider.webviewMatchText;
340
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
341
+ const wvResult = await targetCdp.evaluateInWebviewFrame(webviewScript, matchFn);
342
+ const wvParsed: any = parseMaybeJson(wvResult);
343
+ if (didProviderConfirmSend(wvParsed)) {
344
+ _log(`webviewSendMessage OK`);
345
+ return _logSendSuccess('webview-script');
346
+ }
347
+ }
348
+ } catch (e: any) {
349
+ _log(`webviewSendMessage failed: ${e.message}`);
350
+ }
351
+ }
352
+
353
+ if (provider?.inputMethod === 'cdp-type-and-send' && provider.inputSelector) {
354
+ try {
355
+ const sent = await targetCdp.typeAndSend(provider.inputSelector, text);
356
+ if (sent) {
357
+ _log(`typeAndSend(provider.inputSelector=${provider.inputSelector}) success`);
358
+ return _logSendSuccess('typeAndSend-provider');
359
+ }
360
+ } catch (e: any) {
361
+ _log(`typeAndSend(provider) failed: ${e.message}`);
362
+ }
363
+ }
364
+
365
+ _log('All methods failed');
366
+ return { success: false, error: 'No provider method could send the message' };
367
+ }
368
+
369
+ export async function handleListChats(h: CommandHelpers, args: any): Promise<CommandResult> {
370
+ const provider = h.getProvider(args?.agentType);
371
+ const transport = getTargetTransport(h, provider);
372
+
373
+ // Extension transport: via AgentStreamManager
374
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
375
+ try {
376
+ const chats = await h.agentStream.listSessionChats(h.getCdp()!, h.currentSession.sessionId);
377
+ LOG.info('Command', `[list_chats] Extension: ${chats.length} chats`);
378
+ return { success: true, chats };
379
+ } catch (e: any) {
380
+ LOG.info('Command', `[list_chats] Extension error: ${e.message}`);
381
+ }
382
+ }
383
+
384
+ // webview IDE
385
+ try {
386
+ const webviewScript = h.getProviderScript('webviewListSessions') || h.getProviderScript('webview_list_sessions');
387
+ if (webviewScript) {
388
+ const matchText = provider?.webviewMatchText;
389
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
390
+ const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
391
+ let parsed: any = raw;
392
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
393
+ if (parsed?.sessions) {
394
+ LOG.info('Command', `[list_chats] Webview OK: ${parsed.sessions.length} chats`);
395
+ return { success: true, chats: parsed.sessions };
396
+ }
397
+ }
398
+ } catch (e: any) {
399
+ LOG.info('Command', `[list_chats] Webview error: ${e.message}`);
400
+ }
401
+
402
+ // IDE/default: evaluateProviderScript
403
+ try {
404
+ const evalResult = await h.evaluateProviderScript('listSessions');
405
+ if (evalResult) {
406
+ let parsed = evalResult.result;
407
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
408
+ if (parsed?.sessions && Array.isArray(parsed.sessions)) {
409
+ LOG.info('Command', `[list_chats] OK: ${parsed.sessions.length} chats`);
410
+ return { success: true, chats: parsed.sessions };
411
+ }
412
+ if (parsed?.chats && Array.isArray(parsed.chats)) {
413
+ LOG.info('Command', `[list_chats] OK: ${parsed.chats.length} chats`);
414
+ return { success: true, chats: parsed.chats };
415
+ }
416
+ if (Array.isArray(parsed)) {
417
+ LOG.info('Command', `[list_chats] OK: ${parsed.length} chats`);
418
+ return { success: true, chats: parsed };
419
+ }
420
+ }
421
+ } catch (e: any) {
422
+ LOG.info('Command', `[list_chats] error: ${e.message}`);
423
+ }
424
+
425
+ return { success: false, error: 'listSessions script not available for this provider' };
426
+ }
427
+
428
+ export async function handleNewChat(h: CommandHelpers, args: any): Promise<CommandResult> {
429
+ const provider = h.getProvider(args?.agentType);
430
+ const transport = getTargetTransport(h, provider);
431
+
432
+ if (transport === 'pty') {
433
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
434
+ if (!adapter) return { success: false, error: 'CLI adapter not running' };
435
+ if (typeof adapter.clearHistory === 'function') {
436
+ adapter.clearHistory();
437
+ return { success: true, cleared: true };
438
+ }
439
+ return { success: false, error: 'new_chat not supported by this CLI provider' };
440
+ }
441
+
442
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
443
+ const ok = await h.agentStream.newSession(h.getCdp()!, h.currentSession.sessionId);
444
+ return { success: ok };
445
+ }
446
+
447
+ // webview IDE
448
+ try {
449
+ const webviewScript = h.getProviderScript('webviewNewSession') || h.getProviderScript('webview_new_session');
450
+ if (webviewScript) {
451
+ const matchText = provider?.webviewMatchText;
452
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
453
+ const raw = await h.getCdp()?.evaluateInWebviewFrame?.(webviewScript, matchFn);
454
+ if (raw) return { success: true, result: raw };
455
+ }
456
+ } catch (e: any) {
457
+ return { success: false, error: `webviewNewSession failed: ${e.message}` };
458
+ }
459
+
460
+ try {
461
+ const evalResult = await h.evaluateProviderScript('newSession');
462
+ if (evalResult) return { success: true };
463
+ } catch (e: any) {
464
+ return { success: false, error: `newSession failed: ${e.message}` };
465
+ }
466
+
467
+ return { success: false, error: 'newSession script not available for this provider' };
468
+ }
469
+
470
+ export async function handleSwitchChat(h: CommandHelpers, args: any): Promise<CommandResult> {
471
+ const provider = h.getProvider(args?.agentType);
472
+ const transport = getTargetTransport(h, provider);
473
+ const managerKey = getCurrentManagerKey(h);
474
+ const sessionId = args?.sessionId || args?.id || args?.chatId;
475
+ if (!sessionId) return { success: false, error: 'sessionId required' };
476
+ LOG.info('Command', `[switch_chat] sessionId=${sessionId}, manager=${managerKey}`);
477
+
478
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
479
+ const ok = await h.agentStream.switchConversation(h.getCdp()!, h.currentSession.sessionId, sessionId);
480
+ return { success: ok, result: ok ? 'switched' : 'failed' };
481
+ }
482
+
483
+ const cdp = h.getCdp(managerKey);
484
+ if (!cdp?.isConnected) return { success: false, error: 'CDP not connected' };
485
+
486
+ // webview IDE
487
+ try {
488
+ const webviewScript = h.getProviderScript('webviewSwitchSession', { SESSION_ID: JSON.stringify(sessionId) });
489
+ if (webviewScript) {
490
+ const matchText = provider?.webviewMatchText;
491
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
492
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
493
+ if (raw) return { success: true, result: raw };
494
+ }
495
+ } catch (e: any) {
496
+ return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
497
+ }
498
+
499
+ const switchParams = {
500
+ sessionId,
501
+ title: sessionId,
502
+ id: sessionId,
503
+ SESSION_ID: JSON.stringify(sessionId),
504
+ };
505
+ const script = h.getProviderScript('switchSession', switchParams)
506
+ || h.getProviderScript('switch_session', switchParams);
507
+ if (!script) return { success: false, error: 'switch_session script not available' };
508
+
509
+ try {
510
+ const raw = await cdp.evaluate(script, 15000);
511
+ LOG.info('Command', `[switch_chat] result: ${raw}`);
512
+
513
+ let parsed: any = null;
514
+ try { parsed = typeof raw === 'string' ? JSON.parse(raw) : raw; } catch { }
515
+
516
+ if (parsed?.action === 'click' && parsed.clickX && parsed.clickY) {
517
+ const x = Math.round(parsed.clickX);
518
+ const y = Math.round(parsed.clickY);
519
+ LOG.info('Command', `[switch_chat] CDP click at (${x}, ${y}) for "${parsed.title}"`);
520
+ await cdp.send('Input.dispatchMouseEvent', {
521
+ type: 'mousePressed', x, y, button: 'left', clickCount: 1
522
+ });
523
+ await cdp.send('Input.dispatchMouseEvent', {
524
+ type: 'mouseReleased', x, y, button: 'left', clickCount: 1
525
+ });
526
+ await new Promise(r => setTimeout(r, 2000));
527
+
528
+ // Auto-handle workspace selection dialog
529
+ const wsResult = await cdp.evaluate(`
530
+ (() => {
531
+ const inp = Array.from(document.querySelectorAll('input[type="text"]'))
532
+ .find(i => i.offsetWidth > 0 && (i.placeholder || '').includes('Select where'));
533
+ if (!inp) return null;
534
+ const rows = inp.closest('[class*="quickInput"]')?.querySelectorAll('[class*="cursor-pointer"]');
535
+ if (rows && rows.length > 0) {
536
+ const r = rows[0].getBoundingClientRect();
537
+ return JSON.stringify({ x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) });
538
+ }
539
+ return null;
540
+ })()
541
+ `, 5000);
542
+ if (wsResult) {
543
+ try {
544
+ const ws = JSON.parse(wsResult as string);
545
+ await cdp.send('Input.dispatchMouseEvent', {
546
+ type: 'mousePressed', x: ws.x, y: ws.y, button: 'left', clickCount: 1
547
+ });
548
+ await cdp.send('Input.dispatchMouseEvent', {
549
+ type: 'mouseReleased', x: ws.x, y: ws.y, button: 'left', clickCount: 1
550
+ });
551
+ } catch { }
552
+ }
553
+ return { success: true, result: 'switched' };
554
+ }
555
+
556
+ if (parsed?.error) return { success: false, error: parsed.error };
557
+ return { success: true, result: raw };
558
+ } catch (e: any) {
559
+ LOG.error('Command', `[switch_chat] error: ${e.message}`);
560
+ return { success: false, error: e.message };
561
+ }
562
+ }
563
+
564
+ export async function handleSetMode(h: CommandHelpers, args: any): Promise<CommandResult> {
565
+ const provider = h.getProvider(args?.agentType);
566
+ const transport = getTargetTransport(h, provider);
567
+ const mode = args?.mode || 'agent';
568
+
569
+ // ACP transport
570
+ if (transport === 'acp') {
571
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
572
+ const acpInstance = adapter?._acpInstance;
573
+ if (acpInstance && typeof acpInstance.setMode === 'function') {
574
+ await acpInstance.setMode(mode);
575
+ return { success: true, mode };
576
+ }
577
+ return { success: false, error: 'ACP adapter not found' };
578
+ }
579
+
580
+ // 1. webview setMode
581
+ const webviewScript = h.getProviderScript('webviewSetMode', { MODE: JSON.stringify(mode) });
582
+ if (webviewScript) {
583
+ const cdp = h.getCdp();
584
+ if (cdp?.isConnected) {
585
+ try {
586
+ const matchText = provider?.webviewMatchText;
587
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
588
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
589
+ let result: any = raw;
590
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
591
+ if (result?.success) return { success: true, mode, method: 'webview-script' };
592
+ } catch (e: any) {
593
+ LOG.info('Command', `[set_mode] webview script error: ${e.message}`);
594
+ }
595
+ }
596
+ }
597
+
598
+ // 2. main frame setMode
599
+ const mainScript = h.getProviderScript('setMode', { MODE: JSON.stringify(mode) });
600
+ if (mainScript) {
601
+ try {
602
+ const evalResult = await h.evaluateProviderScript('setMode', { MODE: JSON.stringify(mode) }, 15000);
603
+ if (evalResult?.result) {
604
+ let parsed = evalResult.result;
605
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
606
+ if (parsed?.success) return { success: true, mode, method: 'script' };
607
+ }
608
+ } catch (e: any) {
609
+ LOG.info('Command', `[set_mode] script error: ${e.message}`);
610
+ }
611
+ }
612
+
613
+ return { success: false, error: `setMode '${mode}' not supported by this provider` };
614
+ }
615
+
616
+ export async function handleChangeModel(h: CommandHelpers, args: any): Promise<CommandResult> {
617
+ const provider = h.getProvider(args?.agentType);
618
+ const transport = getTargetTransport(h, provider);
619
+ const model = args?.model;
620
+
621
+ LOG.info('Command', `[change_model] model=${model} provider=${provider?.type} transport=${transport} manager=${getCurrentManagerKey(h)} providerType=${getCurrentProviderType(h)}`);
622
+
623
+ // ACP transport
624
+ if (transport === 'acp') {
625
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
626
+ LOG.info('Command', `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
627
+ const acpInstance = adapter?._acpInstance;
628
+ if (acpInstance && typeof acpInstance.setConfigOption === 'function') {
629
+ await acpInstance.setConfigOption('model', model);
630
+ LOG.info('Command', `[change_model] Updated ACP model to ${model}`);
631
+ return { success: true, model };
632
+ }
633
+ return { success: false, error: 'ACP adapter not found' };
634
+ }
635
+
636
+ // 1. webview setModel
637
+ const webviewScript = h.getProviderScript('webviewSetModel', { MODEL: JSON.stringify(model) });
638
+ if (webviewScript) {
639
+ const cdp = h.getCdp();
640
+ if (cdp?.isConnected) {
641
+ try {
642
+ const matchText = provider?.webviewMatchText;
643
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
644
+ const raw = await cdp.evaluateInWebviewFrame?.(webviewScript, matchFn);
645
+ let result: any = raw;
646
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
647
+ if (result?.success) return { success: true, model, method: 'webview-script' };
648
+ } catch (e: any) {
649
+ LOG.info('Command', `[change_model] webview script error: ${e.message}`);
650
+ }
651
+ }
652
+ }
653
+
654
+ // 2. main frame setModel
655
+ const mainScript = h.getProviderScript('setModel', { MODEL: JSON.stringify(model) });
656
+ if (mainScript) {
657
+ try {
658
+ const evalResult = await h.evaluateProviderScript('setModel', { MODEL: JSON.stringify(model) }, 15000);
659
+ if (evalResult?.result) {
660
+ let parsed = evalResult.result;
661
+ if (typeof parsed === 'string') { try { parsed = JSON.parse(parsed); } catch { } }
662
+ if (parsed?.success) return { success: true, model, method: 'script' };
663
+ }
664
+ } catch (e: any) {
665
+ LOG.info('Command', `[change_model] script error: ${e.message}`);
666
+ }
667
+ }
668
+
669
+ return { success: false, error: 'changeModel not supported by this IDE provider' };
670
+ }
671
+
672
+ export async function handleSetThoughtLevel(h: CommandHelpers, args: any): Promise<CommandResult> {
673
+ const configId = args?.configId;
674
+ const value = args?.value;
675
+ if (!configId || !value) return { success: false, error: 'configId and value required' };
676
+
677
+ const provider = h.getProvider(args?.agentType);
678
+ const transport = getTargetTransport(h, provider);
679
+ if (transport !== 'acp') {
680
+ return { success: false, error: 'set_thought_level only for ACP providers' };
681
+ }
682
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
683
+ const acpInstance = adapter?._acpInstance;
684
+ if (!acpInstance) return { success: false, error: 'ACP instance not found' };
685
+ if (typeof acpInstance.setConfigOption !== 'function') {
686
+ return { success: false, error: 'ACP setConfigOption not available' };
687
+ }
688
+
689
+ try {
690
+ await acpInstance.setConfigOption(configId, value);
691
+ LOG.info('Command', `[set_thought_level] ${configId}=${value} for ${provider?.type || 'unknown_acp'}`);
692
+ return { success: true, configId, value };
693
+ } catch (e: any) {
694
+ return { success: false, error: e?.message };
695
+ }
696
+ }
697
+
698
+ export async function handleResolveAction(h: CommandHelpers, args: any): Promise<CommandResult> {
699
+ const provider = h.getProvider(args?.agentType);
700
+ const transport = getTargetTransport(h, provider);
701
+ const action = args?.action || 'approve';
702
+ const button = args?.button || args?.buttonText
703
+ || (action === 'approve' ? 'Accept' : action === 'reject' ? 'Reject' : 'Accept');
704
+
705
+ LOG.info('Command', `[resolveAction] action=${action} button="${button}" provider=${provider?.type}`);
706
+
707
+ // 0. PTY transport: navigate approval dialog via PTY arrow keys + Enter
708
+ if (transport === 'pty') {
709
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
710
+ if (!adapter) return { success: false, error: 'CLI adapter not running' };
711
+
712
+ // Handle data-driven resolve actions (like from the dashboard 'Fix' button)
713
+ if (args?.data && typeof adapter.resolveAction === 'function') {
714
+ try {
715
+ await adapter.resolveAction(args.data);
716
+ LOG.info('Command', `[resolveAction] CLI PTY → resolveAction triggered with data payload`);
717
+ return { success: true, method: 'cli-resolve-action' };
718
+ } catch (e: any) {
719
+ return { success: false, error: `CLI resolveAction failed: ${e.message}` };
720
+ }
721
+ }
722
+
723
+ const status = adapter.getStatus();
724
+ const targetInstance = getTargetInstance(h, args);
725
+ const targetState = targetInstance?.getState?.() as { activeChat?: { status?: string; activeModal?: { message?: string; buttons?: string[] } | null } } | undefined;
726
+ const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons)
727
+ && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === 'string' && candidate.trim())
728
+ ? targetState.activeChat.activeModal
729
+ : null;
730
+ const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons)
731
+ && status.activeModal.buttons.some((candidate) => typeof candidate === 'string' && candidate.trim())
732
+ ? status.activeModal
733
+ : null;
734
+ const parsedStatus = !statusModal && !surfacedModal && typeof adapter.getScriptParsedStatus === 'function'
735
+ ? (() => {
736
+ try {
737
+ return parseMaybeJson(adapter.getScriptParsedStatus());
738
+ } catch {
739
+ return null;
740
+ }
741
+ })()
742
+ : null;
743
+ const parsedModal = parsedStatus?.status === 'waiting_approval'
744
+ && parsedStatus?.activeModal
745
+ && Array.isArray(parsedStatus.activeModal.buttons)
746
+ && parsedStatus.activeModal.buttons.some((candidate: unknown) => typeof candidate === 'string' && candidate.trim())
747
+ ? parsedStatus.activeModal
748
+ : null;
749
+ const effectiveModal = statusModal || surfacedModal || parsedModal;
750
+ const effectiveStatus = status?.status === 'waiting_approval' || targetState?.activeChat?.status === 'waiting_approval' || parsedStatus?.status === 'waiting_approval'
751
+ ? 'waiting_approval'
752
+ : status?.status;
753
+ LOG.info('Command', `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || '')} rawStatus=${String(status?.status || '')} effectiveStatus=${String(effectiveStatus || '')} statusModal=${statusModal ? 'yes' : 'no'} surfacedModal=${surfacedModal ? 'yes' : 'no'} parsedModal=${parsedModal ? 'yes' : 'no'} instance=${targetInstance ? 'yes' : 'no'}`);
754
+ if (!effectiveModal) {
755
+ // APPROVAL Defect-B (live re-probe race): the modal is gone because the worker
756
+ // already resolved this very approval moments ago (delegated auto-approve fired,
757
+ // or a prior resolveAction landed) and the coordinator's approve raced in just
758
+ // after. That is NOT a caller error — return a SOFT already_resolved result so the
759
+ // coordinator does not hard-fail the task on a benign race. Mirrors the in-modal
760
+ // idempotency guard below (isApprovalRecentlyResolved → stalePrompt). Only a session
761
+ // that never had a recently-resolved approval reports the hard 'Not in approval state'.
762
+ if (typeof adapter.isApprovalRecentlyResolved === 'function' && adapter.isApprovalRecentlyResolved()) {
763
+ LOG.info('Command', `[resolveAction] CLI PTY → already_resolved (modal gone, resolved within cooldown)`);
764
+ return { success: true, alreadyResolved: true, status: 'already_resolved' };
765
+ }
766
+ return { success: false, error: 'Not in approval state' };
767
+ }
768
+ const buttons: string[] = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
769
+ // Resolve button index: explicit buttonIndex arg → exact text match → explicit action mapping
770
+ let buttonIndex = typeof args?.buttonIndex === 'number' ? args.buttonIndex : -1;
771
+ if (buttonIndex < 0 && button) {
772
+ const btnLower = button.toLowerCase();
773
+ buttonIndex = buttons.findIndex(b => b.toLowerCase().includes(btnLower));
774
+ }
775
+ if (buttonIndex < 0 && (action === 'reject' || action === 'deny')) {
776
+ buttonIndex = buttons.findIndex(b => /deny|reject|no/i.test(b));
777
+ }
778
+ if (buttonIndex < 0 && (action === 'always' || /always/i.test(button))) {
779
+ buttonIndex = buttons.findIndex(b => /always/i.test(b));
780
+ }
781
+ if (buttonIndex < 0 && (action === 'approve' || action === 'accept')) {
782
+ buttonIndex = pickApprovalButton(buttons, provider).index;
783
+ }
784
+ if (buttonIndex < 0) {
785
+ return { success: false, error: 'Approval action did not match any visible button' };
786
+ }
787
+ // Idempotency: if the adapter already resolved this approval within cooldown, report
788
+ // stale_prompt rather than writing a second key to the PTY.
789
+ if (typeof adapter.isApprovalRecentlyResolved === 'function' && adapter.isApprovalRecentlyResolved()) {
790
+ LOG.info('Command', `[resolveAction] CLI PTY → stale_prompt (already resolved within cooldown)`);
791
+ return { success: true, stalePrompt: true, buttonIndex, button: buttons[buttonIndex] ?? button };
792
+ }
793
+ if (typeof adapter.resolveModal === 'function') {
794
+ adapter.resolveModal(buttonIndex);
795
+ } else {
796
+ const keys = '\x1B[B'.repeat(Math.max(0, buttonIndex)) + '\r';
797
+ adapter.writeRaw?.(keys);
798
+ }
799
+ LOG.info('Command', `[resolveAction] CLI PTY → buttonIndex=${buttonIndex} "${buttons[buttonIndex] ?? '?'}"`);
800
+ getTargetInstance(h, args)?.recordApprovalSelection?.(buttons[buttonIndex] ?? button);
801
+ return { success: true, buttonIndex, button: buttons[buttonIndex] ?? button };
802
+ }
803
+
804
+ // 1. Extension transport: via AgentStreamManager
805
+ if (isExtensionTransport(transport) && h.agentStream && h.getCdp() && h.currentSession?.sessionId) {
806
+ const ok = await h.agentStream.resolveSessionAction(h.getCdp()!, h.currentSession.sessionId, action, button);
807
+ return { success: ok };
808
+ }
809
+
810
+ // 1.5 ACP transport: resolve protocol permission request directly
811
+ if (transport === 'acp') {
812
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
813
+ const acpInstance = adapter?._acpInstance;
814
+ if (!acpInstance) return { success: false, error: 'ACP instance not found' };
815
+ if (typeof acpInstance.resolvePermission !== 'function') {
816
+ return { success: false, error: 'ACP resolvePermission not available' };
817
+ }
818
+
819
+ try {
820
+ await acpInstance.resolvePermission(action === 'approve' || action === 'accept' || action === 'always');
821
+ LOG.info('Command', `[resolveAction] ACP → ${action}`);
822
+ return { success: true, action };
823
+ } catch (e: any) {
824
+ return { success: false, error: e?.message || 'ACP resolve action failed' };
825
+ }
826
+ }
827
+
828
+ // 2. Webview Provider script
829
+ if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
830
+ const script = h.getProviderScript('webviewResolveAction', { action, button, buttonText: button })
831
+ || h.getProviderScript('webview_resolve_action', { action, button, buttonText: button });
832
+ if (script) {
833
+ const cdp = h.getCdp();
834
+ if (cdp?.isConnected) {
835
+ try {
836
+ const matchText = provider?.webviewMatchText;
837
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
838
+ const raw = await cdp.evaluateInWebviewFrame?.(script, matchFn);
839
+ let result: any = raw;
840
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch { } }
841
+ LOG.info('Command', `[resolveAction] webview script result: ${JSON.stringify(result)}`);
842
+
843
+ if (result?.resolved) return { success: true, clicked: result.clicked };
844
+ if (result?.found && result.x != null && result.y != null) {
845
+ LOG.info('Command', `[resolveAction] Webview coordinate click not fully supported via CDP. Click directly in script.`);
846
+ }
847
+ if (result?.found || result?.resolved) return { success: true };
848
+ } catch (e: any) {
849
+ return { success: false, error: `webviewResolveAction failed: ${e.message}` };
850
+ }
851
+ }
852
+ }
853
+ }
854
+
855
+ // 3. Provider script (Main DOM) → returns coords → CDP mouse click
856
+ if (provider?.scripts?.resolveAction) {
857
+ const script = provider.scripts.resolveAction({ action, button, buttonText: button });
858
+ if (script) {
859
+ const cdp = h.getCdp();
860
+ if (!cdp?.isConnected) return { success: false, error: 'CDP not connected' };
861
+ try {
862
+ const raw = await cdp.evaluate(script, 30000);
863
+ let result: any = raw;
864
+ if (typeof raw === 'string') { try { result = JSON.parse(raw); } catch {} }
865
+ LOG.info('Command', `[resolveAction] script result: ${JSON.stringify(result)}`);
866
+
867
+ if (result?.resolved) {
868
+ LOG.info('Command', `[resolveAction] script-click resolved — "${result.clicked}"`);
869
+ return { success: true, clicked: result.clicked };
870
+ }
871
+ if (result?.found && result.x != null && result.y != null) {
872
+ const x = result.x;
873
+ const y = result.y;
874
+ await cdp.send('Input.dispatchMouseEvent', {
875
+ type: 'mousePressed', x, y, button: 'left', clickCount: 1
876
+ });
877
+ await cdp.send('Input.dispatchMouseEvent', {
878
+ type: 'mouseReleased', x, y, button: 'left', clickCount: 1
879
+ });
880
+ LOG.info('Command', `[resolveAction] CDP click at (${x}, ${y}) — "${result.text}"`);
881
+ return { success: true, clicked: result.text };
882
+ }
883
+ return { success: false, error: result?.found === false ? `Button not found: ${button}` : 'No coordinates' };
884
+ } catch (e: any) {
885
+ return { success: false, error: `resolveAction failed: ${e.message}` };
886
+ }
887
+ }
888
+ }
889
+
890
+ return { success: false, error: 'resolveAction script not available for this provider' };
891
+ }