@namzu/cli 29.1.0 → 32.0.0

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 (311) hide show
  1. package/CHANGELOG.md +296 -1
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +5 -1
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/acp.d.ts +20 -2
  6. package/dist/commands/acp.d.ts.map +1 -1
  7. package/dist/commands/acp.js +42 -5
  8. package/dist/commands/acp.js.map +1 -1
  9. package/dist/commands/drain.d.ts.map +1 -1
  10. package/dist/commands/drain.js +2 -1
  11. package/dist/commands/drain.js.map +1 -1
  12. package/dist/commands/exec-json.d.ts.map +1 -1
  13. package/dist/commands/exec-json.js +24 -1
  14. package/dist/commands/exec-json.js.map +1 -1
  15. package/dist/commands/exec.d.ts.map +1 -1
  16. package/dist/commands/exec.js +5 -1
  17. package/dist/commands/exec.js.map +1 -1
  18. package/dist/commands/prior-messages.d.ts.map +1 -1
  19. package/dist/commands/prior-messages.js +42 -2
  20. package/dist/commands/prior-messages.js.map +1 -1
  21. package/dist/commands/schedule.d.ts.map +1 -1
  22. package/dist/commands/schedule.js +7 -5
  23. package/dist/commands/schedule.js.map +1 -1
  24. package/dist/config/composer-triggers.d.ts +41 -0
  25. package/dist/config/composer-triggers.d.ts.map +1 -0
  26. package/dist/config/composer-triggers.js +80 -0
  27. package/dist/config/composer-triggers.js.map +1 -0
  28. package/dist/config/load.d.ts.map +1 -1
  29. package/dist/config/load.js +58 -0
  30. package/dist/config/load.js.map +1 -1
  31. package/dist/config/schema.d.ts +34 -0
  32. package/dist/config/schema.d.ts.map +1 -1
  33. package/dist/config/schema.js.map +1 -1
  34. package/dist/context/doctrine.d.ts +3 -3
  35. package/dist/context/doctrine.d.ts.map +1 -1
  36. package/dist/context/doctrine.js +3 -3
  37. package/dist/context/doctrine.js.map +1 -1
  38. package/dist/context/environment.d.ts +26 -3
  39. package/dist/context/environment.d.ts.map +1 -1
  40. package/dist/context/environment.js +68 -9
  41. package/dist/context/environment.js.map +1 -1
  42. package/dist/context/runtime-message.d.ts.map +1 -1
  43. package/dist/context/runtime-message.js +4 -0
  44. package/dist/context/runtime-message.js.map +1 -1
  45. package/dist/integrations/mcp/servers.d.ts +72 -5
  46. package/dist/integrations/mcp/servers.d.ts.map +1 -1
  47. package/dist/integrations/mcp/servers.js +144 -23
  48. package/dist/integrations/mcp/servers.js.map +1 -1
  49. package/dist/integrations/notifications/desktop.d.ts +2 -0
  50. package/dist/integrations/notifications/desktop.d.ts.map +1 -1
  51. package/dist/integrations/notifications/desktop.js +6 -5
  52. package/dist/integrations/notifications/desktop.js.map +1 -1
  53. package/dist/integrations/plugins/runtime.d.ts +10 -2
  54. package/dist/integrations/plugins/runtime.d.ts.map +1 -1
  55. package/dist/integrations/plugins/runtime.js +16 -29
  56. package/dist/integrations/plugins/runtime.js.map +1 -1
  57. package/dist/integrations/providers/harness-credentials.d.ts +9 -4
  58. package/dist/integrations/providers/harness-credentials.d.ts.map +1 -1
  59. package/dist/integrations/providers/harness-credentials.js +16 -8
  60. package/dist/integrations/providers/harness-credentials.js.map +1 -1
  61. package/dist/integrations/resident/session-step.d.ts.map +1 -1
  62. package/dist/integrations/resident/session-step.js +2 -1
  63. package/dist/integrations/resident/session-step.js.map +1 -1
  64. package/dist/integrations/sessions/store.d.ts.map +1 -1
  65. package/dist/integrations/sessions/store.js +20 -2
  66. package/dist/integrations/sessions/store.js.map +1 -1
  67. package/dist/integrations/subagents/NamzuCliAgent.d.ts +8 -0
  68. package/dist/integrations/subagents/NamzuCliAgent.d.ts.map +1 -0
  69. package/dist/integrations/subagents/NamzuCliAgent.js +9 -0
  70. package/dist/integrations/subagents/NamzuCliAgent.js.map +1 -0
  71. package/dist/integrations/subagents/runtime.d.ts +5 -4
  72. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  73. package/dist/integrations/subagents/runtime.js +46 -11
  74. package/dist/integrations/subagents/runtime.js.map +1 -1
  75. package/dist/integrations/web/open-url.d.ts +24 -0
  76. package/dist/integrations/web/open-url.d.ts.map +1 -0
  77. package/dist/integrations/web/open-url.js +73 -0
  78. package/dist/integrations/web/open-url.js.map +1 -0
  79. package/dist/integrations/web/search.d.ts.map +1 -1
  80. package/dist/integrations/web/search.js +8 -6
  81. package/dist/integrations/web/search.js.map +1 -1
  82. package/dist/permissions/rules.d.ts +5 -1
  83. package/dist/permissions/rules.d.ts.map +1 -1
  84. package/dist/permissions/rules.js +85 -3
  85. package/dist/permissions/rules.js.map +1 -1
  86. package/dist/schedule/build.d.ts +26 -2
  87. package/dist/schedule/build.d.ts.map +1 -1
  88. package/dist/schedule/build.js +139 -20
  89. package/dist/schedule/build.js.map +1 -1
  90. package/dist/schedule/changes.d.ts +6 -0
  91. package/dist/schedule/changes.d.ts.map +1 -1
  92. package/dist/schedule/changes.js +23 -0
  93. package/dist/schedule/changes.js.map +1 -1
  94. package/dist/schedule/commands/add.d.ts +1 -1
  95. package/dist/schedule/commands/add.d.ts.map +1 -1
  96. package/dist/schedule/commands/add.js +188 -54
  97. package/dist/schedule/commands/add.js.map +1 -1
  98. package/dist/schedule/commands/lifecycle.d.ts.map +1 -1
  99. package/dist/schedule/commands/lifecycle.js +2 -1
  100. package/dist/schedule/commands/lifecycle.js.map +1 -1
  101. package/dist/schedule/commands/list.d.ts +2 -0
  102. package/dist/schedule/commands/list.d.ts.map +1 -1
  103. package/dist/schedule/commands/list.js +69 -20
  104. package/dist/schedule/commands/list.js.map +1 -1
  105. package/dist/schedule/daemon/daemon.d.ts +1 -1
  106. package/dist/schedule/daemon/daemon.d.ts.map +1 -1
  107. package/dist/schedule/daemon/daemon.js +22 -5
  108. package/dist/schedule/daemon/daemon.js.map +1 -1
  109. package/dist/schedule/daemon/notify.d.ts +29 -2
  110. package/dist/schedule/daemon/notify.d.ts.map +1 -1
  111. package/dist/schedule/daemon/notify.js +71 -2
  112. package/dist/schedule/daemon/notify.js.map +1 -1
  113. package/dist/schedule/env.d.ts +8 -4
  114. package/dist/schedule/env.d.ts.map +1 -1
  115. package/dist/schedule/env.js +13 -6
  116. package/dist/schedule/env.js.map +1 -1
  117. package/dist/schedule/fire/calls.d.ts +49 -0
  118. package/dist/schedule/fire/calls.d.ts.map +1 -0
  119. package/dist/schedule/fire/calls.js +114 -0
  120. package/dist/schedule/fire/calls.js.map +1 -0
  121. package/dist/schedule/fire/fire.d.ts +1 -1
  122. package/dist/schedule/fire/fire.d.ts.map +1 -1
  123. package/dist/schedule/fire/fire.js +209 -15
  124. package/dist/schedule/fire/fire.js.map +1 -1
  125. package/dist/schedule/fire/result.d.ts +1 -1
  126. package/dist/schedule/fire/result.d.ts.map +1 -1
  127. package/dist/schedule/fire/result.js +2 -1
  128. package/dist/schedule/fire/result.js.map +1 -1
  129. package/dist/schedule/fire/run-script.d.ts +46 -0
  130. package/dist/schedule/fire/run-script.d.ts.map +1 -0
  131. package/dist/schedule/fire/run-script.js +81 -0
  132. package/dist/schedule/fire/run-script.js.map +1 -0
  133. package/dist/schedule/fire/unattended-note.d.ts +8 -0
  134. package/dist/schedule/fire/unattended-note.d.ts.map +1 -1
  135. package/dist/schedule/fire/unattended-note.js +5 -0
  136. package/dist/schedule/fire/unattended-note.js.map +1 -1
  137. package/dist/schedule/fire/wake-gate.d.ts +39 -0
  138. package/dist/schedule/fire/wake-gate.d.ts.map +1 -0
  139. package/dist/schedule/fire/wake-gate.js +90 -0
  140. package/dist/schedule/fire/wake-gate.js.map +1 -0
  141. package/dist/schedule/floor.d.ts +28 -8
  142. package/dist/schedule/floor.d.ts.map +1 -1
  143. package/dist/schedule/floor.js +624 -114
  144. package/dist/schedule/floor.js.map +1 -1
  145. package/dist/schedule/policy.d.ts +40 -0
  146. package/dist/schedule/policy.d.ts.map +1 -1
  147. package/dist/schedule/policy.js +36 -0
  148. package/dist/schedule/policy.js.map +1 -1
  149. package/dist/schedule/script-check.d.ts +53 -0
  150. package/dist/schedule/script-check.d.ts.map +1 -0
  151. package/dist/schedule/script-check.js +145 -0
  152. package/dist/schedule/script-check.js.map +1 -0
  153. package/dist/schedule/script-shell.d.ts +3 -0
  154. package/dist/schedule/script-shell.d.ts.map +1 -0
  155. package/dist/schedule/script-shell.js +5 -0
  156. package/dist/schedule/script-shell.js.map +1 -0
  157. package/dist/schedule/service/index.d.ts +1 -1
  158. package/dist/schedule/service/index.d.ts.map +1 -1
  159. package/dist/schedule/service/index.js +20 -11
  160. package/dist/schedule/service/index.js.map +1 -1
  161. package/dist/schedule/service/manifest.js +1 -1
  162. package/dist/schedule/service/manifest.js.map +1 -1
  163. package/dist/schedule/service/windows-task.d.ts +7 -0
  164. package/dist/schedule/service/windows-task.d.ts.map +1 -1
  165. package/dist/schedule/service/windows-task.js +65 -0
  166. package/dist/schedule/service/windows-task.js.map +1 -1
  167. package/dist/schedule/service/wsl.d.ts +13 -1
  168. package/dist/schedule/service/wsl.d.ts.map +1 -1
  169. package/dist/schedule/service/wsl.js +16 -6
  170. package/dist/schedule/service/wsl.js.map +1 -1
  171. package/dist/schedule/store/atomic.d.ts +5 -2
  172. package/dist/schedule/store/atomic.d.ts.map +1 -1
  173. package/dist/schedule/store/atomic.js +7 -4
  174. package/dist/schedule/store/atomic.js.map +1 -1
  175. package/dist/schedule/store/claims.js +1 -1
  176. package/dist/schedule/store/claims.js.map +1 -1
  177. package/dist/schedule/store/history.d.ts +1 -1
  178. package/dist/schedule/store/history.d.ts.map +1 -1
  179. package/dist/schedule/store/history.js +4 -1
  180. package/dist/schedule/store/history.js.map +1 -1
  181. package/dist/schedule/store/jobs.d.ts +19 -3
  182. package/dist/schedule/store/jobs.d.ts.map +1 -1
  183. package/dist/schedule/store/jobs.js +83 -16
  184. package/dist/schedule/store/jobs.js.map +1 -1
  185. package/dist/schedule/store/state.js +1 -1
  186. package/dist/schedule/store/state.js.map +1 -1
  187. package/dist/schedule/types.d.ts +98 -6
  188. package/dist/schedule/types.d.ts.map +1 -1
  189. package/dist/schedule/types.js +25 -1
  190. package/dist/schedule/types.js.map +1 -1
  191. package/dist/schedule/visible-source.d.ts +18 -0
  192. package/dist/schedule/visible-source.d.ts.map +1 -0
  193. package/dist/schedule/visible-source.js +59 -0
  194. package/dist/schedule/visible-source.js.map +1 -0
  195. package/dist/skills/directory.d.ts +38 -0
  196. package/dist/skills/directory.d.ts.map +1 -0
  197. package/dist/skills/directory.js +51 -0
  198. package/dist/skills/directory.js.map +1 -0
  199. package/dist/test-support/toolset.d.ts +23 -0
  200. package/dist/test-support/toolset.d.ts.map +1 -0
  201. package/dist/test-support/toolset.js +27 -0
  202. package/dist/test-support/toolset.js.map +1 -0
  203. package/dist/tui/App.d.ts.map +1 -1
  204. package/dist/tui/App.js +343 -64
  205. package/dist/tui/App.js.map +1 -1
  206. package/dist/tui/ChoicePicker.d.ts +2 -0
  207. package/dist/tui/ChoicePicker.d.ts.map +1 -1
  208. package/dist/tui/ChoicePicker.js +10 -2
  209. package/dist/tui/ChoicePicker.js.map +1 -1
  210. package/dist/tui/Composer.d.ts +62 -3
  211. package/dist/tui/Composer.d.ts.map +1 -1
  212. package/dist/tui/Composer.js +162 -25
  213. package/dist/tui/Composer.js.map +1 -1
  214. package/dist/tui/ComposerFrame.d.ts +1 -1
  215. package/dist/tui/ComposerFrame.js +3 -3
  216. package/dist/tui/ComposerFrame.js.map +1 -1
  217. package/dist/tui/EffortSlider.d.ts +8 -9
  218. package/dist/tui/EffortSlider.d.ts.map +1 -1
  219. package/dist/tui/EffortSlider.js +15 -12
  220. package/dist/tui/EffortSlider.js.map +1 -1
  221. package/dist/tui/PermissionOverlay.d.ts +13 -1
  222. package/dist/tui/PermissionOverlay.d.ts.map +1 -1
  223. package/dist/tui/PermissionOverlay.js +26 -4
  224. package/dist/tui/PermissionOverlay.js.map +1 -1
  225. package/dist/tui/StatusBar.d.ts +12 -12
  226. package/dist/tui/StatusBar.d.ts.map +1 -1
  227. package/dist/tui/StatusBar.js +15 -15
  228. package/dist/tui/StatusBar.js.map +1 -1
  229. package/dist/tui/agent.d.ts +73 -12
  230. package/dist/tui/agent.d.ts.map +1 -1
  231. package/dist/tui/agent.js +430 -180
  232. package/dist/tui/agent.js.map +1 -1
  233. package/dist/tui/hypermode.d.ts +37 -0
  234. package/dist/tui/hypermode.d.ts.map +1 -0
  235. package/dist/tui/hypermode.js +58 -0
  236. package/dist/tui/hypermode.js.map +1 -0
  237. package/dist/tui/open-browser.d.ts +29 -1
  238. package/dist/tui/open-browser.d.ts.map +1 -1
  239. package/dist/tui/open-browser.js +83 -11
  240. package/dist/tui/open-browser.js.map +1 -1
  241. package/dist/tui/permission-review.d.ts +11 -2
  242. package/dist/tui/permission-review.d.ts.map +1 -1
  243. package/dist/tui/permission-review.js +176 -19
  244. package/dist/tui/permission-review.js.map +1 -1
  245. package/dist/tui/schedule/host-commands.d.ts.map +1 -1
  246. package/dist/tui/schedule/host-commands.js +95 -33
  247. package/dist/tui/schedule/host-commands.js.map +1 -1
  248. package/dist/tui/schedule/integration.d.ts +6 -2
  249. package/dist/tui/schedule/integration.d.ts.map +1 -1
  250. package/dist/tui/schedule/integration.js +3 -1
  251. package/dist/tui/schedule/integration.js.map +1 -1
  252. package/dist/tui/schedule/resume.d.ts.map +1 -1
  253. package/dist/tui/schedule/resume.js +10 -1
  254. package/dist/tui/schedule/resume.js.map +1 -1
  255. package/dist/tui/schedule/tool-host.d.ts +18 -1
  256. package/dist/tui/schedule/tool-host.d.ts.map +1 -1
  257. package/dist/tui/schedule/tool-host.js +384 -84
  258. package/dist/tui/schedule/tool-host.js.map +1 -1
  259. package/dist/tui/slashCommands.d.ts +23 -5
  260. package/dist/tui/slashCommands.d.ts.map +1 -1
  261. package/dist/tui/slashCommands.js +80 -31
  262. package/dist/tui/slashCommands.js.map +1 -1
  263. package/dist/tui/theme.d.ts +10 -4
  264. package/dist/tui/theme.d.ts.map +1 -1
  265. package/dist/tui/theme.js +4 -3
  266. package/dist/tui/theme.js.map +1 -1
  267. package/dist/tui/triggers/analyze.d.ts +57 -0
  268. package/dist/tui/triggers/analyze.d.ts.map +1 -0
  269. package/dist/tui/triggers/analyze.js +221 -0
  270. package/dist/tui/triggers/analyze.js.map +1 -0
  271. package/dist/tui/triggers/context-text.d.ts +21 -0
  272. package/dist/tui/triggers/context-text.d.ts.map +1 -0
  273. package/dist/tui/triggers/context-text.js +44 -0
  274. package/dist/tui/triggers/context-text.js.map +1 -0
  275. package/dist/tui/triggers/copy.d.ts +38 -0
  276. package/dist/tui/triggers/copy.d.ts.map +1 -0
  277. package/dist/tui/triggers/copy.js +163 -0
  278. package/dist/tui/triggers/copy.js.map +1 -0
  279. package/dist/tui/triggers/detect.d.ts +83 -0
  280. package/dist/tui/triggers/detect.d.ts.map +1 -0
  281. package/dist/tui/triggers/detect.js +295 -0
  282. package/dist/tui/triggers/detect.js.map +1 -0
  283. package/dist/tui/triggers/fold.d.ts +34 -0
  284. package/dist/tui/triggers/fold.d.ts.map +1 -0
  285. package/dist/tui/triggers/fold.js +44 -0
  286. package/dist/tui/triggers/fold.js.map +1 -0
  287. package/dist/tui/triggers/pattern.d.ts +66 -0
  288. package/dist/tui/triggers/pattern.d.ts.map +1 -0
  289. package/dist/tui/triggers/pattern.js +243 -0
  290. package/dist/tui/triggers/pattern.js.map +1 -0
  291. package/dist/tui/triggers/provenance.d.ts +58 -0
  292. package/dist/tui/triggers/provenance.d.ts.map +1 -0
  293. package/dist/tui/triggers/provenance.js +98 -0
  294. package/dist/tui/triggers/provenance.js.map +1 -0
  295. package/dist/tui/triggers/registry.d.ts +113 -0
  296. package/dist/tui/triggers/registry.d.ts.map +1 -0
  297. package/dist/tui/triggers/registry.js +164 -0
  298. package/dist/tui/triggers/registry.js.map +1 -0
  299. package/dist/tui/triggers/setting.d.ts +18 -0
  300. package/dist/tui/triggers/setting.d.ts.map +1 -0
  301. package/dist/tui/triggers/setting.js +61 -0
  302. package/dist/tui/triggers/setting.js.map +1 -0
  303. package/dist/tui/triggers/verbs.d.ts +29 -0
  304. package/dist/tui/triggers/verbs.d.ts.map +1 -0
  305. package/dist/tui/triggers/verbs.js +140 -0
  306. package/dist/tui/triggers/verbs.js.map +1 -0
  307. package/dist/tui/types.d.ts +3 -1
  308. package/dist/tui/types.d.ts.map +1 -1
  309. package/package.json +12 -12
  310. package/skills/README.md +5 -0
  311. package/skills/schedule-task/SKILL.md +123 -5
@@ -0,0 +1,37 @@
1
+ /**
2
+ * How the TUI names its multi-agent session mode, in one place.
3
+ *
4
+ * Hypermode was called "orchestrate" until the rename; `/orchestrate` still
5
+ * works as a deprecated alias of `/hypermode` (see `slashCommands.ts`). The
6
+ * mode pins reasoning effort to `xhigh` — or, on a model whose menu has no
7
+ * `xhigh`, the level nearest below it (see {@link hypermodeEffort}) — and
8
+ * strengthens the delegation doctrine toward delegating by default
9
+ * (`CODING_AGENT_HYPERMODE_DOCTRINE` in `@namzu/sdk`). "Workflows" is this
10
+ * terminal's word for that phased multi-agent work.
11
+ */
12
+ import type { ReasoningEffort } from '@namzu/sdk';
13
+ /** The mode's name wherever the operator reads it: footer, border tag, picker. */
14
+ export declare const HYPERMODE = "hypermode";
15
+ /** The one-line description the effort picker shows for the hypermode stop. */
16
+ export declare const HYPERMODE_SUMMARY = "delegates to parallel agents by default";
17
+ /** The level hypermode pins wherever the model publishes it. */
18
+ export declare const HYPERMODE_EFFORT: ReasoningEffort;
19
+ /**
20
+ * The level hypermode pins on a model that publishes `levels`: `xhigh`, or
21
+ * the highest published level below it when the menu has no `xhigh`
22
+ * (`high` on a menu that stops there). `max` and `ultra` are never chosen
23
+ * over a lower level; only a menu made entirely of levels above `xhigh`
24
+ * gets its lowest one, the nearest there is. `undefined` when the model
25
+ * publishes no menu, or an empty one: nothing is pinned.
26
+ */
27
+ export declare function hypermodeEffort(levels: readonly ReasoningEffort[] | undefined): ReasoningEffort | undefined;
28
+ /**
29
+ * The effort picker's last stop: the level the mode pins, then the mode —
30
+ * `xhigh + hypermode (workflows)`, or `high + hypermode (workflows)` on a
31
+ * model whose menu stops at `high`. Without a published menu there is no
32
+ * level to name.
33
+ */
34
+ export declare function hypermodeStopLabel(pinned: string | undefined): string;
35
+ /** The deprecation line `/orchestrate` prints before it does what `/hypermode` does. */
36
+ export declare const ORCHESTRATE_ALIAS_NOTICE = "/orchestrate is deprecated: the mode is now called hypermode. Use /hypermode; /orchestrate will be removed in a later major version.";
37
+ //# sourceMappingURL=hypermode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hypermode.d.ts","sourceRoot":"","sources":["../../src/tui/hypermode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,kFAAkF;AAClF,eAAO,MAAM,SAAS,cAAc,CAAA;AAEpC,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,4CAA4C,CAAA;AAE1E,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,EAAE,eAAyB,CAAA;AAcxD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,MAAM,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,GAC5C,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAErE;AAED,wFAAwF;AACxF,eAAO,MAAM,wBAAwB,yIACkG,CAAA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * How the TUI names its multi-agent session mode, in one place.
3
+ *
4
+ * Hypermode was called "orchestrate" until the rename; `/orchestrate` still
5
+ * works as a deprecated alias of `/hypermode` (see `slashCommands.ts`). The
6
+ * mode pins reasoning effort to `xhigh` — or, on a model whose menu has no
7
+ * `xhigh`, the level nearest below it (see {@link hypermodeEffort}) — and
8
+ * strengthens the delegation doctrine toward delegating by default
9
+ * (`CODING_AGENT_HYPERMODE_DOCTRINE` in `@namzu/sdk`). "Workflows" is this
10
+ * terminal's word for that phased multi-agent work.
11
+ */
12
+ /** The mode's name wherever the operator reads it: footer, border tag, picker. */
13
+ export const HYPERMODE = 'hypermode';
14
+ /** The one-line description the effort picker shows for the hypermode stop. */
15
+ export const HYPERMODE_SUMMARY = 'delegates to parallel agents by default';
16
+ /** The level hypermode pins wherever the model publishes it. */
17
+ export const HYPERMODE_EFFORT = 'xhigh';
18
+ /** Every effort level, low to high: the order of the SDK's `ReasoningEffort` union. */
19
+ const EFFORT_ORDER = [
20
+ 'none',
21
+ 'minimal',
22
+ 'low',
23
+ 'medium',
24
+ 'high',
25
+ 'xhigh',
26
+ 'max',
27
+ 'ultra',
28
+ ];
29
+ /**
30
+ * The level hypermode pins on a model that publishes `levels`: `xhigh`, or
31
+ * the highest published level below it when the menu has no `xhigh`
32
+ * (`high` on a menu that stops there). `max` and `ultra` are never chosen
33
+ * over a lower level; only a menu made entirely of levels above `xhigh`
34
+ * gets its lowest one, the nearest there is. `undefined` when the model
35
+ * publishes no menu, or an empty one: nothing is pinned.
36
+ */
37
+ export function hypermodeEffort(levels) {
38
+ if (!levels || levels.length === 0)
39
+ return undefined;
40
+ const ceiling = EFFORT_ORDER.indexOf(HYPERMODE_EFFORT);
41
+ const rank = (level) => EFFORT_ORDER.indexOf(level);
42
+ const atOrBelow = levels.filter((level) => rank(level) >= 0 && rank(level) <= ceiling);
43
+ if (atOrBelow.length > 0)
44
+ return atOrBelow.reduce((best, level) => (rank(level) > rank(best) ? level : best));
45
+ return levels.reduce((best, level) => (rank(level) < rank(best) ? level : best));
46
+ }
47
+ /**
48
+ * The effort picker's last stop: the level the mode pins, then the mode —
49
+ * `xhigh + hypermode (workflows)`, or `high + hypermode (workflows)` on a
50
+ * model whose menu stops at `high`. Without a published menu there is no
51
+ * level to name.
52
+ */
53
+ export function hypermodeStopLabel(pinned) {
54
+ return pinned ? `${pinned} + ${HYPERMODE} (workflows)` : `${HYPERMODE} (workflows)`;
55
+ }
56
+ /** The deprecation line `/orchestrate` prints before it does what `/hypermode` does. */
57
+ export const ORCHESTRATE_ALIAS_NOTICE = '/orchestrate is deprecated: the mode is now called hypermode. Use /hypermode; /orchestrate will be removed in a later major version.';
58
+ //# sourceMappingURL=hypermode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hypermode.js","sourceRoot":"","sources":["../../src/tui/hypermode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAA;AAEpC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,yCAAyC,CAAA;AAE1E,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAoB,OAAO,CAAA;AAExD,uFAAuF;AACvF,MAAM,YAAY,GAA+B;IAChD,MAAM;IACN,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;CACP,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC9B,MAA8C;IAE9C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACpD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACtD,MAAM,IAAI,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACpE,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,CAAA;IACtF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QACvB,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACpF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACjF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IAC5D,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,SAAS,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,cAAc,CAAA;AACpF,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,wBAAwB,GACpC,sIAAsI,CAAA"}
@@ -12,6 +12,20 @@
12
12
  * path under the system directory so a same-named executable earlier on `PATH`
13
13
  * cannot answer instead.
14
14
  *
15
+ * ## WSL: the Windows browser
16
+ *
17
+ * Under WSL the desktop the user looks at is Windows', and `xdg-open` reaches
18
+ * a Linux browser at best (usually nothing). With interop on, the address goes
19
+ * to Windows' own protocol handler through `powershell.exe`, named by absolute
20
+ * path, running a CONSTANT script (`Start-Process -FilePath
21
+ * $env:NAMZU_OPEN_URL`) sent as `-EncodedCommand`: the address reaches it only
22
+ * as an environment variable named in `WSLENV`, so nothing parses it as code
23
+ * — the same shape as the WSL toast in `notifications/desktop/windows-toast.ts`.
24
+ * This is what the `open` package does on WSL too, minus its six dependencies
25
+ * and its quoting of the address into the script text. `cmd.exe /c start` is
26
+ * not used, for the reason above; `explorer.exe` is not used because it exits
27
+ * 1 even when it opened the page.
28
+ *
15
29
  * ## Best effort, reported honestly
16
30
  *
17
31
  * Returns whether a launcher was even STARTED, not whether a browser appeared
@@ -20,5 +34,19 @@
20
34
  * stop reading". On a machine with no graphical session there is nothing to
21
35
  * start and this says so, which is the case the paste path exists for.
22
36
  */
23
- export declare function openInBrowser(url: string): boolean;
37
+ /** Where Windows keeps PowerShell, under a WSL mount root (`/mnt/` by default). */
38
+ export declare function wslPowershell(mountRoot?: string): string;
39
+ /** PowerShell under the default mount root. */
40
+ export declare const WSL_POWERSHELL: string;
41
+ /** The whole WSL script. The address is data in the environment, never text here. */
42
+ export declare const WSL_OPEN_SCRIPT: string;
43
+ /** The machine, injectable so a test can describe one it is not running on. */
44
+ export interface BrowserHost {
45
+ readonly platform?: NodeJS.Platform;
46
+ readonly env?: NodeJS.ProcessEnv;
47
+ readonly exists?: (path: string) => boolean;
48
+ /** Reads `/etc/wsl.conf`, for where the Windows drives are mounted. */
49
+ readonly readFile?: (path: string) => string | undefined;
50
+ }
51
+ export declare function openInBrowser(url: string, host?: BrowserHost): boolean;
24
52
  //# sourceMappingURL=open-browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAwBH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA6BlD"}
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AA+BH,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,SAAS,GAAE,MAA+B,GAAG,MAAM,CAEhF;AAED,+CAA+C;AAC/C,eAAO,MAAM,cAAc,QAAkB,CAAA;AAE7C,qFAAqF;AACrF,eAAO,MAAM,eAAe,QAGhB,CAAA;AAEZ,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;IAC3C,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;CACxD;AAwDD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CA0B1E"}
@@ -12,6 +12,20 @@
12
12
  * path under the system directory so a same-named executable earlier on `PATH`
13
13
  * cannot answer instead.
14
14
  *
15
+ * ## WSL: the Windows browser
16
+ *
17
+ * Under WSL the desktop the user looks at is Windows', and `xdg-open` reaches
18
+ * a Linux browser at best (usually nothing). With interop on, the address goes
19
+ * to Windows' own protocol handler through `powershell.exe`, named by absolute
20
+ * path, running a CONSTANT script (`Start-Process -FilePath
21
+ * $env:NAMZU_OPEN_URL`) sent as `-EncodedCommand`: the address reaches it only
22
+ * as an environment variable named in `WSLENV`, so nothing parses it as code
23
+ * — the same shape as the WSL toast in `notifications/desktop/windows-toast.ts`.
24
+ * This is what the `open` package does on WSL too, minus its six dependencies
25
+ * and its quoting of the address into the script text. `cmd.exe /c start` is
26
+ * not used, for the reason above; `explorer.exe` is not used because it exits
27
+ * 1 even when it opened the page.
28
+ *
15
29
  * ## Best effort, reported honestly
16
30
  *
17
31
  * Returns whether a launcher was even STARTED, not whether a browser appeared
@@ -21,12 +35,13 @@
21
35
  * start and this says so, which is the case the paste path exists for.
22
36
  */
23
37
  import { spawn } from 'node:child_process';
24
- import { constants, accessSync } from 'node:fs';
38
+ import { constants, accessSync, existsSync } from 'node:fs';
25
39
  import { platform } from 'node:os';
26
40
  import { delimiter, isAbsolute, join } from 'node:path';
41
+ import { DEFAULT_WSL_MOUNT_ROOT, detectWsl, readWslMountRoot, wslSystem32, } from '../context/environment.js';
27
42
  /** Resolve a launcher before claiming that one started. */
28
- function executableOnPath(name) {
29
- for (const directory of (process.env.PATH ?? '').split(delimiter)) {
43
+ function executableOnPath(name, env) {
44
+ for (const directory of (env.PATH ?? '').split(delimiter)) {
30
45
  // An empty or relative PATH member delegates executable authority to the
31
46
  // project cwd. Opening an OAuth URL must never run a project-owned helper.
32
47
  if (!directory || !isAbsolute(directory))
@@ -42,23 +57,80 @@ function executableOnPath(name) {
42
57
  }
43
58
  return null;
44
59
  }
45
- export function openInBrowser(url) {
60
+ /** Where Windows keeps PowerShell, under a WSL mount root (`/mnt/` by default). */
61
+ export function wslPowershell(mountRoot = DEFAULT_WSL_MOUNT_ROOT) {
62
+ return `${wslSystem32(mountRoot)}/WindowsPowerShell/v1.0/powershell.exe`;
63
+ }
64
+ /** PowerShell under the default mount root. */
65
+ export const WSL_POWERSHELL = wslPowershell();
66
+ /** The whole WSL script. The address is data in the environment, never text here. */
67
+ export const WSL_OPEN_SCRIPT = [
68
+ "$ErrorActionPreference = 'Stop'",
69
+ 'Start-Process -FilePath $env:NAMZU_OPEN_URL',
70
+ ].join('\n');
71
+ /** Windows' protocol handler through interop, or `null` when this is not a WSL that can reach it. */
72
+ function wslLaunch(url, env, host) {
73
+ const exists = host.exists ?? existsSync;
74
+ // `/etc/wsl.conf` can move the drives (`[automount] root = /win/`), and
75
+ // PowerShell and the directory it starts in move with them.
76
+ const mountRoot = host.readFile ? readWslMountRoot(host.readFile) : readWslMountRoot();
77
+ const wsl = detectWsl(env, { exists, list: () => [], mountRoot });
78
+ if (!wsl?.interop)
79
+ return null;
80
+ const powershell = wslPowershell(mountRoot);
81
+ if (!exists(powershell))
82
+ return null;
83
+ const passed = (env.WSLENV ?? '')
84
+ .split(':')
85
+ .filter((name) => name && !name.startsWith('NAMZU_OPEN_URL'));
86
+ return {
87
+ command: powershell,
88
+ args: [
89
+ '-NoProfile',
90
+ '-NonInteractive',
91
+ '-ExecutionPolicy',
92
+ 'Bypass',
93
+ '-EncodedCommand',
94
+ Buffer.from(WSL_OPEN_SCRIPT, 'utf16le').toString('base64'),
95
+ ],
96
+ env: { ...env, NAMZU_OPEN_URL: url, WSLENV: [...passed, 'NAMZU_OPEN_URL'].join(':') },
97
+ // A Windows program started from a Linux directory warns about UNC
98
+ // paths; the drive PowerShell lives on is a Windows directory.
99
+ cwd: `${mountRoot}c`,
100
+ };
101
+ }
102
+ function launchFor(url, host) {
103
+ const currentPlatform = host.platform ?? platform();
104
+ const env = host.env ?? process.env;
105
+ if (currentPlatform === 'win32') {
106
+ return {
107
+ command: join(env.SystemRoot ?? 'C:\\Windows', 'System32', 'rundll32.exe'),
108
+ args: ['url.dll,FileProtocolHandler', url],
109
+ };
110
+ }
111
+ if (currentPlatform === 'linux') {
112
+ const wsl = wslLaunch(url, env, host);
113
+ if (wsl)
114
+ return wsl;
115
+ }
116
+ const command = executableOnPath(currentPlatform === 'darwin' ? 'open' : 'xdg-open', env);
117
+ return command ? { command, args: [url] } : null;
118
+ }
119
+ export function openInBrowser(url, host = {}) {
46
120
  // Refuse anything that is not a web address. This is handed to the
47
121
  // machine's protocol handler, and `file:` or a custom scheme reaching it
48
122
  // would be this function opening something nobody named.
49
123
  if (!/^https?:\/\//i.test(url))
50
124
  return false;
51
- const currentPlatform = platform();
52
- const command = currentPlatform === 'win32'
53
- ? join(process.env.SystemRoot ?? 'C:\\Windows', 'System32', 'rundll32.exe')
54
- : executableOnPath(currentPlatform === 'darwin' ? 'open' : 'xdg-open');
55
- if (!command)
125
+ const launch = launchFor(url, host);
126
+ if (!launch)
56
127
  return false;
57
- const args = currentPlatform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];
58
128
  try {
59
- const child = spawn(command, args, {
129
+ const child = spawn(launch.command, [...launch.args], {
60
130
  stdio: 'ignore',
61
131
  detached: true,
132
+ ...(launch.env ? { env: launch.env } : {}),
133
+ ...(launch.cwd ? { cwd: launch.cwd } : {}),
62
134
  });
63
135
  // A missing launcher — no `xdg-open` in a container — arrives as an
64
136
  // async error event, long after this function returned. Swallowing it
@@ -1 +1 @@
1
- {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEvD,2DAA2D;AAC3D,SAAS,gBAAgB,CAAC,IAAY;IACrC,KAAK,MAAM,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QACnE,yEAAyE;QACzE,2EAA2E;QAC3E,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,SAAQ;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACvC,IAAI,CAAC;YACJ,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;YACrC,OAAO,SAAS,CAAA;QACjB,CAAC;QAAC,MAAM,CAAC;YACR,+DAA+D;QAChE,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACxC,mEAAmE;IACnE,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAE5C,MAAM,eAAe,GAAG,QAAQ,EAAE,CAAA;IAClC,MAAM,OAAO,GACZ,eAAe,KAAK,OAAO;QAC1B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,aAAa,EAAE,UAAU,EAAE,cAAc,CAAC;QAC3E,CAAC,CAAC,gBAAgB,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,IAAI,GAAG,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAEvF,IAAI,CAAC;QACJ,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAClC,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACd,CAAC,CAAA;QACF,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,+DAA+D;QAC/D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACZ,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/tui/open-browser.ts"],"names":[],"mappings":"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"}
@@ -66,7 +66,7 @@ export interface PermissionReviewRow {
66
66
  /**
67
67
  * Serialize the exact executable batch without invoking getters or `toJSON`.
68
68
  *
69
- * `ToolRegistry.prepareExecution()` already publishes detached JSON values,
69
+ * `ToolManager.prepareExecution()` already publishes detached JSON values,
70
70
  * but this is a host boundary and structural SDK implementations can still
71
71
  * supply `unknown`. Ordinary `JSON.stringify` would execute an accessor and
72
72
  * could silently turn a Date/Map/custom object into something other than the
@@ -89,7 +89,16 @@ export declare function buildPermissionReview(calls: readonly PermissionReviewCa
89
89
  * is the one case that opens exact-first: the formatter is stale, and a
90
90
  * reader should see that rather than a projection that happens to be right.
91
91
  */
92
- export declare function buildPermissionSummary(review: string): PermissionReviewSummary;
92
+ /** What the screen can learn, beyond the envelope, to make a call readable. */
93
+ export interface PermissionSummaryContext {
94
+ /**
95
+ * The control a `computer_use` `ui_act` ref names in the latest UI
96
+ * snapshot (`Button "Beş" (e30)`), from the session's tool. Absent, the
97
+ * ref alone is shown.
98
+ */
99
+ readonly describeUiRef?: (ref: string) => string | undefined;
100
+ }
101
+ export declare function buildPermissionSummary(review: string, context?: PermissionSummaryContext): PermissionReviewSummary;
93
102
  /**
94
103
  * Project and wrap exact review text into PHYSICAL terminal rows.
95
104
  *
@@ -1 +1 @@
1
- {"version":3,"file":"permission-review.d.ts","sourceRoot":"","sources":["../../src/tui/permission-review.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAA;AAEhD,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,SAAS;IACnB,QAAQ,CAAC,UAAU,CAAC,EAAE;QACrB,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;QAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KACzC,CAAA;CACD,EAAE,GACD,OAAO,CAKT;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAAA;CAAE,CAAA;AAE3E,MAAM,WAAW,uBAAuB;IACvC,sFAAsF;IACtF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC1B;AASD,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,MAAM,CAIvF;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IACnC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC9B;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,SAAS,oBAAoB,EAAE,EACtC,QAAQ,SAA8B,GACpC,sBAAsB,CAqJxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,uBAAuB,CA+E9E;AAyZD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GAAG,SAAS,GACjC,SAAS,mBAAmB,EAAE,CA6BhC"}
1
+ {"version":3,"file":"permission-review.d.ts","sourceRoot":"","sources":["../../src/tui/permission-review.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAA;AAEhD,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGjF;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,SAAS;IACnB,QAAQ,CAAC,UAAU,CAAC,EAAE;QACrB,QAAQ,CAAC,aAAa,CAAC,EAAE,IAAI,CAAA;QAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KACzC,CAAA;CACD,EAAE,GACD,OAAO,CAKT;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,MAAM,sBAAsB,GAC/B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAAA;CAAE,CAAA;AAE3E,MAAM,WAAW,uBAAuB;IACvC,sFAAsF;IACtF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC1B;AASD,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,GAAG,MAAM,CAIvF;AAED,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IACnC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;CAC9B;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,SAAS,oBAAoB,EAAE,EACtC,QAAQ,SAA8B,GACpC,sBAAsB,CAqJxB;AAED;;;;;;;;;;;;;GAaG;AACH,+EAA+E;AAC/E,MAAM,WAAW,wBAAwB;IACxC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;CAC5D;AAED,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,wBAA6B,GACpC,uBAAuB,CA+EzB;AA+kBD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GAAG,SAAS,GACjC,SAAS,mBAAmB,EAAE,CA6BhC"}
@@ -45,7 +45,7 @@ class ReviewShapeError extends Error {
45
45
  /**
46
46
  * Serialize the exact executable batch without invoking getters or `toJSON`.
47
47
  *
48
- * `ToolRegistry.prepareExecution()` already publishes detached JSON values,
48
+ * `ToolManager.prepareExecution()` already publishes detached JSON values,
49
49
  * but this is a host boundary and structural SDK implementations can still
50
50
  * supply `unknown`. Ordinary `JSON.stringify` would execute an accessor and
51
51
  * could silently turn a Date/Map/custom object into something other than the
@@ -200,21 +200,7 @@ export function buildPermissionReview(calls, maxBytes = MAX_PERMISSION_REVIEW_BY
200
200
  };
201
201
  }
202
202
  }
203
- /**
204
- * Derive a readable review from the immutable exact envelope.
205
- *
206
- * This never reads the original tool objects: `buildPermissionReview` has
207
- * already rejected getters, prototypes and non-JSON values. A summary is
208
- * `complete` when it shows every key of every call, and callers open the
209
- * readable view by default only then — so a friendly label can never hide a
210
- * suffix. Two ways to be complete: a formatter below whose key set and value
211
- * types are exhaustive, or, for a tool no formatter here knows (`read`,
212
- * `grep`, a connected server's tool), every key with its full JSON-escaped
213
- * value. A tool that HAS a formatter but arrives in a shape it does not know
214
- * is the one case that opens exact-first: the formatter is stale, and a
215
- * reader should see that rather than a projection that happens to be right.
216
- */
217
- export function buildPermissionSummary(review) {
203
+ export function buildPermissionSummary(review, context = {}) {
218
204
  let parsed;
219
205
  try {
220
206
  parsed = JSON.parse(review);
@@ -235,7 +221,7 @@ export function buildPermissionSummary(review) {
235
221
  !Object.hasOwn(call, 'input')) {
236
222
  return { text: review, complete: false };
237
223
  }
238
- const readable = summarizeKnownCall(call.name, call.input);
224
+ const readable = summarizeKnownCall(call.name, call.input, context);
239
225
  complete &&= readable.complete;
240
226
  calls.push({
241
227
  name: call.name,
@@ -289,7 +275,7 @@ function commandLines(command) {
289
275
  const [first = '', ...rest] = command.replace(/\r/g, '\\u{000d}').split('\n');
290
276
  return [`$ ${first}`, ...rest.map((line) => ` ${line}`)];
291
277
  }
292
- function summarizeKnownCall(name, input) {
278
+ function summarizeKnownCall(name, input, context = {}) {
293
279
  if (name === 'bash' && isRecord(input)) {
294
280
  const allowed = new Set([
295
281
  'command',
@@ -415,6 +401,11 @@ function summarizeKnownCall(name, input) {
415
401
  if (summary)
416
402
  return summary;
417
403
  }
404
+ if (name === 'computer_use' && isRecord(input)) {
405
+ const summary = summarizeComputerUse(input, context);
406
+ if (summary)
407
+ return summary;
408
+ }
418
409
  if (FORMATTED_TOOLS.has(name)) {
419
410
  // A shape this file formats, in a form it does not know: the formatter
420
411
  // is stale. Exact-first, so nobody reads a projection that merely
@@ -471,9 +462,175 @@ function summarizeBrowserOpen(input) {
471
462
  complete: true,
472
463
  };
473
464
  }
465
+ /**
466
+ * A desktop action, or a batch of them, one numbered line per action in the
467
+ * order they will run: `3 desktop actions, in order` over `1. Click left at
468
+ * (812, 403)`, `2. Type "Bahadır Arda"`, `3. Press ENTER`. Text to be typed is
469
+ * shown whole — it is what lands in whichever window has focus — and the
470
+ * screenshot the coordinates belong to is named, since they are its pixels,
471
+ * not the screen's. An action or field this does not know returns null and
472
+ * the call opens exact-first.
473
+ */
474
+ function summarizeComputerUse(input, context) {
475
+ if (input.screenshot_id !== undefined && typeof input.screenshot_id !== 'string')
476
+ return null;
477
+ const space = typeof input.screenshot_id === 'string'
478
+ ? `Coordinates: pixels of screenshot ${input.screenshot_id}`
479
+ : 'Coordinates: pixels of the latest screenshot';
480
+ if (input.type === 'batch') {
481
+ if (!Object.keys(input).every((key) => ['type', 'actions', 'screenshot_id'].includes(key)))
482
+ return null;
483
+ if (!Array.isArray(input.actions) || input.actions.length === 0)
484
+ return null;
485
+ const lines = [];
486
+ let coordinates = false;
487
+ for (const [index, item] of input.actions.entries()) {
488
+ if (!isRecord(item) || item.type === 'batch' || Object.hasOwn(item, 'screenshot_id'))
489
+ return null;
490
+ const action = computerUseAction(item, [], context);
491
+ if (!action)
492
+ return null;
493
+ coordinates ||= action.coordinates;
494
+ lines.push(`${index + 1}. ${action.line}`);
495
+ }
496
+ const count = input.actions.length;
497
+ return {
498
+ lines: [
499
+ `${count} desktop action${count === 1 ? '' : 's'}, in order; stops at the first that fails`,
500
+ ...lines,
501
+ ...(coordinates ? [space] : []),
502
+ ],
503
+ complete: true,
504
+ };
505
+ }
506
+ if (input.actions !== undefined)
507
+ return null;
508
+ const action = computerUseAction(input, ['screenshot_id'], context);
509
+ if (!action)
510
+ return null;
511
+ return { lines: [action.line, ...(action.coordinates ? [space] : [])], complete: true };
512
+ }
513
+ /** How a person reads each `ui_act` action, before the control it acts on. */
514
+ const UI_ACT_VERBS = {
515
+ invoke: 'Press',
516
+ toggle: 'Toggle',
517
+ select: 'Select',
518
+ expand: 'Expand',
519
+ collapse: 'Collapse',
520
+ focus: 'Focus',
521
+ scroll_into_view: 'Scroll to',
522
+ };
523
+ function computerUseAction(item, extra = [], context = {}) {
524
+ const point = (value) => isRecord(value) &&
525
+ Object.keys(value).every((key) => key === 'x' || key === 'y') &&
526
+ Number.isInteger(value.x) &&
527
+ Number.isInteger(value.y)
528
+ ? `(${value.x}, ${value.y})`
529
+ : null;
530
+ const fields = (...names) => Object.keys(item).every((key) => key === 'type' || names.includes(key) || extra.includes(key));
531
+ const text = (value) => typeof value === 'string';
532
+ switch (item.type) {
533
+ case 'screenshot':
534
+ return fields() ? { line: 'Take a screenshot', coordinates: false } : null;
535
+ case 'cursor_position':
536
+ return fields() ? { line: 'Read the cursor position', coordinates: false } : null;
537
+ case 'list_windows':
538
+ return fields() ? { line: 'List the open windows', coordinates: false } : null;
539
+ case 'wait':
540
+ return fields('ms') && Number.isInteger(item.ms)
541
+ ? { line: `Wait ${item.ms} ms`, coordinates: false }
542
+ : null;
543
+ case 'focus_window':
544
+ return fields('window_id') && text(item.window_id)
545
+ ? {
546
+ line: `Bring window ${JSON.stringify(item.window_id)} to the front`,
547
+ coordinates: false,
548
+ }
549
+ : null;
550
+ case 'type_text':
551
+ return fields('text') && text(item.text)
552
+ ? { line: `Type ${JSON.stringify(item.text)}`, coordinates: false }
553
+ : null;
554
+ case 'key':
555
+ return fields('keys') && text(item.keys)
556
+ ? { line: `Press ${JSON.stringify(item.keys)}`, coordinates: false }
557
+ : null;
558
+ case 'mouse_move': {
559
+ const to = point(item.to);
560
+ return fields('to') && to ? { line: `Move the pointer to ${to}`, coordinates: true } : null;
561
+ }
562
+ case 'mouse_click': {
563
+ const at = point(item.at);
564
+ return fields('at', 'button') && at && text(item.button)
565
+ ? { line: `Click ${item.button} at ${at}`, coordinates: true }
566
+ : null;
567
+ }
568
+ case 'mouse_drag': {
569
+ const from = point(item.from);
570
+ const to = point(item.to);
571
+ return fields('from', 'to', 'button') && from && to && text(item.button)
572
+ ? { line: `Drag ${item.button} from ${from} to ${to}`, coordinates: true }
573
+ : null;
574
+ }
575
+ case 'scroll': {
576
+ const at = point(item.at);
577
+ return fields('at', 'direction', 'amount') &&
578
+ at &&
579
+ text(item.direction) &&
580
+ Number.isInteger(item.amount)
581
+ ? { line: `Scroll ${item.direction} ${item.amount} at ${at}`, coordinates: true }
582
+ : null;
583
+ }
584
+ case 'ui_snapshot':
585
+ return fields('window_id') && (item.window_id === undefined || text(item.window_id))
586
+ ? {
587
+ line: item.window_id === undefined
588
+ ? 'Read the controls of the window in front'
589
+ : `Read the controls of window ${JSON.stringify(item.window_id)}`,
590
+ coordinates: false,
591
+ }
592
+ : null;
593
+ case 'ui_act': {
594
+ if (!fields('ref', 'action', 'value') || !text(item.ref) || !text(item.action))
595
+ return null;
596
+ if (item.value !== undefined && !text(item.value))
597
+ return null;
598
+ // The application's own words for the control, as the session's tool
599
+ // last read them; the ref stays, since that is what runs.
600
+ const target = context.describeUiRef?.(item.ref) ?? `control ${item.ref}`;
601
+ if (item.action === 'set_value')
602
+ return {
603
+ line: `Set ${target} to ${JSON.stringify(item.value ?? '')}`,
604
+ coordinates: false,
605
+ };
606
+ const verb = UI_ACT_VERBS[item.action];
607
+ return verb ? { line: `${verb} ${target}`, coordinates: false } : null;
608
+ }
609
+ case 'zoom': {
610
+ const region = item.region;
611
+ return fields('region') &&
612
+ isRecord(region) &&
613
+ Object.keys(region).every((key) => ['x', 'y', 'width', 'height'].includes(key)) &&
614
+ ['x', 'y', 'width', 'height'].every((key) => Number.isInteger(region[key]))
615
+ ? {
616
+ line: `Zoom into ${region.width}x${region.height} at (${region.x}, ${region.y})`,
617
+ coordinates: true,
618
+ }
619
+ : null;
620
+ }
621
+ default:
622
+ return null;
623
+ }
624
+ }
474
625
  const PLAIN_TOOL_NAME = /^[\w.:-]+$/u;
475
626
  /** The tools with a formatter above; an evolved shape of one opens exact-first. */
476
- const FORMATTED_TOOLS = new Set(['bash', 'edit', 'write', 'Agent']);
627
+ const FORMATTED_TOOLS = new Set([
628
+ 'bash',
629
+ 'edit',
630
+ 'write',
631
+ 'Agent',
632
+ 'computer_use',
633
+ ]);
477
634
  /** Labels group only the calls in this approval; they never invent execution phases. */
478
635
  function compactAgentPlan(calls) {
479
636
  const lines = [];