@zergai/ztc 0.4.0-beta.1 → 0.5.0-beta.1

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 (718) hide show
  1. package/README.md +398 -45
  2. package/RUST_THIRD_PARTY_LICENSES.txt +1080 -822
  3. package/THIRD_PARTY_NOTICES.md +273 -12
  4. package/bin/zmux-darwin-arm64 +0 -0
  5. package/bin/ztc-audio-darwin-arm64 +0 -0
  6. package/bin/ztc-capture-darwin-arm64 +0 -0
  7. package/bin/ztc-computer-darwin-arm64 +0 -0
  8. package/bin/ztc-llm-darwin-arm64 +0 -0
  9. package/bin/ztc-tts-darwin-arm64 +0 -0
  10. package/bin/ztc-tui-darwin-arm64 +0 -0
  11. package/bin/ztc-zlicky-overlay-darwin-arm64 +0 -0
  12. package/bin/zterm-darwin-arm64 +0 -0
  13. package/dist/App.js +1206 -209
  14. package/dist/agent/agent.d.ts +74 -8
  15. package/dist/agent/agent.js +1073 -184
  16. package/dist/agent/backends/account_rotation.d.ts +4 -0
  17. package/dist/agent/backends/account_rotation.js +8 -2
  18. package/dist/agent/backends/anthropic.d.ts +13 -0
  19. package/dist/agent/backends/anthropic.js +169 -28
  20. package/dist/agent/backends/claude_cli.js +18 -8
  21. package/dist/agent/backends/codex_app_server.d.ts +1 -0
  22. package/dist/agent/backends/codex_app_server.js +55 -3
  23. package/dist/agent/backends/codex_auth.d.ts +1 -0
  24. package/dist/agent/backends/codex_auth.js +67 -13
  25. package/dist/agent/backends/codex_buffered_recovery.d.ts +27 -0
  26. package/dist/agent/backends/codex_buffered_recovery.js +293 -0
  27. package/dist/agent/backends/gemini.js +3 -1
  28. package/dist/agent/backends/http_error.d.ts +26 -0
  29. package/dist/agent/backends/http_error.js +221 -0
  30. package/dist/agent/backends/index.d.ts +9 -2
  31. package/dist/agent/backends/index.js +22 -2
  32. package/dist/agent/backends/openai.d.ts +0 -6
  33. package/dist/agent/backends/openai.js +5 -2
  34. package/dist/agent/backends/openai_compatible.d.ts +5 -4
  35. package/dist/agent/backends/openai_compatible.js +26 -19
  36. package/dist/agent/backends/openai_responses.d.ts +8 -3
  37. package/dist/agent/backends/openai_responses.js +77 -33
  38. package/dist/agent/backends/provider_ids.d.ts +1 -0
  39. package/dist/agent/backends/provider_ids.js +4 -0
  40. package/dist/agent/backends/request_metrics.js +12 -2
  41. package/dist/agent/backends/types.d.ts +109 -6
  42. package/dist/agent/backends/types.js +5 -1
  43. package/dist/agent/backends/zrouter_stream.d.ts +6 -1
  44. package/dist/agent/backends/zrouter_stream.js +160 -42
  45. package/dist/agent/background_registry.d.ts +2 -0
  46. package/dist/agent/background_registry.js +1 -0
  47. package/dist/agent/claim_observation.d.ts +6 -0
  48. package/dist/agent/claim_observation.js +54 -0
  49. package/dist/agent/commands/accounts.js +46 -177
  50. package/dist/agent/commands/attention.d.ts +2 -0
  51. package/dist/agent/commands/attention.js +67 -0
  52. package/dist/agent/commands/auth.js +18 -2
  53. package/dist/agent/commands/board.d.ts +2 -0
  54. package/dist/agent/commands/board.js +169 -0
  55. package/dist/agent/commands/clipboard.js +50 -1
  56. package/dist/agent/commands/compact.js +21 -13
  57. package/dist/agent/commands/config.js +4 -1
  58. package/dist/agent/commands/context.js +6 -1
  59. package/dist/agent/commands/desktop.d.ts +2 -0
  60. package/dist/agent/commands/desktop.js +29 -0
  61. package/dist/agent/commands/effort.js +14 -6
  62. package/dist/agent/commands/environment.d.ts +3 -0
  63. package/dist/agent/commands/environment.js +109 -0
  64. package/dist/agent/commands/evidence.d.ts +2 -0
  65. package/dist/agent/commands/evidence.js +9 -0
  66. package/dist/agent/commands/fork.js +4 -3
  67. package/dist/agent/commands/goal.d.ts +33 -1
  68. package/dist/agent/commands/goal.js +174 -14
  69. package/dist/agent/commands/goal_exit.d.ts +36 -0
  70. package/dist/agent/commands/goal_exit.js +120 -0
  71. package/dist/agent/commands/help.js +3 -1
  72. package/dist/agent/commands/history.js +3 -1
  73. package/dist/agent/commands/inbox.d.ts +2 -0
  74. package/dist/agent/commands/inbox.js +148 -0
  75. package/dist/agent/commands/index.js +16 -1
  76. package/dist/agent/commands/input_mode.js +8 -6
  77. package/dist/agent/commands/job.d.ts +2 -0
  78. package/dist/agent/commands/job.js +93 -0
  79. package/dist/agent/commands/keybindings.js +4 -1
  80. package/dist/agent/commands/label.d.ts +2 -0
  81. package/dist/agent/commands/label.js +77 -0
  82. package/dist/agent/commands/layout.d.ts +2 -0
  83. package/dist/agent/commands/layout.js +20 -0
  84. package/dist/agent/commands/mirror.js +16 -1
  85. package/dist/agent/commands/model.js +12 -2
  86. package/dist/agent/commands/permissions.d.ts +3 -1
  87. package/dist/agent/commands/permissions.js +79 -89
  88. package/dist/agent/commands/plan.js +5 -15
  89. package/dist/agent/commands/profile.js +21 -2
  90. package/dist/agent/commands/provider_selection.js +20 -1
  91. package/dist/agent/commands/rename.js +1 -1
  92. package/dist/agent/commands/resources.d.ts +2 -0
  93. package/dist/agent/commands/resources.js +67 -0
  94. package/dist/agent/commands/rewind.d.ts +3 -0
  95. package/dist/agent/commands/rewind.js +16 -0
  96. package/dist/agent/commands/runbooks.d.ts +2 -0
  97. package/dist/agent/commands/runbooks.js +73 -0
  98. package/dist/agent/commands/runbooks_lazy.d.ts +2 -0
  99. package/dist/agent/commands/runbooks_lazy.js +8 -0
  100. package/dist/agent/commands/sessions.d.ts +1 -1
  101. package/dist/agent/commands/sessions.js +33 -5
  102. package/dist/agent/commands/settings.js +185 -39
  103. package/dist/agent/commands/setup.d.ts +2 -0
  104. package/dist/agent/commands/setup.js +78 -0
  105. package/dist/agent/commands/share.d.ts +2 -0
  106. package/dist/agent/commands/share.js +64 -0
  107. package/dist/agent/commands/status.js +14 -2
  108. package/dist/agent/commands/types.d.ts +99 -6
  109. package/dist/agent/commands/update.js +8 -0
  110. package/dist/agent/commands/usage.d.ts +2 -0
  111. package/dist/agent/commands/usage.js +8 -0
  112. package/dist/agent/factory.d.ts +11 -0
  113. package/dist/agent/factory.js +113 -88
  114. package/dist/agent/loop_policy.d.ts +6 -3
  115. package/dist/agent/loop_policy.js +12 -3
  116. package/dist/agent/measurement_guidance.d.ts +2 -0
  117. package/dist/agent/measurement_guidance.js +5 -0
  118. package/dist/agent/request_encoder.d.ts +8 -1
  119. package/dist/agent/request_encoder.js +95 -23
  120. package/dist/agent/runtime/benchmark_comparison.d.ts +30 -0
  121. package/dist/agent/runtime/benchmark_comparison.js +94 -0
  122. package/dist/agent/runtime/benchmark_contract.d.ts +48 -0
  123. package/dist/agent/runtime/benchmark_contract.js +90 -0
  124. package/dist/agent/runtime/checked_commands.d.ts +32 -0
  125. package/dist/agent/runtime/checked_commands.js +119 -0
  126. package/dist/agent/runtime/command_execution_policy.d.ts +26 -0
  127. package/dist/agent/runtime/command_execution_policy.js +91 -0
  128. package/dist/agent/runtime/command_jobs.d.ts +36 -18
  129. package/dist/agent/runtime/command_jobs.js +151 -13
  130. package/dist/agent/runtime/command_panes.d.ts +59 -0
  131. package/dist/agent/runtime/command_panes.js +398 -0
  132. package/dist/agent/runtime/command_wait.d.ts +19 -0
  133. package/dist/agent/runtime/command_wait.js +167 -0
  134. package/dist/agent/runtime/cpu_benchmark.d.ts +30 -0
  135. package/dist/agent/runtime/cpu_benchmark.js +126 -0
  136. package/dist/agent/runtime/delegated_evidence.d.ts +26 -0
  137. package/dist/agent/runtime/delegated_evidence.js +80 -0
  138. package/dist/agent/runtime/evidence.d.ts +127 -0
  139. package/dist/agent/runtime/evidence.js +468 -0
  140. package/dist/agent/runtime/execution_context.d.ts +7 -0
  141. package/dist/agent/runtime/execution_context.js +39 -3
  142. package/dist/agent/runtime/json_verifier_recipe.d.ts +8 -0
  143. package/dist/agent/runtime/json_verifier_recipe.js +66 -0
  144. package/dist/agent/runtime/measurements.d.ts +110 -0
  145. package/dist/agent/runtime/measurements.js +317 -0
  146. package/dist/agent/runtime/policy.d.ts +4 -0
  147. package/dist/agent/runtime/policy.js +31 -20
  148. package/dist/agent/runtime/provider_native_evidence.d.ts +20 -0
  149. package/dist/agent/runtime/provider_native_evidence.js +86 -0
  150. package/dist/agent/runtime/recovery.d.ts +2 -0
  151. package/dist/agent/runtime/recovery.js +45 -2
  152. package/dist/agent/runtime/remote_broker_transport.d.ts +10 -0
  153. package/dist/agent/runtime/remote_broker_transport.js +84 -0
  154. package/dist/agent/runtime/remote_deletion_receipts.d.ts +3 -0
  155. package/dist/agent/runtime/remote_deletion_receipts.js +43 -0
  156. package/dist/agent/runtime/remote_journal_replay.d.ts +13 -0
  157. package/dist/agent/runtime/remote_journal_replay.js +233 -0
  158. package/dist/agent/runtime/remote_mutation_journal.d.ts +25 -0
  159. package/dist/agent/runtime/remote_mutation_journal.js +208 -0
  160. package/dist/agent/runtime/remote_resource_endpoint.d.ts +7 -0
  161. package/dist/agent/runtime/remote_resource_endpoint.js +6 -0
  162. package/dist/agent/runtime/remote_resource_errors.d.ts +5 -0
  163. package/dist/agent/runtime/remote_resource_errors.js +9 -0
  164. package/dist/agent/runtime/remote_resource_script.d.ts +2 -0
  165. package/dist/agent/runtime/remote_resource_script.js +1009 -0
  166. package/dist/agent/runtime/remote_resources.d.ts +29 -0
  167. package/dist/agent/runtime/remote_resources.js +160 -0
  168. package/dist/agent/runtime/source_verification.d.ts +12 -0
  169. package/dist/agent/runtime/source_verification.js +210 -0
  170. package/dist/agent/runtime/source_verification_contract.d.ts +75 -0
  171. package/dist/agent/runtime/source_verification_contract.js +203 -0
  172. package/dist/agent/runtime/tool_checkpoints.d.ts +11 -0
  173. package/dist/agent/runtime/tool_checkpoints.js +26 -0
  174. package/dist/agent/runtime/tool_effects.d.ts +5 -0
  175. package/dist/agent/runtime/tool_progress.d.ts +12 -0
  176. package/dist/agent/runtime/tool_progress.js +76 -0
  177. package/dist/agent/runtime/tool_runtime.d.ts +16 -1
  178. package/dist/agent/runtime/tool_runtime.js +204 -10
  179. package/dist/agent/runtime/tracing.d.ts +1 -1
  180. package/dist/agent/runtime/verifier_capture.d.ts +9 -0
  181. package/dist/agent/runtime/verifier_capture.js +100 -0
  182. package/dist/agent/runtime/verifier_contract.d.ts +24 -0
  183. package/dist/agent/runtime/verifier_contract.js +41 -0
  184. package/dist/agent/subagent.d.ts +20 -10
  185. package/dist/agent/subagent.js +266 -29
  186. package/dist/agent/tool_response_directory.d.ts +24 -0
  187. package/dist/agent/tool_response_directory.js +61 -0
  188. package/dist/agent/tool_response_source.d.ts +8 -0
  189. package/dist/agent/tool_response_source.js +49 -0
  190. package/dist/agent/tool_response_store.d.ts +75 -4
  191. package/dist/agent/tool_response_store.js +583 -64
  192. package/dist/agent/tools/ask_user.d.ts +3 -1
  193. package/dist/agent/tools/ask_user.js +30 -11
  194. package/dist/agent/tools/background.js +1 -0
  195. package/dist/agent/tools/benchmark_cpu.d.ts +2 -0
  196. package/dist/agent/tools/benchmark_cpu.js +102 -0
  197. package/dist/agent/tools/compare_benchmarks.d.ts +2 -0
  198. package/dist/agent/tools/compare_benchmarks.js +53 -0
  199. package/dist/agent/tools/deferred.js +1 -0
  200. package/dist/agent/tools/delegate.js +18 -2
  201. package/dist/agent/tools/helper_requirements.d.ts +7 -0
  202. package/dist/agent/tools/helper_requirements.js +19 -0
  203. package/dist/agent/tools/index.d.ts +1 -0
  204. package/dist/agent/tools/index.js +3 -0
  205. package/dist/agent/tools/measurement_report.d.ts +22 -0
  206. package/dist/agent/tools/measurement_report.js +190 -0
  207. package/dist/agent/tools/pane.d.ts +0 -7
  208. package/dist/agent/tools/pane.js +5 -4
  209. package/dist/agent/tools/project_context.d.ts +3 -0
  210. package/dist/agent/tools/project_context.js +45 -0
  211. package/dist/agent/tools/recall_tool_response.d.ts +3 -5
  212. package/dist/agent/tools/recall_tool_response.js +19 -29
  213. package/dist/agent/tools/registry.d.ts +1 -0
  214. package/dist/agent/tools/registry.js +23 -0
  215. package/dist/agent/tools/related_sessions.d.ts +2 -0
  216. package/dist/agent/tools/related_sessions.js +156 -0
  217. package/dist/agent/tools/routine.js +13 -3
  218. package/dist/agent/tools/session_evidence.d.ts +3 -0
  219. package/dist/agent/tools/session_evidence.js +72 -0
  220. package/dist/agent/tools/shell.d.ts +4 -3
  221. package/dist/agent/tools/shell.js +174 -47
  222. package/dist/agent/tools/tool_search.js +3 -2
  223. package/dist/agent/tools/types.d.ts +28 -0
  224. package/dist/agent/tools/verify_artifact.d.ts +2 -0
  225. package/dist/agent/tools/verify_artifact.js +60 -0
  226. package/dist/agent/tools/workflow.js +1 -0
  227. package/dist/app/activity.d.ts +6 -1
  228. package/dist/app/activity.js +81 -12
  229. package/dist/app/agent_runner.d.ts +6 -1
  230. package/dist/app/agent_runner.js +34 -19
  231. package/dist/app/command_context.js +106 -10
  232. package/dist/app/controller.d.ts +15 -4
  233. package/dist/app/controller.js +29 -3
  234. package/dist/app/escape_stop.d.ts +11 -0
  235. package/dist/app/escape_stop.js +15 -0
  236. package/dist/app/liveness.d.ts +6 -4
  237. package/dist/app/liveness.js +13 -3
  238. package/dist/app/model_catalog_cache.d.ts +5 -0
  239. package/dist/app/model_catalog_cache.js +138 -0
  240. package/dist/app/ordered_transcript.js +43 -4
  241. package/dist/app/prompt_turn.d.ts +14 -0
  242. package/dist/app/prompt_turn.js +53 -0
  243. package/dist/app/recap.d.ts +3 -0
  244. package/dist/app/recap.js +9 -3
  245. package/dist/app/restart.d.ts +3 -2
  246. package/dist/app/restart.js +22 -7
  247. package/dist/app/rewind.d.ts +3 -3
  248. package/dist/app/rewind.js +3 -3
  249. package/dist/app/selection_completion.d.ts +17 -2
  250. package/dist/app/selection_completion.js +84 -9
  251. package/dist/app/session_manager.d.ts +38 -6
  252. package/dist/app/session_manager.js +263 -60
  253. package/dist/app/session_messages.d.ts +3 -0
  254. package/dist/app/session_messages.js +60 -0
  255. package/dist/app/task_scope_router.d.ts +20 -0
  256. package/dist/app/task_scope_router.js +173 -0
  257. package/dist/app/transcript_window.d.ts +2 -0
  258. package/dist/app/transcript_window.js +4 -0
  259. package/dist/app/workspace_admission_details.d.ts +3 -0
  260. package/dist/app/workspace_admission_details.js +26 -0
  261. package/dist/app/workspace_layout_controller.d.ts +11 -0
  262. package/dist/app/workspace_layout_controller.js +88 -0
  263. package/dist/app/workspace_monitor.d.ts +1 -0
  264. package/dist/app/workspace_monitor.js +216 -0
  265. package/dist/app/workspace_presets.d.ts +29 -0
  266. package/dist/app/workspace_presets.js +192 -0
  267. package/dist/attention/queue.d.ts +37 -0
  268. package/dist/attention/queue.js +183 -0
  269. package/dist/bench/rf_shared.d.ts +2 -0
  270. package/dist/board/binding.d.ts +42 -0
  271. package/dist/board/binding.js +38 -0
  272. package/dist/board/client.d.ts +42 -0
  273. package/dist/board/client.js +60 -0
  274. package/dist/cli.js +1 -1
  275. package/dist/cli_args.js +19 -17
  276. package/dist/cli_main.js +110 -13
  277. package/dist/cli_ratatui.d.ts +183 -16
  278. package/dist/cli_ratatui.js +3989 -1255
  279. package/dist/components/ActivityLine.d.ts +3 -2
  280. package/dist/components/ActivityLine.js +2 -2
  281. package/dist/components/InputArea.d.ts +19 -1
  282. package/dist/components/InputArea.js +264 -190
  283. package/dist/components/MessageList.d.ts +2 -0
  284. package/dist/components/MessageList.js +3 -1
  285. package/dist/components/SingleMessage.d.ts +2 -0
  286. package/dist/components/SingleMessage.js +4 -2
  287. package/dist/components/StatusBar.d.ts +4 -2
  288. package/dist/components/StatusBar.js +3 -1
  289. package/dist/conductor_branch.js +3 -0
  290. package/dist/config/api_retry.d.ts +6 -1
  291. package/dist/config/api_retry.js +19 -1
  292. package/dist/config/defaults.d.ts +2 -1
  293. package/dist/config/defaults.js +9 -2
  294. package/dist/config/message_display.d.ts +1 -0
  295. package/dist/config/message_display.js +17 -2
  296. package/dist/config/permissions.d.ts +21 -0
  297. package/dist/config/permissions.js +89 -0
  298. package/dist/config/resolved.d.ts +2 -2
  299. package/dist/config/types.d.ts +32 -5
  300. package/dist/config.d.ts +38 -4
  301. package/dist/config.js +290 -42
  302. package/dist/context/project_intelligence.d.ts +44 -0
  303. package/dist/context/project_intelligence.js +246 -0
  304. package/dist/desktop/cli_launch.d.ts +8 -0
  305. package/dist/desktop/cli_launch.js +6 -0
  306. package/dist/desktop/cli_shim.d.ts +8 -0
  307. package/dist/desktop/cli_shim.js +120 -0
  308. package/dist/desktop/runtime.d.ts +16 -0
  309. package/dist/desktop/runtime.js +161 -0
  310. package/dist/desktop/worker_launch.d.ts +7 -0
  311. package/dist/desktop/worker_launch.js +7 -0
  312. package/dist/diagnostics/cargo_mutants_selection.d.ts +27 -0
  313. package/dist/diagnostics/cargo_mutants_selection.js +48 -0
  314. package/dist/diagnostics/native_terminal_benchmark.d.ts +58 -0
  315. package/dist/diagnostics/native_terminal_benchmark.js +1247 -0
  316. package/dist/diagnostics/session_evidence_package.d.ts +40 -0
  317. package/dist/diagnostics/session_evidence_package.js +234 -0
  318. package/dist/diagnostics/session_export.d.ts +93 -0
  319. package/dist/diagnostics/session_export.js +634 -0
  320. package/dist/emulation/tool_adapters.js +48 -18
  321. package/dist/emulation/ztc_addendum.d.ts +1 -0
  322. package/dist/emulation/ztc_addendum.js +13 -12
  323. package/dist/environment/service_runner.d.ts +1 -0
  324. package/dist/environment/service_runner.js +68 -0
  325. package/dist/environment/store.d.ts +120 -0
  326. package/dist/environment/store.js +387 -0
  327. package/dist/events.d.ts +40 -1
  328. package/dist/events.js +10 -17
  329. package/dist/goal_contract.d.ts +25 -0
  330. package/dist/goal_contract.js +44 -0
  331. package/dist/headless.d.ts +31 -0
  332. package/dist/headless.js +578 -70
  333. package/dist/headless_cli.js +8 -0
  334. package/dist/headless_cli_args.d.ts +1 -0
  335. package/dist/headless_cli_args.js +1 -0
  336. package/dist/intake/cli.d.ts +1 -0
  337. package/dist/intake/cli.js +33 -0
  338. package/dist/intake/format.d.ts +2 -0
  339. package/dist/intake/format.js +14 -0
  340. package/dist/intake/notifications.d.ts +16 -0
  341. package/dist/intake/notifications.js +132 -0
  342. package/dist/intake/store.d.ts +56 -0
  343. package/dist/intake/store.js +238 -0
  344. package/dist/library.d.ts +8 -0
  345. package/dist/library.js +19 -10
  346. package/dist/mcp/client.d.ts +1 -0
  347. package/dist/mcp/client.js +20 -0
  348. package/dist/modes/builtin/plan.yaml +2 -2
  349. package/dist/modes/handlers.js +1 -1
  350. package/dist/onboarding/first_run.d.ts +3 -0
  351. package/dist/onboarding/first_run.js +33 -25
  352. package/dist/onboarding/setup.d.ts +32 -0
  353. package/dist/onboarding/setup.js +133 -0
  354. package/dist/onboarding/setup_agent_health.d.ts +17 -0
  355. package/dist/onboarding/setup_agent_health.js +79 -0
  356. package/dist/onboarding/setup_environment.d.ts +66 -0
  357. package/dist/onboarding/setup_environment.js +219 -0
  358. package/dist/onboarding/setup_workspace.d.ts +17 -0
  359. package/dist/onboarding/setup_workspace.js +129 -0
  360. package/dist/optimize/adapters/index.d.ts +4 -1
  361. package/dist/optimize/adapters/index.js +7 -0
  362. package/dist/optimize/adapters/kernelbench.js +14 -5
  363. package/dist/optimize/adapters/popcorn.js +3 -2
  364. package/dist/optimize/adapters/profile_benchmark.js +13 -7
  365. package/dist/optimize/adapters/rfbench.js +25 -14
  366. package/dist/optimize/adapters/types.d.ts +3 -0
  367. package/dist/optimize/adapters/zergpod.js +5 -2
  368. package/dist/optimize/baseline.js +10 -21
  369. package/dist/optimize/branch.js +9 -12
  370. package/dist/optimize/combine.js +2 -3
  371. package/dist/optimize/executor.js +34 -48
  372. package/dist/optimize/measurements.d.ts +55 -0
  373. package/dist/optimize/measurements.js +173 -0
  374. package/dist/optimize/results.d.ts +1 -0
  375. package/dist/optimize/results.js +11 -33
  376. package/dist/optimize/tge.js +2 -1
  377. package/dist/panes/initial_input.d.ts +19 -0
  378. package/dist/panes/initial_input.js +206 -0
  379. package/dist/panes/labels.d.ts +16 -0
  380. package/dist/panes/labels.js +42 -0
  381. package/dist/panes/model_catalog.d.ts +3 -3
  382. package/dist/panes/model_catalog.js +28 -4
  383. package/dist/panes/pane_registry.js +6 -2
  384. package/dist/panes/types.d.ts +3 -0
  385. package/dist/panes/ztc_launch.js +19 -0
  386. package/dist/plugin/optimization.d.ts +2 -0
  387. package/dist/plugin/optimization.js +1 -0
  388. package/dist/plugin/runtime.d.ts +2 -0
  389. package/dist/plugin/simulation.d.ts +6 -1
  390. package/dist/plugin/simulation_contract.d.ts +836 -1
  391. package/dist/plugin/simulation_documents.d.ts +22 -0
  392. package/dist/plugin/simulation_documents.js +1 -0
  393. package/dist/plugin/simulation_interventions.d.ts +103 -0
  394. package/dist/plugin/simulation_interventions.js +1 -0
  395. package/dist/plugin/simulation_living.d.ts +1 -0
  396. package/dist/plugin/simulation_living.js +3 -0
  397. package/dist/plugin/simulation_meetings.d.ts +121 -0
  398. package/dist/plugin/simulation_meetings.js +1 -0
  399. package/dist/plugin/simulation_story_review.d.ts +111 -0
  400. package/dist/plugin/simulation_story_review.js +1 -0
  401. package/dist/plugin/simulation_storyteller.d.ts +91 -0
  402. package/dist/plugin/simulation_storyteller.js +1 -0
  403. package/dist/plugin/simulation_structured.d.ts +2 -0
  404. package/dist/plugin/simulation_structured.js +2 -0
  405. package/dist/plugin/simulation_toolkit.d.ts +21 -0
  406. package/dist/plugin/simulation_toolkit.js +24 -0
  407. package/dist/prompts/tool_delegate_task.j2 +1 -1
  408. package/dist/remote-broker/Dockerfile +10 -0
  409. package/dist/remote-broker/archive.py +1227 -0
  410. package/dist/remote-broker/cutover.py +761 -0
  411. package/dist/remote-broker/requirements.txt +5 -0
  412. package/dist/remote-broker/resources.json +6 -0
  413. package/dist/remote-broker/resources.write-staging.example.json +18 -0
  414. package/dist/remote-broker/retained.py +686 -0
  415. package/dist/remote-broker/retained_cleanup.py +550 -0
  416. package/dist/remote-broker/server.py +648 -0
  417. package/dist/remote-broker/worker.py +1007 -0
  418. package/dist/router_auth.d.ts +31 -0
  419. package/dist/router_auth.js +155 -9
  420. package/dist/runbooks/catalog.d.ts +3 -0
  421. package/dist/runbooks/catalog.js +26 -0
  422. package/dist/runbooks/library.d.ts +11 -0
  423. package/dist/runbooks/library.js +95 -0
  424. package/dist/runbooks/package.d.ts +43 -0
  425. package/dist/runbooks/package.js +102 -0
  426. package/dist/session.d.ts +65 -13
  427. package/dist/session.js +548 -43
  428. package/dist/session_handoff.d.ts +25 -0
  429. package/dist/session_handoff.js +322 -0
  430. package/dist/session_handoff_contract.d.ts +89 -0
  431. package/dist/session_handoff_contract.js +179 -0
  432. package/dist/session_media.d.ts +41 -0
  433. package/dist/session_media.js +357 -0
  434. package/dist/session_ownership.d.ts +16 -0
  435. package/dist/session_ownership.js +221 -0
  436. package/dist/session_public.d.ts +10 -2
  437. package/dist/session_public.js +6 -1
  438. package/dist/simulation/dynamic_history.d.ts +42 -0
  439. package/dist/simulation/dynamic_history.js +173 -0
  440. package/dist/simulation/engines/swarm/pane_manager.js +7 -6
  441. package/dist/simulation/inference.d.ts +3 -1
  442. package/dist/simulation/inference.js +19 -1
  443. package/dist/simulation/intervention_generation.d.ts +27 -0
  444. package/dist/simulation/intervention_generation.js +246 -0
  445. package/dist/simulation/intervention_material.d.ts +4 -0
  446. package/dist/simulation/intervention_material.js +81 -0
  447. package/dist/simulation/living/context.d.ts +3130 -0
  448. package/dist/simulation/living/context.js +944 -0
  449. package/dist/simulation/living/definer.d.ts +12 -0
  450. package/dist/simulation/living/definer.js +223 -0
  451. package/dist/simulation/living/definition.d.ts +257 -0
  452. package/dist/simulation/living/definition.js +341 -0
  453. package/dist/simulation/living/frame.d.ts +259 -0
  454. package/dist/simulation/living/frame.js +223 -0
  455. package/dist/simulation/living/identifiers.d.ts +2 -0
  456. package/dist/simulation/living/identifiers.js +12 -0
  457. package/dist/simulation/living/index.d.ts +15 -0
  458. package/dist/simulation/living/index.js +15 -0
  459. package/dist/simulation/living/inference.d.ts +219 -0
  460. package/dist/simulation/living/inference.js +576 -0
  461. package/dist/simulation/living/mechanics.d.ts +54 -0
  462. package/dist/simulation/living/mechanics.js +588 -0
  463. package/dist/simulation/living/model-input.d.ts +25 -0
  464. package/dist/simulation/living/model-input.js +215 -0
  465. package/dist/simulation/living/open-world.d.ts +257 -0
  466. package/dist/simulation/living/open-world.js +102 -0
  467. package/dist/simulation/living/projection.d.ts +7 -0
  468. package/dist/simulation/living/projection.js +31 -0
  469. package/dist/simulation/living/recall.d.ts +17 -0
  470. package/dist/simulation/living/recall.js +25 -0
  471. package/dist/simulation/living/reduce.d.ts +15 -0
  472. package/dist/simulation/living/reduce.js +1853 -0
  473. package/dist/simulation/living/replay.d.ts +6 -0
  474. package/dist/simulation/living/replay.js +22 -0
  475. package/dist/simulation/living/runtime.d.ts +140 -0
  476. package/dist/simulation/living/runtime.js +3020 -0
  477. package/dist/simulation/living/shared-kinds.d.ts +24 -0
  478. package/dist/simulation/living/shared-kinds.js +96 -0
  479. package/dist/simulation/living/types.d.ts +2785 -0
  480. package/dist/simulation/living/types.js +669 -0
  481. package/dist/simulation/llm.d.ts +3 -1
  482. package/dist/simulation/llm.js +90 -30
  483. package/dist/simulation/memory/embedding.d.ts +1 -1
  484. package/dist/simulation/memory/embedding.js +9 -3
  485. package/dist/simulation/memory/filesystem.d.ts +2 -0
  486. package/dist/simulation/memory/filesystem.js +5 -1
  487. package/dist/simulation/memory/filesystem_file_tree.d.ts +4 -1
  488. package/dist/simulation/memory/filesystem_file_tree.js +41 -10
  489. package/dist/simulation/memory/filesystem_invariants.js +1 -2
  490. package/dist/simulation/memory/filesystem_types.d.ts +1 -0
  491. package/dist/simulation/memory/memory.d.ts +2 -0
  492. package/dist/simulation/memory/memory.js +5 -1
  493. package/dist/simulation/orchestration/intent.js +0 -2
  494. package/dist/simulation/orchestration/lifecycle.js +0 -2
  495. package/dist/simulation/plugin_host.d.ts +25 -1
  496. package/dist/simulation/plugin_host.js +334 -17
  497. package/dist/simulation/session_documents.d.ts +20 -0
  498. package/dist/simulation/session_documents.js +62 -0
  499. package/dist/simulation/session_input_validation.d.ts +43 -0
  500. package/dist/simulation/session_input_validation.js +364 -0
  501. package/dist/simulation/session_inputs.d.ts +32 -0
  502. package/dist/simulation/session_inputs.js +154 -0
  503. package/dist/simulation/telemetry.d.ts +11 -14
  504. package/dist/simulation/telemetry.js +177 -54
  505. package/dist/simulation/toolkit/bounded_turns.d.ts +13 -0
  506. package/dist/simulation/toolkit/bounded_turns.js +80 -0
  507. package/dist/simulation/toolkit/dynamic_agents.d.ts +25 -0
  508. package/dist/simulation/toolkit/dynamic_agents.js +218 -0
  509. package/dist/simulation/toolkit/dynamic_digest.d.ts +1 -0
  510. package/dist/simulation/toolkit/dynamic_digest.js +8 -0
  511. package/dist/simulation/toolkit/dynamic_documents.d.ts +7 -0
  512. package/dist/simulation/toolkit/dynamic_documents.js +71 -0
  513. package/dist/simulation/toolkit/dynamic_driver.d.ts +8 -0
  514. package/dist/simulation/toolkit/dynamic_driver.js +269 -0
  515. package/dist/simulation/toolkit/dynamic_game.d.ts +53 -0
  516. package/dist/simulation/toolkit/dynamic_game.js +805 -0
  517. package/dist/simulation/toolkit/dynamic_knowledge.d.ts +15 -0
  518. package/dist/simulation/toolkit/dynamic_knowledge.js +91 -0
  519. package/dist/simulation/toolkit/dynamic_mechanics.d.ts +22 -0
  520. package/dist/simulation/toolkit/dynamic_mechanics.js +910 -0
  521. package/dist/simulation/toolkit/dynamic_meetings.d.ts +239 -0
  522. package/dist/simulation/toolkit/dynamic_meetings.js +350 -0
  523. package/dist/simulation/toolkit/dynamic_progress.d.ts +131 -0
  524. package/dist/simulation/toolkit/dynamic_progress.js +214 -0
  525. package/dist/simulation/toolkit/dynamic_projection.d.ts +9 -0
  526. package/dist/simulation/toolkit/dynamic_projection.js +219 -0
  527. package/dist/simulation/toolkit/dynamic_runtime.d.ts +412 -0
  528. package/dist/simulation/toolkit/dynamic_runtime.js +6536 -0
  529. package/dist/simulation/toolkit/dynamic_state.d.ts +111 -0
  530. package/dist/simulation/toolkit/dynamic_state.js +1967 -0
  531. package/dist/simulation/toolkit/dynamic_story_review.d.ts +508 -0
  532. package/dist/simulation/toolkit/dynamic_story_review.js +333 -0
  533. package/dist/simulation/toolkit/dynamic_storyteller.d.ts +77 -0
  534. package/dist/simulation/toolkit/dynamic_storyteller.js +114 -0
  535. package/dist/simulation/toolkit/dynamic_storyteller_runtime.d.ts +26 -0
  536. package/dist/simulation/toolkit/dynamic_storyteller_runtime.js +126 -0
  537. package/dist/simulation/toolkit/dynamic_world.d.ts +22 -0
  538. package/dist/simulation/toolkit/dynamic_world.js +377 -0
  539. package/dist/simulation/toolkit/structured_output.d.ts +5 -0
  540. package/dist/simulation/toolkit/structured_output.js +321 -0
  541. package/dist/simulation/types/world.d.ts +2 -0
  542. package/dist/simulation/world/artifact_store.js +1 -1
  543. package/dist/simulation/world/memory_manager.d.ts +5 -0
  544. package/dist/simulation/world/memory_manager.js +17 -2
  545. package/dist/simulation/world/state.d.ts +3 -2
  546. package/dist/simulation/world/state.js +15 -5
  547. package/dist/skills/bundled/measurement-validation/SKILL.md +144 -0
  548. package/dist/terminal_attach.d.ts +1 -0
  549. package/dist/terminal_attach.js +113 -0
  550. package/dist/tool_progress.d.ts +3 -0
  551. package/dist/tool_progress.js +27 -0
  552. package/dist/types.d.ts +145 -10
  553. package/dist/types.js +3 -0
  554. package/dist/ui/core/input.d.ts +3 -0
  555. package/dist/ui/core/input_segments.d.ts +18 -1
  556. package/dist/ui/core/input_segments.js +131 -47
  557. package/dist/ui/core/input_state.d.ts +12 -0
  558. package/dist/ui/core/layout_yoga.d.ts +1 -1
  559. package/dist/ui/core/turn_metadata.d.ts +5 -0
  560. package/dist/ui/core/turn_metadata.js +22 -0
  561. package/dist/ui/ink/render.d.ts +2 -1
  562. package/dist/ui/ink/render.js +6 -5
  563. package/dist/ui/ratatui/headless_pane_manager.d.ts +14 -1
  564. package/dist/ui/ratatui/headless_pane_manager.js +293 -104
  565. package/dist/ui/ratatui/index.d.ts +1 -0
  566. package/dist/ui/ratatui/input.d.ts +4 -0
  567. package/dist/ui/ratatui/input.js +15 -0
  568. package/dist/ui/ratatui/ipc_path.d.ts +2 -0
  569. package/dist/ui/ratatui/ipc_path.js +29 -1
  570. package/dist/ui/ratatui/mux_persistence.d.ts +3 -1
  571. package/dist/ui/ratatui/mux_persistence.js +139 -1
  572. package/dist/ui/ratatui/pane_relay.d.ts +1 -1
  573. package/dist/ui/ratatui/pane_relay.js +55 -27
  574. package/dist/ui/ratatui/process.d.ts +17 -1
  575. package/dist/ui/ratatui/process.js +80 -7
  576. package/dist/ui/ratatui/protocol.d.ts +236 -1
  577. package/dist/ui/ratatui/protocol.js +90 -0
  578. package/dist/ui/scrollback.d.ts +2 -1
  579. package/dist/ui/scrollback.js +9 -4
  580. package/dist/ui/stream_typewriter.d.ts +8 -3
  581. package/dist/ui/stream_typewriter.js +30 -1
  582. package/dist/ui/streaming_scrollback.d.ts +1 -0
  583. package/dist/ui/streaming_scrollback.js +1 -1
  584. package/dist/ui/transcript_render_cache.js +10 -0
  585. package/dist/ui/views/activity_line.d.ts +5 -3
  586. package/dist/ui/views/activity_line.js +65 -7
  587. package/dist/ui/views/app.d.ts +6 -3
  588. package/dist/ui/views/app.js +17 -6
  589. package/dist/ui/views/completion_menu.js +10 -5
  590. package/dist/ui/views/input_area.d.ts +7 -3
  591. package/dist/ui/views/input_area.js +15 -9
  592. package/dist/ui/views/message_list.d.ts +4 -1
  593. package/dist/ui/views/message_list.js +89 -19
  594. package/dist/ui/views/queue_panel.d.ts +3 -1
  595. package/dist/ui/views/queue_panel.js +9 -2
  596. package/dist/ui/views/status_bar.d.ts +4 -2
  597. package/dist/ui/views/status_bar.js +28 -13
  598. package/dist/ui/views/theme.d.ts +2 -0
  599. package/dist/ui/views/theme.js +2 -0
  600. package/dist/ui/widgets/color_panel.js +18 -0
  601. package/dist/ui/widgets/form.js +8 -0
  602. package/dist/ui/widgets/log_view.js +7 -0
  603. package/dist/ui/widgets/navigator_panel.js +8 -0
  604. package/dist/ui/widgets/prompt_viewer.js +2 -0
  605. package/dist/ui/widgets/questionnaire.d.ts +2 -0
  606. package/dist/ui/widgets/questionnaire.js +79 -16
  607. package/dist/ui/widgets/resume_panel.d.ts +2 -0
  608. package/dist/ui/widgets/resume_panel.js +26 -15
  609. package/dist/ui/widgets/rewind_panel.d.ts +2 -2
  610. package/dist/ui/widgets/rewind_panel.js +4 -2
  611. package/dist/ui/widgets/select.js +16 -27
  612. package/dist/ui/widgets/settings_panel.js +16 -0
  613. package/dist/ui/widgets/status_line_panel.d.ts +1 -0
  614. package/dist/ui/widgets/status_line_panel.js +30 -4
  615. package/dist/ui/widgets/text_input.d.ts +2 -0
  616. package/dist/ui/widgets/text_input.js +15 -1
  617. package/dist/ui/widgets/types.d.ts +2 -0
  618. package/dist/usage_projection.d.ts +24 -0
  619. package/dist/usage_projection.js +130 -0
  620. package/dist/usage_snapshot.d.ts +36 -0
  621. package/dist/usage_snapshot.js +131 -0
  622. package/dist/utils/assistant_message.d.ts +2 -0
  623. package/dist/utils/assistant_message.js +5 -0
  624. package/dist/utils/atomic_write.d.ts +6 -2
  625. package/dist/utils/atomic_write.js +29 -4
  626. package/dist/utils/checked_shell.d.ts +25 -0
  627. package/dist/utils/checked_shell.js +107 -0
  628. package/dist/utils/compaction.d.ts +4 -1
  629. package/dist/utils/compaction.js +31 -7
  630. package/dist/utils/context.d.ts +4 -4
  631. package/dist/utils/context.js +14 -12
  632. package/dist/utils/deepseek.d.ts +2 -2
  633. package/dist/utils/deepseek.js +13 -5
  634. package/dist/utils/ephemeral.js +4 -0
  635. package/dist/utils/ephemeral_tools.d.ts +18 -0
  636. package/dist/utils/ephemeral_tools.js +97 -0
  637. package/dist/utils/jev_client.d.ts +4 -0
  638. package/dist/utils/jev_client.js +15 -0
  639. package/dist/utils/model_cache.d.ts +15 -0
  640. package/dist/utils/model_cache.js +143 -0
  641. package/dist/utils/models.d.ts +4 -2
  642. package/dist/utils/models.js +12 -16
  643. package/dist/utils/reasoning.d.ts +8 -1
  644. package/dist/utils/reasoning.js +31 -11
  645. package/dist/utils/router_catalog.d.ts +49 -0
  646. package/dist/utils/router_catalog.js +271 -0
  647. package/dist/utils/sandbox.d.ts +9 -0
  648. package/dist/utils/sandbox.js +118 -15
  649. package/dist/utils/shell.d.ts +7 -0
  650. package/dist/utils/shell.js +98 -34
  651. package/dist/utils/subprocess_env.d.ts +3 -0
  652. package/dist/utils/subprocess_env.js +27 -1
  653. package/dist/web/accounts_mirror.d.ts +3 -1
  654. package/dist/web/accounts_mirror.js +13 -9
  655. package/dist/web/child_publication.d.ts +17 -0
  656. package/dist/web/child_publication.js +45 -0
  657. package/dist/web/mirror_authenticator.d.ts +31 -11
  658. package/dist/web/mirror_authenticator.js +67 -17
  659. package/dist/web/mirror_client.d.ts +31 -4
  660. package/dist/web/mirror_client.js +189 -23
  661. package/dist/web/mirror_stream.d.ts +84 -22
  662. package/dist/web/mirror_stream.js +676 -95
  663. package/dist/web/observer_query_redaction.d.ts +6 -0
  664. package/dist/web/observer_query_redaction.js +58 -0
  665. package/dist/web/pane_registry.d.ts +2 -0
  666. package/dist/web/pane_registry.js +86 -22
  667. package/dist/web/tool_image.d.ts +6 -0
  668. package/dist/web/tool_image.js +17 -0
  669. package/dist/web/view_plugin.d.ts +14 -0
  670. package/dist/web/view_plugin.js +23 -1
  671. package/dist/worker/executor.js +31 -12
  672. package/dist/worker/index.d.ts +1 -0
  673. package/dist/worker/toolsets.js +3 -1
  674. package/dist/worker/types.d.ts +12 -1
  675. package/dist/workflows/registry.js +1 -0
  676. package/dist/workflows/registry_handle.d.ts +2 -0
  677. package/dist/workflows/runtime.d.ts +2 -0
  678. package/dist/workflows/runtime.js +1 -0
  679. package/dist/workspace_agent.d.ts +7 -0
  680. package/dist/workspace_agent.js +36 -0
  681. package/dist/workspace_collision.d.ts +76 -0
  682. package/dist/workspace_collision.js +688 -0
  683. package/dist/workspace_layout.d.ts +18 -0
  684. package/dist/workspace_layout.js +121 -0
  685. package/dist/workspace_runtime.d.ts +44 -0
  686. package/dist/workspace_runtime.js +82 -0
  687. package/dist/workspace_session_context.d.ts +62 -0
  688. package/dist/workspace_session_context.js +160 -0
  689. package/dist/zlm-embed.mjs +32518 -9615
  690. package/dist/zlm.js +1 -0
  691. package/node_modules/@zerg/model-contracts/LICENSE.md +375 -0
  692. package/node_modules/@zerg/model-contracts/README.md +90 -0
  693. package/node_modules/@zerg/model-contracts/index.d.ts +20 -0
  694. package/node_modules/@zerg/model-contracts/index.js +223 -0
  695. package/node_modules/@zerg/model-contracts/package.json +8 -0
  696. package/node_modules/glob/node_modules/brace-expansion/index.js +78 -22
  697. package/node_modules/glob/node_modules/brace-expansion/package.json +1 -1
  698. package/node_modules/readdir-glob/node_modules/brace-expansion/index.js +78 -22
  699. package/node_modules/readdir-glob/node_modules/brace-expansion/package.json +1 -1
  700. package/package.json +45 -24
  701. package/packages/model-contracts/LICENSE.md +375 -0
  702. package/packages/model-contracts/README.md +90 -0
  703. package/packages/model-contracts/index.d.ts +20 -0
  704. package/packages/model-contracts/index.js +223 -0
  705. package/packages/model-contracts/package.json +8 -0
  706. package/remote-broker/Dockerfile +10 -0
  707. package/remote-broker/README.md +308 -0
  708. package/remote-broker/archive.py +1227 -0
  709. package/remote-broker/cutover.py +761 -0
  710. package/remote-broker/requirements.txt +5 -0
  711. package/remote-broker/resources.example.json +6 -0
  712. package/remote-broker/resources.write-staging.example.json +18 -0
  713. package/remote-broker/retained.py +686 -0
  714. package/remote-broker/retained_cleanup.py +550 -0
  715. package/remote-broker/server.py +648 -0
  716. package/scripts/build-remote-broker.mjs +13 -0
  717. package/scripts/ensure-local-packages.mjs +6 -0
  718. package/scripts/node-pty-helpers.mjs +103 -0
@@ -9,13 +9,10 @@
9
9
  * /accounts login <id> run the official CLI login at the account's dir
10
10
  * /accounts remove <id> drop an account from the pool
11
11
  */
12
- import { spawnSync } from 'node:child_process';
13
12
  import { configStore } from '../../config.js';
14
- import { buildLoginCommand, canonicalAccountProvider, defaultAccountDir, defaultSourceFor, ensureAccountDir, findCodexHomeCollision, isAccountProvider, probeAccountUsable, sourceDir, } from '../backends/account_pool.js';
15
- import { loginAutoRunEnabled, loginFailureReasonText, runLoginCommand } from '../backends/account_login.js';
16
- import { notifyAccountsChanged } from '../backends/account_events.js';
13
+ import { canonicalAccountProvider, defaultAccountDir, defaultSourceFor, findCodexHomeCollision, isAccountProvider, probeAccountUsable, sourceDir, } from '../backends/account_pool.js';
17
14
  import { codexStatusCache } from '../backends/codex_account_status.js';
18
- import { runKimiDeviceLogin } from '../backends/kimi_code_auth.js';
15
+ import { applyAccountOp } from '../../web/accounts_mirror.js';
19
16
  const PROVIDER_LABELS = {
20
17
  claude_code: 'Claude Code (claude CLI)',
21
18
  codex_app_server: 'Codex (codex app-server)',
@@ -121,21 +118,28 @@ function parseAdd(args) {
121
118
  }
122
119
  return { provider, id, label: labelParts.join(' ') || id, path };
123
120
  }
124
- async function addAccount(parsed) {
125
- if (configStore.getAccount(parsed.id)) {
126
- return { error: 'duplicate_id', message: `An account with id "${parsed.id}" already exists. Remove it first or pick another id.` };
127
- }
128
- const dir = parsed.path ?? defaultAccountDir(parsed.provider, parsed.id);
129
- const source = defaultSourceFor(parsed.provider, dir);
130
- const collision = findCodexHomeCollision(configStore.listAccounts(), source);
131
- if (collision) {
132
- return { error: 'codex_home_collision', message: `That Codex credential home is already used by "${collision.label}". Choose another path.` };
121
+ /** All mutating CLI and terminal-panel actions use the same owner admission and
122
+ * canonical operation as the mirror. The owner callback holds its runtime lease. */
123
+ async function applyOperation(body, ctx) {
124
+ return ctx.applyAccountOperation
125
+ ? ctx.applyAccountOperation(body)
126
+ : applyAccountOp(body, configStore, () => ctx.reloadAgent());
127
+ }
128
+ function showOperationResult(result, ctx) {
129
+ say(ctx, [result.ok ? result.message : result.error, result.loginCommand]
130
+ .filter(Boolean).join('\n\n'));
131
+ }
132
+ async function addAccount(parsed, ctx) {
133
+ const result = await applyOperation({ op: 'add', ...parsed }, ctx);
134
+ if (!result.ok) {
135
+ const dir = parsed.path ?? defaultAccountDir(parsed.provider, parsed.id);
136
+ const collision = findCodexHomeCollision(configStore.listAccounts(), defaultSourceFor(parsed.provider, dir));
137
+ return {
138
+ error: configStore.getAccount(parsed.id) ? 'duplicate_id' : collision ? 'codex_home_collision' : 'operation_failed',
139
+ message: result.error ?? 'Account operation failed.',
140
+ };
133
141
  }
134
- ensureAccountDir(source);
135
- const account = { id: parsed.id, label: parsed.label, provider: parsed.provider, source };
136
- configStore.addAccount(account);
137
- await configStore.save();
138
- return { account };
142
+ return { account: configStore.getAccount(parsed.id) };
139
143
  }
140
144
  async function handleAdd(args, ctx) {
141
145
  const parsed = parseAdd(args);
@@ -143,7 +147,7 @@ async function handleAdd(args, ctx) {
143
147
  say(ctx, parsed);
144
148
  return;
145
149
  }
146
- const result = await addAccount(parsed);
150
+ const result = await addAccount(parsed, ctx);
147
151
  if ('error' in result) {
148
152
  say(ctx, result.message);
149
153
  return;
@@ -162,151 +166,20 @@ async function handleAdd(args, ctx) {
162
166
  async function handleUse(args, ctx) {
163
167
  const id = args[0];
164
168
  if (!id) {
165
- say(ctx, `Usage: /accounts use <id>`);
169
+ say(ctx, 'Usage: /accounts use <id>');
166
170
  return;
167
171
  }
168
- const account = configStore.getAccount(id);
169
- if (!account) {
170
- say(ctx, `No account "${id}". See /accounts.`);
171
- return;
172
- }
173
- if (account.source.kind === 'codex_home') {
174
- const status = await codexStatusCache.read(account.source.path, true);
175
- if (status.state === 'reauth_required' || status.state === 'unavailable') {
176
- say(ctx, status.state === 'reauth_required'
177
- ? `"${account.label}" needs a fresh ChatGPT sign-in. Run /accounts login ${account.id}, then switch again.`
178
- : `"${account.label}" could not be verified. Refresh its status or sign in, then switch again.`);
179
- return;
180
- }
181
- }
182
- configStore.setActiveAccount(account.provider, account.id);
183
- await configStore.save();
184
- const accountKey = canonicalAccountProvider(account.provider);
185
- const isCurrentProvider = canonicalAccountProvider(configStore.getProvider()) === accountKey;
186
- if (!probeAccountUsable(account)) {
187
- say(ctx, `"${account.label}" is now the active ${PROVIDER_LABELS[account.provider]} account, but it has no credentials yet. Run /accounts login ${account.id}.`);
188
- return;
189
- }
190
- if (isCurrentProvider) {
191
- ctx.reloadAgent();
192
- say(ctx, `Switched live ${PROVIDER_LABELS[account.provider]} account to "${account.label}".`);
193
- }
194
- else {
195
- say(ctx, `Set "${account.label}" active for ${PROVIDER_LABELS[account.provider]}. It goes live when you switch to that provider with /model.`);
196
- }
172
+ showOperationResult(await applyOperation({ op: 'use', id }, ctx), ctx);
197
173
  }
198
174
  async function handleLogin(args, ctx) {
199
175
  const id = args[0];
200
176
  if (!id) {
201
- say(ctx, `Usage: /accounts login <id>`);
202
- return;
203
- }
204
- const account = configStore.getAccount(id);
205
- if (!account) {
206
- say(ctx, `No account "${id}". See /accounts.`);
177
+ say(ctx, 'Usage: /accounts login <id>');
207
178
  return;
208
179
  }
209
- ensureAccountDir(account.source);
210
- // kimi_code: native device-flow login — no external CLI involved. Show the
211
- // user code + link here, poll until the browser step completes.
212
- if (account.source.kind === 'kimi_creds_file') {
213
- const credsPath = account.source.path;
214
- say(ctx, 'Starting Kimi sign-in…');
215
- try {
216
- const result = await runKimiDeviceLogin({
217
- authFilePath: credsPath,
218
- onCode: (flow) => {
219
- say(ctx, [
220
- `Open this link to sign in "${account.label}":`,
221
- '',
222
- ` ${flow.verificationUriComplete}`,
223
- '',
224
- `and confirm the code: ${flow.userCode}`,
225
- '',
226
- 'Waiting for the sign-in to complete…',
227
- ].join('\n'));
228
- },
229
- });
230
- if (result.outcome === 'succeeded') {
231
- notifyAccountsChanged();
232
- // Hot-swap only when this login changes creds the live agent is using.
233
- const isCurrentActive = configStore.getActiveAccount(configStore.getProvider())?.id === account.id;
234
- if (isCurrentActive)
235
- ctx.reloadAgent();
236
- say(ctx, `"${account.label}" is signed in. Make it live with: /accounts use ${account.id}`);
237
- }
238
- else {
239
- const why = result.outcome === 'denied'
240
- ? `the sign-in was denied${result.description ? ` (${result.description})` : ''}`
241
- : result.outcome === 'expired'
242
- ? 'the code expired'
243
- : 'the sign-in timed out';
244
- say(ctx, `Kimi sign-in failed — ${why}. Try again: /accounts login ${account.id}`);
245
- }
246
- }
247
- catch (error) {
248
- say(ctx, `Kimi sign-in failed: ${error.message}`);
249
- }
250
- return;
251
- }
252
- const login = buildLoginCommand(account);
253
- const manualHint = [
254
- `Run this in a terminal to sign in "${account.label}" (no token enters ztc):`,
255
- '',
256
- ` ${login.display}`,
257
- '',
258
- `Then: /accounts use ${account.id}`,
259
- ].join('\n');
260
- // A blocking spawnSync(stdio:'inherit') would freeze the Node event loop —
261
- // and with it every mirror pane — for the entire OAuth, and attach the login
262
- // prompt to a terminal a web-mirror user cannot see. When there is no TTY, OR
263
- // a web mirror is attached, auto-run the OAuth with piped stdio (non-blocking)
264
- // and only hand the command back if it fails. No token enters ztc either way.
265
- if (!process.stdout.isTTY || ctx.mirror?.isRunning()) {
266
- if (!loginAutoRunEnabled()) {
267
- say(ctx, manualHint);
268
- return;
269
- }
270
- say(ctx, `Signing in "${account.label}" on the ztc host — complete it in the browser…`);
271
- const attempt = await runLoginCommand(login, () => probeAccountUsable(account));
272
- if (attempt.outcome === 'succeeded') {
273
- if (account.source.kind === 'codex_home') {
274
- codexStatusCache.invalidate(account.source.path);
275
- const status = await codexStatusCache.read(account.source.path, true);
276
- if (status.state === 'reauth_required' || status.state === 'unavailable') {
277
- notifyAccountsChanged();
278
- say(ctx, `"${account.label}" saved credentials, but the ChatGPT subscription could not be verified. Run /accounts login ${account.id} again.`);
279
- return;
280
- }
281
- }
282
- notifyAccountsChanged();
283
- say(ctx, `"${account.label}" is signed in. Make it live with: /accounts use ${account.id}`);
284
- }
285
- else {
286
- say(ctx, [`Auto sign-in failed — ${loginFailureReasonText(attempt)}.`, '', manualHint].join('\n'));
287
- }
288
- return;
289
- }
290
- say(ctx, `Launching: ${login.display}\nComplete the login in the browser, then return here.`);
291
- const result = spawnSync(login.command, login.args, { stdio: 'inherit', env: login.env });
292
- if (result.error) {
293
- say(ctx, [
294
- `Couldn't launch "${login.command}" (${result.error.message}).`,
295
- `Run it yourself:`,
296
- '',
297
- ` ${login.display}`,
298
- ].join('\n'));
299
- return;
300
- }
301
- let ready = probeAccountUsable(account);
302
- if (ready && account.source.kind === 'codex_home') {
303
- codexStatusCache.invalidate(account.source.path);
304
- const status = await codexStatusCache.read(account.source.path, true);
305
- ready = status.state === 'ready' || status.state === 'quota_unavailable';
306
- }
307
- say(ctx, ready
308
- ? `"${account.label}" is signed in. Make it live with: /accounts use ${account.id}`
309
- : `Login exited without usable credentials in ${sourceDir(account.source)}. Try again: /accounts login ${account.id}`);
180
+ // The canonical operation returns pending while the official/device login
181
+ // runs. Completion notification and idle-safe reload belong to the owner.
182
+ showOperationResult(await applyOperation({ op: 'login', id }, ctx), ctx);
310
183
  }
311
184
  function describeRotation() {
312
185
  const r = configStore.getRotation();
@@ -327,50 +200,45 @@ async function handleRotation(args, ctx) {
327
200
  say(ctx, describeRotation());
328
201
  return;
329
202
  }
203
+ const patch = { op: 'rotation' };
330
204
  switch (field) {
331
205
  case 'on':
332
- configStore.setRotation({ enabled: true });
206
+ patch.enabled = true;
333
207
  break;
334
208
  case 'off':
335
- configStore.setRotation({ enabled: false });
209
+ patch.enabled = false;
336
210
  break;
337
211
  case 'mode':
338
212
  if (value !== 'failover' && value !== 'round_robin') {
339
213
  say(ctx, 'Usage: /accounts rotation mode failover|round_robin');
340
214
  return;
341
215
  }
342
- configStore.setRotation({ mode: value });
216
+ patch.mode = value;
343
217
  break;
344
218
  case 'subagents':
345
219
  if (value !== 'inherit' && value !== 'pool') {
346
220
  say(ctx, 'Usage: /accounts rotation subagents inherit|pool');
347
221
  return;
348
222
  }
349
- configStore.setRotation({ subagentInheritance: value });
223
+ patch.subagentInheritance = value;
350
224
  break;
351
225
  default:
352
226
  say(ctx, `Unknown rotation field "${field}".\n\n${describeRotation()}`);
353
227
  return;
354
228
  }
355
- await configStore.save();
356
- // Re-mint the agent so a freshly enabled pool wraps (or unwraps) the backend now.
357
- ctx.reloadAgent();
358
- say(ctx, describeRotation());
229
+ const result = await applyOperation(patch, ctx);
230
+ if (!result.ok)
231
+ showOperationResult(result, ctx);
232
+ else
233
+ say(ctx, describeRotation());
359
234
  }
360
235
  async function handleRemove(args, ctx) {
361
236
  const id = args[0];
362
237
  if (!id) {
363
- say(ctx, `Usage: /accounts remove <id>`);
364
- return;
365
- }
366
- const account = configStore.getAccount(id);
367
- if (!account) {
368
- say(ctx, `No account "${id}". See /accounts.`);
238
+ say(ctx, 'Usage: /accounts remove <id>');
369
239
  return;
370
240
  }
371
- configStore.removeAccount(id);
372
- await configStore.save();
373
- say(ctx, `Removed "${account.label}" (${id}) from the pool. Its credential dir was left in place:\n ${sourceDir(account.source)}`);
241
+ showOperationResult(await applyOperation({ op: 'remove', id }, ctx), ctx);
374
242
  }
375
243
  // --- interactive terminal settings page (text list in non-interactive output) ---
376
244
  function accountFamily(provider) {
@@ -440,10 +308,11 @@ function interactiveAddPage(ctx, provider) {
440
308
  id,
441
309
  label: draft.label.trim() || id,
442
310
  path: draft.path.trim() || undefined,
443
- }).then(result => {
311
+ }, ctx).then(result => {
444
312
  if ('error' in result) {
445
- error = result.error === 'duplicate_id' ? 'Account ID already exists' : 'Credential directory in use';
446
- errorField = result.error === 'duplicate_id' ? 'id' : 'path';
313
+ error = result.error === 'duplicate_id' ? 'Account ID already exists'
314
+ : result.error === 'codex_home_collision' ? 'Credential directory in use' : result.message;
315
+ errorField = result.error === 'duplicate_id' ? 'id' : result.error === 'codex_home_collision' ? 'path' : 'create';
447
316
  showPage(errorField);
448
317
  }
449
318
  else {
@@ -0,0 +1,2 @@
1
+ import type { Command } from './types.js';
2
+ export declare const attentionCommand: Command;
@@ -0,0 +1,67 @@
1
+ const USAGE = '/attention [list [page]|show <ID>|answer <ID> <text or JSON>|approve|deny <ID> [reason]|dismiss <ID>]';
2
+ function describe(item) {
3
+ const seconds = Math.max(0, Math.floor((Date.now() - Date.parse(item.createdAt)) / 1000));
4
+ const age = seconds < 60 ? `${seconds}s` : `${Math.floor(seconds / 60)}m`;
5
+ return `${item.id}\n ${item.kind} · ${item.agent} · session ${item.sessionId} · pane ${item.paneId} · ${age}\n Task: ${item.task}\n Needs you: ${item.blocker}\n Action: /attention ${item.primaryAction === 'inspect' ? 'show' : item.primaryAction} ${item.id}`;
6
+ }
7
+ export const attentionCommand = {
8
+ name: 'attention', description: 'Inspect and resolve requests that need a human', usage: USAGE,
9
+ handler: async (args, ctx) => {
10
+ const say = (content) => ctx.addMessage({ role: 'system', content });
11
+ const action = args[0] ?? 'list';
12
+ if (ctx.commandOrigin === 'agent' && !['list', 'show'].includes(action)) {
13
+ say('Only you can answer, approve or acknowledge human attention.');
14
+ return;
15
+ }
16
+ try {
17
+ if (!ctx.attention)
18
+ throw new Error('Open the attention queue in the native overseer session.');
19
+ if (action === 'list') {
20
+ const page = Number(args[1] ?? 1);
21
+ if (!Number.isSafeInteger(page) || page < 1)
22
+ throw new Error('Page must be a positive integer.');
23
+ const snapshot = ctx.attention.snapshot(100, (page - 1) * 100);
24
+ say(snapshot.total === 0 ? 'No requests need your attention.' : [`Human attention · ${snapshot.total} items · page ${page}`,
25
+ ...snapshot.items.map(describe), ...(snapshot.total > page * 100 ? [`Next: /attention list ${page + 1}`] : [])].join('\n'));
26
+ return;
27
+ }
28
+ const id = args[1];
29
+ if (!id)
30
+ throw new Error(USAGE);
31
+ if (action === 'dismiss') {
32
+ ctx.attention.dismiss(id);
33
+ say('Attention acknowledged.');
34
+ return;
35
+ }
36
+ if (action === 'approve' || action === 'deny') {
37
+ ctx.attention.respond(id, { decision: action, reason: args.slice(2).join(' ') });
38
+ say(`Approval ${action === 'approve' ? 'approved' : 'denied'}.`);
39
+ return;
40
+ }
41
+ const snapshot = ctx.attention.snapshot();
42
+ // Search all pages so an ID in a large queue retains its exact owner.
43
+ let item = snapshot.items.find(item => item.id === id);
44
+ for (let offset = 100; !item && offset < snapshot.total; offset += 100) {
45
+ item = ctx.attention.snapshot(100, offset).items.find(item => item.id === id);
46
+ }
47
+ if (!item)
48
+ throw new Error('Stale attention request; inspect the current queue.');
49
+ if (action === 'show') {
50
+ say(describe(item));
51
+ return;
52
+ }
53
+ if (action === 'answer') {
54
+ const text = args.slice(2).join(' ');
55
+ const response = item.kind === 'prompt'
56
+ ? text.trim().startsWith('{') ? JSON.parse(text) : { value: text } : text;
57
+ ctx.attention.respond(id, response);
58
+ say('Answer delivered to its request owner.');
59
+ return;
60
+ }
61
+ throw new Error(USAGE);
62
+ }
63
+ catch (error) {
64
+ say(`Attention: ${error instanceof Error ? error.message : String(error)}`);
65
+ }
66
+ },
67
+ };
@@ -3,12 +3,15 @@ import { runRouterAuthCommand } from '../../router_auth.js';
3
3
  export const authCommand = {
4
4
  name: 'auth',
5
5
  description: 'Manage Zerg Router authentication',
6
- usage: '<login|logout|status> [options]',
6
+ usage: '<login|logout|status|readiness|billing> [options]',
7
+ agentRunnable: false,
7
8
  handler: async (args, ctx) => {
8
9
  if (args.length === 0 || args[0] === 'help') {
9
10
  ctx.addMessage({ role: 'system', content: [
10
11
  'Zerg Router authentication:',
11
12
  ' /auth login [--url <origin>] [--no-browser] - Sign in through your browser',
13
+ ' /auth readiness [--json] - Check personal funding and model availability without using quota',
14
+ ' /auth billing [--no-browser] - Review personal pay-as-you-go funding in the browser',
12
15
  ' /auth status [--json] - Show the current Router session',
13
16
  ' /auth logout [--local-only] - Sign out',
14
17
  '',
@@ -17,11 +20,24 @@ export const authCommand = {
17
20
  return;
18
21
  }
19
22
  try {
20
- await runRouterAuthCommand(args, message => {
23
+ // Keep process-only --router-url overrides when signing in from a session.
24
+ const origin = args[0] === 'login' && !args.includes('--url')
25
+ ? configStore.get().zergProxyUrl : undefined;
26
+ await runRouterAuthCommand(origin ? [...args, '--url', origin] : args, message => {
21
27
  ctx.addMessage({ role: 'system', content: message.trimEnd() });
22
28
  });
23
29
  if (args[0] === 'login' || args[0] === 'logout') {
24
30
  await configStore.refresh();
31
+ if (args[0] === 'login' && configStore.resolveLLMBackendConfig().useProxy) {
32
+ // Sign-in changes catalog ownership. Discover before constructing the
33
+ // backend so the first turn uses the new account's model metadata.
34
+ try {
35
+ await ctx.models.catalog?.(undefined, { refresh: true });
36
+ }
37
+ catch {
38
+ // Catalog availability must not undo a successful sign-in.
39
+ }
40
+ }
25
41
  // Logout must dispose of the old backend without building a new one
26
42
  // from missing credentials. Login builds from the newly loaded session.
27
43
  ctx.reloadAgent({ defer: args[0] === 'logout' });
@@ -0,0 +1,2 @@
1
+ import type { Command } from './types.js';
2
+ export declare const boardCommand: Command;
@@ -0,0 +1,169 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { BOARD_PENDING_MAX_BYTES } from '../../board/binding.js';
4
+ import { boardRequest, configuredBoardOrigin, boardCardResponse, boardDetailsResponse, boardAttachmentResponse } from '../../board/client.js';
5
+ import { buildSessionEvidencePackage } from '../../diagnostics/session_evidence_package.js';
6
+ import { loadSessionFromFile, updateSessionBoardBinding } from '../../session.js';
7
+ import { projectTaskHandoff } from '../../session_handoff_contract.js';
8
+ import { withPathLock } from '../../utils/path_lock.js';
9
+ const usage = '/board attach <board-uuid> <card-uuid> | create <board-uuid> <column-uuid> <title> | status | refresh | state <running|blocked|review|done> <state-uuid> | share | sync | discard <operation-uuid> | detach';
10
+ const identity = (value) => z.string().uuid('Invalid Zergboard UUID').parse(value);
11
+ const taskId = (session) => session.task_handoff?.taskId
12
+ ?? `request:${session.messages.find(message => message.role === 'user')?.id ?? session.metadata.id}`;
13
+ async function run(args, ctx) {
14
+ const action = args[0];
15
+ if (!action)
16
+ return usage;
17
+ if (!['status'].includes(action) && ctx.commandOrigin === 'agent')
18
+ return 'Zergboard writes and association changes require an explicit user command.';
19
+ if (!ctx.checkpointSession || !ctx.getSessionId)
20
+ return 'Zergboard sync requires a host with a saved session checkpoint.';
21
+ const sessionId = ctx.getSessionId();
22
+ const file = await ctx.checkpointSession();
23
+ // Distinct from the canonical writer lock: serialize whole board operations
24
+ // in this process, but allow ordinary autosaves while HTTP is pending.
25
+ return withPathLock(file + '.board-operation', async () => {
26
+ const session = await loadSessionFromFile(file, false);
27
+ if (!session || session.metadata.id !== sessionId)
28
+ throw new Error('Zergboard checkpoint does not belong to the current session');
29
+ let binding = session.board_binding;
30
+ const save = async (next) => {
31
+ await updateSessionBoardBinding(file, sessionId, binding, next);
32
+ binding = next;
33
+ };
34
+ const origin = configuredBoardOrigin();
35
+ if (binding && binding.origin !== origin)
36
+ throw new Error('Configured Zergboard origin differs from the attached destination');
37
+ if (action === 'discard') {
38
+ if (args.length !== 2)
39
+ return usage;
40
+ const key = identity(args[1]);
41
+ if (!binding?.pending || binding.pending.key !== key)
42
+ return 'Discard requires the matching pending operation ID; use /board status to inspect it.';
43
+ // This is an explicit local retirement, not remote cancellation. An
44
+ // accepted operation can still exist even when its receipt was lost.
45
+ const next = binding.pending.kind === 'create' ? undefined : { ...binding, pending: undefined };
46
+ await save(next);
47
+ return `Pending operation ${key} discarded locally; remote outcome remains unknown. Inspect Zergboard before choosing a fresh operation; /board refresh acknowledges manual changes on an attached card.`;
48
+ }
49
+ if (action === 'detach') {
50
+ if (args.length !== 1)
51
+ return usage;
52
+ if (binding?.pending)
53
+ return `Pending operation ${binding.pending.key} has an unknown remote outcome. Use /board sync first; explicitly /board discard ${binding.pending.key} only after inspecting Zergboard.`;
54
+ await save(undefined);
55
+ return 'Zergboard card detached; remote card unchanged.';
56
+ }
57
+ if (action === 'attach' || action === 'create') {
58
+ if (binding)
59
+ return 'Session already linked or has a pending operation. Use /board status or /board sync; detach before choosing a different task.';
60
+ const boardId = identity(args[1]), target = identity(args[2]);
61
+ if (action === 'attach' && args.length !== 3)
62
+ return usage;
63
+ if (action === 'create' && args.length < 4)
64
+ return usage;
65
+ const details = await boardRequest(origin, sessionId, `/api/boards/${boardId}`, boardDetailsResponse);
66
+ if (details.board.id !== boardId)
67
+ throw new Error('Zergboard response belongs to a different board');
68
+ const next = { version: 1, sessionId, taskUuid: randomUUID(), taskId: taskId(session), origin, boardId };
69
+ if (action === 'attach') {
70
+ const { card } = await boardRequest(origin, sessionId, `/api/cards/${target}`, boardCardResponse);
71
+ if (card.id !== target || card.board_id !== boardId)
72
+ throw new Error('Zergboard card belongs to a different board');
73
+ await save({ ...next, cardId: card.id, revision: card.revision });
74
+ return `Attached Zergboard card ${card.id} to task ${next.taskUuid}. ${card.title} — ${card.status} (revision ${card.revision}).`;
75
+ }
76
+ if (!details.columns.some(column => column.id === target))
77
+ throw new Error('Zergboard column does not belong to the selected board');
78
+ const title = z.string().min(1).max(255).parse(args.slice(3).join(' '));
79
+ await save({ ...next, pending: { kind: 'create', key: randomUUID(), body: { boardId, columnId: target, title,
80
+ description: `ZTC session ${sessionId}\nTask ${next.taskUuid}\nSource task ${next.taskId}\nCompletion requires an explicit user decision; idle is not completion.` } } });
81
+ }
82
+ else if (!binding)
83
+ return 'No Zergboard card attached. ' + usage;
84
+ if (!binding)
85
+ throw new Error('Zergboard association unavailable');
86
+ if (action === 'status' || action === 'refresh') {
87
+ if (args.length !== 1)
88
+ return usage;
89
+ if (!binding.cardId)
90
+ return `Zergboard creation pending for task ${binding.taskUuid}; operation ${binding.pending?.key}. Use /board sync first; inspect Zergboard before explicitly discarding an unknown outcome.`;
91
+ const { card } = await boardRequest(origin, sessionId, `/api/cards/${binding.cardId}`, boardCardResponse);
92
+ if (card.id !== binding.cardId || card.board_id !== binding.boardId)
93
+ throw new Error('Attached card moved to a different board; sync refused');
94
+ if (action === 'refresh') {
95
+ if (binding.pending)
96
+ return `Pending operation ${binding.pending.key} retains its original revision. Use /board sync first; inspect Zergboard before explicitly /board discard ${binding.pending.key}.`;
97
+ await save({ ...binding, revision: card.revision });
98
+ }
99
+ return `Zergboard ${card.id}: ${card.title} — ${card.status}, state ${card.state_id ?? 'unknown'}, revision ${card.revision}; acknowledged revision ${binding.revision}. Task ${binding.taskUuid}.${binding.pending ? ` Pending operation ${binding.pending.key} retained; use /board sync first; inspect Zergboard before explicitly discarding an unknown outcome.` : ''} Idle never establishes completion.`;
100
+ }
101
+ if (action === 'state') {
102
+ if (args.length !== 3 || !['running', 'blocked', 'review', 'done'].includes(args[1]))
103
+ return usage;
104
+ if (!binding.cardId || binding.pending)
105
+ return 'Reconcile the pending operation with /board sync before changing state.';
106
+ const stateId = identity(args[2]);
107
+ const details = await boardRequest(origin, sessionId, `/api/boards/${binding.boardId}`, boardDetailsResponse);
108
+ const state = details.states.find(state => state.id === stateId);
109
+ if (details.board.id !== binding.boardId || !state || (args[1] === 'done') !== (state.kind === 'done'))
110
+ throw new Error('Selected state is not a matching state on the attached board');
111
+ const { card } = await boardRequest(origin, sessionId, `/api/cards/${binding.cardId}`, boardCardResponse, { method: 'PATCH', body: { stateId }, revision: binding.revision });
112
+ if (card.id !== binding.cardId || card.board_id !== binding.boardId || card.state_id !== stateId)
113
+ throw new Error('Zergboard state receipt does not match the requested card/state');
114
+ await save({ ...binding, revision: card.revision });
115
+ return `Zergboard ${args[1]} decision saved: ${card.status}, revision ${card.revision}.`;
116
+ }
117
+ if (action === 'share') {
118
+ if (args.length !== 1)
119
+ return usage;
120
+ if (binding.pending)
121
+ return 'Pending operation retained. Use /board sync before sharing a newer checkpoint.';
122
+ if (!binding.cardId)
123
+ return 'Create or attach a card before sharing evidence.';
124
+ if (binding.taskId !== taskId(session))
125
+ return 'Current session task changed; detach and explicitly attach the new task before sharing evidence.';
126
+ const pkg = buildSessionEvidencePackage({ sessionId, messages: session.messages, diagnostics: session.diagnostics,
127
+ evidence: session.evidence, taskHandoff: session.task_handoff ? projectTaskHandoff(session.task_handoff) : null });
128
+ if (binding.lastEvidence?.packageId === pkg.packageId)
129
+ return `Evidence package ${pkg.packageId} already shared as attachment ${binding.lastEvidence.attachmentId}.`;
130
+ const bytes = Buffer.from(JSON.stringify(pkg));
131
+ if (bytes.length > BOARD_PENDING_MAX_BYTES)
132
+ return 'Evidence package exceeds the 512 KiB sync limit. Use /clipboard package save to export the full package to a file.';
133
+ await save({ ...binding, pending: { kind: 'evidence', key: randomUUID(), packageId: pkg.packageId,
134
+ expectedRevision: binding.revision, body: { filename: `ztc-${pkg.packageId}.json`, mime_type: 'application/json', data: bytes.toString('base64') } } });
135
+ }
136
+ if (['sync', 'share', 'create'].includes(action)) {
137
+ if (action === 'sync' && args.length !== 1)
138
+ return usage;
139
+ const pending = binding.pending;
140
+ if (!pending)
141
+ return 'No pending Zergboard operation. Use /board status to inspect the remote card.';
142
+ if (pending.kind === 'create') {
143
+ const { card } = await boardRequest(origin, sessionId, '/api/cards/terminal-sync-v1', boardCardResponse, { method: 'POST', body: pending.body, key: pending.key });
144
+ if (card.board_id !== binding.boardId)
145
+ throw new Error('Zergboard creation receipt belongs to a different board');
146
+ await save({ ...binding, pending: undefined, cardId: card.id, revision: card.revision });
147
+ return `Attached Zergboard card ${card.id} to task ${binding.taskUuid}.`;
148
+ }
149
+ const receipt = await boardRequest(origin, sessionId, `/api/cards/${binding.cardId}/terminal-evidence-v1`, boardAttachmentResponse, { method: 'POST', body: pending.body, key: pending.key, revision: pending.expectedRevision });
150
+ if (receipt.attachment.card_id !== binding.cardId)
151
+ throw new Error('Zergboard evidence receipt belongs to a different card');
152
+ await save({ ...binding, pending: undefined, revision: receipt.revision,
153
+ lastEvidence: { packageId: pending.packageId, attachmentId: receipt.attachment.id, revision: receipt.revision } });
154
+ return `Evidence receipt saved: attachment ${receipt.attachment.id}, package ${pending.packageId}. Receipt proves accepted bytes; it does not establish task completion.`;
155
+ }
156
+ return usage;
157
+ });
158
+ }
159
+ export const boardCommand = { name: 'board', description: 'Attach a saved session to Zergboard and explicitly sync state/evidence', usage,
160
+ async handler(args, ctx) {
161
+ try {
162
+ ctx.addMessage({ role: 'system', content: await run(args, ctx) });
163
+ }
164
+ catch (error) {
165
+ // Never echo remote response bodies or credentials into the transcript.
166
+ const message = error instanceof Error ? error.message : 'Request failed';
167
+ ctx.addMessage({ role: 'system', content: `Zergboard: ${message}. Operation outcome may be unknown; pending intent is retained for /board sync.` });
168
+ }
169
+ } };