@zergai/ztc 0.4.1-dev.36919234045 → 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 (678) hide show
  1. package/README.md +390 -44
  2. package/RUST_THIRD_PARTY_LICENSES.txt +1080 -822
  3. package/THIRD_PARTY_NOTICES.md +269 -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 +1204 -207
  14. package/dist/agent/agent.d.ts +74 -8
  15. package/dist/agent/agent.js +1035 -182
  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 +164 -18
  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 +1 -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 +8 -2
  31. package/dist/agent/backends/index.js +12 -1
  32. package/dist/agent/backends/openai_compatible.d.ts +3 -4
  33. package/dist/agent/backends/openai_compatible.js +8 -11
  34. package/dist/agent/backends/openai_responses.d.ts +8 -3
  35. package/dist/agent/backends/openai_responses.js +77 -33
  36. package/dist/agent/backends/request_metrics.js +12 -2
  37. package/dist/agent/backends/types.d.ts +108 -6
  38. package/dist/agent/backends/types.js +5 -1
  39. package/dist/agent/backends/zrouter_stream.d.ts +2 -1
  40. package/dist/agent/backends/zrouter_stream.js +26 -12
  41. package/dist/agent/background_registry.d.ts +2 -0
  42. package/dist/agent/background_registry.js +1 -0
  43. package/dist/agent/claim_observation.d.ts +6 -0
  44. package/dist/agent/claim_observation.js +54 -0
  45. package/dist/agent/commands/accounts.js +46 -177
  46. package/dist/agent/commands/attention.d.ts +2 -0
  47. package/dist/agent/commands/attention.js +67 -0
  48. package/dist/agent/commands/auth.js +18 -2
  49. package/dist/agent/commands/board.d.ts +2 -0
  50. package/dist/agent/commands/board.js +169 -0
  51. package/dist/agent/commands/clipboard.js +50 -1
  52. package/dist/agent/commands/compact.js +15 -8
  53. package/dist/agent/commands/desktop.d.ts +2 -0
  54. package/dist/agent/commands/desktop.js +29 -0
  55. package/dist/agent/commands/environment.d.ts +3 -0
  56. package/dist/agent/commands/environment.js +109 -0
  57. package/dist/agent/commands/evidence.d.ts +2 -0
  58. package/dist/agent/commands/evidence.js +9 -0
  59. package/dist/agent/commands/fork.js +4 -3
  60. package/dist/agent/commands/goal.d.ts +33 -1
  61. package/dist/agent/commands/goal.js +174 -14
  62. package/dist/agent/commands/goal_exit.d.ts +36 -0
  63. package/dist/agent/commands/goal_exit.js +120 -0
  64. package/dist/agent/commands/help.js +3 -1
  65. package/dist/agent/commands/history.js +3 -1
  66. package/dist/agent/commands/inbox.d.ts +2 -0
  67. package/dist/agent/commands/inbox.js +148 -0
  68. package/dist/agent/commands/index.js +16 -1
  69. package/dist/agent/commands/input_mode.js +8 -6
  70. package/dist/agent/commands/job.d.ts +2 -0
  71. package/dist/agent/commands/job.js +93 -0
  72. package/dist/agent/commands/keybindings.js +4 -1
  73. package/dist/agent/commands/label.d.ts +2 -0
  74. package/dist/agent/commands/label.js +77 -0
  75. package/dist/agent/commands/layout.d.ts +2 -0
  76. package/dist/agent/commands/layout.js +20 -0
  77. package/dist/agent/commands/mirror.js +16 -1
  78. package/dist/agent/commands/permissions.d.ts +3 -1
  79. package/dist/agent/commands/permissions.js +79 -89
  80. package/dist/agent/commands/plan.js +5 -15
  81. package/dist/agent/commands/provider_selection.js +9 -3
  82. package/dist/agent/commands/rename.js +1 -1
  83. package/dist/agent/commands/resources.d.ts +2 -0
  84. package/dist/agent/commands/resources.js +67 -0
  85. package/dist/agent/commands/rewind.d.ts +3 -0
  86. package/dist/agent/commands/rewind.js +16 -0
  87. package/dist/agent/commands/runbooks.d.ts +2 -0
  88. package/dist/agent/commands/runbooks.js +73 -0
  89. package/dist/agent/commands/runbooks_lazy.d.ts +2 -0
  90. package/dist/agent/commands/runbooks_lazy.js +8 -0
  91. package/dist/agent/commands/sessions.d.ts +1 -1
  92. package/dist/agent/commands/sessions.js +33 -5
  93. package/dist/agent/commands/settings.js +140 -32
  94. package/dist/agent/commands/setup.d.ts +2 -0
  95. package/dist/agent/commands/setup.js +78 -0
  96. package/dist/agent/commands/share.d.ts +2 -0
  97. package/dist/agent/commands/share.js +64 -0
  98. package/dist/agent/commands/status.js +14 -2
  99. package/dist/agent/commands/types.d.ts +81 -7
  100. package/dist/agent/commands/update.js +8 -0
  101. package/dist/agent/commands/usage.d.ts +2 -0
  102. package/dist/agent/commands/usage.js +8 -0
  103. package/dist/agent/factory.d.ts +11 -0
  104. package/dist/agent/factory.js +100 -21
  105. package/dist/agent/loop_policy.d.ts +6 -3
  106. package/dist/agent/loop_policy.js +12 -3
  107. package/dist/agent/measurement_guidance.d.ts +2 -0
  108. package/dist/agent/measurement_guidance.js +5 -0
  109. package/dist/agent/request_encoder.d.ts +8 -1
  110. package/dist/agent/request_encoder.js +95 -23
  111. package/dist/agent/runtime/benchmark_comparison.d.ts +30 -0
  112. package/dist/agent/runtime/benchmark_comparison.js +94 -0
  113. package/dist/agent/runtime/benchmark_contract.d.ts +48 -0
  114. package/dist/agent/runtime/benchmark_contract.js +90 -0
  115. package/dist/agent/runtime/checked_commands.d.ts +32 -0
  116. package/dist/agent/runtime/checked_commands.js +119 -0
  117. package/dist/agent/runtime/command_execution_policy.d.ts +26 -0
  118. package/dist/agent/runtime/command_execution_policy.js +91 -0
  119. package/dist/agent/runtime/command_jobs.d.ts +36 -18
  120. package/dist/agent/runtime/command_jobs.js +151 -13
  121. package/dist/agent/runtime/command_panes.d.ts +59 -0
  122. package/dist/agent/runtime/command_panes.js +398 -0
  123. package/dist/agent/runtime/command_wait.d.ts +19 -0
  124. package/dist/agent/runtime/command_wait.js +167 -0
  125. package/dist/agent/runtime/cpu_benchmark.d.ts +30 -0
  126. package/dist/agent/runtime/cpu_benchmark.js +126 -0
  127. package/dist/agent/runtime/delegated_evidence.d.ts +26 -0
  128. package/dist/agent/runtime/delegated_evidence.js +80 -0
  129. package/dist/agent/runtime/evidence.d.ts +127 -0
  130. package/dist/agent/runtime/evidence.js +468 -0
  131. package/dist/agent/runtime/execution_context.d.ts +7 -0
  132. package/dist/agent/runtime/execution_context.js +39 -3
  133. package/dist/agent/runtime/json_verifier_recipe.d.ts +8 -0
  134. package/dist/agent/runtime/json_verifier_recipe.js +66 -0
  135. package/dist/agent/runtime/measurements.d.ts +110 -0
  136. package/dist/agent/runtime/measurements.js +317 -0
  137. package/dist/agent/runtime/policy.d.ts +4 -0
  138. package/dist/agent/runtime/policy.js +31 -20
  139. package/dist/agent/runtime/provider_native_evidence.d.ts +20 -0
  140. package/dist/agent/runtime/provider_native_evidence.js +86 -0
  141. package/dist/agent/runtime/recovery.d.ts +2 -0
  142. package/dist/agent/runtime/recovery.js +45 -2
  143. package/dist/agent/runtime/remote_broker_transport.d.ts +10 -0
  144. package/dist/agent/runtime/remote_broker_transport.js +84 -0
  145. package/dist/agent/runtime/remote_deletion_receipts.d.ts +3 -0
  146. package/dist/agent/runtime/remote_deletion_receipts.js +43 -0
  147. package/dist/agent/runtime/remote_journal_replay.d.ts +13 -0
  148. package/dist/agent/runtime/remote_journal_replay.js +233 -0
  149. package/dist/agent/runtime/remote_mutation_journal.d.ts +25 -0
  150. package/dist/agent/runtime/remote_mutation_journal.js +208 -0
  151. package/dist/agent/runtime/remote_resource_endpoint.d.ts +7 -0
  152. package/dist/agent/runtime/remote_resource_endpoint.js +6 -0
  153. package/dist/agent/runtime/remote_resource_errors.d.ts +5 -0
  154. package/dist/agent/runtime/remote_resource_errors.js +9 -0
  155. package/dist/agent/runtime/remote_resource_script.d.ts +2 -0
  156. package/dist/agent/runtime/remote_resource_script.js +1009 -0
  157. package/dist/agent/runtime/remote_resources.d.ts +29 -0
  158. package/dist/agent/runtime/remote_resources.js +160 -0
  159. package/dist/agent/runtime/source_verification.d.ts +12 -0
  160. package/dist/agent/runtime/source_verification.js +210 -0
  161. package/dist/agent/runtime/source_verification_contract.d.ts +75 -0
  162. package/dist/agent/runtime/source_verification_contract.js +203 -0
  163. package/dist/agent/runtime/tool_checkpoints.d.ts +11 -0
  164. package/dist/agent/runtime/tool_checkpoints.js +26 -0
  165. package/dist/agent/runtime/tool_effects.d.ts +5 -0
  166. package/dist/agent/runtime/tool_progress.d.ts +12 -0
  167. package/dist/agent/runtime/tool_progress.js +76 -0
  168. package/dist/agent/runtime/tool_runtime.d.ts +16 -1
  169. package/dist/agent/runtime/tool_runtime.js +204 -10
  170. package/dist/agent/runtime/tracing.d.ts +1 -1
  171. package/dist/agent/runtime/verifier_capture.d.ts +9 -0
  172. package/dist/agent/runtime/verifier_capture.js +100 -0
  173. package/dist/agent/runtime/verifier_contract.d.ts +24 -0
  174. package/dist/agent/runtime/verifier_contract.js +41 -0
  175. package/dist/agent/subagent.d.ts +20 -0
  176. package/dist/agent/subagent.js +244 -29
  177. package/dist/agent/tool_response_directory.d.ts +24 -0
  178. package/dist/agent/tool_response_directory.js +61 -0
  179. package/dist/agent/tool_response_source.d.ts +8 -0
  180. package/dist/agent/tool_response_source.js +49 -0
  181. package/dist/agent/tool_response_store.d.ts +74 -3
  182. package/dist/agent/tool_response_store.js +579 -62
  183. package/dist/agent/tools/ask_user.d.ts +3 -1
  184. package/dist/agent/tools/ask_user.js +30 -11
  185. package/dist/agent/tools/background.js +1 -0
  186. package/dist/agent/tools/benchmark_cpu.d.ts +2 -0
  187. package/dist/agent/tools/benchmark_cpu.js +102 -0
  188. package/dist/agent/tools/compare_benchmarks.d.ts +2 -0
  189. package/dist/agent/tools/compare_benchmarks.js +53 -0
  190. package/dist/agent/tools/deferred.js +1 -0
  191. package/dist/agent/tools/delegate.js +18 -2
  192. package/dist/agent/tools/helper_requirements.d.ts +7 -0
  193. package/dist/agent/tools/helper_requirements.js +19 -0
  194. package/dist/agent/tools/index.d.ts +1 -0
  195. package/dist/agent/tools/index.js +3 -0
  196. package/dist/agent/tools/measurement_report.d.ts +22 -0
  197. package/dist/agent/tools/measurement_report.js +190 -0
  198. package/dist/agent/tools/project_context.d.ts +3 -0
  199. package/dist/agent/tools/project_context.js +45 -0
  200. package/dist/agent/tools/recall_tool_response.d.ts +3 -5
  201. package/dist/agent/tools/recall_tool_response.js +19 -29
  202. package/dist/agent/tools/registry.d.ts +1 -0
  203. package/dist/agent/tools/registry.js +23 -0
  204. package/dist/agent/tools/related_sessions.d.ts +2 -0
  205. package/dist/agent/tools/related_sessions.js +156 -0
  206. package/dist/agent/tools/routine.js +13 -3
  207. package/dist/agent/tools/session_evidence.d.ts +3 -0
  208. package/dist/agent/tools/session_evidence.js +72 -0
  209. package/dist/agent/tools/shell.d.ts +4 -3
  210. package/dist/agent/tools/shell.js +174 -47
  211. package/dist/agent/tools/tool_search.js +3 -2
  212. package/dist/agent/tools/types.d.ts +28 -0
  213. package/dist/agent/tools/verify_artifact.d.ts +2 -0
  214. package/dist/agent/tools/verify_artifact.js +60 -0
  215. package/dist/agent/tools/workflow.js +1 -0
  216. package/dist/app/activity.d.ts +6 -1
  217. package/dist/app/activity.js +81 -12
  218. package/dist/app/agent_runner.d.ts +6 -1
  219. package/dist/app/agent_runner.js +34 -19
  220. package/dist/app/command_context.js +76 -3
  221. package/dist/app/controller.d.ts +15 -4
  222. package/dist/app/controller.js +29 -3
  223. package/dist/app/escape_stop.d.ts +11 -0
  224. package/dist/app/escape_stop.js +15 -0
  225. package/dist/app/liveness.d.ts +6 -4
  226. package/dist/app/liveness.js +13 -3
  227. package/dist/app/ordered_transcript.js +43 -4
  228. package/dist/app/prompt_turn.d.ts +14 -0
  229. package/dist/app/prompt_turn.js +53 -0
  230. package/dist/app/recap.d.ts +3 -0
  231. package/dist/app/recap.js +9 -3
  232. package/dist/app/restart.d.ts +3 -2
  233. package/dist/app/restart.js +7 -3
  234. package/dist/app/rewind.d.ts +3 -3
  235. package/dist/app/rewind.js +3 -3
  236. package/dist/app/selection_completion.js +10 -3
  237. package/dist/app/session_manager.d.ts +38 -6
  238. package/dist/app/session_manager.js +252 -54
  239. package/dist/app/session_messages.d.ts +3 -0
  240. package/dist/app/session_messages.js +60 -0
  241. package/dist/app/task_scope_router.d.ts +20 -0
  242. package/dist/app/task_scope_router.js +173 -0
  243. package/dist/app/transcript_window.d.ts +2 -0
  244. package/dist/app/transcript_window.js +4 -0
  245. package/dist/app/workspace_admission_details.d.ts +3 -0
  246. package/dist/app/workspace_admission_details.js +26 -0
  247. package/dist/app/workspace_layout_controller.d.ts +11 -0
  248. package/dist/app/workspace_layout_controller.js +88 -0
  249. package/dist/app/workspace_monitor.d.ts +1 -0
  250. package/dist/app/workspace_monitor.js +216 -0
  251. package/dist/app/workspace_presets.d.ts +29 -0
  252. package/dist/app/workspace_presets.js +192 -0
  253. package/dist/attention/queue.d.ts +37 -0
  254. package/dist/attention/queue.js +183 -0
  255. package/dist/bench/rf_shared.d.ts +2 -0
  256. package/dist/board/binding.d.ts +42 -0
  257. package/dist/board/binding.js +38 -0
  258. package/dist/board/client.d.ts +42 -0
  259. package/dist/board/client.js +60 -0
  260. package/dist/cli.js +1 -1
  261. package/dist/cli_args.js +17 -1
  262. package/dist/cli_main.js +86 -8
  263. package/dist/cli_ratatui.d.ts +183 -16
  264. package/dist/cli_ratatui.js +3916 -1219
  265. package/dist/components/ActivityLine.d.ts +3 -2
  266. package/dist/components/ActivityLine.js +2 -2
  267. package/dist/components/InputArea.d.ts +19 -1
  268. package/dist/components/InputArea.js +264 -190
  269. package/dist/components/MessageList.d.ts +2 -0
  270. package/dist/components/MessageList.js +3 -1
  271. package/dist/components/SingleMessage.d.ts +2 -0
  272. package/dist/components/SingleMessage.js +4 -2
  273. package/dist/components/StatusBar.d.ts +4 -2
  274. package/dist/components/StatusBar.js +3 -1
  275. package/dist/conductor_branch.js +3 -0
  276. package/dist/config/api_retry.d.ts +6 -1
  277. package/dist/config/api_retry.js +19 -1
  278. package/dist/config/message_display.d.ts +1 -0
  279. package/dist/config/message_display.js +17 -2
  280. package/dist/config/permissions.d.ts +21 -0
  281. package/dist/config/permissions.js +89 -0
  282. package/dist/config/types.d.ts +32 -5
  283. package/dist/config.d.ts +4 -2
  284. package/dist/config.js +63 -13
  285. package/dist/context/project_intelligence.d.ts +44 -0
  286. package/dist/context/project_intelligence.js +246 -0
  287. package/dist/desktop/cli_launch.d.ts +8 -0
  288. package/dist/desktop/cli_launch.js +6 -0
  289. package/dist/desktop/cli_shim.d.ts +8 -0
  290. package/dist/desktop/cli_shim.js +120 -0
  291. package/dist/desktop/runtime.d.ts +16 -0
  292. package/dist/desktop/runtime.js +161 -0
  293. package/dist/desktop/worker_launch.d.ts +7 -0
  294. package/dist/desktop/worker_launch.js +7 -0
  295. package/dist/diagnostics/cargo_mutants_selection.d.ts +27 -0
  296. package/dist/diagnostics/cargo_mutants_selection.js +48 -0
  297. package/dist/diagnostics/native_terminal_benchmark.d.ts +58 -0
  298. package/dist/diagnostics/native_terminal_benchmark.js +1247 -0
  299. package/dist/diagnostics/session_evidence_package.d.ts +40 -0
  300. package/dist/diagnostics/session_evidence_package.js +234 -0
  301. package/dist/diagnostics/session_export.d.ts +93 -0
  302. package/dist/diagnostics/session_export.js +634 -0
  303. package/dist/emulation/tool_adapters.js +48 -18
  304. package/dist/emulation/ztc_addendum.d.ts +1 -0
  305. package/dist/emulation/ztc_addendum.js +13 -12
  306. package/dist/environment/service_runner.d.ts +1 -0
  307. package/dist/environment/service_runner.js +68 -0
  308. package/dist/environment/store.d.ts +120 -0
  309. package/dist/environment/store.js +387 -0
  310. package/dist/events.d.ts +40 -1
  311. package/dist/events.js +10 -17
  312. package/dist/goal_contract.d.ts +25 -0
  313. package/dist/goal_contract.js +44 -0
  314. package/dist/headless.d.ts +31 -0
  315. package/dist/headless.js +576 -70
  316. package/dist/headless_cli.js +8 -0
  317. package/dist/headless_cli_args.d.ts +1 -0
  318. package/dist/headless_cli_args.js +1 -0
  319. package/dist/intake/cli.d.ts +1 -0
  320. package/dist/intake/cli.js +33 -0
  321. package/dist/intake/format.d.ts +2 -0
  322. package/dist/intake/format.js +14 -0
  323. package/dist/intake/notifications.d.ts +16 -0
  324. package/dist/intake/notifications.js +132 -0
  325. package/dist/intake/store.d.ts +56 -0
  326. package/dist/intake/store.js +238 -0
  327. package/dist/library.d.ts +8 -0
  328. package/dist/library.js +19 -10
  329. package/dist/mcp/client.d.ts +1 -0
  330. package/dist/mcp/client.js +20 -0
  331. package/dist/modes/builtin/plan.yaml +2 -2
  332. package/dist/modes/handlers.js +1 -1
  333. package/dist/onboarding/first_run.d.ts +3 -0
  334. package/dist/onboarding/first_run.js +28 -24
  335. package/dist/onboarding/setup.d.ts +32 -0
  336. package/dist/onboarding/setup.js +133 -0
  337. package/dist/onboarding/setup_agent_health.d.ts +17 -0
  338. package/dist/onboarding/setup_agent_health.js +79 -0
  339. package/dist/onboarding/setup_environment.d.ts +66 -0
  340. package/dist/onboarding/setup_environment.js +219 -0
  341. package/dist/onboarding/setup_workspace.d.ts +17 -0
  342. package/dist/onboarding/setup_workspace.js +129 -0
  343. package/dist/optimize/adapters/index.d.ts +4 -1
  344. package/dist/optimize/adapters/index.js +7 -0
  345. package/dist/optimize/adapters/kernelbench.js +14 -5
  346. package/dist/optimize/adapters/popcorn.js +3 -2
  347. package/dist/optimize/adapters/profile_benchmark.js +13 -7
  348. package/dist/optimize/adapters/rfbench.js +25 -14
  349. package/dist/optimize/adapters/types.d.ts +3 -0
  350. package/dist/optimize/adapters/zergpod.js +5 -2
  351. package/dist/optimize/baseline.js +10 -21
  352. package/dist/optimize/branch.js +9 -12
  353. package/dist/optimize/combine.js +2 -3
  354. package/dist/optimize/executor.js +34 -48
  355. package/dist/optimize/measurements.d.ts +55 -0
  356. package/dist/optimize/measurements.js +173 -0
  357. package/dist/optimize/results.d.ts +1 -0
  358. package/dist/optimize/results.js +11 -33
  359. package/dist/optimize/tge.js +2 -1
  360. package/dist/panes/initial_input.d.ts +19 -0
  361. package/dist/panes/initial_input.js +206 -0
  362. package/dist/panes/labels.d.ts +16 -0
  363. package/dist/panes/labels.js +42 -0
  364. package/dist/panes/types.d.ts +1 -0
  365. package/dist/panes/ztc_launch.js +7 -0
  366. package/dist/plugin/optimization.d.ts +2 -0
  367. package/dist/plugin/optimization.js +1 -0
  368. package/dist/plugin/runtime.d.ts +2 -0
  369. package/dist/plugin/simulation.d.ts +6 -1
  370. package/dist/plugin/simulation_contract.d.ts +836 -1
  371. package/dist/plugin/simulation_documents.d.ts +22 -0
  372. package/dist/plugin/simulation_documents.js +1 -0
  373. package/dist/plugin/simulation_interventions.d.ts +103 -0
  374. package/dist/plugin/simulation_interventions.js +1 -0
  375. package/dist/plugin/simulation_living.d.ts +1 -0
  376. package/dist/plugin/simulation_living.js +3 -0
  377. package/dist/plugin/simulation_meetings.d.ts +121 -0
  378. package/dist/plugin/simulation_meetings.js +1 -0
  379. package/dist/plugin/simulation_story_review.d.ts +111 -0
  380. package/dist/plugin/simulation_story_review.js +1 -0
  381. package/dist/plugin/simulation_storyteller.d.ts +91 -0
  382. package/dist/plugin/simulation_storyteller.js +1 -0
  383. package/dist/plugin/simulation_structured.d.ts +2 -0
  384. package/dist/plugin/simulation_structured.js +2 -0
  385. package/dist/plugin/simulation_toolkit.d.ts +21 -0
  386. package/dist/plugin/simulation_toolkit.js +24 -0
  387. package/dist/prompts/tool_delegate_task.j2 +1 -1
  388. package/dist/remote-broker/Dockerfile +10 -0
  389. package/dist/remote-broker/archive.py +1227 -0
  390. package/dist/remote-broker/cutover.py +761 -0
  391. package/dist/remote-broker/requirements.txt +5 -0
  392. package/dist/remote-broker/resources.json +6 -0
  393. package/dist/remote-broker/resources.write-staging.example.json +18 -0
  394. package/dist/remote-broker/retained.py +686 -0
  395. package/dist/remote-broker/retained_cleanup.py +550 -0
  396. package/dist/remote-broker/server.py +648 -0
  397. package/dist/remote-broker/worker.py +1007 -0
  398. package/dist/router_auth.d.ts +31 -0
  399. package/dist/router_auth.js +155 -9
  400. package/dist/runbooks/catalog.d.ts +3 -0
  401. package/dist/runbooks/catalog.js +26 -0
  402. package/dist/runbooks/library.d.ts +11 -0
  403. package/dist/runbooks/library.js +95 -0
  404. package/dist/runbooks/package.d.ts +43 -0
  405. package/dist/runbooks/package.js +102 -0
  406. package/dist/session.d.ts +59 -11
  407. package/dist/session.js +483 -33
  408. package/dist/session_handoff.d.ts +25 -0
  409. package/dist/session_handoff.js +322 -0
  410. package/dist/session_handoff_contract.d.ts +89 -0
  411. package/dist/session_handoff_contract.js +179 -0
  412. package/dist/session_media.d.ts +41 -0
  413. package/dist/session_media.js +357 -0
  414. package/dist/session_ownership.d.ts +16 -0
  415. package/dist/session_ownership.js +221 -0
  416. package/dist/session_public.d.ts +10 -2
  417. package/dist/session_public.js +6 -1
  418. package/dist/simulation/dynamic_history.d.ts +42 -0
  419. package/dist/simulation/dynamic_history.js +173 -0
  420. package/dist/simulation/engines/swarm/pane_manager.js +7 -6
  421. package/dist/simulation/inference.d.ts +3 -1
  422. package/dist/simulation/inference.js +19 -1
  423. package/dist/simulation/intervention_generation.d.ts +27 -0
  424. package/dist/simulation/intervention_generation.js +246 -0
  425. package/dist/simulation/intervention_material.d.ts +4 -0
  426. package/dist/simulation/intervention_material.js +81 -0
  427. package/dist/simulation/living/context.d.ts +3130 -0
  428. package/dist/simulation/living/context.js +944 -0
  429. package/dist/simulation/living/definer.d.ts +12 -0
  430. package/dist/simulation/living/definer.js +223 -0
  431. package/dist/simulation/living/definition.d.ts +257 -0
  432. package/dist/simulation/living/definition.js +341 -0
  433. package/dist/simulation/living/frame.d.ts +259 -0
  434. package/dist/simulation/living/frame.js +223 -0
  435. package/dist/simulation/living/identifiers.d.ts +2 -0
  436. package/dist/simulation/living/identifiers.js +12 -0
  437. package/dist/simulation/living/index.d.ts +15 -0
  438. package/dist/simulation/living/index.js +15 -0
  439. package/dist/simulation/living/inference.d.ts +219 -0
  440. package/dist/simulation/living/inference.js +576 -0
  441. package/dist/simulation/living/mechanics.d.ts +54 -0
  442. package/dist/simulation/living/mechanics.js +588 -0
  443. package/dist/simulation/living/model-input.d.ts +25 -0
  444. package/dist/simulation/living/model-input.js +215 -0
  445. package/dist/simulation/living/open-world.d.ts +257 -0
  446. package/dist/simulation/living/open-world.js +102 -0
  447. package/dist/simulation/living/projection.d.ts +7 -0
  448. package/dist/simulation/living/projection.js +31 -0
  449. package/dist/simulation/living/recall.d.ts +17 -0
  450. package/dist/simulation/living/recall.js +25 -0
  451. package/dist/simulation/living/reduce.d.ts +15 -0
  452. package/dist/simulation/living/reduce.js +1853 -0
  453. package/dist/simulation/living/replay.d.ts +6 -0
  454. package/dist/simulation/living/replay.js +22 -0
  455. package/dist/simulation/living/runtime.d.ts +140 -0
  456. package/dist/simulation/living/runtime.js +3020 -0
  457. package/dist/simulation/living/shared-kinds.d.ts +24 -0
  458. package/dist/simulation/living/shared-kinds.js +96 -0
  459. package/dist/simulation/living/types.d.ts +2785 -0
  460. package/dist/simulation/living/types.js +669 -0
  461. package/dist/simulation/llm.d.ts +3 -1
  462. package/dist/simulation/llm.js +90 -30
  463. package/dist/simulation/memory/embedding.d.ts +1 -1
  464. package/dist/simulation/memory/embedding.js +9 -3
  465. package/dist/simulation/memory/filesystem.d.ts +2 -0
  466. package/dist/simulation/memory/filesystem.js +5 -1
  467. package/dist/simulation/memory/filesystem_file_tree.d.ts +4 -1
  468. package/dist/simulation/memory/filesystem_file_tree.js +41 -10
  469. package/dist/simulation/memory/filesystem_invariants.js +1 -2
  470. package/dist/simulation/memory/filesystem_types.d.ts +1 -0
  471. package/dist/simulation/memory/memory.d.ts +2 -0
  472. package/dist/simulation/memory/memory.js +5 -1
  473. package/dist/simulation/orchestration/intent.js +0 -2
  474. package/dist/simulation/orchestration/lifecycle.js +0 -2
  475. package/dist/simulation/plugin_host.d.ts +25 -1
  476. package/dist/simulation/plugin_host.js +334 -17
  477. package/dist/simulation/session_documents.d.ts +20 -0
  478. package/dist/simulation/session_documents.js +62 -0
  479. package/dist/simulation/session_input_validation.d.ts +43 -0
  480. package/dist/simulation/session_input_validation.js +364 -0
  481. package/dist/simulation/session_inputs.d.ts +32 -0
  482. package/dist/simulation/session_inputs.js +154 -0
  483. package/dist/simulation/telemetry.d.ts +11 -14
  484. package/dist/simulation/telemetry.js +177 -54
  485. package/dist/simulation/toolkit/bounded_turns.d.ts +13 -0
  486. package/dist/simulation/toolkit/bounded_turns.js +80 -0
  487. package/dist/simulation/toolkit/dynamic_agents.d.ts +25 -0
  488. package/dist/simulation/toolkit/dynamic_agents.js +218 -0
  489. package/dist/simulation/toolkit/dynamic_digest.d.ts +1 -0
  490. package/dist/simulation/toolkit/dynamic_digest.js +8 -0
  491. package/dist/simulation/toolkit/dynamic_documents.d.ts +7 -0
  492. package/dist/simulation/toolkit/dynamic_documents.js +71 -0
  493. package/dist/simulation/toolkit/dynamic_driver.d.ts +8 -0
  494. package/dist/simulation/toolkit/dynamic_driver.js +269 -0
  495. package/dist/simulation/toolkit/dynamic_game.d.ts +53 -0
  496. package/dist/simulation/toolkit/dynamic_game.js +805 -0
  497. package/dist/simulation/toolkit/dynamic_knowledge.d.ts +15 -0
  498. package/dist/simulation/toolkit/dynamic_knowledge.js +91 -0
  499. package/dist/simulation/toolkit/dynamic_mechanics.d.ts +22 -0
  500. package/dist/simulation/toolkit/dynamic_mechanics.js +910 -0
  501. package/dist/simulation/toolkit/dynamic_meetings.d.ts +239 -0
  502. package/dist/simulation/toolkit/dynamic_meetings.js +350 -0
  503. package/dist/simulation/toolkit/dynamic_progress.d.ts +131 -0
  504. package/dist/simulation/toolkit/dynamic_progress.js +214 -0
  505. package/dist/simulation/toolkit/dynamic_projection.d.ts +9 -0
  506. package/dist/simulation/toolkit/dynamic_projection.js +219 -0
  507. package/dist/simulation/toolkit/dynamic_runtime.d.ts +412 -0
  508. package/dist/simulation/toolkit/dynamic_runtime.js +6536 -0
  509. package/dist/simulation/toolkit/dynamic_state.d.ts +111 -0
  510. package/dist/simulation/toolkit/dynamic_state.js +1967 -0
  511. package/dist/simulation/toolkit/dynamic_story_review.d.ts +508 -0
  512. package/dist/simulation/toolkit/dynamic_story_review.js +333 -0
  513. package/dist/simulation/toolkit/dynamic_storyteller.d.ts +77 -0
  514. package/dist/simulation/toolkit/dynamic_storyteller.js +114 -0
  515. package/dist/simulation/toolkit/dynamic_storyteller_runtime.d.ts +26 -0
  516. package/dist/simulation/toolkit/dynamic_storyteller_runtime.js +126 -0
  517. package/dist/simulation/toolkit/dynamic_world.d.ts +22 -0
  518. package/dist/simulation/toolkit/dynamic_world.js +377 -0
  519. package/dist/simulation/toolkit/structured_output.d.ts +5 -0
  520. package/dist/simulation/toolkit/structured_output.js +321 -0
  521. package/dist/simulation/types/world.d.ts +2 -0
  522. package/dist/simulation/world/artifact_store.js +1 -1
  523. package/dist/simulation/world/memory_manager.d.ts +5 -0
  524. package/dist/simulation/world/memory_manager.js +17 -2
  525. package/dist/simulation/world/state.d.ts +3 -2
  526. package/dist/simulation/world/state.js +15 -5
  527. package/dist/skills/bundled/measurement-validation/SKILL.md +144 -0
  528. package/dist/terminal_attach.d.ts +1 -0
  529. package/dist/terminal_attach.js +113 -0
  530. package/dist/tool_progress.d.ts +3 -0
  531. package/dist/tool_progress.js +27 -0
  532. package/dist/types.d.ts +145 -10
  533. package/dist/types.js +3 -0
  534. package/dist/ui/core/input.d.ts +3 -0
  535. package/dist/ui/core/input_segments.d.ts +18 -1
  536. package/dist/ui/core/input_segments.js +131 -47
  537. package/dist/ui/core/input_state.d.ts +12 -0
  538. package/dist/ui/core/layout_yoga.d.ts +1 -1
  539. package/dist/ui/core/turn_metadata.d.ts +5 -0
  540. package/dist/ui/core/turn_metadata.js +22 -0
  541. package/dist/ui/ink/render.d.ts +2 -1
  542. package/dist/ui/ink/render.js +6 -5
  543. package/dist/ui/ratatui/headless_pane_manager.d.ts +14 -1
  544. package/dist/ui/ratatui/headless_pane_manager.js +293 -104
  545. package/dist/ui/ratatui/index.d.ts +1 -0
  546. package/dist/ui/ratatui/input.d.ts +4 -0
  547. package/dist/ui/ratatui/input.js +15 -0
  548. package/dist/ui/ratatui/ipc_path.d.ts +2 -0
  549. package/dist/ui/ratatui/ipc_path.js +29 -1
  550. package/dist/ui/ratatui/mux_persistence.d.ts +3 -1
  551. package/dist/ui/ratatui/mux_persistence.js +139 -1
  552. package/dist/ui/ratatui/pane_relay.d.ts +1 -1
  553. package/dist/ui/ratatui/pane_relay.js +55 -27
  554. package/dist/ui/ratatui/process.d.ts +17 -1
  555. package/dist/ui/ratatui/process.js +80 -7
  556. package/dist/ui/ratatui/protocol.d.ts +236 -1
  557. package/dist/ui/ratatui/protocol.js +90 -0
  558. package/dist/ui/scrollback.d.ts +2 -1
  559. package/dist/ui/scrollback.js +9 -4
  560. package/dist/ui/stream_typewriter.d.ts +8 -3
  561. package/dist/ui/stream_typewriter.js +30 -1
  562. package/dist/ui/streaming_scrollback.d.ts +1 -0
  563. package/dist/ui/streaming_scrollback.js +1 -1
  564. package/dist/ui/transcript_render_cache.js +10 -0
  565. package/dist/ui/views/activity_line.d.ts +5 -3
  566. package/dist/ui/views/activity_line.js +65 -7
  567. package/dist/ui/views/app.d.ts +6 -3
  568. package/dist/ui/views/app.js +17 -6
  569. package/dist/ui/views/input_area.d.ts +7 -3
  570. package/dist/ui/views/input_area.js +15 -9
  571. package/dist/ui/views/message_list.d.ts +4 -1
  572. package/dist/ui/views/message_list.js +89 -19
  573. package/dist/ui/views/queue_panel.d.ts +3 -1
  574. package/dist/ui/views/queue_panel.js +9 -2
  575. package/dist/ui/views/status_bar.d.ts +4 -2
  576. package/dist/ui/views/status_bar.js +19 -8
  577. package/dist/ui/views/theme.d.ts +2 -0
  578. package/dist/ui/views/theme.js +2 -0
  579. package/dist/ui/widgets/color_panel.js +18 -0
  580. package/dist/ui/widgets/form.js +8 -0
  581. package/dist/ui/widgets/log_view.js +7 -0
  582. package/dist/ui/widgets/navigator_panel.js +8 -0
  583. package/dist/ui/widgets/prompt_viewer.js +2 -0
  584. package/dist/ui/widgets/questionnaire.d.ts +2 -0
  585. package/dist/ui/widgets/questionnaire.js +79 -16
  586. package/dist/ui/widgets/resume_panel.js +9 -0
  587. package/dist/ui/widgets/rewind_panel.d.ts +2 -2
  588. package/dist/ui/widgets/rewind_panel.js +4 -2
  589. package/dist/ui/widgets/select.js +16 -27
  590. package/dist/ui/widgets/settings_panel.js +16 -0
  591. package/dist/ui/widgets/status_line_panel.d.ts +1 -0
  592. package/dist/ui/widgets/status_line_panel.js +30 -4
  593. package/dist/ui/widgets/text_input.d.ts +2 -0
  594. package/dist/ui/widgets/text_input.js +15 -1
  595. package/dist/ui/widgets/types.d.ts +2 -0
  596. package/dist/usage_projection.d.ts +24 -0
  597. package/dist/usage_projection.js +130 -0
  598. package/dist/usage_snapshot.d.ts +36 -0
  599. package/dist/usage_snapshot.js +131 -0
  600. package/dist/utils/assistant_message.d.ts +2 -0
  601. package/dist/utils/assistant_message.js +5 -0
  602. package/dist/utils/atomic_write.d.ts +6 -2
  603. package/dist/utils/atomic_write.js +29 -4
  604. package/dist/utils/checked_shell.d.ts +25 -0
  605. package/dist/utils/checked_shell.js +107 -0
  606. package/dist/utils/compaction.d.ts +3 -0
  607. package/dist/utils/compaction.js +29 -5
  608. package/dist/utils/ephemeral.js +4 -0
  609. package/dist/utils/ephemeral_tools.d.ts +18 -0
  610. package/dist/utils/ephemeral_tools.js +97 -0
  611. package/dist/utils/jev_client.d.ts +4 -0
  612. package/dist/utils/jev_client.js +15 -0
  613. package/dist/utils/router_catalog.d.ts +4 -2
  614. package/dist/utils/router_catalog.js +54 -5
  615. package/dist/utils/sandbox.d.ts +9 -0
  616. package/dist/utils/sandbox.js +118 -15
  617. package/dist/utils/shell.d.ts +7 -0
  618. package/dist/utils/shell.js +98 -34
  619. package/dist/utils/subprocess_env.d.ts +3 -0
  620. package/dist/utils/subprocess_env.js +27 -1
  621. package/dist/web/accounts_mirror.d.ts +3 -1
  622. package/dist/web/accounts_mirror.js +13 -9
  623. package/dist/web/child_publication.d.ts +17 -0
  624. package/dist/web/child_publication.js +45 -0
  625. package/dist/web/mirror_authenticator.d.ts +31 -11
  626. package/dist/web/mirror_authenticator.js +67 -17
  627. package/dist/web/mirror_client.d.ts +31 -4
  628. package/dist/web/mirror_client.js +189 -23
  629. package/dist/web/mirror_stream.d.ts +84 -22
  630. package/dist/web/mirror_stream.js +676 -95
  631. package/dist/web/observer_query_redaction.d.ts +6 -0
  632. package/dist/web/observer_query_redaction.js +58 -0
  633. package/dist/web/pane_registry.d.ts +2 -0
  634. package/dist/web/pane_registry.js +86 -22
  635. package/dist/web/tool_image.d.ts +6 -0
  636. package/dist/web/tool_image.js +17 -0
  637. package/dist/web/view_plugin.d.ts +14 -0
  638. package/dist/web/view_plugin.js +23 -1
  639. package/dist/worker/executor.js +31 -12
  640. package/dist/worker/index.d.ts +1 -0
  641. package/dist/worker/toolsets.js +3 -1
  642. package/dist/worker/types.d.ts +12 -1
  643. package/dist/workflows/registry.js +1 -0
  644. package/dist/workflows/registry_handle.d.ts +2 -0
  645. package/dist/workflows/runtime.d.ts +2 -0
  646. package/dist/workflows/runtime.js +1 -0
  647. package/dist/workspace_agent.d.ts +7 -0
  648. package/dist/workspace_agent.js +36 -0
  649. package/dist/workspace_collision.d.ts +76 -0
  650. package/dist/workspace_collision.js +688 -0
  651. package/dist/workspace_layout.d.ts +18 -0
  652. package/dist/workspace_layout.js +121 -0
  653. package/dist/workspace_runtime.d.ts +44 -0
  654. package/dist/workspace_runtime.js +82 -0
  655. package/dist/workspace_session_context.d.ts +62 -0
  656. package/dist/workspace_session_context.js +160 -0
  657. package/dist/zlm-embed.mjs +26056 -3819
  658. package/dist/zlm.js +1 -0
  659. package/node_modules/@zerg/model-contracts/README.md +12 -0
  660. package/node_modules/@zerg/model-contracts/index.d.ts +2 -0
  661. package/node_modules/@zerg/model-contracts/index.js +4 -1
  662. package/package.json +44 -26
  663. package/packages/model-contracts/README.md +12 -0
  664. package/packages/model-contracts/index.d.ts +2 -0
  665. package/packages/model-contracts/index.js +4 -1
  666. package/remote-broker/Dockerfile +10 -0
  667. package/remote-broker/README.md +308 -0
  668. package/remote-broker/archive.py +1227 -0
  669. package/remote-broker/cutover.py +761 -0
  670. package/remote-broker/requirements.txt +5 -0
  671. package/remote-broker/resources.example.json +6 -0
  672. package/remote-broker/resources.write-staging.example.json +18 -0
  673. package/remote-broker/retained.py +686 -0
  674. package/remote-broker/retained_cleanup.py +550 -0
  675. package/remote-broker/server.py +648 -0
  676. package/scripts/build-remote-broker.mjs +13 -0
  677. package/scripts/ensure-local-packages.mjs +6 -0
  678. package/scripts/node-pty-helpers.mjs +103 -0
@@ -1,3 +1,4 @@
1
+ import { normalizeInputMode } from '../../types.js';
1
2
  import { MODE_CONFIGS } from '../../app/modes.js';
2
3
  import { getProviderDisplayName } from '../../agent/backends/provider_ids.js';
3
4
  import { formatTokenCount, cacheHitRate } from '../../utils/context.js';
@@ -86,9 +87,11 @@ const CONNECTION_COLORS = {
86
87
  */
87
88
  function statusItemForms(item, props) {
88
89
  const modeConfig = MODE_CONFIGS[props.mode];
89
- const modeLabel = modeConfig.label
90
- ? modeConfig.label[0].toUpperCase() + modeConfig.label.slice(1)
91
- : props.mode;
90
+ const modeLabel = props.mode === 'auto-accept'
91
+ ? 'Auto-accept'
92
+ : modeConfig.label
93
+ ? modeConfig.label[0].toUpperCase() + modeConfig.label.slice(1)
94
+ : props.mode;
92
95
  const providerName = props.provider ? getProviderDisplayName(props.provider) : '';
93
96
  const displayModel = props.model ? ellipsize(props.model, 20) : '';
94
97
  // Router IDs may already carry the provider. Strip it only in the combined label.
@@ -113,8 +116,9 @@ function statusItemForms(item, props) {
113
116
  const percentage = props.contextStatus && props.contextStatus.total > 0 ? `${Math.round(props.contextStatus.percentage)}%` : undefined;
114
117
  const remaining = props.contextStatus && props.contextStatus.total > 0 ? `${Math.max(0, Math.round(props.contextStatus.remaining))}%` : undefined;
115
118
  const reasoning = reasoningEnabled(props.effort);
116
- const inputMode = props.inputMode && props.inputMode !== 'queue'
117
- ? props.inputMode[0].toUpperCase() + props.inputMode.slice(1)
119
+ const canonicalInputMode = normalizeInputMode(props.inputMode ?? 'steer');
120
+ const inputMode = canonicalInputMode !== 'steer'
121
+ ? canonicalInputMode[0].toUpperCase() + canonicalInputMode.slice(1)
118
122
  : undefined;
119
123
  const model = providerName && pairedModel
120
124
  ? `${providerName}/${pairedModel}`
@@ -179,7 +183,11 @@ function statusItemForms(item, props) {
179
183
  case 'effort': {
180
184
  const unsupported = props.unsupportedEffort;
181
185
  if (!unsupported) {
182
- return { raw: props.effort, short: props.effort && `eff ${props.effort}`, long: props.effort && `Effort ${props.effort}` };
186
+ return {
187
+ raw: props.effort ?? 'default',
188
+ short: `eff ${props.effort ?? 'default'}`,
189
+ long: `Effort ${props.effort ?? 'provider default'}`,
190
+ };
183
191
  }
184
192
  return {
185
193
  raw: unsupported,
@@ -193,14 +201,14 @@ function statusItemForms(item, props) {
193
201
  // The field is the thinking switch, so the short form says the thing the
194
202
  // user is actually turning on rather than restating the flag.
195
203
  return reasoning === undefined
196
- ? {}
204
+ ? { raw: 'default', short: 'thinking default', long: 'Reasoning provider default' }
197
205
  : {
198
206
  raw: reasoning ? 'on' : 'off',
199
207
  short: reasoning ? 'thinking' : 'no thinking',
200
208
  long: `Reasoning ${reasoning ? 'on' : 'off'}`,
201
209
  };
202
210
  case 'input-mode':
203
- return { raw: props.inputMode === 'queue' ? undefined : props.inputMode, short: inputMode, long: inputMode && `Input: ${inputMode}` };
211
+ return { raw: canonicalInputMode === 'steer' ? undefined : canonicalInputMode, short: inputMode, long: inputMode && `Input: ${inputMode}` };
204
212
  case 'version':
205
213
  return { raw: props.version, short: `v${props.version}`, long: `ZTC v${props.version}` };
206
214
  case 'connection':
@@ -320,6 +328,9 @@ export function buildStatusBarView(rawProps) {
320
328
  let right = settings.right
321
329
  .map(item => statusItemSegment(item, props, settings.variants[item]))
322
330
  .filter((segment) => segment !== null);
331
+ if (props.escapeHint) {
332
+ right.push({ value: props.escapeHint, color: TERMINAL_THEME.muted, priority: 900, protected: true });
333
+ }
323
334
  const alerts = [];
324
335
  if (props.state.authError) {
325
336
  alerts.push({ value: 'auth!', color: TERMINAL_THEME.error, priority: 1000, protected: true });
@@ -12,4 +12,6 @@ export declare const TERMINAL_THEME: {
12
12
  readonly error: "#f85149";
13
13
  readonly success: "#3fb950";
14
14
  };
15
+ /** Rules and glyphs remain distinct on both dark and light terminal backgrounds. */
16
+ export declare const PLAN_ACCENT = "#b7791f";
15
17
  export declare function modeColor(mode: string): string;
@@ -12,6 +12,8 @@ export const TERMINAL_THEME = {
12
12
  error: '#f85149',
13
13
  success: '#3fb950',
14
14
  };
15
+ /** Rules and glyphs remain distinct on both dark and light terminal backgrounds. */
16
+ export const PLAN_ACCENT = '#b7791f';
15
17
  export function modeColor(mode) {
16
18
  if (mode === 'plan')
17
19
  return TERMINAL_THEME.attention;
@@ -200,6 +200,24 @@ export class ColorPanelWidget {
200
200
  handleInput(input, key) {
201
201
  if (!this.active)
202
202
  return;
203
+ if (key.paste) {
204
+ if (!input)
205
+ return;
206
+ if (this.hexEditing) {
207
+ this.hexValue += input;
208
+ this.notice = null;
209
+ }
210
+ else if (this.filterMode) {
211
+ this.filterText += input;
212
+ this.presetIndex = 0;
213
+ this.presetScroll = 0;
214
+ }
215
+ else {
216
+ return;
217
+ }
218
+ this.host.render();
219
+ return;
220
+ }
203
221
  if (this.hexEditing) {
204
222
  this.handleHexInput(input, key);
205
223
  return;
@@ -28,6 +28,14 @@ export class FormWidget {
28
28
  handleInput(input, key) {
29
29
  if (!this.active)
30
30
  return;
31
+ if (key.paste) {
32
+ const field = this.active.fields[this.focusedField];
33
+ if (!input || !field)
34
+ return;
35
+ this.values[field.name] = (this.values[field.name] || '') + input;
36
+ this.host.render();
37
+ return;
38
+ }
31
39
  const fields = this.active.fields;
32
40
  // Ctrl+C / Escape to cancel. Invoke the callback with an empty map (like a
33
41
  // submit with no values) BEFORE clearing state — mirror the submit branch.
@@ -90,6 +90,13 @@ export class LogViewWidget {
90
90
  handleInput(input, key) {
91
91
  if (!this.active)
92
92
  return;
93
+ if (key.paste) {
94
+ if (input && this.filterMode) {
95
+ this.filterInput += input;
96
+ this.host.render();
97
+ }
98
+ return;
99
+ }
93
100
  // Filter mode
94
101
  if (this.filterMode) {
95
102
  if (key.escape) {
@@ -372,6 +372,14 @@ export class NavigatorPanelWidget {
372
372
  handleInput(input, key) {
373
373
  if (!this.active)
374
374
  return;
375
+ if (key.paste) {
376
+ if (!input)
377
+ return;
378
+ this.filterMode = true;
379
+ this.filterText += input;
380
+ this.applyFilter();
381
+ return;
382
+ }
375
383
  if (key.ctrl && input.toLowerCase() === 'c') {
376
384
  this.cancel();
377
385
  return;
@@ -108,6 +108,8 @@ export class PromptViewerWidget {
108
108
  this.detailScrollOffset = 0;
109
109
  }
110
110
  handleInput(input, key) {
111
+ if (key.paste)
112
+ return;
111
113
  // Normalize: detect arrow keys from both structured key flags and ANSI escape sequences
112
114
  const up = key.upArrow || input === '\x1b[A';
113
115
  const down = key.downArrow || input === '\x1b[B';
@@ -10,6 +10,8 @@ export interface QuestionnaireOption {
10
10
  label: string;
11
11
  /** Shown only while this option is highlighted, so lists stay one row per option. */
12
12
  description?: string;
13
+ /** A short next-step preview, shown only for the highlighted option. */
14
+ preview?: string;
13
15
  /** Marks the option the agent suggests; gets a badge and starts highlighted. */
14
16
  recommended?: boolean;
15
17
  }
@@ -111,10 +111,27 @@ export class QuestionnaireWidget {
111
111
  return question.options.findIndex(option => option.recommended === true);
112
112
  }
113
113
  show(data) {
114
- this.active = data;
114
+ this.active = {
115
+ ...data,
116
+ questions: data.questions.map(question => {
117
+ if (!question.options)
118
+ return { ...question };
119
+ const recommendation = question.options.findIndex(option => option.recommended === true);
120
+ const options = question.options.map((option, index) => ({
121
+ ...option,
122
+ ...(option.recommended === true && index !== recommendation ? { recommended: false } : {}),
123
+ }));
124
+ return {
125
+ ...question,
126
+ options: recommendation > 0
127
+ ? [options[recommendation], ...options.filter((_option, index) => index !== recommendation)]
128
+ : options,
129
+ };
130
+ }),
131
+ };
115
132
  this.tabIndex = 0;
116
133
  // Start on the recommended option so Enter accepts the agent's suggestion.
117
- this.optionIndex = Math.max(0, QuestionnaireWidget.recommendedOptionIndex(data.questions[0]));
134
+ this.optionIndex = Math.max(0, QuestionnaireWidget.recommendedOptionIndex(this.active.questions[0]));
118
135
  this.answers = {};
119
136
  this.checked.clear();
120
137
  this.otherMode = false;
@@ -123,8 +140,8 @@ export class QuestionnaireWidget {
123
140
  this.optionNotes.clear();
124
141
  this.editingOptionNote = false;
125
142
  // Pre-fill defaults
126
- for (let i = 0; i < data.questions.length; i++) {
127
- const q = data.questions[i];
143
+ for (let i = 0; i < this.active.questions.length; i++) {
144
+ const q = this.active.questions[i];
128
145
  if (q.default !== undefined) {
129
146
  this.answers[q.name] = q.default;
130
147
  if (q.type === 'multiselect' && Array.isArray(q.default) && q.options) {
@@ -370,6 +387,31 @@ export class QuestionnaireWidget {
370
387
  handleInput(input, key) {
371
388
  if (!this.active)
372
389
  return;
390
+ if (key.paste) {
391
+ const question = this.active.questions[this.tabIndex];
392
+ if (!input || !question)
393
+ return;
394
+ if (this.otherMode) {
395
+ this.otherValue += input;
396
+ this.host.render();
397
+ }
398
+ else if (question.type === 'text' || question.type === 'textarea') {
399
+ this.textValues[this.tabIndex] = (this.textValues[this.tabIndex] || '') + input;
400
+ this.host.render();
401
+ }
402
+ else if (this.active.allowOptionNotes && question.type === 'select') {
403
+ this.selectHighlightedOption(question);
404
+ this.editingOptionNote = true;
405
+ this.setOptionNote(insertText(this.getOptionNote(), input));
406
+ }
407
+ else if (this.active.allowOther && question.type === 'select') {
408
+ this.otherMode = true;
409
+ this.otherValue = input;
410
+ this.optionIndex = (question.options || []).length;
411
+ this.host.render();
412
+ }
413
+ return;
414
+ }
373
415
  const questions = this.active.questions;
374
416
  const totalTabs = questions.length;
375
417
  const currentQ = questions[this.tabIndex];
@@ -385,7 +427,7 @@ export class QuestionnaireWidget {
385
427
  }
386
428
  if (key.return) {
387
429
  if (this.otherValue.trim()) {
388
- this.answers[currentQ.name] = this.otherValue.trim();
430
+ this.answers[currentQ.name] = this.otherValue;
389
431
  this.otherMode = false;
390
432
  this.otherValue = '';
391
433
  this.advanceOrSubmit();
@@ -635,6 +677,11 @@ export class QuestionnaireWidget {
635
677
  const question = questions[this.tabIndex];
636
678
  if (!question)
637
679
  return { content: '', view: box([], {}), lineCount: 0 };
680
+ const cap = typeof maxRows === 'number' && Number.isFinite(maxRows)
681
+ ? Math.max(0, Math.floor(maxRows))
682
+ : Number.POSITIVE_INFINITY;
683
+ if (cap === 0)
684
+ return { content: '', view: box([], {}), lineCount: 0 };
638
685
  // The form shares the pane width with the composer: it must reflow on
639
686
  // every build so a terminal or zmux-pane resize mid-question is picked up.
640
687
  // A cap here froze the frame at 88 columns on wide panes.
@@ -650,7 +697,6 @@ export class QuestionnaireWidget {
650
697
  const separator = () => ({
651
698
  segments: [{ text: `├${'─'.repeat(width - 2)}┤`, style: { color: TERMINAL_THEME.borderSubtle } }],
652
699
  });
653
- lines.push(topBorder(width, title || 'Questions', ''));
654
700
  const unanswered = questions.filter((candidate, index) => {
655
701
  const answer = this.answers[candidate.name];
656
702
  const draft = this.textValues[index];
@@ -669,7 +715,6 @@ export class QuestionnaireWidget {
669
715
  if (question.header) {
670
716
  progress.push({ text: ` · ${question.header}`, style: { color: TERMINAL_THEME.subtle } });
671
717
  }
672
- lines.push(framed(progress));
673
718
  // One content column for the whole card. The question, every option label,
674
719
  // and every description start at this same column; the selection caret,
675
720
  // number, and state marker are outdented into the gutter to its left. Lining
@@ -688,7 +733,17 @@ export class QuestionnaireWidget {
688
733
  // caret + space + (padded number) + space + marker + space
689
734
  const gutter = ' '.repeat(displayWidth('› ') + numberWidth + 1 + 1 + markerWidth + 1);
690
735
  const questionLines = wrapText(question.question, innerWidth - gutter.length, 2);
691
- for (const questionLine of questionLines) {
736
+ // Keep at least one answer row. In short panes, collapse metadata and
737
+ // separators before sacrificing the actual question or highlighted choice.
738
+ const compactChrome = cap < questionLines.length + 6;
739
+ const showFrame = !compactChrome || cap >= questionLines.length + 4;
740
+ const footerRows = compactChrome ? (showFrame ? 2 : cap > 1 ? 1 : 0) : 3;
741
+ if (showFrame)
742
+ lines.push(topBorder(width, title || 'Questions', compactChrome ? `${this.tabIndex + 1}/${questions.length}` : ''));
743
+ if (!compactChrome)
744
+ lines.push(framed(progress));
745
+ const questionRowCount = Math.max(0, Math.min(questionLines.length, cap - lines.length - footerRows - 1));
746
+ for (const questionLine of questionLines.slice(0, questionRowCount)) {
692
747
  lines.push(framed([
693
748
  { text: gutter },
694
749
  { text: questionLine, style: { color: TERMINAL_THEME.text, bold: true } },
@@ -697,12 +752,8 @@ export class QuestionnaireWidget {
697
752
  // The box is sized to the question it renders (capped by the caller's
698
753
  // budget). Filling the whole budget left the transcript hidden behind a
699
754
  // wall of empty rows.
700
- const footerRows = 3;
701
- const cap = typeof maxRows === 'number' && Number.isFinite(maxRows)
702
- ? Math.max(0, Math.floor(maxRows))
703
- : Number.POSITIVE_INFINITY;
704
755
  const roomForBody = Math.max(0, cap - lines.length - footerRows);
705
- const spacerRows = roomForBody > 1 ? 1 : 0;
756
+ const spacerRows = !compactChrome && roomForBody > 1 ? 1 : 0;
706
757
  const bodyRows = Math.max(0, roomForBody - spacerRows);
707
758
  const body = [];
708
759
  let optionPosition = '';
@@ -805,6 +856,15 @@ export class QuestionnaireWidget {
805
856
  ], TERMINAL_THEME.bgElevated));
806
857
  }
807
858
  }
859
+ if (highlighted && option.preview) {
860
+ const previewWidth = Math.max(1, innerWidth - displayWidth(prefix));
861
+ for (const line of wrapText(`Next: ${option.preview}`, previewWidth, Number.MAX_SAFE_INTEGER)) {
862
+ rows.push(framed([
863
+ { text: ' '.repeat(displayWidth(prefix)) },
864
+ { text: line, style: { color: TERMINAL_THEME.info } },
865
+ ], TERMINAL_THEME.bgElevated));
866
+ }
867
+ }
808
868
  return { rows };
809
869
  });
810
870
  if (allowOther && !(allowOptionNotes && question.type === 'select')) {
@@ -880,7 +940,8 @@ export class QuestionnaireWidget {
880
940
  if (spacerRows > 0)
881
941
  lines.push(blank());
882
942
  lines.push(...body);
883
- lines.push(separator());
943
+ if (!compactChrome)
944
+ lines.push(separator());
884
945
  const isLast = this.tabIndex === questions.length - 1;
885
946
  let hint;
886
947
  if (this.otherMode) {
@@ -907,8 +968,10 @@ export class QuestionnaireWidget {
907
968
  ? [{ text: `${optionPosition} · `, style: { color: TERMINAL_THEME.subtle } }]
908
969
  : [];
909
970
  hintSegments.push({ text: hint, style: { color: TERMINAL_THEME.muted } });
910
- lines.push(framed(hintSegments));
911
- lines.push(bottomBorder(width));
971
+ if (cap > 1)
972
+ lines.push(framed(hintSegments));
973
+ if (showFrame)
974
+ lines.push(bottomBorder(width));
912
975
  return {
913
976
  content: lines.map(lineText).join('\n'),
914
977
  view: box(lines.map(line => box(line.segments.map(segment => text(segment.text, segment.style)), { flexDirection: 'row', height: 1, flexShrink: 0, backgroundColor: line.backgroundColor })), { flexDirection: 'column', height: lines.length, flexShrink: 0 }),
@@ -326,6 +326,15 @@ export class ResumePanelWidget {
326
326
  handleInput(input, key) {
327
327
  if (!this.active)
328
328
  return;
329
+ if (key.paste) {
330
+ if (!input)
331
+ return;
332
+ this.filterMode = true;
333
+ this.filterText += input;
334
+ this.applyFilter();
335
+ this.host.render();
336
+ return;
337
+ }
329
338
  if (key.ctrl && input.toLowerCase() === 'c') {
330
339
  this.cancel();
331
340
  return;
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Rewind panel — full-page prompt picker opened with Esc while the agent is
3
- * idle.
2
+ * Rewind panel — full-page prompt picker opened with /rewind while the agent
3
+ * is idle.
4
4
  *
5
5
  * The list is anchored to the bottom of its pane: the prompt just sent sits on
6
6
  * the last row and older prompts climb upward, so the newest entry is where the
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Rewind panel — full-page prompt picker opened with Esc while the agent is
3
- * idle.
2
+ * Rewind panel — full-page prompt picker opened with /rewind while the agent
3
+ * is idle.
4
4
  *
5
5
  * The list is anchored to the bottom of its pane: the prompt just sent sits on
6
6
  * the last row and older prompts climb upward, so the newest entry is where the
@@ -124,6 +124,8 @@ export class RewindPanelWidget {
124
124
  handleInput(input, key) {
125
125
  if (!this.active)
126
126
  return;
127
+ if (key.paste)
128
+ return;
127
129
  const entries = this.active.entries;
128
130
  if (key.escape || isCtrlKey(input, key, 'c')) {
129
131
  this.cancel();
@@ -4,6 +4,7 @@
4
4
  * Extracted from cli_ratatui.ts to reduce file size.
5
5
  */
6
6
  import { displayWidth } from '../core/text_width.js';
7
+ import { wrapText } from '../core/wrap_text.js';
7
8
  export class SelectWidget {
8
9
  host;
9
10
  active = null;
@@ -85,6 +86,17 @@ export class SelectWidget {
85
86
  handleInput(input, key) {
86
87
  if (!this.active)
87
88
  return;
89
+ if (key.paste) {
90
+ if (!input)
91
+ return;
92
+ if (this.otherMode || (this.active.allowOther && this.active.type === 'select')) {
93
+ this.otherMode = true;
94
+ this.selectedIndex = this.active.options.length;
95
+ this.otherValue += input;
96
+ this.host.render();
97
+ }
98
+ return;
99
+ }
88
100
  const options = this.active.options;
89
101
  const totalOptions = options.length + (this.active.allowOther ? 1 : 0);
90
102
  // If in "Other" text input mode
@@ -285,35 +297,12 @@ export class SelectWidget {
285
297
  const titleFill = Math.max(0, width - 3 - displayWidth(titlePart));
286
298
  const topLine = '╭─' + titlePart + '─'.repeat(titleFill) + '╮';
287
299
  lines.push(topLine);
288
- // Question (word-wrap if longer than available width)
300
+ // Keep explicit metadata rows and wrap long path tokens at visible cells.
289
301
  const maxQWidth = width - 4;
290
- // Both branches indent to the option label column. Fixing only the wrapped
291
- // branch left short questions flush at column 1 while their labels started
292
- // at the gutter, so the two disagreed for the commonest case.
293
302
  const questionGutter = SelectWidget.labelColumn(type);
294
- if (displayWidth(questionGutter + question) <= maxQWidth) {
295
- lines.push('│ ' + pad(questionGutter + question, maxQWidth) + ' │');
296
- }
297
- else {
298
- // Indent the question to the option label column so the card has one left
299
- // edge. Deriving it from the real gutter keeps the two in step for both
300
- // the select radio and the wider multiselect checkbox.
301
- const gutter = questionGutter;
302
- const innerQ = Math.max(1, maxQWidth - displayWidth(gutter));
303
- const words = question.split(' ');
304
- let line = '';
305
- for (const word of words) {
306
- if (displayWidth(line + word) > innerQ && line.length > 0) {
307
- lines.push('│ ' + pad(gutter + line.trimEnd(), maxQWidth) + ' │');
308
- line = word + ' ';
309
- }
310
- else {
311
- line += word + ' ';
312
- }
313
- }
314
- if (line.trimEnd().length > 0) {
315
- lines.push('│ ' + pad(gutter + line.trimEnd(), maxQWidth) + ' │');
316
- }
303
+ const innerQ = Math.max(1, maxQWidth - displayWidth(questionGutter));
304
+ for (const line of wrapText(question, innerQ)) {
305
+ lines.push('│ ' + pad(questionGutter + line, maxQWidth) + ' │');
317
306
  }
318
307
  lines.push('│' + ' '.repeat(width - 2) + '│');
319
308
  // If in "Other" text input mode
@@ -575,6 +575,22 @@ export class SettingsPanelWidget {
575
575
  handleInput(input, key) {
576
576
  if (!this.active)
577
577
  return;
578
+ if (key.paste) {
579
+ // Key capture and expanded choices have no literal text destination.
580
+ if (!input || this.captureSetting || this.expandedSetting)
581
+ return;
582
+ if (this.editMode) {
583
+ this.editValue += input;
584
+ this.editDirty = true;
585
+ }
586
+ else {
587
+ this.filterMode = true;
588
+ this.filterText += input;
589
+ this.applyFilter();
590
+ }
591
+ this.host.render();
592
+ return;
593
+ }
578
594
  // Capture mode is modal: the next keystroke becomes the binding.
579
595
  if (this.captureSetting) {
580
596
  this.handleCaptureInput(input, key);
@@ -104,6 +104,7 @@ export declare class StatusLinePanelWidget {
104
104
  /** Fields currently listed, in row order; `fieldIndex` indexes into this. */
105
105
  private catalogueFields;
106
106
  private currentOption;
107
+ private selectedDescription;
107
108
  /**
108
109
  * Typing a query puts the cursor on the first match, so the field you then
109
110
  * toggle is the best one the search found rather than wherever the cursor
@@ -17,7 +17,7 @@
17
17
  import { displayWidth, padEndDisplay } from '../core/text_width.js';
18
18
  import { TERMINAL_THEME } from '../views/theme.js';
19
19
  import { fuzzyMatch } from '../../utils/fuzzy_match.js';
20
- import { cycleStatusLineVariant, resolveStatusLineVariants, statusLineItemGroups, statusLineItemOptions, STATUS_LINE_VARIANT_LABELS, } from '../status_line_config.js';
20
+ import { cycleStatusLineVariant, resolveStatusLineVariants, statusLineItemGroups, statusLineItemOptions, STATUS_LINE_ITEM_DESCRIPTIONS, STATUS_LINE_VARIANT_LABELS, } from '../status_line_config.js';
21
21
  import { bodyBand, bottomBorder, clipText, dropLastGrapheme, fitSegments, framedLine, isInsideBand, joinColumns, lineText, planPanelSplit, sideBySideBands, stackedBands, topBorder, buildWidgetFrameView, widgetFrameGeometry, } from './panel_frame.js';
22
22
  /** The order pane is the point of this page, so it keeps a workable width. */
23
23
  const ORDER_PANE_MIN_WIDTH = 34;
@@ -89,6 +89,7 @@ export class StatusLinePanelWidget {
89
89
  this.lineScroll = 0;
90
90
  this.held = null;
91
91
  this.notice = null;
92
+ this.resetFieldCursor();
92
93
  this.host.render();
93
94
  }
94
95
  isActive() {
@@ -171,13 +172,20 @@ export class StatusLinePanelWidget {
171
172
  currentOption() {
172
173
  return this.catalogueFields()[this.fieldIndex];
173
174
  }
175
+ selectedDescription() {
176
+ if (this.focus === 'fields')
177
+ return this.currentOption()?.description;
178
+ const item = this.sideItems(this.side)[this.lineIndex];
179
+ return item ? STATUS_LINE_ITEM_DESCRIPTIONS[item] : undefined;
180
+ }
174
181
  /**
175
182
  * Typing a query puts the cursor on the first match, so the field you then
176
183
  * toggle is the best one the search found rather than wherever the cursor
177
184
  * happened to be sitting.
178
185
  */
179
186
  resetFieldCursor() {
180
- this.fieldIndex = 0;
187
+ const exact = this.catalogueFields().findIndex(option => option.value === this.filterText.trim().toLowerCase());
188
+ this.fieldIndex = Math.max(0, exact);
181
189
  this.fieldScroll = 0;
182
190
  }
183
191
  // ── Mutations ─────────────────────────────────────────────────────────────
@@ -295,6 +303,15 @@ export class StatusLinePanelWidget {
295
303
  handleInput(input, key) {
296
304
  if (!this.active)
297
305
  return;
306
+ if (key.paste) {
307
+ if (!input)
308
+ return;
309
+ this.filterMode = true;
310
+ this.filterText += input;
311
+ this.resetFieldCursor();
312
+ this.host.render();
313
+ return;
314
+ }
298
315
  if (this.filterMode) {
299
316
  if (key.ctrl && input.toLowerCase() === 'c') {
300
317
  this.cancel();
@@ -596,7 +613,7 @@ export class StatusLinePanelWidget {
596
613
  if (this.focus === 'line') {
597
614
  return [{ text: '↑↓ move · Space pick up · v variant · x remove · Tab fields · Esc close', style: { color: TERMINAL_THEME.muted, dimColor: true } }];
598
615
  }
599
- return [{ text: '↑↓ move · Space add or remove · Tab the line · ←→ side · / search · Esc close', style: { color: TERMINAL_THEME.muted, dimColor: true } }];
616
+ return [{ text: '↑↓ move · Space toggle · Tab pane · ←→ side · / search · Esc close', style: { color: TERMINAL_THEME.muted, dimColor: true } }];
600
617
  }
601
618
  /**
602
619
  * Move the cursor of whichever pane the wheel is over.
@@ -656,11 +673,14 @@ export class StatusLinePanelWidget {
656
673
  const showHeadings = height >= 6;
657
674
  const showChrome = height >= 8;
658
675
  const showPreview = height >= 11 && this.active.enabled !== false;
676
+ const description = this.selectedDescription();
677
+ const showDescription = height >= 8 && description !== undefined;
659
678
  // The body owns its heading rows, so they are not counted as chrome here.
660
679
  const fixed = 2
661
680
  + (showFooter ? 1 : 0)
662
681
  + (showChrome ? 2 : 0)
663
- + (showPreview ? 1 : 0);
682
+ + (showPreview ? 1 : 0)
683
+ + (showDescription ? 1 : 0);
664
684
  const bodyRows = Math.max(1, height - fixed);
665
685
  this.lastBodyRows = Math.max(1, bodyRows - 1);
666
686
  if (showChrome) {
@@ -738,6 +758,12 @@ export class StatusLinePanelWidget {
738
758
  this.fieldBand = kind === 'fields' ? band : null;
739
759
  this.lineBand = kind === 'line' ? band : null;
740
760
  }
761
+ if (showDescription) {
762
+ lines.push(framedLine([{
763
+ text: clipText(description, innerWidth),
764
+ style: { color: TERMINAL_THEME.muted },
765
+ }], width, TERMINAL_THEME.bgPanel));
766
+ }
741
767
  if (showPreview) {
742
768
  lines.push(framedLine(this.previewSegments(innerWidth), width, TERMINAL_THEME.bgPanel));
743
769
  }
@@ -9,6 +9,8 @@ export interface TextInputData {
9
9
  question: string;
10
10
  placeholder?: string;
11
11
  defaultValue?: string;
12
+ isPassword?: boolean;
13
+ allowEmptySubmit?: boolean;
12
14
  callback: (value: string | null) => void | Promise<void>;
13
15
  }
14
16
  export declare class TextInputWidget {
@@ -37,6 +37,16 @@ export class TextInputWidget {
37
37
  handleInput(input, key) {
38
38
  if (!this.active)
39
39
  return;
40
+ if (key.paste) {
41
+ if (!input)
42
+ return;
43
+ this.completions = [];
44
+ this.completionIndex = 0;
45
+ this.value = this.value.slice(0, this.cursor) + input + this.value.slice(this.cursor);
46
+ this.cursor += input.length;
47
+ this.host.render();
48
+ return;
49
+ }
40
50
  // Ctrl+C or Escape to cancel
41
51
  if ((key.ctrl && input === 'c') || key.escape) {
42
52
  this.host.addSystemMessage('Cancelled.');
@@ -48,6 +58,8 @@ export class TextInputWidget {
48
58
  }
49
59
  // Enter to submit
50
60
  if (key.return) {
61
+ if (this.active.allowEmptySubmit === false && !this.value.trim())
62
+ return;
51
63
  const callback = this.active.callback;
52
64
  const value = this.value;
53
65
  this.cancel();
@@ -105,6 +117,8 @@ export class TextInputWidget {
105
117
  }
106
118
  // Tab - path completion
107
119
  if (key.tab) {
120
+ if (this.active.isPassword)
121
+ return;
108
122
  // If we have alternatives and Tab again, cycle through them
109
123
  if (this.completions.length > 1) {
110
124
  this.completionIndex = (this.completionIndex + 1) % this.completions.length;
@@ -163,7 +177,7 @@ export class TextInputWidget {
163
177
  lines.push('│ ' + pad(question) + ' │');
164
178
  // Input field with block cursor (█)
165
179
  const inputWidth = width - 6;
166
- let displayValue = this.value;
180
+ let displayValue = this.active.isPassword ? '•'.repeat(this.value.length) : this.value;
167
181
  let cursorPos = this.cursor;
168
182
  // Truncate if too long, keeping cursor visible
169
183
  if (displayValue.length >= inputWidth) {