@timurproko/a1 0.2.6 → 0.2.7-dev.1221

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 (410) hide show
  1. package/README.md +41 -3
  2. package/bin/automatic-update.js +7 -0
  3. package/bin/cli.js +4 -0
  4. package/bin/guardian.js +5 -0
  5. package/bin/tab-launch-context.d.ts +27 -0
  6. package/bin/tab-launch-context.js +94 -0
  7. package/bin/ui.js +107 -59
  8. package/dist/app/session-shell/clipboard-diagnostics.js +1 -1
  9. package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
  10. package/dist/app/session-shell/dialog-coordinator.js +133 -0
  11. package/dist/app/session-shell/dock-chrome.d.ts +34 -0
  12. package/dist/app/session-shell/dock-chrome.js +109 -0
  13. package/dist/app/session-shell/exit-notice.d.ts +1 -1
  14. package/dist/app/session-shell/exit-notice.js +1 -1
  15. package/dist/app/session-shell/extension-surface.d.ts +30 -0
  16. package/dist/app/session-shell/extension-surface.js +105 -0
  17. package/dist/app/session-shell/helper-pool.d.ts +3 -5
  18. package/dist/app/session-shell/helper-pool.js +3 -5
  19. package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
  20. package/dist/app/session-shell/input-surface-switch.js +85 -0
  21. package/dist/app/session-shell/login-interaction.d.ts +27 -0
  22. package/dist/app/session-shell/login-interaction.js +91 -0
  23. package/dist/app/session-shell/prompt-submission.d.ts +48 -0
  24. package/dist/app/session-shell/prompt-submission.js +276 -0
  25. package/dist/app/session-shell/resident-tab-coordinator.d.ts +38 -0
  26. package/dist/app/session-shell/resident-tab-coordinator.js +77 -0
  27. package/dist/app/session-shell/response-copy-helper.js +21 -6
  28. package/dist/app/session-shell/response-copy-protocol.d.ts +1 -1
  29. package/dist/app/session-shell/response-copy-transport.d.ts +16 -6
  30. package/dist/app/session-shell/response-copy-transport.js +69 -17
  31. package/dist/app/session-shell/session-concern.d.ts +22 -0
  32. package/dist/app/session-shell/session-concern.js +29 -0
  33. package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
  34. package/dist/app/session-shell/session-lifecycle.js +49 -0
  35. package/dist/app/session-shell/session-shell-root.d.ts +42 -6
  36. package/dist/app/session-shell/session-shell-root.js +196 -908
  37. package/dist/app/session-shell/session-shell.d.ts +3 -8
  38. package/dist/app/session-shell/session-shell.js +324 -835
  39. package/dist/app/session-shell/session-viewport-controller.d.ts +2 -2
  40. package/dist/app/session-shell/session-viewport-controller.js +29 -15
  41. package/dist/app/session-shell/settings-bindings.d.ts +17 -0
  42. package/dist/app/session-shell/settings-bindings.js +91 -0
  43. package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
  44. package/dist/app/session-shell/shell-editor-factory.js +102 -0
  45. package/dist/app/session-shell/shell-host.d.ts +6 -0
  46. package/dist/app/session-shell/shell-host.js +34 -7
  47. package/dist/app/session-shell/shell-layout.d.ts +64 -0
  48. package/dist/app/session-shell/shell-layout.js +18 -0
  49. package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
  50. package/dist/app/session-shell/suggestion-surface.js +63 -0
  51. package/dist/app/session-shell/transcript-document.d.ts +78 -0
  52. package/dist/app/session-shell/transcript-document.js +365 -0
  53. package/dist/app/session-shell/viewport-layout.d.ts +31 -0
  54. package/dist/app/session-shell/viewport-layout.js +160 -0
  55. package/dist/app/session-shell/workflow-output.d.ts +33 -0
  56. package/dist/app/session-shell/workflow-output.js +174 -0
  57. package/dist/app/session-shell/workflow-router.d.ts +25 -0
  58. package/dist/app/session-shell/workflow-router.js +39 -0
  59. package/dist/cli/dispatch.d.ts +11 -1
  60. package/dist/cli/dispatch.js +79 -5
  61. package/dist/cli/tabs-request.d.ts +7 -0
  62. package/dist/cli/tabs-request.js +1 -0
  63. package/dist/cli/tabs.d.ts +14 -0
  64. package/dist/cli/tabs.js +151 -0
  65. package/dist/cli/version-stats.js +38 -3
  66. package/dist/composition/owned-settings.d.ts +12 -0
  67. package/dist/composition/owned-settings.js +36 -0
  68. package/dist/composition/owned-ui.d.ts +27 -28
  69. package/dist/composition/owned-ui.js +205 -153
  70. package/dist/composition/resident-tab-bridge.d.ts +25 -0
  71. package/dist/composition/resident-tab-bridge.js +180 -0
  72. package/dist/composition/session-backend.d.ts +19 -0
  73. package/dist/composition/session-backend.js +1 -0
  74. package/dist/composition/session-runtime-registry.d.ts +20 -0
  75. package/dist/composition/session-runtime-registry.js +85 -0
  76. package/dist/composition/settings-route-host.d.ts +16 -1
  77. package/dist/composition/settings-route-host.js +29 -10
  78. package/dist/composition/settings-search-input.d.ts +9 -0
  79. package/dist/composition/settings-search-input.js +58 -0
  80. package/dist/composition/startup-route.d.ts +32 -0
  81. package/dist/composition/startup-route.js +72 -0
  82. package/dist/composition/utility-tab.d.ts +28 -0
  83. package/dist/composition/utility-tab.js +242 -0
  84. package/dist/contracts/owned-ui/index.d.ts +1 -1
  85. package/dist/contracts/owned-ui/model.d.ts +3 -0
  86. package/dist/contracts/owned-ui/session-backend.d.ts +3 -0
  87. package/dist/contracts/owned-ui/session-workflows.d.ts +11 -4
  88. package/dist/contracts/presentation/index.d.ts +11 -0
  89. package/dist/contracts/presentation/index.js +12 -0
  90. package/dist/features/launch/development-launch.js +6 -0
  91. package/dist/features/launch/index.d.ts +1 -1
  92. package/dist/features/launch/intent.d.ts +3 -1
  93. package/dist/features/launch/intent.js +7 -4
  94. package/dist/features/launch/profile-paths.js +4 -0
  95. package/dist/features/owned-ui/plus-menu-dialog.d.ts +22 -0
  96. package/dist/features/owned-ui/plus-menu-dialog.js +76 -0
  97. package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
  98. package/dist/features/owned-ui/project-trust-dialog.js +6 -8
  99. package/dist/features/owned-ui/project-trust-prompt.d.ts +1 -0
  100. package/dist/features/owned-ui/project-trust-prompt.js +7 -3
  101. package/dist/features/owned-ui/reference-screen-app.d.ts +2 -0
  102. package/dist/features/owned-ui/reference-screen-app.js +12 -2
  103. package/dist/features/owned-ui/settings-app.d.ts +12 -2
  104. package/dist/features/owned-ui/settings-app.js +116 -81
  105. package/dist/features/owned-ui/settings-search-input.d.ts +29 -0
  106. package/dist/features/owned-ui/settings-search-input.js +1 -0
  107. package/dist/features/prompt-history/index.d.ts +1 -1
  108. package/dist/features/prompt-history/paths.d.ts +2 -1
  109. package/dist/features/prompt-history/paths.js +10 -2
  110. package/dist/features/prompt-history/service.d.ts +5 -0
  111. package/dist/features/prompt-history/service.js +1 -1
  112. package/dist/features/resident-tab/auto-name.d.ts +11 -0
  113. package/dist/features/resident-tab/auto-name.js +44 -0
  114. package/dist/features/resident-tab/index.d.ts +5 -0
  115. package/dist/features/resident-tab/index.js +7 -0
  116. package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
  117. package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
  118. package/dist/features/resident-tab/shortcut-declarations.d.ts +13 -0
  119. package/dist/features/resident-tab/shortcut-declarations.js +26 -0
  120. package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
  121. package/dist/features/resident-tab/shortcut-projection.js +64 -0
  122. package/dist/features/resident-tab/status-deriver.d.ts +10 -0
  123. package/dist/features/resident-tab/status-deriver.js +12 -0
  124. package/dist/foundation/launch-context/index.d.ts +12 -0
  125. package/dist/foundation/launch-context/index.js +26 -0
  126. package/dist/foundation/launch-guardian/exit-watcher.d.ts +14 -0
  127. package/dist/foundation/launch-guardian/exit-watcher.js +94 -0
  128. package/dist/foundation/launch-guardian/main.d.ts +7 -1
  129. package/dist/foundation/launch-guardian/main.js +60 -7
  130. package/dist/foundation/lifecycle/session-repository-context.js +16 -2
  131. package/dist/foundation/process-containment/{native-guardian-containment.d.ts → addon-containment.d.ts} +7 -5
  132. package/dist/foundation/process-containment/addon-containment.js +139 -0
  133. package/dist/foundation/process-containment/addon-process-inspector.d.ts +11 -0
  134. package/dist/foundation/process-containment/addon-process-inspector.js +36 -0
  135. package/dist/foundation/process-containment/addon.d.ts +42 -0
  136. package/dist/foundation/process-containment/addon.js +57 -0
  137. package/dist/foundation/process-containment/artifact.d.ts +1 -1
  138. package/dist/foundation/process-containment/artifact.js +6 -5
  139. package/dist/foundation/process-containment/contracts.d.ts +2 -0
  140. package/dist/foundation/process-containment/index.d.ts +4 -4
  141. package/dist/foundation/process-containment/index.js +3 -3
  142. package/dist/foundation/process-containment/native-process-inspector.d.ts +2 -1
  143. package/dist/foundation/process-containment/native-process-inspector.js +10 -10
  144. package/dist/foundation/release/automatic-update.d.ts +37 -0
  145. package/dist/foundation/release/automatic-update.js +265 -0
  146. package/dist/foundation/release/bootstrap.d.ts +7 -9
  147. package/dist/foundation/release/bootstrap.js +107 -24
  148. package/dist/foundation/release/cohort-state.d.ts +1 -1
  149. package/dist/foundation/release/cohort-state.js +1 -1
  150. package/dist/foundation/release/dependency-certification.js +54 -19
  151. package/dist/foundation/release/early-accent.d.ts +12 -0
  152. package/dist/foundation/release/early-accent.js +59 -0
  153. package/dist/foundation/release/index.d.ts +2 -2
  154. package/dist/foundation/release/index.js +2 -2
  155. package/dist/foundation/release/latest-release.d.ts +24 -2
  156. package/dist/foundation/release/latest-release.js +51 -1
  157. package/dist/foundation/release/progress-palette.generated.d.ts +137 -3
  158. package/dist/foundation/release/progress-palette.generated.js +137 -3
  159. package/dist/foundation/release/release-gc.d.ts +3 -0
  160. package/dist/foundation/release/release-gc.js +59 -8
  161. package/dist/foundation/release/release-store.d.ts +12 -0
  162. package/dist/foundation/release/release-store.js +124 -2
  163. package/dist/foundation/release/update-execution-lease.d.ts +48 -0
  164. package/dist/foundation/release/update-execution-lease.js +161 -0
  165. package/dist/foundation/release/update.d.ts +12 -7
  166. package/dist/foundation/release/update.js +281 -196
  167. package/dist/foundation/resident-tabs/bounded-host-command.d.ts +18 -0
  168. package/dist/foundation/resident-tabs/bounded-host-command.js +39 -0
  169. package/dist/foundation/resident-tabs/bridge-client.d.ts +70 -0
  170. package/dist/foundation/resident-tabs/bridge-client.js +321 -0
  171. package/dist/foundation/resident-tabs/doctor.d.ts +28 -0
  172. package/dist/foundation/resident-tabs/doctor.js +166 -0
  173. package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
  174. package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
  175. package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +36 -0
  176. package/dist/foundation/resident-tabs/ensure-terminal-host.js +151 -0
  177. package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
  178. package/dist/foundation/resident-tabs/fault-injection.js +26 -0
  179. package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
  180. package/dist/foundation/resident-tabs/fixture-control.js +35 -0
  181. package/dist/foundation/resident-tabs/host-entry.d.ts +1 -0
  182. package/dist/foundation/resident-tabs/host-entry.js +17 -0
  183. package/dist/foundation/resident-tabs/index.d.ts +12 -0
  184. package/dist/foundation/resident-tabs/index.js +6 -0
  185. package/dist/foundation/resident-tabs/maintenance.d.ts +39 -0
  186. package/dist/foundation/resident-tabs/maintenance.js +75 -0
  187. package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +34 -0
  188. package/dist/foundation/resident-tabs/progress-observation-schema.js +1 -0
  189. package/dist/foundation/resident-tabs/progress-observation.d.ts +4 -0
  190. package/dist/foundation/resident-tabs/progress-observation.js +150 -0
  191. package/dist/foundation/resident-tabs/prompt-journal.d.ts +63 -0
  192. package/dist/foundation/resident-tabs/prompt-journal.js +213 -0
  193. package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
  194. package/dist/foundation/resident-tabs/protocol.js +195 -0
  195. package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
  196. package/dist/foundation/resident-tabs/recovery.js +205 -0
  197. package/dist/foundation/resident-tabs/release-holds.d.ts +28 -0
  198. package/dist/foundation/resident-tabs/release-holds.js +75 -0
  199. package/dist/foundation/resident-tabs/routes.d.ts +5 -0
  200. package/dist/foundation/resident-tabs/routes.js +5 -0
  201. package/dist/foundation/resident-tabs/routing.d.ts +11 -0
  202. package/dist/foundation/resident-tabs/routing.js +10 -0
  203. package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
  204. package/dist/foundation/resident-tabs/session-sync.js +37 -0
  205. package/dist/foundation/resident-tabs/settings.d.ts +12 -0
  206. package/dist/foundation/resident-tabs/settings.js +58 -0
  207. package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +14 -0
  208. package/dist/foundation/resident-tabs/terminal-host-artifact.js +78 -0
  209. package/dist/foundation/resident-tabs/zip-archive.d.ts +9 -0
  210. package/dist/foundation/resident-tabs/zip-archive.js +56 -0
  211. package/dist/foundation/session-writer-lock/index.d.ts +30 -0
  212. package/dist/foundation/session-writer-lock/index.js +203 -0
  213. package/dist/foundation/startup/startup-descriptor.js +2 -2
  214. package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
  215. package/dist/foundation/terminal-cleanup/index.js +1 -1
  216. package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +6 -0
  217. package/dist/foundation/terminal-cleanup/terminal-reset.js +6 -0
  218. package/dist/integrations/pi/components/editor-interaction.d.ts +2 -0
  219. package/dist/integrations/pi/components/modal-frame.d.ts +17 -1
  220. package/dist/integrations/pi/components/modal-frame.js +48 -9
  221. package/dist/integrations/pi/components/models-dialog.js +4 -52
  222. package/dist/integrations/pi/components/owned-editor-ux.d.ts +6 -1
  223. package/dist/integrations/pi/components/owned-editor-ux.js +90 -6
  224. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
  225. package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
  226. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -0
  227. package/dist/integrations/pi/components/share-operation-dialog.js +2 -1
  228. package/dist/integrations/pi/components/shell-editor-autocomplete.js +58 -36
  229. package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
  230. package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
  231. package/dist/integrations/pi/components/shell-footer-status.js +21 -5
  232. package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
  233. package/dist/integrations/pi/components/shell-presenters-info.d.ts +5 -2
  234. package/dist/integrations/pi/components/shell-presenters-info.js +18 -4
  235. package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -1
  236. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -1
  237. package/dist/integrations/pi/components/shell-shared-facade.d.ts +12 -1
  238. package/dist/integrations/pi/components/skills-dialog.js +2 -2
  239. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  240. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
  241. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  242. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  243. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  244. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  245. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  246. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  247. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  248. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  249. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +8 -6
  250. package/dist/integrations/pi/components/upstream/components/owned-editor.js +16 -9
  251. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  252. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +4 -4
  253. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +2 -2
  254. package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +2 -1
  255. package/dist/integrations/pi/components/upstream/components/session-footer.js +31 -25
  256. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  257. package/dist/integrations/pi/components/upstream/components/session-selector.js +8 -7
  258. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  259. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  260. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
  261. package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
  262. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  263. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  264. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +8 -7
  265. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +10 -9
  266. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -6
  267. package/dist/integrations/pi/components/upstream/components/tool-execution.js +103 -101
  268. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +9 -9
  269. package/dist/integrations/pi/components/upstream/components/tree-selector.js +13 -21
  270. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  271. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  272. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
  273. package/dist/integrations/pi/components/upstream/history/editor-core.js +7 -5
  274. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  275. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  276. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  277. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  278. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  279. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  280. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  281. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  282. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  283. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  284. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -0
  285. package/dist/integrations/pi/components/upstream/theme/theme.js +29 -2
  286. package/dist/integrations/pi/engine/adapter.d.ts +5 -77
  287. package/dist/integrations/pi/engine/adapter.js +95 -394
  288. package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
  289. package/dist/integrations/pi/engine/command-dispatch.js +57 -0
  290. package/dist/integrations/pi/engine/host.js +2 -2
  291. package/dist/integrations/pi/engine/offline-settings-port.d.ts +23 -0
  292. package/dist/integrations/pi/engine/offline-settings-port.js +53 -0
  293. package/dist/integrations/pi/engine/pi-settings-metadata.json +14 -2
  294. package/dist/integrations/pi/engine/ports.d.ts +56 -0
  295. package/dist/integrations/pi/engine/ports.js +93 -0
  296. package/dist/integrations/pi/engine/prompt-suggestions.d.ts +1 -0
  297. package/dist/integrations/pi/engine/prompt-suggestions.js +40 -0
  298. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  299. package/dist/integrations/pi/engine/runtime-integration.js +102 -29
  300. package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
  301. package/dist/integrations/pi/engine/session-runtime.js +13 -5
  302. package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
  303. package/dist/integrations/pi/engine/session-selection.js +45 -9
  304. package/dist/integrations/pi/engine/settings-bridge.d.ts +5 -0
  305. package/dist/integrations/pi/engine/settings-bridge.js +15 -0
  306. package/dist/integrations/pi/engine/settings-port.js +11 -15
  307. package/dist/integrations/pi/engine/view-state.d.ts +42 -0
  308. package/dist/integrations/pi/engine/view-state.js +126 -0
  309. package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
  310. package/dist/integrations/pi/engine/workflow-runner.js +73 -4
  311. package/dist/integrations/pi/engine/workflow-support.d.ts +12 -0
  312. package/dist/integrations/pi/engine/workflow-support.js +36 -0
  313. package/dist/integrations/pi/engine/workflows.d.ts +3 -1
  314. package/dist/integrations/pi/engine/workflows.js +1 -0
  315. package/dist/integrations/pi/startup-public.js +257 -310
  316. package/dist/integrations/pi/startup-public.manifest.json +564 -440
  317. package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
  318. package/dist/integrations/pi/tui-runtime/adapter.js +32 -1
  319. package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
  320. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +12 -1
  321. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +31 -2
  322. package/dist/native/darwin-arm64/manifest.json +10 -7
  323. package/dist/native/darwin-arm64/process-guardian.node +0 -0
  324. package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +10500 -0
  325. package/dist/native/darwin-arm64/terminal-host.manifest.json +46 -0
  326. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  327. package/dist/native/darwin-x64/manifest.json +23 -0
  328. package/dist/native/darwin-x64/process-guardian.node +0 -0
  329. package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10737 -0
  330. package/dist/native/darwin-x64/terminal-host.manifest.json +46 -0
  331. package/dist/native/darwin-x64/terminal-host.node +0 -0
  332. package/dist/native/linux-x64/manifest.json +10 -7
  333. package/dist/native/linux-x64/process-guardian.node +0 -0
  334. package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +11226 -0
  335. package/dist/native/linux-x64/terminal-host.manifest.json +46 -0
  336. package/dist/native/linux-x64/terminal-host.node +0 -0
  337. package/dist/native/win32-x64/manifest.json +10 -7
  338. package/dist/native/win32-x64/process-guardian.node +0 -0
  339. package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10757 -0
  340. package/dist/native/win32-x64/terminal-host.manifest.json +46 -0
  341. package/dist/native/win32-x64/terminal-host.node +0 -0
  342. package/dist/product-identity.d.ts +3 -3
  343. package/dist/product-identity.js +4 -4
  344. package/dist/product-identity.json +16 -2
  345. package/dist/runtime-payload-inventory.json +6330 -6677
  346. package/dist/ui/apps/host.d.ts +2 -0
  347. package/dist/ui/apps/host.js +7 -1
  348. package/dist/ui/components/dialog-panel.js +35 -30
  349. package/dist/ui/components/index.d.ts +2 -2
  350. package/dist/ui/components/index.js +1 -1
  351. package/dist/ui/components/line-input.d.ts +4 -1
  352. package/dist/ui/components/line-input.js +3 -1
  353. package/dist/ui/components/prompt-input.d.ts +11 -8
  354. package/dist/ui/components/prompt-input.js +15 -13
  355. package/dist/ui/components/selection-copy.d.ts +2 -0
  356. package/dist/ui/components/selection-copy.js +13 -0
  357. package/dist/ui/components/spans.js +2 -2
  358. package/dist/ui/components/submitted-prompt.d.ts +9 -6
  359. package/dist/ui/components/submitted-prompt.js +20 -12
  360. package/dist/ui/components/surface.js +4 -2
  361. package/dist/ui/components/text.d.ts +3 -6
  362. package/dist/ui/components/text.js +6 -8
  363. package/dist/ui/components/transcript-viewport.d.ts +9 -2
  364. package/dist/ui/components/transcript-viewport.js +176 -55
  365. package/dist/ui/settings/declarations.d.ts +90 -16
  366. package/dist/ui/settings/declarations.js +67 -14
  367. package/dist/ui/settings/early-accent.d.ts +81 -0
  368. package/dist/ui/settings/early-accent.js +50 -0
  369. package/dist/ui/settings/index.d.ts +4 -2
  370. package/dist/ui/settings/index.js +2 -1
  371. package/dist/ui/settings/manager.d.ts +16 -3
  372. package/dist/ui/settings/manager.js +122 -33
  373. package/dist/ui/settings/migrations.d.ts +6 -0
  374. package/dist/ui/settings/migrations.js +73 -0
  375. package/dist/ui/settings/profile-document.d.ts +26 -0
  376. package/dist/ui/settings/profile-document.js +164 -0
  377. package/dist/ui/settings/progress-palette.generated.d.ts +139 -0
  378. package/dist/ui/settings/progress-palette.generated.js +139 -0
  379. package/dist/ui/settings/sections.d.ts +4 -0
  380. package/dist/ui/settings/sections.js +9 -3
  381. package/docs/architecture/boundaries.md +24 -9
  382. package/docs/architecture/evidence/resident-tabs/linux-x64.md +37 -0
  383. package/docs/architecture/evidence/resident-tabs/macos-arm64.md +36 -0
  384. package/docs/architecture/evidence/resident-tabs/macos-x64.md +35 -0
  385. package/docs/architecture/evidence/resident-tabs/windows-x64.md +36 -0
  386. package/docs/architecture/internal-naming.md +3 -1
  387. package/docs/architecture/process-guardian-provenance.md +18 -10
  388. package/docs/architecture/project-structure.md +8 -0
  389. package/docs/architecture/resident-tabs-requirements.md +18 -0
  390. package/docs/architecture/resident-tabs.md +648 -0
  391. package/docs/architecture/response-copy-delivery.md +1 -1
  392. package/docs/architecture/terminal-host-proof-gate.md +2 -0
  393. package/docs/architecture/terminal-host-provenance.md +16 -4
  394. package/docs/architecture/tool-image-presentation.md +2 -1
  395. package/docs/architecture/toolchain.md +11 -9
  396. package/docs/ci-release-runbook.md +14 -7
  397. package/docs/features/launch-profiles.md +11 -8
  398. package/docs/features/prompt-history.md +41 -20
  399. package/docs/manual-resident-tabs-acceptance.md +51 -0
  400. package/docs/openspec-archive-automation.md +49 -22
  401. package/docs/validation.md +49 -9
  402. package/package.json +19 -6
  403. package/dist/foundation/process-containment/darwin-process-inspector.d.ts +0 -5
  404. package/dist/foundation/process-containment/darwin-process-inspector.js +0 -7
  405. package/dist/foundation/process-containment/native-guardian-containment.js +0 -152
  406. package/dist/foundation/process-containment/windows-process-inspector.d.ts +0 -19
  407. package/dist/foundation/process-containment/windows-process-inspector.js +0 -56
  408. package/dist/native/darwin-arm64/process-guardian +0 -0
  409. package/dist/native/linux-x64/process-guardian +0 -0
  410. package/dist/native/win32-x64/process-guardian.exe +0 -0
@@ -48,6 +48,7 @@ export class ReferenceScreenApp {
48
48
  #title;
49
49
  #document;
50
50
  #scrollSettings;
51
+ #pinned;
51
52
  #scroll = 0;
52
53
  #interruptArmed = false;
53
54
  #failure = null;
@@ -67,6 +68,7 @@ export class ReferenceScreenApp {
67
68
  this.#title = options.title;
68
69
  this.#document = options.document;
69
70
  this.#scrollSettings = options.scrollSettings;
71
+ this.#pinned = options.pinned === true;
70
72
  }
71
73
  onActivate(host) {
72
74
  const ready = this.#document.ready;
@@ -139,7 +141,7 @@ export class ReferenceScreenApp {
139
141
  const withRail = withScrollbarRail(body.slice(0, bodyHeight), geometry, contentWidth, theme, { presentation });
140
142
  const hint = this.#interruptArmed
141
143
  ? theme.fg("dim", " press ctrl+c again to exit a1")
142
- : renderShortcutHintsWithClose(REFERENCE_SCREEN_SHORTCUTS.hintEntries(SCOPE), theme, rect.width, 1);
144
+ : renderShortcutHintsWithClose(this.#hintEntries(), theme, rect.width, 1);
143
145
  // Compatibility: the v2 reference screen frames its document between two border-coloured rules.
144
146
  const rule = theme.fg("border", "─".repeat(rect.width));
145
147
  // Invariant: dialog chrome shares the title's one-cell inset; document content keeps its own layout.
@@ -153,7 +155,8 @@ export class ReferenceScreenApp {
153
155
  return { consumed: false };
154
156
  switch (action) {
155
157
  case "close":
156
- host.close();
158
+ if (!this.#pinned)
159
+ host.close();
157
160
  return { consumed: true };
158
161
  case "up":
159
162
  this.#scrollBy(-1);
@@ -216,6 +219,13 @@ export class ReferenceScreenApp {
216
219
  }
217
220
  return { owned: true, changed: true };
218
221
  }
222
+ // Invariant: a pinned screen is its tab and `Esc` does not close it, so it shows no close hint.
223
+ #hintEntries() {
224
+ const entries = REFERENCE_SCREEN_SHORTCUTS.hintEntries(SCOPE);
225
+ if (!this.#pinned)
226
+ return entries;
227
+ return entries.filter(entry => entry.key !== DIALOG_CLOSE_SHORTCUT_HINT.key || entry.action !== DIALOG_CLOSE_SHORTCUT_HINT.action);
228
+ }
219
229
  // Invariant: the title is the first document row, as in v2, so it scrolls with the document.
220
230
  #content(width, theme) {
221
231
  // Compatibility: one leading space, so the title lines up with the padded Markdown rows as in v2.
@@ -1,8 +1,9 @@
1
1
  import type { AppHostServices, UiApp } from "../../ui/apps/index.js";
2
2
  import { ShortcutRegistry, type PaneInputResult, type PaneMouseEvent, type PaneRect } from "../../ui/components/index.js";
3
3
  import type { OwnedSettingsManager } from "../../ui/settings/index.js";
4
+ import type { SettingsSearchInputFactory } from "./settings-search-input.js";
4
5
  export { SETTINGS_APP_ID, SETTINGS_ROUTE } from "./settings-route.js";
5
- type Action = "move-up" | "move-down" | "block-up" | "block-down" | "first" | "last" | "page-up" | "page-down" | "previous-value" | "next-value" | "activate" | "open-filter" | "close" | "undo" | "part-previous" | "part-next" | "part-change";
6
+ type Action = "move-up" | "move-down" | "block-up" | "block-down" | "first" | "last" | "page-up" | "page-down" | "previous-value" | "next-value" | "activate" | "edit-filter" | "close" | "undo" | "part-previous" | "part-next" | "part-change";
6
7
  export declare const SETTINGS_SHORTCUTS: ShortcutRegistry<Action>;
7
8
  /**
8
9
  * The settings screen. Rows, sticky headers, scrolling, and the keymap come from
@@ -12,7 +13,16 @@ export declare const SETTINGS_SHORTCUTS: ShortcutRegistry<Action>;
12
13
  export declare class SettingsApp implements UiApp {
13
14
  #private;
14
15
  readonly id = "settings";
15
- constructor(session: OwnedSettingsManager);
16
+ /**
17
+ * `pinned` presents the screen as a resident Settings tab, which offers no screen-level close;
18
+ * `configurePlusMenu` opens the tab bar's Plus Menu dialog in place of this screen's own.
19
+ */
20
+ constructor(session: OwnedSettingsManager, options: {
21
+ readonly pinned?: boolean;
22
+ readonly searchInputFactory: SettingsSearchInputFactory;
23
+ readonly copyText?: (text: string) => void;
24
+ readonly configurePlusMenu?: (() => boolean) | null;
25
+ });
16
26
  onActivate(host: AppHostServices): void;
17
27
  onClose(_host: AppHostServices): void;
18
28
  render(rect: PaneRect, host: AppHostServices): readonly string[];
@@ -1,5 +1,6 @@
1
1
  import { DIALOG_BACK_SHORTCUT_HINT, DIALOG_CLOSE_SHORTCUT_HINT } from "../../contracts/presentation/index.js";
2
- import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, numericValues, RAIL_COLUMNS, renderDialogPanel, renderSteppedDialogPanel, renderEmptyState, renderGroupHeader, renderInputRow, renderListRow, renderNote, renderShortcutHintsWithClose, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, handleLineInputKey, humanizeLabel, humanizeTitle, indexOfKey, layoutList, moveSelection, rowKey, scrollForSelection, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, ScrollbarRails, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
2
+ import { GLOBAL_SCOPE, LineInput, PLAIN_THEME, ShortcutRegistry, assertNoShortcutConflicts, blockJumpTarget, numericValues, RAIL_COLUMNS, renderDialogPanel, renderSteppedDialogPanel, renderEmptyState, renderGroupHeader, renderListRow, renderNote, renderShortcutHintsWithClose, menuRowAt, regionAt, renderValueMenu, withScrollbarRail, stepperEnds, steppedValue, truncateToWidth, valueColumnFor, valueMenuFrame, blockRowSpan, displayWidth, formatLocalTime, handleLineInputKey, humanizeLabel, humanizeTitle, indexOfKey, layoutList, moveSelection, rowKey, scrollForSelection, scrollForTrackPage, scrollbarGeometry, scrollbarPresentation, ScrollbarRails, scrollbarWheelRows, selectableIndexes, } from "../../ui/components/index.js";
3
+ import { PLUS_MENU_SETTING_ID, PlusMenuDialog } from "./plus-menu-dialog.js";
3
4
  import { SETTINGS_APP_ID } from "./settings-route.js";
4
5
  export { SETTINGS_APP_ID, SETTINGS_ROUTE } from "./settings-route.js";
5
6
  const SCOPE = SETTINGS_APP_ID;
@@ -19,11 +20,10 @@ const RAIL_KEY = "settings";
19
20
  // Compatibility: the transcript rail stays lit this long after a scroll, and repaints just after.
20
21
  const SCROLL_LINGER_MS = 900;
21
22
  const SCROLL_LINGER_REPAINT_MS = 925;
22
- const SEARCH_PLACEHOLDER = "search settings";
23
23
  /** What a structured value offers instead of printing itself. */
24
24
  const CONFIGURE = "configure";
25
25
  export const SETTINGS_SHORTCUTS = new ShortcutRegistry();
26
- SETTINGS_SHORTCUTS.declare({ key: "/", scope: SCOPE, description: "Search settings", section: "Change", hint: { keys: "/", does: "search" } }, "open-filter");
26
+ SETTINGS_SHORTCUTS.declare({ key: "edit", scope: SCOPE, description: "Search settings", section: "Change", hint: { keys: "Type", does: "search" } }, "edit-filter");
27
27
  SETTINGS_SHORTCUTS.declare({ key: "up", scope: SCOPE, description: "Previous setting", section: "Navigate", hint: { keys: "↑↓", does: "navigate" } }, "move-up");
28
28
  SETTINGS_SHORTCUTS.declare({ key: "down", scope: SCOPE, description: "Next setting", section: "Navigate", hint: { keys: "↑↓", does: "navigate" } }, "move-down");
29
29
  SETTINGS_SHORTCUTS.declare({ key: "shift+up", scope: SCOPE, description: "Previous section", section: "Navigate", hint: { keys: "Shift+↑↓", does: "jump" } }, "block-up");
@@ -78,7 +78,6 @@ const KEYS = {
78
78
  "\r": "enter",
79
79
  "\n": "enter",
80
80
  " ": "space",
81
- "/": "/",
82
81
  "\u001a": "ctrl+z",
83
82
  };
84
83
  /**
@@ -94,12 +93,9 @@ export class SettingsApp {
94
93
  // Invariant: keyboard navigation requests visibility once; pointer scrolling then stays free.
95
94
  #selectionNeedsReveal = true;
96
95
  #reveal;
97
- #notice = null;
98
- #filter = null;
99
- #scrollBeforeFilter = null;
96
+ #search;
100
97
  #menu = null;
101
98
  #structured = null;
102
- #interruptArmed = false;
103
99
  // Invariant: pending values remain visible until the source reflects them.
104
100
  #pending = new Map();
105
101
  #undoHistory = [];
@@ -122,8 +118,20 @@ export class SettingsApp {
122
118
  #activeUntil = 0;
123
119
  #activityTimer;
124
120
  #renderedScroll;
125
- constructor(session) {
121
+ #options;
122
+ /**
123
+ * `pinned` presents the screen as a resident Settings tab, which offers no screen-level close;
124
+ * `configurePlusMenu` opens the tab bar's Plus Menu dialog in place of this screen's own.
125
+ */
126
+ constructor(session, options) {
126
127
  this.#session = session;
128
+ this.#options = { pinned: options.pinned === true, configurePlusMenu: options.configurePlusMenu ?? null };
129
+ this.#search = {
130
+ input: null,
131
+ scrollBefore: null,
132
+ factory: options.searchInputFactory,
133
+ copyText: options.copyText ?? (() => { }),
134
+ };
127
135
  }
128
136
  onActivate(host) {
129
137
  this.#closed = false;
@@ -133,18 +141,19 @@ export class SettingsApp {
133
141
  this.#closed = true;
134
142
  this.#undoHistory.length = 0;
135
143
  this.#undoRequests = 0;
144
+ this.#search.input?.setFocused(false);
145
+ this.#search.input = null;
136
146
  this.#clearActivityTimer();
137
147
  this.#rails.clear();
138
148
  }
139
149
  render(rect, host) {
140
150
  const theme = host.theme ?? PLAIN_THEME;
141
- this.#interruptArmed = host.interruptArmed;
142
151
  const rows = this.#rows();
143
152
  const selected = indexOfKey(rows, this.#selectedKey);
144
153
  const footer = this.#footerLines(rect.width, theme);
145
154
  // Invariant: the shared search input and structured panel each begin with their own standard rule.
146
155
  // That rule replaces the ordinary content/footer divider instead of stacking beneath it.
147
- const dividerRows = this.#filter === null && this.#structured === null ? SETTINGS_FOOTER_DIVIDER_ROWS : 0;
156
+ const dividerRows = this.#search.input === null && this.#structured === null ? SETTINGS_FOOTER_DIVIDER_ROWS : 0;
148
157
  const topRows = Math.min(SETTINGS_TOP_RULE_ROWS, rect.height);
149
158
  const contentHeight = Math.max(0, rect.height - topRows - dividerRows - footer.length);
150
159
  let titleRows = this.#scroll <= 0 ? Math.min(SETTINGS_TITLE_ROWS, contentHeight) : 0;
@@ -205,7 +214,7 @@ export class SettingsApp {
205
214
  const body = [];
206
215
  this.#frameRows = [];
207
216
  if (rows.length === 0) {
208
- body.push(...renderEmptyState("No settings found.", "👀", bodyHeight, contentWidth, theme));
217
+ body.push(...renderEmptyState("No settings found", "👀", bodyHeight, contentWidth, theme));
209
218
  }
210
219
  else {
211
220
  if (layout.topPadding > 0)
@@ -240,27 +249,32 @@ export class SettingsApp {
240
249
  return frame.slice(0, rect.height).concat(Array(Math.max(0, rect.height - frame.length)).fill(""));
241
250
  }
242
251
  onInput(data, host) {
252
+ if (data === "\u0003" && this.#search.input === null)
253
+ return { consumed: false };
243
254
  if (this.#structured !== null)
244
255
  return this.#structuredKey(data);
245
256
  if (this.#menu !== null)
246
257
  return this.#menuKey(data);
247
- if (this.#filter !== null)
258
+ if (this.#search.input !== null)
248
259
  return this.#filterKey(data);
249
- const key = KEYS[data] ?? data;
250
- const action = SETTINGS_SHORTCUTS.resolve(key, SCOPE);
251
- if (action === null)
252
- return { consumed: false };
260
+ const key = KEYS[data];
261
+ const action = key === undefined ? null : SETTINGS_SHORTCUTS.resolve(key, SCOPE);
262
+ if (action === null) {
263
+ if (!this.#search.factory.isTextInput(data))
264
+ return { consumed: false };
265
+ openSettingsSearch(this.#search, host, data, this.#scroll);
266
+ this.#scroll = 0;
267
+ return { consumed: true };
268
+ }
253
269
  const rows = this.#rows();
254
270
  const selected = indexOfKey(rows, this.#selectedKey);
255
271
  switch (action) {
256
272
  case "close":
257
- host.close();
258
- return { consumed: true };
259
- case "open-filter":
260
- this.#scrollBeforeFilter = this.#scroll;
261
- this.#filter = new LineInput("");
262
- this.#notice = null;
273
+ if (!this.#options.pinned)
274
+ host.close();
263
275
  return { consumed: true };
276
+ case "edit-filter":
277
+ return { consumed: false };
264
278
  case "activate": {
265
279
  const row = rows[selected];
266
280
  if (row?.kind === "element" && row.value.structured)
@@ -310,6 +324,9 @@ export class SettingsApp {
310
324
  }
311
325
  }
312
326
  onMouse(event, _host) {
327
+ const searchPointer = handleSettingsSearchPointer(this.#search, event, this.#panelTopForFrame);
328
+ if (searchPointer !== null)
329
+ return searchPointer;
313
330
  const menu = this.#menu;
314
331
  const frame = this.#menuFrame;
315
332
  if (menu !== null && frame !== null) {
@@ -349,13 +366,13 @@ export class SettingsApp {
349
366
  // Invariant: the whole list pane owns wheel scrolling, including blank space beside
350
367
  // short labels. A fixed structured dialog keeps that content interaction available.
351
368
  const screenRow = event.row - 1;
352
- const wheelBottom = this.#filter === null
369
+ const wheelBottom = this.#search.input === null
353
370
  ? this.#bodyTopForFrame + this.#bodyHeightForFrame
354
371
  : this.#panelTopForFrame + SETTINGS_SEARCH_INPUT_ROWS + SETTINGS_STATUS_ROWS;
355
372
  if (screenRow >= 0 && screenRow < wheelBottom) {
356
373
  const distance = scrollbarWheelRows(this.#scrollbarSpeed());
357
- if (this.#filter !== null)
358
- this.#scrollBeforeFilter = null;
374
+ if (this.#search.input !== null)
375
+ this.#search.scrollBefore = null;
359
376
  this.#scroll = Math.max(0, this.#scroll + (event.kind === "wheel-down" ? distance : -distance));
360
377
  return { consumed: true };
361
378
  }
@@ -385,7 +402,6 @@ export class SettingsApp {
385
402
  const index = rows.findIndex(candidate => rowKey(candidate) === row.key);
386
403
  if (index >= 0) {
387
404
  // Rationale: the pointer acts where it points; the arrow belongs to the keyboard.
388
- this.#notice = null;
389
405
  if (this.#hoverRegion === "minus")
390
406
  this.#cycle(rows, index, -1);
391
407
  else if (this.#hoverRegion === "plus")
@@ -458,10 +474,8 @@ export class SettingsApp {
458
474
  // and pointing at it is not a request for anything else.
459
475
  if (typeof shown === "number")
460
476
  return;
461
- if (!entry.editable || entry.choices === null || entry.choices.length === 0) {
462
- this.#notice = `${labelOf(entry)} cannot be changed here`;
477
+ if (!entry.editable || entry.choices === null || entry.choices.length === 0)
463
478
  return;
464
- }
465
479
  const current = shown === null ? 0 : Math.max(0, entry.choices.indexOf(shown));
466
480
  const anchorKey = `${entry.backend}:${entry.id}`;
467
481
  // Compatibility: pointer opening already brightens the source value. Enter borrows that
@@ -492,10 +506,11 @@ export class SettingsApp {
492
506
  #openStructured(entry) {
493
507
  // Invariant: the flags come from the declaration, not from the stored value: an unset
494
508
  // flag still has a row, showing the default the source would apply.
495
- if (entry.flags.length === 0) {
496
- this.#notice = `${labelOf(entry)} has nothing to configure`;
509
+ if (entry.flags.length === 0)
510
+ return;
511
+ // Rationale: beside a tab bar, its own Plus Menu dialog configures `+`, so both ways look the same.
512
+ if (entry.backend === "a1" && entry.id === PLUS_MENU_SETTING_ID && this.#options.configurePlusMenu?.() === true)
497
513
  return;
498
- }
499
514
  const stored = typeof entry.rawValue === "object" && entry.rawValue !== null && !Array.isArray(entry.rawValue)
500
515
  ? entry.rawValue
501
516
  : {};
@@ -516,6 +531,7 @@ export class SettingsApp {
516
531
  entry,
517
532
  flags: entry.flags.map(flag => flag.key),
518
533
  modelDialog,
534
+ plusMenu: entry.backend === "a1" && entry.id === PLUS_MENU_SETTING_ID ? new PlusMenuDialog(entry.flags) : null,
519
535
  filter: modelDialog ? new LineInput("") : null,
520
536
  step: "model",
521
537
  modelKey: null,
@@ -530,6 +546,12 @@ export class SettingsApp {
530
546
  return { consumed: false };
531
547
  if (open.modelDialog)
532
548
  return this.#modelDialogKey(open, data);
549
+ if (open.plusMenu !== null) {
550
+ const outcome = open.plusMenu.handle(KEYS[data] ?? data, data, key => this.#toggleFlag(open.flags.indexOf(key)));
551
+ if (outcome === "close")
552
+ this.#structured = null;
553
+ return { consumed: true };
554
+ }
533
555
  switch (SETTINGS_SHORTCUTS.resolve(KEYS[data] ?? data, DIALOG_SCOPE)) {
534
556
  case "close":
535
557
  this.#structured = null;
@@ -648,13 +670,11 @@ export class SettingsApp {
648
670
  const failure = changeFailure(outcome);
649
671
  if (failure === null) {
650
672
  this.#recordUndo({ kind: "structured", sequence, entry: open.entry, previous, forward });
651
- this.#notice = null;
652
673
  return;
653
674
  }
654
675
  // Concurrency: only roll back the dialog if no later press has moved the record on.
655
676
  if (this.#structured === open && sameRecord(open.record, forward))
656
677
  replaceRecord(open.record, previous);
657
- this.#notice = `Could not save ${labelOf(open.entry)}: ${failure}`;
658
678
  });
659
679
  }
660
680
  #menuKey(data) {
@@ -686,18 +706,18 @@ export class SettingsApp {
686
706
  return { consumed: true };
687
707
  }
688
708
  #filterKey(data) {
689
- const input = this.#filter;
709
+ const input = this.#search.input;
690
710
  if (input === null)
691
711
  return { consumed: false };
692
- const key = KEYS[data];
693
- if (SETTINGS_SHORTCUTS.resolve(key ?? data, SCOPE) === "undo") {
694
- this.#undo();
712
+ if (data === "\u001b" || (data === "\u0003" && !input.hasSelection())) {
713
+ this.#scroll = closeSettingsSearch(this.#search) ?? this.#scroll;
695
714
  return { consumed: true };
696
715
  }
716
+ const key = KEYS[data];
697
717
  // Rationale: the boundary chords jump through the results; plain Home and End stay with
698
- // the search cursor, which the shared line input moves below.
718
+ // the search cursor, which the shared interactive input moves below.
699
719
  if (key === "ctrl+home" || key === "ctrl+end") {
700
- this.#scrollBeforeFilter = null;
720
+ this.#search.scrollBefore = null;
701
721
  const rows = this.#rows();
702
722
  const selectable = selectableIndexes(rows);
703
723
  const target = key === "ctrl+end" ? selectable.at(-1) : selectable[0];
@@ -709,7 +729,7 @@ export class SettingsApp {
709
729
  return { consumed: true };
710
730
  }
711
731
  if (key === "up" || key === "down" || key === "shift+up" || key === "shift+down") {
712
- this.#scrollBeforeFilter = null;
732
+ this.#search.scrollBefore = null;
713
733
  const rows = this.#rows();
714
734
  // Rationale: nothing found means nothing to move through; the key is still swallowed
715
735
  // rather than typed into the search.
@@ -726,15 +746,10 @@ export class SettingsApp {
726
746
  this.#select(rows, moveSelection(rows, selected, forward ? 1 : -1));
727
747
  return { consumed: true };
728
748
  }
729
- const outcome = handleLineInputKey(input, data);
730
- if (outcome.kind === "cancelled") {
731
- this.#filter = null;
732
- if (this.#scrollBeforeFilter !== null)
733
- this.#scroll = this.#scrollBeforeFilter;
734
- this.#scrollBeforeFilter = null;
735
- }
736
- else {
737
- this.#scrollBeforeFilter = null;
749
+ const before = input.getText();
750
+ input.handleInput(data);
751
+ if (input.getText() !== before) {
752
+ this.#search.scrollBefore = null;
738
753
  this.#scroll = 0;
739
754
  }
740
755
  return { consumed: true };
@@ -744,10 +759,8 @@ export class SettingsApp {
744
759
  if (row === undefined || row.kind !== "element")
745
760
  return;
746
761
  const entry = row.value;
747
- if (!entry.editable) {
748
- this.#notice = `${labelOf(entry)} cannot be changed here`;
762
+ if (!entry.editable)
749
763
  return;
750
- }
751
764
  const shown = this.#shownValue(entry);
752
765
  if (typeof shown === "number") {
753
766
  // Rationale: at the end of the range there is nothing to say: the arrow already reads
@@ -758,10 +771,8 @@ export class SettingsApp {
758
771
  return;
759
772
  }
760
773
  const choices = entry.choices;
761
- if (choices === null || choices.length === 0) {
762
- this.#notice = `${labelOf(entry)} cannot be changed here`;
774
+ if (choices === null || choices.length === 0)
763
775
  return;
764
- }
765
776
  const current = shown === null ? -1 : choices.indexOf(shown);
766
777
  const next = choices[current < 0
767
778
  ? (delta > 0 ? 0 : choices.length - 1)
@@ -781,7 +792,6 @@ export class SettingsApp {
781
792
  if (failure !== null) {
782
793
  if (this.#pending.get(key) === value)
783
794
  this.#pending.delete(key);
784
- this.#notice = `Could not save ${labelOf(entry)}: ${failure}`;
785
795
  return;
786
796
  }
787
797
  if (previous !== null && previous !== value)
@@ -789,7 +799,6 @@ export class SettingsApp {
789
799
  // Concurrency: a later press may have moved on; only the last request clears itself.
790
800
  if (this.#pending.get(key) === value)
791
801
  this.#pending.delete(key);
792
- this.#notice = null;
793
802
  });
794
803
  }
795
804
  #shownValue(entry) {
@@ -841,13 +850,8 @@ export class SettingsApp {
841
850
  }
842
851
  #finishUndo(record, outcome) {
843
852
  const failure = changeFailure(outcome);
844
- if (failure !== null) {
853
+ if (failure !== null)
845
854
  this.#recordUndo(record);
846
- this.#notice = `Could not restore ${labelOf(record.entry)}: ${failure}`;
847
- }
848
- else {
849
- this.#notice = null;
850
- }
851
855
  this.#undoActive = false;
852
856
  this.#drainUndo();
853
857
  }
@@ -878,10 +882,9 @@ export class SettingsApp {
878
882
  return;
879
883
  this.#selectedKey = rowKey(rows[index]);
880
884
  this.#selectionNeedsReveal = true;
881
- this.#notice = null;
882
885
  }
883
886
  #rows() {
884
- const needle = this.#filter?.value.trim().toLowerCase() ?? "";
887
+ const needle = this.#search.input?.getText().trim().toLowerCase() ?? "";
885
888
  const matches = (entry) => needle.length === 0
886
889
  || entry.id.toLowerCase().includes(needle)
887
890
  || labelOf(entry).toLowerCase().includes(needle);
@@ -944,7 +947,7 @@ export class SettingsApp {
944
947
  ? CONFIGURE
945
948
  : shown === null
946
949
  ? describeRaw(entry.rawValue)
947
- : displayValue(shown);
950
+ : displaySettingValue(entry, shown);
948
951
  const range = rangeOf(entry);
949
952
  return {
950
953
  key,
@@ -961,11 +964,11 @@ export class SettingsApp {
961
964
  return lines;
962
965
  }
963
966
  const state = {
964
- choices: menu.choices.map(choice => displayValue(choice)),
967
+ choices: menu.choices.map(choice => displaySettingValue(menu.entry, choice)),
965
968
  ...(menu.entry.id === "accentColor" ? {
966
969
  previews: menu.choices.map(choice => theme.accentPreview?.(String(choice), "■") ?? ""),
967
970
  } : {}),
968
- current: this.#shownValue(menu.entry) === null ? null : displayValue(this.#shownValue(menu.entry)),
971
+ current: this.#shownValue(menu.entry) === null ? null : displaySettingValue(menu.entry, this.#shownValue(menu.entry)),
969
972
  index: menu.index,
970
973
  };
971
974
  const frame = valueMenuFrame(state, {
@@ -983,6 +986,8 @@ export class SettingsApp {
983
986
  #dialogLines(open, width, theme) {
984
987
  if (open.modelDialog)
985
988
  return this.#modelDialogLines(open, width, theme);
989
+ if (open.plusMenu !== null)
990
+ return open.plusMenu.lines(open.record, width, theme);
986
991
  const rows = open.flags.map(key => {
987
992
  const declared = open.entry.flags.find(flag => flag.key === key);
988
993
  return {
@@ -1037,19 +1042,46 @@ export class SettingsApp {
1037
1042
  const open = this.#structured;
1038
1043
  if (open !== null)
1039
1044
  return this.#dialogLines(open, width, theme);
1040
- const notice = this.#notice;
1041
- const plainStatus = notice !== null && notice.length > 0
1042
- ? notice
1043
- : this.#interruptArmed ? "press ctrl+c again to exit a1" : null;
1044
- const status = plainStatus === null
1045
- ? renderShortcutHintsWithClose(SETTINGS_SHORTCUTS.hintEntries(SCOPE), theme, width, width > 0 ? 1 : 0)
1046
- : truncateToWidth(`${width > 0 ? " " : ""}${theme.fg("dim", plainStatus)}`, width);
1047
- const input = this.#filter;
1045
+ // Rationale: standing guidance is more useful than transient feedback; failures still
1046
+ // roll back without displacing the Settings interaction contract.
1047
+ const entries = SETTINGS_SHORTCUTS.hintEntries(SCOPE).filter(entry => !this.#options.pinned
1048
+ || entry.key !== DIALOG_CLOSE_SHORTCUT_HINT.key || entry.action !== DIALOG_CLOSE_SHORTCUT_HINT.action);
1049
+ const status = renderShortcutHintsWithClose(entries, theme, width, width > 0 ? 1 : 0);
1050
+ const input = this.#search.input;
1048
1051
  if (input === null)
1049
1052
  return [status];
1050
- return [...renderInputRow(input, width, { placeholder: SEARCH_PLACEHOLDER, theme }).lines, status];
1053
+ return [...input.render(width), status];
1051
1054
  }
1052
1055
  }
1056
+ function openSettingsSearch(state, host, initial, scroll) {
1057
+ state.scrollBefore = scroll;
1058
+ state.input = state.factory.create({
1059
+ theme: host.theme ?? PLAIN_THEME,
1060
+ getRows: () => host.getSize().height,
1061
+ requestRender: () => host.requestRender(),
1062
+ copyText: state.copyText,
1063
+ });
1064
+ state.input.setFocused(true);
1065
+ state.input.handleInput(initial);
1066
+ }
1067
+ function closeSettingsSearch(state) {
1068
+ state.input?.setFocused(false);
1069
+ state.input = null;
1070
+ const scroll = state.scrollBefore;
1071
+ state.scrollBefore = null;
1072
+ return scroll;
1073
+ }
1074
+ function handleSettingsSearchPointer(state, event, panelTop) {
1075
+ const input = state.input;
1076
+ if (input === null || event.kind === "wheel-up" || event.kind === "wheel-down")
1077
+ return null;
1078
+ const row = event.row - panelTop;
1079
+ const overInput = row >= 1 && row <= SETTINGS_SEARCH_INPUT_ROWS;
1080
+ if (!overInput && !input.ownsPointer())
1081
+ return null;
1082
+ const handled = input.handlePointer({ kind: event.kind, button: event.button, column: event.column, row });
1083
+ return { consumed: handled || overInput, render: handled };
1084
+ }
1053
1085
  function modelLabelParts(label) {
1054
1086
  const match = /^(.*?)(\s+\[[^\]]+\])$/u.exec(label);
1055
1087
  return match === null ? { label } : { label: match[1] ?? label, labelSuffix: match[2] ?? "" };
@@ -1111,8 +1143,11 @@ function labelOf(entry) {
1111
1143
  function rangeOf(entry) {
1112
1144
  return { minimum: entry.minimum, maximum: entry.maximum, values: numericValues(entry.choices) };
1113
1145
  }
1114
- /** Booleans read as yes and no; everything else prints as itself. */
1115
- function displayValue(value) {
1146
+ /** Booleans read as yes and no; time-format choices preview the current local time. */
1147
+ function displaySettingValue(entry, value) {
1148
+ if (entry.backend === "a1" && entry.id === "timeFormat" && (value === "20:00" || value === "8:00 PM")) {
1149
+ return formatLocalTime(new Date(), value) ?? value;
1150
+ }
1116
1151
  if (typeof value === "boolean")
1117
1152
  return value ? "yes" : "no";
1118
1153
  return String(value);
@@ -0,0 +1,29 @@
1
+ import type { UiTheme } from "../../ui/components/index.js";
2
+ export interface SettingsSearchPointerEvent {
3
+ readonly kind: "press" | "motion" | "release";
4
+ readonly button: number;
5
+ readonly column: number;
6
+ /** One-based row relative to the search input's top rule. */
7
+ readonly row: number;
8
+ }
9
+ /** The shared interactive input as consumed by the Settings surface. */
10
+ export interface SettingsSearchInput {
11
+ render(width: number): readonly string[];
12
+ handleInput(data: string): void;
13
+ handlePointer(event: SettingsSearchPointerEvent): boolean;
14
+ getText(): string;
15
+ hasSelection(): boolean;
16
+ ownsPointer(): boolean;
17
+ setFocused(focused: boolean): void;
18
+ }
19
+ export interface SettingsSearchInputOptions {
20
+ readonly theme: UiTheme;
21
+ readonly getRows: () => number;
22
+ readonly requestRender: () => void;
23
+ readonly copyText: (text: string) => void;
24
+ }
25
+ /** Composition supplies the same configurable editor component used by the agent prompt. */
26
+ export interface SettingsSearchInputFactory {
27
+ create(options: SettingsSearchInputOptions): SettingsSearchInput;
28
+ isTextInput(data: string): boolean;
29
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
1
  export { PromptHistoryService } from "./service.js";
2
- export { resolvePromptHistoryPath } from "./paths.js";
2
+ export { resolvePromptHistoryPath, type PromptHistoryScope } from "./paths.js";
3
3
  export { PromptImageSidecar, collectImageChipIdentifiers } from "./image-sidecar.js";
4
4
  export type { PromptImageSidecarRecord, PromptImageSidecarAttachment } from "./image-sidecar.js";
@@ -1,4 +1,5 @@
1
- export declare function resolvePromptHistoryPath(dataDir: string, profileRoot: string, platform?: NodeJS.Platform): {
1
+ export type PromptHistoryScope = "unique" | "shared";
2
+ export declare function resolvePromptHistoryPath(dataDir: string, profileRoot: string, platform?: NodeJS.Platform, scope?: PromptHistoryScope, sessionId?: string): {
2
3
  path: string;
3
4
  profileId: string;
4
5
  imagesDir: string;
@@ -1,7 +1,7 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { posix, win32 } from "node:path";
3
3
  import { PRODUCT_IDENTITY } from "../../product-identity.js";
4
- export function resolvePromptHistoryPath(dataDir, profileRoot, platform = process.platform) {
4
+ export function resolvePromptHistoryPath(dataDir, profileRoot, platform = process.platform, scope = "shared", sessionId) {
5
5
  const paths = platform === "win32" ? win32 : posix;
6
6
  if (!paths.isAbsolute(dataDir) || !paths.isAbsolute(profileRoot) || dataDir.includes("\0") || profileRoot.includes("\0"))
7
7
  throw new TypeError("History requires absolute roots");
@@ -11,7 +11,15 @@ export function resolvePromptHistoryPath(dataDir, profileRoot, platform = proces
11
11
  if (platform === "win32")
12
12
  normalized = normalized.replaceAll("\\", "/").toLowerCase();
13
13
  const digest = createHash("sha256").update(JSON.stringify([1, PRODUCT_IDENTITY.commandName, normalized])).digest("hex");
14
- const profileId = `${PRODUCT_IDENTITY.filesystem.temporaryPrefix}${digest}`;
14
+ if (scope !== "unique" && scope !== "shared")
15
+ throw new TypeError("Invalid history scope");
16
+ if (scope === "unique" && (typeof sessionId !== "string" || sessionId.length === 0 || sessionId.length > 256 || sessionId.includes("\0"))) {
17
+ throw new TypeError("Unique history requires a valid session ID");
18
+ }
19
+ // Compatibility: preserve the former Shared identity; a separate domain prevents
20
+ // collisions with per-session databases and image sidecars.
21
+ const profileId = scope === "shared" ? `${PRODUCT_IDENTITY.filesystem.temporaryPrefix}${digest}`
22
+ : `${PRODUCT_IDENTITY.filesystem.temporaryPrefix}${createHash("sha256").update(JSON.stringify([2, PRODUCT_IDENTITY.commandName, normalized, sessionId])).digest("hex")}`;
15
23
  const historyDir = paths.join(dataDir, "history");
16
24
  return { path: paths.join(historyDir, `${profileId}.sqlite3`), profileId, imagesDir: paths.join(historyDir, `${profileId}-images`) };
17
25
  }
@@ -1,5 +1,6 @@
1
1
  import type { Worker } from "node:worker_threads";
2
2
  import { type PromptHistoryFailure, type PromptHistoryPort, type PromptHistoryResult, type PromptHistorySnapshot, type PromptHistorySubmission } from "../../contracts/owned-ui/index.js";
3
+ import { type PromptHistoryScope } from "./paths.js";
3
4
  export type HistoryRecoveryState = "starting" | "ready" | "recovering" | "blocked-storage" | "closing" | "closed";
4
5
  export interface HistoryClock {
5
6
  now(): number;
@@ -13,6 +14,8 @@ export declare class PromptHistoryService implements PromptHistoryPort {
13
14
  dataDir: string;
14
15
  profileRoot: string;
15
16
  limit: number;
17
+ scope?: PromptHistoryScope;
18
+ sessionId?: string;
16
19
  createWorker?: () => Worker;
17
20
  clock?: HistoryClock;
18
21
  random?: () => number;
@@ -21,6 +24,8 @@ export declare class PromptHistoryService implements PromptHistoryPort {
21
24
  dataDir: string;
22
25
  profileRoot: string;
23
26
  limit: number;
27
+ scope?: PromptHistoryScope;
28
+ sessionId?: string;
24
29
  createWorker?: () => Worker;
25
30
  clock?: HistoryClock;
26
31
  random?: () => number;
@@ -129,7 +129,7 @@ export class PromptHistoryService {
129
129
  const { Worker } = await import("node:worker_threads");
130
130
  if (this.#isClosed() || generation !== this.#generation)
131
131
  return;
132
- const location = resolvePromptHistoryPath(this.options.dataDir, this.options.profileRoot);
132
+ const location = resolvePromptHistoryPath(this.options.dataDir, this.options.profileRoot, process.platform, this.options.scope, this.options.sessionId);
133
133
  const source = import.meta.url.endsWith(".ts");
134
134
  const entry = new URL(source ? "./worker.ts" : "./worker.js", import.meta.url);
135
135
  const options = { workerData: { ...location, limit: this.options.limit }, stdout: true, stderr: true };
@@ -0,0 +1,11 @@
1
+ export declare const AUTO_NAME_MAX_LENGTH = 16;
2
+ export declare const AUTO_NAME_TIMEOUT_MS = 30000;
3
+ export declare const AUTO_NAME_TOKEN_BUDGETS: readonly [4096, 32768];
4
+ export declare function normalizeAutoName(value: string): string | null;
5
+ export declare function fallbackAutoName(prompt: string): string;
6
+ export interface AutoNameCompletion {
7
+ readonly prompt: string;
8
+ readonly maxTokens: number;
9
+ readonly signal: AbortSignal;
10
+ }
11
+ export declare function generateAutoName(firstPrompt: string, complete: (request: AutoNameCompletion) => Promise<string | null>, timeoutMs?: number): Promise<string>;