@timurproko/a1 0.1.8-dev.de7821a → 0.2.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 (916) hide show
  1. package/README.md +104 -65
  2. package/bin/activate.js +8 -0
  3. package/bin/cli.js +37 -11
  4. package/bin/guardian.js +21 -6
  5. package/bin/module-identity.js +76 -69
  6. package/bin/module-resolver.js +138 -0
  7. package/bin/pinned-pi-public.d.ts +3 -0
  8. package/bin/pinned-pi-public.js +93 -0
  9. package/bin/release-cleanup.js +8 -0
  10. package/bin/supervisor.js +2 -2
  11. package/bin/sync-pi-tui-proxy.js +7 -0
  12. package/bin/ui.js +67 -22
  13. package/bin/update-recovery.js +365 -0
  14. package/bin/warmup.js +28 -0
  15. package/dist/app/session-shell/clipboard-diagnostics.d.ts +16 -0
  16. package/dist/app/session-shell/clipboard-diagnostics.js +65 -0
  17. package/dist/app/session-shell/clipboard-image.d.ts +11 -0
  18. package/dist/app/session-shell/clipboard-image.js +38 -0
  19. package/dist/app/session-shell/editor-hyperlink-budget.d.ts +9 -0
  20. package/dist/app/session-shell/editor-hyperlink-budget.js +23 -0
  21. package/dist/app/session-shell/helper-pool.d.ts +33 -0
  22. package/dist/app/session-shell/helper-pool.js +98 -0
  23. package/dist/app/session-shell/image-preparation-client.d.ts +20 -0
  24. package/dist/app/session-shell/image-preparation-client.js +145 -0
  25. package/dist/app/session-shell/image-preparation.d.ts +18 -0
  26. package/dist/app/session-shell/image-preparation.js +126 -0
  27. package/dist/app/session-shell/image-source.d.ts +13 -0
  28. package/dist/app/session-shell/image-source.js +171 -0
  29. package/dist/app/session-shell/image-worker.d.ts +17 -0
  30. package/dist/app/session-shell/image-worker.js +23 -0
  31. package/dist/app/session-shell/index.d.ts +7 -0
  32. package/dist/app/session-shell/index.js +4 -0
  33. package/dist/app/session-shell/paste-executor.d.ts +18 -0
  34. package/dist/app/session-shell/paste-executor.js +253 -0
  35. package/dist/app/session-shell/paste-helper.js +173 -0
  36. package/dist/app/session-shell/paste-preparation-client.d.ts +31 -0
  37. package/dist/app/session-shell/paste-preparation-client.js +170 -0
  38. package/dist/app/session-shell/paste-protocol.d.ts +78 -0
  39. package/dist/app/session-shell/paste-protocol.js +18 -0
  40. package/dist/app/session-shell/paste-text-preparation.d.ts +6 -0
  41. package/dist/app/session-shell/paste-text-preparation.js +134 -0
  42. package/dist/app/session-shell/paste-text-worker.js +12 -0
  43. package/dist/app/session-shell/paste-types.d.ts +17 -0
  44. package/dist/app/session-shell/path-chip-presentation.d.ts +7 -0
  45. package/dist/app/session-shell/path-chip-presentation.js +24 -0
  46. package/dist/app/session-shell/prompt-chips.d.ts +76 -0
  47. package/dist/app/session-shell/prompt-chips.js +499 -0
  48. package/dist/app/session-shell/prompt-history-controller.d.ts +36 -0
  49. package/dist/app/session-shell/prompt-history-controller.js +170 -0
  50. package/dist/app/session-shell/prompt-suggestion-controller.d.ts +37 -0
  51. package/dist/app/session-shell/prompt-suggestion-controller.js +219 -0
  52. package/dist/app/session-shell/quit-outro-effects.d.ts +29 -0
  53. package/dist/app/session-shell/quit-outro-effects.js +242 -0
  54. package/dist/app/session-shell/quit-outro.d.ts +38 -0
  55. package/dist/app/session-shell/quit-outro.js +98 -0
  56. package/dist/app/session-shell/response-copy-coordinator.d.ts +27 -0
  57. package/dist/app/session-shell/response-copy-coordinator.js +187 -0
  58. package/dist/app/session-shell/response-copy-helper.js +122 -0
  59. package/dist/app/session-shell/response-copy-protocol.d.ts +56 -0
  60. package/dist/app/session-shell/response-copy-protocol.js +5 -0
  61. package/dist/app/session-shell/response-copy-transport.d.ts +39 -0
  62. package/dist/app/session-shell/response-copy-transport.js +217 -0
  63. package/dist/app/session-shell/session-shell-root.d.ts +278 -0
  64. package/dist/app/session-shell/session-shell-root.js +1442 -0
  65. package/dist/app/session-shell/session-shell.d.ts +66 -0
  66. package/dist/app/session-shell/session-shell.js +2151 -0
  67. package/dist/app/session-shell/session-viewport-controller.d.ts +62 -0
  68. package/dist/app/session-shell/session-viewport-controller.js +623 -0
  69. package/dist/app/session-shell/stream-presentation-coalescer.d.ts +29 -0
  70. package/dist/app/session-shell/stream-presentation-coalescer.js +79 -0
  71. package/dist/app/session-shell/system-clipboard.d.ts +20 -0
  72. package/dist/app/session-shell/system-clipboard.js +159 -0
  73. package/dist/app/session-shell/text-paste.d.ts +5 -0
  74. package/dist/app/session-shell/text-paste.js +16 -0
  75. package/dist/cli/capabilities.d.ts +6 -0
  76. package/dist/cli/capabilities.js +7 -0
  77. package/dist/cli/dispatch.d.ts +53 -0
  78. package/dist/cli/dispatch.js +287 -0
  79. package/dist/cli/index.d.ts +8 -0
  80. package/dist/cli/index.js +4 -0
  81. package/dist/cli/package-messages.d.ts +27 -0
  82. package/dist/cli/package-messages.js +83 -0
  83. package/dist/cli/packages.d.ts +32 -0
  84. package/dist/cli/packages.js +81 -0
  85. package/dist/cli/session-context.d.ts +9 -0
  86. package/dist/cli/session-context.js +29 -0
  87. package/dist/cli/version-stats.d.ts +22 -0
  88. package/dist/cli/version-stats.js +112 -0
  89. package/dist/composition/index.d.ts +2 -0
  90. package/dist/composition/index.js +2 -0
  91. package/dist/composition/owned-ui.d.ts +37 -0
  92. package/dist/composition/owned-ui.js +159 -0
  93. package/dist/composition/settings-route-host.d.ts +16 -0
  94. package/dist/composition/settings-route-host.js +141 -0
  95. package/dist/contracts/agent-engine/capability-ports.d.ts +95 -0
  96. package/dist/contracts/agent-engine/domain-validation.js +107 -0
  97. package/dist/contracts/agent-engine/domain.d.ts +138 -0
  98. package/dist/contracts/agent-engine/index.d.ts +11 -0
  99. package/dist/contracts/agent-engine/index.js +6 -0
  100. package/dist/contracts/agent-engine/package-ports.d.ts +60 -0
  101. package/dist/contracts/agent-engine/ports.js +1 -0
  102. package/dist/contracts/owned-ui/extension-ui.d.ts +310 -0
  103. package/dist/contracts/owned-ui/image-attachments.d.ts +36 -0
  104. package/dist/contracts/owned-ui/image-attachments.js +67 -0
  105. package/dist/contracts/owned-ui/index.d.ts +14 -0
  106. package/dist/contracts/owned-ui/index.js +9 -0
  107. package/dist/contracts/owned-ui/model.d.ts +383 -0
  108. package/dist/contracts/owned-ui/prompt-chips.d.ts +15 -0
  109. package/dist/contracts/owned-ui/prompt-chips.js +59 -0
  110. package/dist/contracts/owned-ui/prompt-history.d.ts +55 -0
  111. package/dist/contracts/owned-ui/prompt-history.js +23 -0
  112. package/dist/contracts/owned-ui/prompt-suggestions.d.ts +3 -0
  113. package/dist/contracts/owned-ui/prompt-suggestions.js +44 -0
  114. package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +22 -0
  115. package/dist/contracts/owned-ui/suggestion-diagnostics.js +9 -0
  116. package/dist/contracts/owned-ui/transcript-lifecycle.d.ts +5 -0
  117. package/dist/contracts/owned-ui/transcript-lifecycle.js +33 -0
  118. package/dist/contracts/owned-ui/validation.d.ts +15 -0
  119. package/dist/contracts/owned-ui/validation.js +554 -0
  120. package/dist/contracts/presentation/index.d.ts +117 -0
  121. package/dist/contracts/presentation/index.js +68 -0
  122. package/dist/features/launch/development-launch.js +36 -0
  123. package/dist/features/launch/index.d.ts +14 -0
  124. package/dist/features/launch/index.js +7 -0
  125. package/dist/features/launch/intent.d.ts +12 -0
  126. package/dist/features/launch/intent.js +8 -0
  127. package/dist/features/launch/prepare-launch.d.ts +11 -0
  128. package/dist/features/launch/prepare-launch.js +14 -0
  129. package/dist/features/launch/profile-paths.d.ts +16 -0
  130. package/dist/features/launch/profile-paths.js +36 -0
  131. package/dist/features/launch/runtime-selection.d.ts +16 -0
  132. package/dist/features/launch/runtime-selection.js +13 -0
  133. package/dist/features/launch/session-context.d.ts +8 -0
  134. package/dist/features/launch/session-context.js +8 -0
  135. package/dist/features/owned-ui/index.d.ts +9 -0
  136. package/dist/features/owned-ui/index.js +6 -0
  137. package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
  138. package/dist/features/owned-ui/project-trust-prompt.js +149 -0
  139. package/dist/features/owned-ui/reference-routes.d.ts +6 -0
  140. package/dist/features/owned-ui/reference-routes.js +6 -0
  141. package/dist/features/owned-ui/reference-screen-app.d.ts +43 -0
  142. package/dist/features/owned-ui/reference-screen-app.js +279 -0
  143. package/dist/features/owned-ui/run.d.ts +17 -0
  144. package/dist/features/owned-ui/run.js +64 -0
  145. package/dist/features/owned-ui/session-fork-prompt.d.ts +8 -0
  146. package/dist/features/owned-ui/session-fork-prompt.js +34 -0
  147. package/dist/features/owned-ui/settings-app.d.ts +21 -0
  148. package/dist/features/owned-ui/settings-app.js +851 -0
  149. package/dist/features/owned-ui/settings-route.d.ts +2 -0
  150. package/dist/features/owned-ui/settings-route.js +2 -0
  151. package/dist/features/prompt-history/image-sidecar.d.ts +32 -0
  152. package/dist/features/prompt-history/image-sidecar.js +130 -0
  153. package/dist/features/prompt-history/index.d.ts +4 -0
  154. package/dist/features/prompt-history/index.js +3 -0
  155. package/dist/features/prompt-history/paths.d.ts +5 -0
  156. package/dist/features/prompt-history/paths.js +17 -0
  157. package/dist/features/prompt-history/service.d.ts +54 -0
  158. package/dist/features/prompt-history/service.js +425 -0
  159. package/dist/features/prompt-history/store.d.ts +16 -0
  160. package/dist/features/prompt-history/store.js +219 -0
  161. package/dist/features/prompt-history/worker.d.ts +9 -0
  162. package/dist/features/prompt-history/worker.js +45 -0
  163. package/dist/features/prompt-suggestions/diagnostics.d.ts +18 -0
  164. package/dist/features/prompt-suggestions/diagnostics.js +82 -0
  165. package/dist/features/prompt-suggestions/index.d.ts +2 -0
  166. package/dist/features/prompt-suggestions/index.js +1 -0
  167. package/dist/foundation/launch-context/index.d.ts +59 -0
  168. package/dist/foundation/launch-context/index.js +136 -0
  169. package/dist/foundation/launch-guardian/index.d.ts +2 -0
  170. package/dist/foundation/launch-guardian/index.js +1 -0
  171. package/dist/foundation/launch-guardian/main.d.ts +33 -0
  172. package/dist/foundation/launch-guardian/main.js +179 -0
  173. package/dist/foundation/lifecycle/commands.js +1 -0
  174. package/dist/foundation/lifecycle/index.d.ts +13 -0
  175. package/dist/foundation/lifecycle/index.js +6 -0
  176. package/dist/foundation/lifecycle/model.d.ts +64 -0
  177. package/dist/foundation/lifecycle/model.js +40 -0
  178. package/dist/foundation/lifecycle/paths.d.ts +30 -0
  179. package/dist/foundation/lifecycle/paths.js +70 -0
  180. package/dist/foundation/lifecycle/session-repository-context.d.ts +18 -0
  181. package/dist/foundation/lifecycle/session-repository-context.js +173 -0
  182. package/dist/foundation/lifecycle/session-selection.d.ts +9 -0
  183. package/dist/foundation/lifecycle/session-selection.js +39 -0
  184. package/dist/foundation/lifecycle/supervisor-startup.d.ts +30 -0
  185. package/dist/foundation/lifecycle/supervisor-startup.js +106 -0
  186. package/dist/foundation/process-containment/darwin-process-inspector.d.ts +5 -0
  187. package/dist/foundation/process-containment/darwin-process-inspector.js +7 -0
  188. package/dist/foundation/process-containment/index.d.ts +8 -0
  189. package/dist/foundation/process-containment/index.js +6 -0
  190. package/dist/foundation/process-containment/linux-process-inspector.d.ts +7 -0
  191. package/dist/foundation/process-containment/linux-process-inspector.js +27 -0
  192. package/dist/foundation/process-containment/native-guardian-containment.d.ts +17 -0
  193. package/dist/foundation/process-containment/native-guardian-containment.js +140 -0
  194. package/dist/foundation/process-containment/windows-process-inspector.d.ts +19 -0
  195. package/dist/foundation/process-containment/windows-process-inspector.js +56 -0
  196. package/dist/foundation/protocol/client.d.ts +18 -0
  197. package/dist/foundation/protocol/client.js +130 -0
  198. package/dist/foundation/protocol/index.d.ts +3 -0
  199. package/dist/foundation/protocol/index.js +2 -0
  200. package/dist/foundation/protocol/messages.d.ts +90 -0
  201. package/dist/foundation/protocol/messages.js +100 -0
  202. package/dist/foundation/release/bootstrap.d.ts +51 -0
  203. package/dist/foundation/release/bootstrap.js +470 -0
  204. package/dist/foundation/release/cohort-state.d.ts +159 -0
  205. package/dist/foundation/release/cohort-state.js +507 -0
  206. package/dist/foundation/release/dependency-certification-retention.d.ts +7 -0
  207. package/dist/foundation/release/dependency-certification-retention.js +88 -0
  208. package/dist/foundation/release/dependency-certification.d.ts +24 -0
  209. package/dist/foundation/release/dependency-certification.js +266 -0
  210. package/dist/foundation/release/dependency-layer.d.ts +78 -0
  211. package/dist/foundation/release/dependency-layer.js +466 -0
  212. package/dist/foundation/release/endpoints.d.ts +24 -0
  213. package/dist/foundation/release/endpoints.js +134 -0
  214. package/dist/foundation/release/immutable-platform.d.ts +6 -0
  215. package/dist/foundation/release/immutable-platform.js +13 -0
  216. package/dist/foundation/release/index.d.ts +33 -0
  217. package/dist/foundation/release/index.js +18 -0
  218. package/dist/foundation/release/ordinary-launch-selection.d.ts +14 -0
  219. package/dist/foundation/release/ordinary-launch-selection.js +15 -0
  220. package/dist/foundation/release/release-gc.d.ts +71 -0
  221. package/dist/foundation/release/release-gc.js +764 -0
  222. package/dist/foundation/release/release-store.d.ts +49 -0
  223. package/dist/foundation/release/release-store.js +235 -0
  224. package/dist/foundation/release/release.d.ts +43 -0
  225. package/dist/foundation/release/release.js +215 -0
  226. package/dist/foundation/release/restart-certification.d.ts +68 -0
  227. package/dist/foundation/release/restart-certification.js +227 -0
  228. package/dist/foundation/release/types.d.ts +11 -0
  229. package/dist/foundation/release/types.js +1 -0
  230. package/dist/foundation/release/update-activation.d.ts +72 -0
  231. package/dist/foundation/release/update-activation.js +204 -0
  232. package/dist/foundation/release/update-launch.d.ts +6 -0
  233. package/dist/foundation/release/update-launch.js +17 -0
  234. package/dist/foundation/release/update-recovery.d.ts +82 -0
  235. package/dist/foundation/release/update-recovery.js +386 -0
  236. package/dist/foundation/release/update-transaction.d.ts +42 -0
  237. package/dist/foundation/release/update-transaction.js +101 -0
  238. package/dist/foundation/release/update.d.ts +142 -0
  239. package/dist/foundation/release/update.js +773 -0
  240. package/dist/foundation/release/warmup.d.ts +3 -0
  241. package/dist/foundation/release/warmup.js +47 -0
  242. package/dist/foundation/startup/index.d.ts +4 -0
  243. package/dist/foundation/startup/index.js +2 -0
  244. package/dist/foundation/startup/startup-budget.d.ts +46 -0
  245. package/dist/foundation/startup/startup-budget.js +42 -0
  246. package/dist/foundation/startup/startup-descriptor.js +34 -0
  247. package/dist/foundation/startup/startup-runtime.d.ts +27 -0
  248. package/dist/foundation/startup/startup-runtime.js +128 -0
  249. package/dist/foundation/storage/control-store.d.ts +18 -0
  250. package/dist/foundation/storage/control-store.js +342 -0
  251. package/dist/foundation/storage/index.d.ts +1 -0
  252. package/dist/foundation/storage/index.js +1 -0
  253. package/dist/foundation/supervision/index.d.ts +3 -0
  254. package/dist/foundation/supervision/index.js +3 -0
  255. package/dist/foundation/supervision/main.d.ts +1 -0
  256. package/dist/foundation/supervision/main.js +84 -0
  257. package/dist/foundation/supervision/paths.d.ts +1 -0
  258. package/dist/foundation/supervision/paths.js +1 -0
  259. package/dist/foundation/supervision/server.d.ts +46 -0
  260. package/dist/foundation/supervision/server.js +584 -0
  261. package/dist/foundation/terminal-cleanup/fatal-exit.d.ts +12 -0
  262. package/dist/foundation/terminal-cleanup/fatal-exit.js +87 -0
  263. package/dist/foundation/terminal-cleanup/index.d.ts +3 -0
  264. package/dist/foundation/terminal-cleanup/index.js +2 -0
  265. package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +4 -0
  266. package/dist/foundation/terminal-cleanup/terminal-reset.js +40 -0
  267. package/dist/integrations/pi/components/components.d.ts +4 -0
  268. package/dist/integrations/pi/components/components.js +64 -0
  269. package/dist/integrations/pi/components/conformance.d.ts +18 -0
  270. package/dist/integrations/pi/components/conformance.js +70 -0
  271. package/dist/integrations/pi/components/editor-interaction.d.ts +38 -0
  272. package/dist/integrations/pi/components/editor-interaction.js +1 -0
  273. package/dist/integrations/pi/components/history-editor-loader.d.ts +5 -0
  274. package/dist/integrations/pi/components/history-editor-loader.js +5 -0
  275. package/dist/integrations/pi/components/index.d.ts +26 -0
  276. package/dist/integrations/pi/components/index.js +16 -0
  277. package/dist/integrations/pi/components/modal-frame.d.ts +41 -0
  278. package/dist/integrations/pi/components/modal-frame.js +110 -0
  279. package/dist/integrations/pi/components/models-dialog.d.ts +55 -0
  280. package/dist/integrations/pi/components/models-dialog.js +403 -0
  281. package/dist/integrations/pi/components/owned-editor-ux.d.ts +74 -0
  282. package/dist/integrations/pi/components/owned-editor-ux.js +1094 -0
  283. package/dist/integrations/pi/components/path-word-ranges.d.ts +2 -0
  284. package/dist/integrations/pi/components/path-word-ranges.js +37 -0
  285. package/dist/integrations/pi/components/prompt-input-port.d.ts +18 -0
  286. package/dist/integrations/pi/components/prompt-input-port.js +1 -0
  287. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +167 -0
  288. package/dist/integrations/pi/components/resources/builtin-themes.js +168 -0
  289. package/dist/integrations/pi/components/shell-components.d.ts +7 -0
  290. package/dist/integrations/pi/components/shell-components.js +7 -0
  291. package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +23 -0
  292. package/dist/integrations/pi/components/shell-editor-autocomplete.js +357 -0
  293. package/dist/integrations/pi/components/shell-extension-ui.d.ts +35 -0
  294. package/dist/integrations/pi/components/shell-extension-ui.js +282 -0
  295. package/dist/integrations/pi/components/shell-footer-status.d.ts +8 -0
  296. package/dist/integrations/pi/components/shell-footer-status.js +287 -0
  297. package/dist/integrations/pi/components/shell-hotkey-sections.d.ts +7 -0
  298. package/dist/integrations/pi/components/shell-hotkey-sections.js +29 -0
  299. package/dist/integrations/pi/components/shell-presenters-info.d.ts +73 -0
  300. package/dist/integrations/pi/components/shell-presenters-info.js +188 -0
  301. package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +29 -0
  302. package/dist/integrations/pi/components/shell-presenters-transcript.js +435 -0
  303. package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +134 -0
  304. package/dist/integrations/pi/components/shell-selectors-dialogs.js +286 -0
  305. package/dist/integrations/pi/components/shell-shared-facade.d.ts +233 -0
  306. package/dist/integrations/pi/components/shell-shared-facade.js +92 -0
  307. package/dist/integrations/pi/components/skills-command.d.ts +49 -0
  308. package/dist/integrations/pi/components/skills-command.js +119 -0
  309. package/dist/integrations/pi/components/skills-dialog.d.ts +9 -0
  310. package/dist/integrations/pi/components/skills-dialog.js +128 -0
  311. package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +17 -0
  312. package/dist/integrations/pi/components/submitted-prompt-adapter.js +52 -0
  313. package/dist/integrations/pi/components/theme.d.ts +5 -0
  314. package/dist/integrations/pi/components/theme.js +11 -0
  315. package/dist/integrations/pi/components/thinking-selector-dialog.d.ts +8 -0
  316. package/dist/integrations/pi/components/thinking-selector-dialog.js +22 -0
  317. package/dist/integrations/pi/components/tool-image-presentation.d.ts +21 -0
  318. package/dist/integrations/pi/components/tool-image-presentation.js +83 -0
  319. package/dist/integrations/pi/components/tool-result-adapter.d.ts +6 -0
  320. package/dist/integrations/pi/components/tool-result-adapter.js +27 -0
  321. package/dist/integrations/pi/components/transcript-image-resolver.d.ts +7 -0
  322. package/dist/integrations/pi/components/transcript-image-resolver.js +19 -0
  323. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +445 -0
  324. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +371 -0
  325. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +12 -0
  326. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +13 -0
  327. package/dist/integrations/pi/components/upstream/components/daxnuts.d.ts +29 -0
  328. package/dist/integrations/pi/components/upstream/components/daxnuts.js +146 -0
  329. package/dist/integrations/pi/components/upstream/components/earendil-announcement.d.ts +4 -0
  330. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +48 -0
  331. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +22 -0
  332. package/dist/integrations/pi/components/upstream/components/extension-editor.js +89 -0
  333. package/dist/integrations/pi/components/upstream/components/extension-input.d.ts +17 -0
  334. package/dist/integrations/pi/components/upstream/components/extension-input.js +73 -0
  335. package/dist/integrations/pi/components/upstream/components/extension-selector.d.ts +15 -0
  336. package/dist/integrations/pi/components/upstream/components/extension-selector.js +93 -0
  337. package/dist/integrations/pi/components/upstream/components/mermaid.js +81 -0
  338. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +52 -0
  339. package/dist/integrations/pi/components/upstream/components/owned-editor.js +222 -0
  340. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +60 -0
  341. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +347 -0
  342. package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +12 -0
  343. package/dist/integrations/pi/components/upstream/components/session-footer.js +150 -0
  344. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +161 -0
  345. package/dist/integrations/pi/components/upstream/components/session-selector.d.ts +97 -0
  346. package/dist/integrations/pi/components/upstream/components/session-selector.js +935 -0
  347. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +21 -0
  348. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +54 -0
  349. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +35 -0
  350. package/dist/integrations/pi/components/upstream/components/status-indicator.js +69 -0
  351. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +36 -0
  352. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +153 -0
  353. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +67 -0
  354. package/dist/integrations/pi/components/upstream/components/tool-execution.js +365 -0
  355. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +102 -0
  356. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1294 -0
  357. package/dist/integrations/pi/components/upstream/components/trust-selector.d.ts +33 -0
  358. package/dist/integrations/pi/components/upstream/components/trust-selector.js +87 -0
  359. package/dist/integrations/pi/components/upstream/external-editor.js +43 -0
  360. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +289 -0
  361. package/dist/integrations/pi/components/upstream/history/editor-core.js +2145 -0
  362. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +35 -0
  363. package/dist/integrations/pi/components/upstream/history/kill-ring.js +51 -0
  364. package/dist/integrations/pi/components/upstream/history/printable-key.d.ts +1 -0
  365. package/dist/integrations/pi/components/upstream/history/printable-key.js +43 -0
  366. package/dist/integrations/pi/components/upstream/history/text-helpers.d.ts +17 -0
  367. package/dist/integrations/pi/components/upstream/history/text-helpers.js +34 -0
  368. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +25 -0
  369. package/dist/integrations/pi/components/upstream/history/undo-stack.js +39 -0
  370. package/dist/integrations/pi/components/upstream/history/word-navigation.d.ts +24 -0
  371. package/dist/integrations/pi/components/upstream/history/word-navigation.js +103 -0
  372. package/dist/integrations/pi/components/upstream/model-search.d.ts +18 -0
  373. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +33 -0
  374. package/dist/integrations/pi/components/upstream/theme/theme-controller.js +114 -0
  375. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +61 -0
  376. package/dist/integrations/pi/components/upstream/theme/theme.js +337 -0
  377. package/dist/integrations/pi/engine/adapter.d.ts +140 -0
  378. package/dist/integrations/pi/engine/adapter.js +663 -0
  379. package/dist/integrations/pi/engine/changelog.d.ts +2 -0
  380. package/dist/integrations/pi/engine/changelog.js +63 -0
  381. package/dist/integrations/pi/engine/command-dispatch.d.ts +41 -0
  382. package/dist/integrations/pi/engine/command-dispatch.js +125 -0
  383. package/dist/integrations/pi/engine/compaction-progress.d.ts +24 -0
  384. package/dist/integrations/pi/engine/compaction-progress.js +97 -0
  385. package/dist/integrations/pi/engine/conformance.d.ts +39 -0
  386. package/dist/integrations/pi/engine/conformance.js +140 -0
  387. package/dist/integrations/pi/engine/event-delivery.d.ts +100 -0
  388. package/dist/integrations/pi/engine/event-delivery.js +184 -0
  389. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +35 -0
  390. package/dist/integrations/pi/engine/extension-ui-binding.js +81 -0
  391. package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
  392. package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
  393. package/dist/integrations/pi/engine/index.d.ts +18 -0
  394. package/dist/integrations/pi/engine/index.js +10 -0
  395. package/dist/integrations/pi/engine/message-values.d.ts +29 -0
  396. package/dist/integrations/pi/engine/message-values.js +169 -0
  397. package/dist/integrations/pi/engine/package-integration.d.ts +13 -0
  398. package/dist/integrations/pi/engine/package-integration.js +118 -0
  399. package/dist/integrations/pi/engine/pending-delivery.d.ts +30 -0
  400. package/dist/integrations/pi/engine/pending-delivery.js +156 -0
  401. package/dist/integrations/pi/engine/pi-settings-metadata.json +397 -0
  402. package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
  403. package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
  404. package/dist/integrations/pi/engine/prompt-suggestions.d.ts +30 -0
  405. package/dist/integrations/pi/engine/prompt-suggestions.js +102 -0
  406. package/dist/integrations/pi/engine/provider-authentication.d.ts +34 -0
  407. package/dist/integrations/pi/engine/provider-authentication.js +209 -0
  408. package/dist/integrations/pi/engine/repository-pr.d.ts +8 -0
  409. package/dist/integrations/pi/engine/repository-pr.js +62 -0
  410. package/dist/integrations/pi/engine/resource-catalog.d.ts +50 -0
  411. package/dist/integrations/pi/engine/resource-catalog.js +299 -0
  412. package/dist/integrations/pi/engine/resources/changelog.json +12 -0
  413. package/dist/integrations/pi/engine/runtime-integration.d.ts +53 -0
  414. package/dist/integrations/pi/engine/runtime-integration.js +118 -0
  415. package/dist/integrations/pi/engine/session-events.d.ts +48 -0
  416. package/dist/integrations/pi/engine/session-events.js +223 -0
  417. package/dist/integrations/pi/engine/session-integration.d.ts +67 -0
  418. package/dist/integrations/pi/engine/session-integration.js +195 -0
  419. package/dist/integrations/pi/engine/session-runtime.d.ts +98 -0
  420. package/dist/integrations/pi/engine/session-runtime.js +412 -0
  421. package/dist/integrations/pi/engine/session-selection.d.ts +28 -0
  422. package/dist/integrations/pi/engine/session-selection.js +90 -0
  423. package/dist/integrations/pi/engine/settings-bridge.d.ts +121 -0
  424. package/dist/integrations/pi/engine/settings-bridge.js +516 -0
  425. package/dist/integrations/pi/engine/settings-metadata.d.ts +31 -0
  426. package/dist/integrations/pi/engine/settings-metadata.js +67 -0
  427. package/dist/integrations/pi/engine/settings-port.d.ts +42 -0
  428. package/dist/integrations/pi/engine/settings-port.js +363 -0
  429. package/dist/integrations/pi/engine/tool-rendering.d.ts +13 -0
  430. package/dist/integrations/pi/engine/tool-rendering.js +145 -0
  431. package/dist/integrations/pi/engine/transcript-image-assets.d.ts +11 -0
  432. package/dist/integrations/pi/engine/transcript-image-assets.js +86 -0
  433. package/dist/integrations/pi/engine/transcript-projection.d.ts +39 -0
  434. package/dist/integrations/pi/engine/transcript-projection.js +440 -0
  435. package/dist/integrations/pi/engine/usage-view.d.ts +4 -0
  436. package/dist/integrations/pi/engine/usage-view.js +56 -0
  437. package/dist/integrations/pi/engine/windows-filesystem-hygiene.d.ts +21 -0
  438. package/dist/integrations/pi/engine/windows-filesystem-hygiene.js +55 -0
  439. package/dist/integrations/pi/engine/workflow-contexts.d.ts +66 -0
  440. package/dist/integrations/pi/engine/workflow-contexts.js +360 -0
  441. package/dist/integrations/pi/engine/workflow-runner.d.ts +60 -0
  442. package/dist/integrations/pi/engine/workflow-runner.js +536 -0
  443. package/dist/integrations/pi/engine/workflow-support.d.ts +38 -0
  444. package/dist/integrations/pi/engine/workflow-support.js +386 -0
  445. package/dist/integrations/pi/engine/workflows.d.ts +308 -0
  446. package/dist/integrations/pi/engine/workflows.js +81 -0
  447. package/dist/integrations/pi/startup-public.d.ts +2 -0
  448. package/dist/integrations/pi/startup-public.js +2254 -0
  449. package/dist/integrations/pi/startup-public.manifest.json +12679 -0
  450. package/dist/integrations/pi/tui-runtime/adapter.d.ts +58 -0
  451. package/dist/integrations/pi/tui-runtime/adapter.js +792 -0
  452. package/dist/integrations/pi/tui-runtime/contracts.d.ts +158 -0
  453. package/dist/integrations/pi/tui-runtime/contracts.js +1 -0
  454. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +88 -0
  455. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +439 -0
  456. package/dist/integrations/pi/tui-runtime/index.d.ts +9 -0
  457. package/dist/integrations/pi/tui-runtime/index.js +5 -0
  458. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
  459. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
  460. package/dist/integrations/pi/tui-runtime/mouse-report-input.d.ts +19 -0
  461. package/dist/integrations/pi/tui-runtime/mouse-report-input.js +91 -0
  462. package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +32 -0
  463. package/dist/integrations/pi/tui-runtime/overlay-geometry.js +158 -0
  464. package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +4 -0
  465. package/dist/integrations/pi/tui-runtime/presentation-adapter.js +48 -0
  466. package/dist/native/darwin-arm64/manifest.json +4 -4
  467. package/dist/native/darwin-arm64/process-guardian +0 -0
  468. package/dist/native/linux-x64/manifest.json +3 -3
  469. package/dist/native/linux-x64/process-guardian +0 -0
  470. package/dist/native/win32-x64/manifest.json +3 -3
  471. package/dist/native/win32-x64/process-guardian.exe +0 -0
  472. package/dist/product-identity.d.ts +37 -0
  473. package/dist/product-identity.js +119 -0
  474. package/dist/product-identity.json +87 -0
  475. package/dist/runtime-payload-inventory.json +134179 -0
  476. package/dist/ui/apps/contracts.d.ts +72 -0
  477. package/dist/ui/apps/host.d.ts +42 -0
  478. package/dist/ui/apps/host.js +156 -0
  479. package/dist/ui/apps/index.d.ts +5 -0
  480. package/dist/ui/apps/index.js +3 -0
  481. package/dist/ui/apps/registry.d.ts +12 -0
  482. package/dist/ui/apps/registry.js +33 -0
  483. package/dist/ui/components/dialog-panel.d.ts +37 -0
  484. package/dist/ui/components/dialog-panel.js +58 -0
  485. package/dist/ui/components/frame.d.ts +22 -0
  486. package/dist/ui/components/frame.js +55 -0
  487. package/dist/ui/components/index.d.ts +50 -0
  488. package/dist/ui/components/index.js +26 -0
  489. package/dist/ui/components/line-input.d.ts +68 -0
  490. package/dist/ui/components/line-input.js +224 -0
  491. package/dist/ui/components/list-block.d.ts +70 -0
  492. package/dist/ui/components/list-block.js +189 -0
  493. package/dist/ui/components/list-view.d.ts +60 -0
  494. package/dist/ui/components/list-view.js +84 -0
  495. package/dist/ui/components/mouse.d.ts +25 -0
  496. package/dist/ui/components/mouse.js +72 -0
  497. package/dist/ui/components/progress-status.d.ts +9 -0
  498. package/dist/ui/components/progress-status.js +25 -0
  499. package/dist/ui/components/prompt-input.d.ts +32 -0
  500. package/dist/ui/components/prompt-input.js +51 -0
  501. package/dist/ui/components/scrollbar.d.ts +88 -0
  502. package/dist/ui/components/scrollbar.js +137 -0
  503. package/dist/ui/components/selection-copy.d.ts +24 -0
  504. package/dist/ui/components/selection-copy.js +39 -0
  505. package/dist/ui/components/shortcut-hints.d.ts +7 -0
  506. package/dist/ui/components/shortcut-hints.js +12 -0
  507. package/dist/ui/components/shortcuts.d.ts +60 -0
  508. package/dist/ui/components/shortcuts.js +85 -0
  509. package/dist/ui/components/spans.d.ts +28 -0
  510. package/dist/ui/components/spans.js +266 -0
  511. package/dist/ui/components/submitted-prompt.d.ts +23 -0
  512. package/dist/ui/components/submitted-prompt.js +50 -0
  513. package/dist/ui/components/surface.d.ts +20 -0
  514. package/dist/ui/components/surface.js +44 -0
  515. package/dist/ui/components/text-selection.d.ts +62 -0
  516. package/dist/ui/components/text-selection.js +210 -0
  517. package/dist/ui/components/text.d.ts +38 -0
  518. package/dist/ui/components/text.js +185 -0
  519. package/dist/ui/components/theme.d.ts +19 -0
  520. package/dist/ui/components/theme.js +9 -0
  521. package/dist/ui/components/transcript-viewport.d.ts +187 -0
  522. package/dist/ui/components/transcript-viewport.js +886 -0
  523. package/dist/ui/components/value-menu.d.ts +43 -0
  524. package/dist/ui/components/value-menu.js +41 -0
  525. package/dist/ui/components/visible-hyperlinks.d.ts +26 -0
  526. package/dist/ui/components/visible-hyperlinks.js +97 -0
  527. package/dist/ui/settings/declarations.d.ts +127 -0
  528. package/dist/ui/settings/declarations.js +124 -0
  529. package/dist/ui/settings/index.d.ts +10 -0
  530. package/dist/ui/settings/index.js +5 -0
  531. package/dist/ui/settings/manager.d.ts +54 -0
  532. package/dist/ui/settings/manager.js +256 -0
  533. package/dist/ui/settings/migrations.d.ts +13 -0
  534. package/dist/ui/settings/migrations.js +92 -0
  535. package/dist/ui/settings/sections.d.ts +52 -0
  536. package/dist/ui/settings/sections.js +112 -0
  537. package/docs/architecture/boundaries.md +17 -13
  538. package/docs/architecture/code-documentation.md +77 -0
  539. package/docs/architecture/history-editor-provenance.md +100 -0
  540. package/docs/architecture/internal-naming.md +94 -0
  541. package/docs/architecture/process-guardian-provenance.md +3 -1
  542. package/docs/architecture/project-structure.md +72 -30
  543. package/docs/architecture/prompt-suggestions.md +68 -0
  544. package/docs/architecture/resource-and-data-policy.md +28 -2
  545. package/docs/architecture/response-copy-delivery.md +85 -0
  546. package/docs/architecture/terminal-host-proof-gate.md +1 -1
  547. package/docs/architecture/terminal-host-spike-evidence.md +1 -1
  548. package/docs/architecture/tool-image-presentation.md +62 -0
  549. package/docs/architecture/toolchain.md +34 -10
  550. package/docs/architecture/ui-reference-provenance.md +73 -6
  551. package/docs/ci-release-runbook.md +266 -79
  552. package/docs/features/launch-profiles.md +24 -17
  553. package/docs/features/modal-content-interaction.md +38 -0
  554. package/docs/features/prompt-history.md +149 -0
  555. package/docs/local-worktree-cleanup.md +214 -0
  556. package/docs/manual-code-streaming-cleanup.md +88 -0
  557. package/docs/manual-ghost-link-baseline.md +89 -0
  558. package/docs/manual-launch-instance-acceptance.md +12 -35
  559. package/docs/manual-owned-ui-checkpoint.md +79 -0
  560. package/docs/manual-pi-boundary-candidate.md +4 -5
  561. package/docs/manual-terminal-colour-check.md +4 -3
  562. package/docs/openspec-archive-automation.md +269 -0
  563. package/docs/repository-governance-live-acceptance.md +77 -0
  564. package/docs/validation.md +105 -0
  565. package/package.json +53 -34
  566. package/dist/src/cli/capabilities.d.ts +0 -15
  567. package/dist/src/cli/capabilities.js +0 -7
  568. package/dist/src/cli/dispatch.d.ts +0 -32
  569. package/dist/src/cli/dispatch.js +0 -142
  570. package/dist/src/cli/index.d.ts +0 -5
  571. package/dist/src/cli/index.js +0 -5
  572. package/dist/src/cli/packages.d.ts +0 -23
  573. package/dist/src/cli/packages.js +0 -84
  574. package/dist/src/cli/version-stats.d.ts +0 -16
  575. package/dist/src/cli/version-stats.js +0 -72
  576. package/dist/src/cli/version.d.ts +0 -2
  577. package/dist/src/cli/version.js +0 -23
  578. package/dist/src/composition/index.d.ts +0 -48
  579. package/dist/src/composition/index.js +0 -258
  580. package/dist/src/features/launch/development-launch.js +0 -28
  581. package/dist/src/features/launch/index.d.ts +0 -7
  582. package/dist/src/features/launch/index.js +0 -7
  583. package/dist/src/features/launch/intent.d.ts +0 -7
  584. package/dist/src/features/launch/intent.js +0 -4
  585. package/dist/src/features/launch/prepare-launch.d.ts +0 -13
  586. package/dist/src/features/launch/prepare-launch.js +0 -21
  587. package/dist/src/features/launch/profile-paths.d.ts +0 -15
  588. package/dist/src/features/launch/profile-paths.js +0 -31
  589. package/dist/src/features/launch/profiles.d.ts +0 -12
  590. package/dist/src/features/launch/profiles.js +0 -26
  591. package/dist/src/features/launch/runtime-selection.d.ts +0 -19
  592. package/dist/src/features/launch/runtime-selection.js +0 -13
  593. package/dist/src/features/owned-ui/customization.d.ts +0 -38
  594. package/dist/src/features/owned-ui/customization.js +0 -108
  595. package/dist/src/features/owned-ui/diagnostics.d.ts +0 -33
  596. package/dist/src/features/owned-ui/diagnostics.js +0 -94
  597. package/dist/src/features/owned-ui/index.d.ts +0 -4
  598. package/dist/src/features/owned-ui/index.js +0 -4
  599. package/dist/src/features/owned-ui/run.d.ts +0 -11
  600. package/dist/src/features/owned-ui/run.js +0 -15
  601. package/dist/src/features/owned-ui/settings-app.d.ts +0 -22
  602. package/dist/src/features/owned-ui/settings-app.js +0 -633
  603. package/dist/src/features/workspace/capabilities.d.ts +0 -31
  604. package/dist/src/features/workspace/capabilities.js +0 -75
  605. package/dist/src/features/workspace/index.d.ts +0 -6
  606. package/dist/src/features/workspace/index.js +0 -6
  607. package/dist/src/features/workspace/presentation.d.ts +0 -30
  608. package/dist/src/features/workspace/presentation.js +0 -70
  609. package/dist/src/features/workspace/reconciliation.d.ts +0 -15
  610. package/dist/src/features/workspace/reconciliation.js +0 -82
  611. package/dist/src/features/workspace/reducer.d.ts +0 -42
  612. package/dist/src/features/workspace/reducer.js +0 -213
  613. package/dist/src/features/workspace/router.d.ts +0 -31
  614. package/dist/src/features/workspace/router.js +0 -124
  615. package/dist/src/features/workspace/store.d.ts +0 -17
  616. package/dist/src/features/workspace/store.js +0 -54
  617. package/dist/src/foundation/agent-engine-contracts/capability-ports.d.ts +0 -95
  618. package/dist/src/foundation/agent-engine-contracts/domain-validation.js +0 -89
  619. package/dist/src/foundation/agent-engine-contracts/domain.d.ts +0 -116
  620. package/dist/src/foundation/agent-engine-contracts/index.d.ts +0 -8
  621. package/dist/src/foundation/agent-engine-contracts/index.js +0 -8
  622. package/dist/src/foundation/agent-engine-contracts/package-ports.d.ts +0 -54
  623. package/dist/src/foundation/launch-guardian/index.d.ts +0 -1
  624. package/dist/src/foundation/launch-guardian/index.js +0 -1
  625. package/dist/src/foundation/launch-guardian/main.d.ts +0 -31
  626. package/dist/src/foundation/launch-guardian/main.js +0 -165
  627. package/dist/src/foundation/lifecycle/index.d.ts +0 -4
  628. package/dist/src/foundation/lifecycle/index.js +0 -4
  629. package/dist/src/foundation/lifecycle/model.d.ts +0 -64
  630. package/dist/src/foundation/lifecycle/model.js +0 -40
  631. package/dist/src/foundation/lifecycle/paths.d.ts +0 -10
  632. package/dist/src/foundation/lifecycle/paths.js +0 -42
  633. package/dist/src/foundation/native-host-protocol/codec.d.ts +0 -11
  634. package/dist/src/foundation/native-host-protocol/codec.js +0 -56
  635. package/dist/src/foundation/native-host-protocol/evidence.d.ts +0 -67
  636. package/dist/src/foundation/native-host-protocol/evidence.js +0 -141
  637. package/dist/src/foundation/native-host-protocol/index.d.ts +0 -4
  638. package/dist/src/foundation/native-host-protocol/index.js +0 -4
  639. package/dist/src/foundation/native-host-protocol/messages.d.ts +0 -56
  640. package/dist/src/foundation/native-host-protocol/messages.js +0 -149
  641. package/dist/src/foundation/native-host-protocol/proof-gate.d.ts +0 -13
  642. package/dist/src/foundation/native-host-protocol/proof-gate.js +0 -33
  643. package/dist/src/foundation/owned-ui-contracts/extension-ui.d.ts +0 -302
  644. package/dist/src/foundation/owned-ui-contracts/index.d.ts +0 -3
  645. package/dist/src/foundation/owned-ui-contracts/index.js +0 -3
  646. package/dist/src/foundation/owned-ui-contracts/model.d.ts +0 -241
  647. package/dist/src/foundation/owned-ui-contracts/validation.d.ts +0 -11
  648. package/dist/src/foundation/owned-ui-contracts/validation.js +0 -395
  649. package/dist/src/foundation/owned-ui-settings/declarations.d.ts +0 -13
  650. package/dist/src/foundation/owned-ui-settings/declarations.js +0 -39
  651. package/dist/src/foundation/owned-ui-settings/index.d.ts +0 -6
  652. package/dist/src/foundation/owned-ui-settings/index.js +0 -6
  653. package/dist/src/foundation/owned-ui-settings/migrations.d.ts +0 -13
  654. package/dist/src/foundation/owned-ui-settings/migrations.js +0 -28
  655. package/dist/src/foundation/owned-ui-settings/sections.d.ts +0 -70
  656. package/dist/src/foundation/owned-ui-settings/sections.js +0 -93
  657. package/dist/src/foundation/owned-ui-settings/session.d.ts +0 -44
  658. package/dist/src/foundation/owned-ui-settings/session.js +0 -145
  659. package/dist/src/foundation/owned-ui-settings/store.d.ts +0 -28
  660. package/dist/src/foundation/owned-ui-settings/store.js +0 -90
  661. package/dist/src/foundation/pi-component-adapter/components.d.ts +0 -4
  662. package/dist/src/foundation/pi-component-adapter/components.js +0 -64
  663. package/dist/src/foundation/pi-component-adapter/conformance.d.ts +0 -17
  664. package/dist/src/foundation/pi-component-adapter/conformance.js +0 -69
  665. package/dist/src/foundation/pi-component-adapter/index.d.ts +0 -13
  666. package/dist/src/foundation/pi-component-adapter/index.js +0 -13
  667. package/dist/src/foundation/pi-component-adapter/resources/builtin-themes.d.ts +0 -165
  668. package/dist/src/foundation/pi-component-adapter/resources/builtin-themes.js +0 -166
  669. package/dist/src/foundation/pi-component-adapter/shell-components.d.ts +0 -6
  670. package/dist/src/foundation/pi-component-adapter/shell-components.js +0 -6
  671. package/dist/src/foundation/pi-component-adapter/shell-editor-autocomplete.d.ts +0 -11
  672. package/dist/src/foundation/pi-component-adapter/shell-editor-autocomplete.js +0 -162
  673. package/dist/src/foundation/pi-component-adapter/shell-extension-ui.d.ts +0 -35
  674. package/dist/src/foundation/pi-component-adapter/shell-extension-ui.js +0 -279
  675. package/dist/src/foundation/pi-component-adapter/shell-footer-status.d.ts +0 -7
  676. package/dist/src/foundation/pi-component-adapter/shell-footer-status.js +0 -189
  677. package/dist/src/foundation/pi-component-adapter/shell-presenters-transcript.d.ts +0 -57
  678. package/dist/src/foundation/pi-component-adapter/shell-presenters-transcript.js +0 -429
  679. package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.d.ts +0 -113
  680. package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.js +0 -235
  681. package/dist/src/foundation/pi-component-adapter/shell-shared-facade.d.ts +0 -116
  682. package/dist/src/foundation/pi-component-adapter/shell-shared-facade.js +0 -87
  683. package/dist/src/foundation/pi-component-adapter/theme.d.ts +0 -1
  684. package/dist/src/foundation/pi-component-adapter/theme.js +0 -1
  685. package/dist/src/foundation/pi-component-adapter/upstream/adjacent/core/keybindings.d.ts +0 -422
  686. package/dist/src/foundation/pi-component-adapter/upstream/adjacent/core/keybindings.js +0 -296
  687. package/dist/src/foundation/pi-component-adapter/upstream/components/countdown-timer.d.ts +0 -10
  688. package/dist/src/foundation/pi-component-adapter/upstream/components/custom-entry.d.ts +0 -17
  689. package/dist/src/foundation/pi-component-adapter/upstream/components/custom-entry.js +0 -51
  690. package/dist/src/foundation/pi-component-adapter/upstream/components/daxnuts.d.ts +0 -22
  691. package/dist/src/foundation/pi-component-adapter/upstream/components/daxnuts.js +0 -142
  692. package/dist/src/foundation/pi-component-adapter/upstream/components/earendil-announcement.d.ts +0 -4
  693. package/dist/src/foundation/pi-component-adapter/upstream/components/earendil-announcement.js +0 -19
  694. package/dist/src/foundation/pi-component-adapter/upstream/components/extension-editor.d.ts +0 -17
  695. package/dist/src/foundation/pi-component-adapter/upstream/components/extension-editor.js +0 -81
  696. package/dist/src/foundation/pi-component-adapter/upstream/components/first-time-setup.d.ts +0 -24
  697. package/dist/src/foundation/pi-component-adapter/upstream/components/first-time-setup.js +0 -105
  698. package/dist/src/foundation/pi-component-adapter/upstream/components/markdown-transform.d.ts +0 -2
  699. package/dist/src/foundation/pi-component-adapter/upstream/components/markdown-transform.js +0 -18
  700. package/dist/src/foundation/pi-component-adapter/upstream/components/mermaid.js +0 -77
  701. package/dist/src/foundation/pi-component-adapter/upstream/components/owned-editor.d.ts +0 -18
  702. package/dist/src/foundation/pi-component-adapter/upstream/components/owned-editor.js +0 -55
  703. package/dist/src/foundation/pi-component-adapter/upstream/components/scoped-models-selector.d.ts +0 -55
  704. package/dist/src/foundation/pi-component-adapter/upstream/components/scoped-models-selector.js +0 -342
  705. package/dist/src/foundation/pi-component-adapter/upstream/components/session-footer.d.ts +0 -10
  706. package/dist/src/foundation/pi-component-adapter/upstream/components/session-footer.js +0 -120
  707. package/dist/src/foundation/pi-component-adapter/upstream/components/session-selector-search.js +0 -159
  708. package/dist/src/foundation/pi-component-adapter/upstream/components/session-selector.d.ts +0 -95
  709. package/dist/src/foundation/pi-component-adapter/upstream/components/session-selector.js +0 -889
  710. package/dist/src/foundation/pi-component-adapter/upstream/components/skill-invocation-message.d.ts +0 -19
  711. package/dist/src/foundation/pi-component-adapter/upstream/components/skill-invocation-message.js +0 -44
  712. package/dist/src/foundation/pi-component-adapter/upstream/components/status-indicator.d.ts +0 -30
  713. package/dist/src/foundation/pi-component-adapter/upstream/components/status-indicator.js +0 -59
  714. package/dist/src/foundation/pi-component-adapter/upstream/components/tree-selector.d.ts +0 -98
  715. package/dist/src/foundation/pi-component-adapter/upstream/components/tree-selector.js +0 -1272
  716. package/dist/src/foundation/pi-component-adapter/upstream/components/trust-selector.d.ts +0 -33
  717. package/dist/src/foundation/pi-component-adapter/upstream/components/trust-selector.js +0 -76
  718. package/dist/src/foundation/pi-component-adapter/upstream/external-editor.js +0 -39
  719. package/dist/src/foundation/pi-component-adapter/upstream/model-search.d.ts +0 -15
  720. package/dist/src/foundation/pi-component-adapter/upstream/theme/theme-controller.d.ts +0 -25
  721. package/dist/src/foundation/pi-component-adapter/upstream/theme/theme-controller.js +0 -117
  722. package/dist/src/foundation/pi-component-adapter/upstream/theme/theme.d.ts +0 -61
  723. package/dist/src/foundation/pi-component-adapter/upstream/theme/theme.js +0 -326
  724. package/dist/src/foundation/pi-engine-adapter/adapter.d.ts +0 -164
  725. package/dist/src/foundation/pi-engine-adapter/adapter.js +0 -2367
  726. package/dist/src/foundation/pi-engine-adapter/conformance.d.ts +0 -37
  727. package/dist/src/foundation/pi-engine-adapter/conformance.js +0 -130
  728. package/dist/src/foundation/pi-engine-adapter/index.d.ts +0 -10
  729. package/dist/src/foundation/pi-engine-adapter/index.js +0 -10
  730. package/dist/src/foundation/pi-engine-adapter/model-auth-integration.d.ts +0 -30
  731. package/dist/src/foundation/pi-engine-adapter/model-auth-integration.js +0 -61
  732. package/dist/src/foundation/pi-engine-adapter/package-integration.d.ts +0 -13
  733. package/dist/src/foundation/pi-engine-adapter/package-integration.js +0 -112
  734. package/dist/src/foundation/pi-engine-adapter/pi-settings-metadata.json +0 -374
  735. package/dist/src/foundation/pi-engine-adapter/resource-extension-integration.d.ts +0 -31
  736. package/dist/src/foundation/pi-engine-adapter/resource-extension-integration.js +0 -80
  737. package/dist/src/foundation/pi-engine-adapter/runtime-integration.d.ts +0 -35
  738. package/dist/src/foundation/pi-engine-adapter/runtime-integration.js +0 -67
  739. package/dist/src/foundation/pi-engine-adapter/session-integration.d.ts +0 -43
  740. package/dist/src/foundation/pi-engine-adapter/session-integration.js +0 -97
  741. package/dist/src/foundation/pi-engine-adapter/settings-integration.d.ts +0 -55
  742. package/dist/src/foundation/pi-engine-adapter/settings-integration.js +0 -233
  743. package/dist/src/foundation/pi-engine-adapter/workflow-controllers.d.ts +0 -20
  744. package/dist/src/foundation/pi-engine-adapter/workflow-controllers.js +0 -48
  745. package/dist/src/foundation/pi-engine-adapter/workflows.d.ts +0 -173
  746. package/dist/src/foundation/pi-engine-adapter/workflows.js +0 -60
  747. package/dist/src/foundation/pi-owned-ui-integration/index.d.ts +0 -2
  748. package/dist/src/foundation/pi-owned-ui-integration/index.js +0 -2
  749. package/dist/src/foundation/pi-owned-ui-integration/route-host.d.ts +0 -29
  750. package/dist/src/foundation/pi-owned-ui-integration/session-shell.d.ts +0 -106
  751. package/dist/src/foundation/pi-owned-ui-integration/session-shell.js +0 -1518
  752. package/dist/src/foundation/pi-tui-runtime-adapter/adapter.d.ts +0 -39
  753. package/dist/src/foundation/pi-tui-runtime-adapter/adapter.js +0 -493
  754. package/dist/src/foundation/pi-tui-runtime-adapter/conformance.d.ts +0 -18
  755. package/dist/src/foundation/pi-tui-runtime-adapter/conformance.js +0 -145
  756. package/dist/src/foundation/pi-tui-runtime-adapter/contracts.d.ts +0 -120
  757. package/dist/src/foundation/pi-tui-runtime-adapter/index.d.ts +0 -4
  758. package/dist/src/foundation/pi-tui-runtime-adapter/index.js +0 -4
  759. package/dist/src/foundation/pi-tui-runtime-adapter/presentation-adapter.d.ts +0 -4
  760. package/dist/src/foundation/pi-tui-runtime-adapter/presentation-adapter.js +0 -48
  761. package/dist/src/foundation/presentation-contracts/index.d.ts +0 -96
  762. package/dist/src/foundation/presentation-contracts/index.js +0 -38
  763. package/dist/src/foundation/process-containment/index.d.ts +0 -5
  764. package/dist/src/foundation/process-containment/index.js +0 -5
  765. package/dist/src/foundation/process-containment/linux-process-inspector.d.ts +0 -6
  766. package/dist/src/foundation/process-containment/linux-process-inspector.js +0 -26
  767. package/dist/src/foundation/process-containment/native-guardian-containment.d.ts +0 -16
  768. package/dist/src/foundation/process-containment/native-guardian-containment.js +0 -139
  769. package/dist/src/foundation/process-containment/windows-process-inspector.d.ts +0 -17
  770. package/dist/src/foundation/process-containment/windows-process-inspector.js +0 -53
  771. package/dist/src/foundation/protocol/client.d.ts +0 -17
  772. package/dist/src/foundation/protocol/client.js +0 -129
  773. package/dist/src/foundation/protocol/index.d.ts +0 -2
  774. package/dist/src/foundation/protocol/index.js +0 -2
  775. package/dist/src/foundation/protocol/messages.d.ts +0 -89
  776. package/dist/src/foundation/protocol/messages.js +0 -99
  777. package/dist/src/foundation/release/bootstrap.d.ts +0 -29
  778. package/dist/src/foundation/release/bootstrap.js +0 -335
  779. package/dist/src/foundation/release/cohort-state.d.ts +0 -70
  780. package/dist/src/foundation/release/cohort-state.js +0 -202
  781. package/dist/src/foundation/release/index.d.ts +0 -10
  782. package/dist/src/foundation/release/index.js +0 -10
  783. package/dist/src/foundation/release/release-gc.d.ts +0 -5
  784. package/dist/src/foundation/release/release-gc.js +0 -16
  785. package/dist/src/foundation/release/release-store.d.ts +0 -43
  786. package/dist/src/foundation/release/release-store.js +0 -175
  787. package/dist/src/foundation/release/release.d.ts +0 -38
  788. package/dist/src/foundation/release/release.js +0 -204
  789. package/dist/src/foundation/release/update-transaction.d.ts +0 -31
  790. package/dist/src/foundation/release/update-transaction.js +0 -89
  791. package/dist/src/foundation/release/update.d.ts +0 -82
  792. package/dist/src/foundation/release/update.js +0 -529
  793. package/dist/src/foundation/storage/control-store.d.ts +0 -61
  794. package/dist/src/foundation/storage/control-store.js +0 -530
  795. package/dist/src/foundation/storage/index.d.ts +0 -1
  796. package/dist/src/foundation/storage/index.js +0 -1
  797. package/dist/src/foundation/structured-agent-runtime/backpressure.d.ts +0 -46
  798. package/dist/src/foundation/structured-agent-runtime/backpressure.js +0 -118
  799. package/dist/src/foundation/structured-agent-runtime/commands.d.ts +0 -52
  800. package/dist/src/foundation/structured-agent-runtime/commands.js +0 -164
  801. package/dist/src/foundation/structured-agent-runtime/handshake.d.ts +0 -41
  802. package/dist/src/foundation/structured-agent-runtime/handshake.js +0 -151
  803. package/dist/src/foundation/structured-agent-runtime/index.d.ts +0 -5
  804. package/dist/src/foundation/structured-agent-runtime/index.js +0 -5
  805. package/dist/src/foundation/structured-agent-runtime/reconnection.d.ts +0 -37
  806. package/dist/src/foundation/structured-agent-runtime/reconnection.js +0 -129
  807. package/dist/src/foundation/structured-agent-runtime/state.d.ts +0 -56
  808. package/dist/src/foundation/structured-agent-runtime/state.js +0 -118
  809. package/dist/src/foundation/supervision/index.d.ts +0 -3
  810. package/dist/src/foundation/supervision/index.js +0 -3
  811. package/dist/src/foundation/supervision/main.d.ts +0 -1
  812. package/dist/src/foundation/supervision/main.js +0 -41
  813. package/dist/src/foundation/supervision/paths.d.ts +0 -1
  814. package/dist/src/foundation/supervision/paths.js +0 -1
  815. package/dist/src/foundation/supervision/server.d.ts +0 -22
  816. package/dist/src/foundation/supervision/server.js +0 -451
  817. package/dist/src/foundation/ui-apps/contracts.d.ts +0 -42
  818. package/dist/src/foundation/ui-apps/host.d.ts +0 -42
  819. package/dist/src/foundation/ui-apps/host.js +0 -152
  820. package/dist/src/foundation/ui-apps/index.d.ts +0 -3
  821. package/dist/src/foundation/ui-apps/index.js +0 -3
  822. package/dist/src/foundation/ui-apps/registry.d.ts +0 -11
  823. package/dist/src/foundation/ui-apps/registry.js +0 -32
  824. package/dist/src/foundation/ui-components/dialog-panel.d.ts +0 -36
  825. package/dist/src/foundation/ui-components/dialog-panel.js +0 -47
  826. package/dist/src/foundation/ui-components/frame.d.ts +0 -21
  827. package/dist/src/foundation/ui-components/frame.js +0 -54
  828. package/dist/src/foundation/ui-components/index.d.ts +0 -18
  829. package/dist/src/foundation/ui-components/index.js +0 -18
  830. package/dist/src/foundation/ui-components/line-input.d.ts +0 -74
  831. package/dist/src/foundation/ui-components/line-input.js +0 -245
  832. package/dist/src/foundation/ui-components/list-block.d.ts +0 -66
  833. package/dist/src/foundation/ui-components/list-block.js +0 -176
  834. package/dist/src/foundation/ui-components/list-view.d.ts +0 -66
  835. package/dist/src/foundation/ui-components/list-view.js +0 -76
  836. package/dist/src/foundation/ui-components/mouse.d.ts +0 -15
  837. package/dist/src/foundation/ui-components/mouse.js +0 -46
  838. package/dist/src/foundation/ui-components/scrollbar.d.ts +0 -62
  839. package/dist/src/foundation/ui-components/scrollbar.js +0 -102
  840. package/dist/src/foundation/ui-components/shortcuts.d.ts +0 -57
  841. package/dist/src/foundation/ui-components/shortcuts.js +0 -81
  842. package/dist/src/foundation/ui-components/spans.d.ts +0 -7
  843. package/dist/src/foundation/ui-components/spans.js +0 -59
  844. package/dist/src/foundation/ui-components/surface.d.ts +0 -20
  845. package/dist/src/foundation/ui-components/surface.js +0 -38
  846. package/dist/src/foundation/ui-components/text.d.ts +0 -24
  847. package/dist/src/foundation/ui-components/text.js +0 -123
  848. package/dist/src/foundation/ui-components/theme.d.ts +0 -23
  849. package/dist/src/foundation/ui-components/theme.js +0 -13
  850. package/dist/src/foundation/ui-components/value-menu.d.ts +0 -41
  851. package/dist/src/foundation/ui-components/value-menu.js +0 -33
  852. package/dist/src/foundation/workspace-contracts/index.d.ts +0 -2
  853. package/dist/src/foundation/workspace-contracts/index.js +0 -2
  854. package/dist/src/foundation/workspace-contracts/model.d.ts +0 -248
  855. package/dist/src/foundation/workspace-contracts/model.js +0 -2
  856. package/dist/src/foundation/workspace-contracts/validation.d.ts +0 -13
  857. package/dist/src/foundation/workspace-contracts/validation.js +0 -335
  858. package/dist/src/product-identity.d.ts +0 -37
  859. package/dist/src/product-identity.js +0 -150
  860. package/dist/src/product-identity.json +0 -99
  861. package/docs/manual-transparent-checkpoint.md +0 -53
  862. /package/dist/{src/foundation/agent-engine-contracts/domain.js → app/session-shell/paste-helper.d.ts} +0 -0
  863. /package/dist/{src/foundation/agent-engine-contracts/ports.js → app/session-shell/paste-text-worker.d.ts} +0 -0
  864. /package/dist/{src/foundation/lifecycle/commands.js → app/session-shell/paste-types.js} +0 -0
  865. /package/dist/{src/foundation/pi-owned-ui-integration/route-host.js → app/session-shell/response-copy-helper.d.ts} +0 -0
  866. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/capability-ports.js +0 -0
  867. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain-validation.d.ts +0 -0
  868. /package/dist/{src/foundation/pi-tui-runtime-adapter/contracts.js → contracts/agent-engine/domain.js} +0 -0
  869. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.d.ts +0 -0
  870. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.js +0 -0
  871. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/package-ports.js +0 -0
  872. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/ports.d.ts +0 -0
  873. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.d.ts +0 -0
  874. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.js +0 -0
  875. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.d.ts +0 -0
  876. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.js +0 -0
  877. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/extension-ui.js +0 -0
  878. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/model.js +0 -0
  879. /package/dist/{src/features → features}/launch/development-launch.d.ts +0 -0
  880. /package/dist/{src/features → features}/launch/initialize-profile.d.ts +0 -0
  881. /package/dist/{src/features → features}/launch/initialize-profile.js +0 -0
  882. /package/dist/{src/foundation → foundation}/lifecycle/commands.d.ts +0 -0
  883. /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.d.ts +0 -0
  884. /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.js +0 -0
  885. /package/dist/{src/foundation → foundation}/process-containment/artifact.d.ts +0 -0
  886. /package/dist/{src/foundation → foundation}/process-containment/artifact.js +0 -0
  887. /package/dist/{src/foundation → foundation}/process-containment/contracts.d.ts +0 -0
  888. /package/dist/{src/foundation → foundation}/process-containment/contracts.js +0 -0
  889. /package/dist/{src/foundation → foundation}/release/cohort-selection.d.ts +0 -0
  890. /package/dist/{src/foundation → foundation}/release/cohort-selection.js +0 -0
  891. /package/dist/{src/foundation → foundation}/release/concurrency.d.ts +0 -0
  892. /package/dist/{src/foundation → foundation}/release/concurrency.js +0 -0
  893. /package/dist/{src/foundation → foundation}/release/process-cleanup.d.ts +0 -0
  894. /package/dist/{src/foundation → foundation}/release/process-cleanup.js +0 -0
  895. /package/dist/{src/foundation → foundation}/release/stable-release.d.ts +0 -0
  896. /package/dist/{src/foundation → foundation}/release/stable-release.js +0 -0
  897. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/countdown-timer.js +0 -0
  898. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/mermaid.d.ts +0 -0
  899. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector-search.d.ts +0 -0
  900. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/external-editor.d.ts +0 -0
  901. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/model-search.js +0 -0
  902. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.d.ts +0 -0
  903. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.js +0 -0
  904. /package/dist/{src/foundation/ui-apps → ui/apps}/contracts.js +0 -0
  905. /package/dist/{src/foundation/ui-components → ui/components}/label.d.ts +0 -0
  906. /package/dist/{src/foundation/ui-components → ui/components}/label.js +0 -0
  907. /package/dist/{src/foundation/ui-components → ui/components}/pane.d.ts +0 -0
  908. /package/dist/{src/foundation/ui-components → ui/components}/pane.js +0 -0
  909. /package/dist/{src/foundation/ui-components → ui/components}/revision.d.ts +0 -0
  910. /package/dist/{src/foundation/ui-components → ui/components}/revision.js +0 -0
  911. /package/dist/{src/foundation/ui-components → ui/components}/status-line.d.ts +0 -0
  912. /package/dist/{src/foundation/ui-components → ui/components}/status-line.js +0 -0
  913. /package/dist/{src/foundation/ui-components → ui/components}/stepper.d.ts +0 -0
  914. /package/dist/{src/foundation/ui-components → ui/components}/stepper.js +0 -0
  915. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.d.ts +0 -0
  916. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.js +0 -0
@@ -0,0 +1,2151 @@
1
+ import { ResponseCopyCoordinator } from "./response-copy-coordinator.js";
2
+ import { createResponseCopyExecutor, hasAsyncClipboardOutput, responseCopyDestination } from "./response-copy-transport.js";
3
+ import { MAX_COPY_CONTROL_BYTES } from "./response-copy-protocol.js";
4
+ import { PromptHistoryController } from "./prompt-history-controller.js";
5
+ import { PRODUCT_TEXT } from "../../product-identity.js";
6
+ import { boundedCleanup } from "../../foundation/terminal-cleanup/terminal-reset.js";
7
+ import { assertOwnedUiCommand } from "../../contracts/owned-ui/index.js";
8
+ import { assertPromptImages, ImageAttachmentError } from "../../contracts/owned-ui/index.js";
9
+ import { ContextualPromptSuggestionController } from "./prompt-suggestion-controller.js";
10
+ import { MOUSE_TRACKING_OFF, MOUSE_TRACKING_ON, parseMouseInput } from "../../ui/components/mouse.js";
11
+ import { readVisibleHyperlinks } from "../../ui/components/visible-hyperlinks.js";
12
+ import { PINNED_PI_HIDDEN_COMMAND_NAMES, workflowCommandNames } from "../../integrations/pi/engine/workflows.js";
13
+ import { createPiExtensionUiBridge } from "../../integrations/pi/components/shell-extension-ui.js";
14
+ import { createPiShellEditor } from "../../integrations/pi/components/shell-editor-autocomplete.js";
15
+ import { SKILLS_COMMAND_NAME, findSkillByArgument, rewriteSkillsTunnelSubmission, skillPrompt, skillsFromCommands, } from "../../integrations/pi/components/skills-command.js";
16
+ import { createPiQueuedInputStatus, createPiShellFooter, createPiShellHeader, createPiShellLoadedResources, createPiShellStatus, } from "../../integrations/pi/components/shell-footer-status.js";
17
+ import { createPiShellArmin, createPiShellAuthProviderSelector, createPiShellDaxnuts, createPiShellDialog, createPiShellEarendilAnnouncement, createPiShellExtensionSelector, createPiShellLoginDialog, createPiShellModelSelector, createPiShellModelsDialog, createPiShellOperationLoader, createPiShellReloadBox, createPiShellScopedModelsSelector, createPiShellSelector, createPiShellSessionSelector, createPiShellSettingsSelector, createPiShellSkillsSelector, createPiShellTreeSelector, createPiShellTrustSelector, createPiShellUserMessageSelector, } from "../../integrations/pi/components/shell-selectors-dialogs.js";
18
+ import { createPiShellChangelog, createPiShellHotkeys, createPiShellSessionInfo, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
19
+ import { createPiShellTranscriptComponent, renderPiShellPackageUpdateNotice, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
20
+ import { onPiThemeChange, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
21
+ import { DamageAwareTerminalAdapter } from "../../integrations/pi/tui-runtime/damage-aware-terminal.js";
22
+ import { PiTuiRuntimeAdapter } from "../../integrations/pi/tui-runtime/adapter.js";
23
+ import { classifyPiTuiInput } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
24
+ import { runImageWorker } from "./image-preparation-client.js";
25
+ import { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer, } from "./stream-presentation-coalescer.js";
26
+ import { writeSystemClipboardText, } from "./system-clipboard.js";
27
+ import { OwnedUiSessionShellRoot, shellResourceEntries, } from "./session-shell-root.js";
28
+ export { OwnedUiSessionShellRoot, } from "./session-shell-root.js";
29
+ /** Coordinates backend, owned presentation, and Pi TUI lifecycles for one interactive session. */
30
+ export class OwnedUiSessionShell {
31
+ backend;
32
+ root;
33
+ runtime;
34
+ #cwd;
35
+ #listeners = new Set();
36
+ #unsubscribe;
37
+ #unsubscribePromptSuggestions;
38
+ #promptSuggestions;
39
+ #skills;
40
+ #unsubscribeSkills;
41
+ #installedCommandSignature = "";
42
+ #promptHistory = null;
43
+ #promptHistoryImageSidecar;
44
+ #extensionBridge;
45
+ #stopped;
46
+ #resolveStopped;
47
+ #dialogId;
48
+ #dialogSource;
49
+ #routeHost;
50
+ #dialogHandle;
51
+ #sequence = 0;
52
+ #editorRevision = 0;
53
+ #started = false;
54
+ #disposed = false;
55
+ #shutdownPromise;
56
+ #disposePromise;
57
+ #pointerReporting = false;
58
+ // Invariant: the startup release-note diagnostic creates at most one dock notice per shell.
59
+ #startupChangelogHandled = false;
60
+ #customViewport;
61
+ #responseCopy;
62
+ // Rationale: only an executor this shell created owns a spare copy helper worth warming and disposing.
63
+ #copyExecutor;
64
+ #copyIntentSequence = 0;
65
+ #unbindClipboardWriter;
66
+ #damageTerminal;
67
+ #quitOutro;
68
+ #reloadPresentation;
69
+ #streamPresentation;
70
+ #removeViewportPreInput;
71
+ #unsubscribeSettings;
72
+ #unbindPiSettings;
73
+ #unbindTerminalSettings;
74
+ #unbindShutdownSettings;
75
+ #terminalProgressEnabled = false;
76
+ #showImages = true;
77
+ #imageWidthCells = 80;
78
+ #fullscreenExitOutput = "transcript";
79
+ #waitingImages = new Map();
80
+ #lastClearTime = 0;
81
+ #lastEscapeTime = 0;
82
+ #activeLoginDialog;
83
+ #sessionGeneration;
84
+ #sessionBindingGeneration;
85
+ #suggestionModelKey;
86
+ constructor(options) {
87
+ const { backend, cwd, routeHost, sessionLayout } = options.engine;
88
+ const { terminal, startup, viewportSettings, quitOutro, reload: reloadPresentation, stream: streamPresentationOptions, input: inputPresentation } = options.presentation ?? {};
89
+ const { clipboard, responseCopy, paste: pasteDiagnostics, pastePreparation } = options.diagnostics ?? {};
90
+ const promptHistory = options.history;
91
+ this.backend = backend;
92
+ this.#sessionGeneration = this.backend.sessionGeneration;
93
+ this.#sessionBindingGeneration = this.backend.sessionBindingGeneration;
94
+ this.#suggestionModelKey = modelKey(this.backend.view());
95
+ this.#cwd = cwd;
96
+ this.#routeHost = routeHost ?? null;
97
+ this.#customViewport = sessionLayout === "custom-viewport";
98
+ this.#stopped = new Promise(resolve => {
99
+ this.#resolveStopped = resolve;
100
+ });
101
+ let runtime;
102
+ let damageTerminal;
103
+ let streamPresentation;
104
+ let pendingClipboardWrite = Promise.resolve();
105
+ let promptSuggestionController = null;
106
+ // Invariant: the collapsed skills presentation is a bare-A1 replacement; comparison profiles keep the pinned list.
107
+ this.#skills = this.#customViewport ? options.skills ?? null : null;
108
+ const terminalCopy = terminal !== undefined || hasAsyncClipboardOutput();
109
+ this.#responseCopy = this.#customViewport ? new ResponseCopyCoordinator({
110
+ execute: responseCopy?.execute ?? (this.#copyExecutor = createResponseCopyExecutor({
111
+ ...(terminal === undefined && clipboard === undefined ? {} : { destination: "terminal" }),
112
+ ...(clipboard?.writeText === undefined ? {} : { writeText: (text, signal) => clipboard.writeText(text, signal) }),
113
+ ...(terminalCopy ? { terminal: { submit: async (control, signal) => {
114
+ if (signal.aborted || this.#disposed || !runtime?.active)
115
+ throw new Error("Copy canceled");
116
+ // Performance: never grow the real terminal's pending buffer with another clipboard payload.
117
+ if (terminal === undefined && process.stdout.writableLength + control.length > MAX_COPY_CONTROL_BYTES) {
118
+ throw new Error("Clipboard terminal is busy");
119
+ }
120
+ runtime.writeControl(control);
121
+ } } } : {}),
122
+ })),
123
+ ...(responseCopy?.onEvent === undefined ? {} : { onEvent: responseCopy.onEvent }),
124
+ onFailure: result => {
125
+ if (this.#disposed || !runtime?.active)
126
+ return;
127
+ this.root.appendWorkflowStatus(result.outcome === "timed-out" ? "Copy timed out; the clipboard did not respond."
128
+ : result.failure === "size" ? "Selection exceeds this clipboard route's size limit."
129
+ : "Could not copy the selection; the clipboard is unavailable.");
130
+ runtime.requestRender();
131
+ },
132
+ }) : null;
133
+ const readClipboard = async (signal) => {
134
+ if (signal.aborted)
135
+ throw new ImageAttachmentError("image-canceled");
136
+ if (clipboard === undefined)
137
+ return runImageWorker({ kind: "clipboard" }, signal);
138
+ try {
139
+ const image = await clipboard.readImage?.(signal);
140
+ if (image !== null && image !== undefined) {
141
+ const canonical = await runImageWorker({ kind: "canonicalize", source: image }, signal);
142
+ if (canonical !== null)
143
+ return { kind: "image", ...canonical };
144
+ }
145
+ }
146
+ catch (error) {
147
+ if (error instanceof ImageAttachmentError)
148
+ throw error;
149
+ // Compatibility: an unavailable image reader can still provide text.
150
+ }
151
+ const text = await clipboard.readText(signal);
152
+ return text === null ? null : { kind: "text", text };
153
+ };
154
+ this.root = new OwnedUiSessionShellRoot(this.backend.view(), cwd, {
155
+ getColumns: () => runtime?.viewport().columns ?? terminal?.columns ?? 80,
156
+ getRows: () => runtime?.viewport().rows ?? terminal?.rows ?? 24,
157
+ requestRender: force => runtime?.requestRender(force),
158
+ requestHyperlinkCleanup: rows => damageTerminal?.requestHyperlinkCleanup(rows),
159
+ onViewportFrame: frame => damageTerminal?.arm(frame.descriptor, {
160
+ overlayActive: runtime?.hasOverlay() ?? false,
161
+ selectionActive: this.root.hasActiveSelection(),
162
+ replacementSurfaceActive: !this.root.usesDefaultInputSurface(),
163
+ }),
164
+ enableDockInputReuse: inputPresentation?.viewportReuse !== false,
165
+ persistentHistory: this.#customViewport && promptHistory !== undefined,
166
+ ...(promptHistory === undefined ? {} : { historyEditor: promptHistory.editor }),
167
+ onSubmit: text => { void this.submit(text).catch(() => this.#reportSubmissionError()); },
168
+ onPasteRejected: error => this.#reportSubmissionError(error),
169
+ onInterrupt: () => { void this.interrupt(); },
170
+ onClear: () => { void this.clearOrExit(); },
171
+ onExit: () => { void this.shutdown(); },
172
+ onModelSelect: () => this.#customViewport ? this.showModelsDialog() : this.showModelSelector(),
173
+ onModelCycle: direction => { void this.cycleModel(direction); },
174
+ onThinkingCycle: () => { void this.cycleThinkingLevel(); },
175
+ onThinkingToggle: () => {
176
+ this.root.toggleThinkingVisibility();
177
+ this.runtime.requestRender();
178
+ },
179
+ onMessageCopy: () => { void this.runWorkflow({ command: "copy", argument: "" }); },
180
+ onFollowUp: () => { void this.queueFollowUp().catch(() => this.#reportSubmissionError()); },
181
+ onDequeue: () => this.restoreQueuedInput(),
182
+ onEditorChange: () => { this.#editorRevision++; promptSuggestionController?.abortPending(); },
183
+ onPromptSuggestionAccepted: () => promptSuggestionController?.accept(),
184
+ onInputSurfaceChanged: () => {
185
+ promptSuggestionController?.invalidate();
186
+ this.#promptHistory?.synchronize();
187
+ },
188
+ onCopyText: text => {
189
+ if (this.#responseCopy !== null) {
190
+ void this.#responseCopy.submitText(text);
191
+ return;
192
+ }
193
+ const write = () => {
194
+ if (this.#disposed)
195
+ return Promise.resolve();
196
+ runtime?.writeControl(`\u001b]52;c;${Buffer.from(text, "utf8").toString("base64")}\u0007`);
197
+ return clipboard === undefined ? writeSystemClipboardText(text)
198
+ : clipboard.writeText?.(text) ?? Promise.resolve();
199
+ };
200
+ // Compatibility: comparison profiles retain their existing clipboard path.
201
+ pendingClipboardWrite = write().catch(() => { });
202
+ },
203
+ readClipboardContent: async (signal = new AbortController().signal) => {
204
+ await pendingClipboardWrite;
205
+ return readClipboard(signal);
206
+ },
207
+ captureClipboardPaste: () => {
208
+ const before = this.#responseCopy?.capturePasteBarrier() ?? (async () => true);
209
+ if (clipboard !== undefined)
210
+ return { kind: "provided", read: readClipboard, before };
211
+ if (responseCopyDestination(process.env) === "terminal")
212
+ return {
213
+ kind: "provided", before, read: async () => { throw new ImageAttachmentError("paste-unavailable"); },
214
+ };
215
+ return { kind: "native", before };
216
+ },
217
+ ...(pasteDiagnostics === undefined ? {} : { pasteDiagnostics: pasteDiagnostics }),
218
+ ...(pastePreparation === undefined ? {} : { pastePreparation }),
219
+ skillsPresentation: () => this.#skills?.presentation() ?? "expand",
220
+ }, {
221
+ ...startup,
222
+ resources: startup?.resources ?? shellResourceEntries(this.backend),
223
+ }, this.backend.agentDir, {
224
+ getMessageRenderer: customType => this.backend.pinnedMessageRenderer(customType),
225
+ getToolDefinition: toolName => this.backend.pinnedToolDefinition(toolName),
226
+ getShortcuts: bindings => this.backend.pinnedShortcutDescriptions(bindings),
227
+ }, sessionLayout, {
228
+ resolve: assetId => this.backend.resolveTranscriptImage(assetId),
229
+ });
230
+ // Invariant: bare A1 owns a bounded viewport and therefore always runs on the alternate
231
+ // fullscreen surface. The pinned comparison profiles still honor Pi's mode.
232
+ const tuiMode = this.#customViewport
233
+ ? "fullscreen"
234
+ : this.backend.disposed ? "regular" : this.backend.pinnedSettingsSnapshot().tuiMode;
235
+ const runtimeOptions = {
236
+ root: this.root,
237
+ mode: tuiMode,
238
+ ...(this.#customViewport ? {
239
+ // Invariant: the owned shell enables and routes mouse reports itself. Pi's
240
+ // enclosing fullscreen renderer must never establish a competing white selection.
241
+ mouse: false,
242
+ consumeUnhandledMouse: true,
243
+ onOverlayGeometry: surfaces => this.root.setViewportOverlaySurfaces(surfaces),
244
+ decorateTerminal: (terminal) => {
245
+ damageTerminal = new DamageAwareTerminalAdapter(terminal, {
246
+ regionalScroll: process.env.TERM !== "dumb",
247
+ inspectHyperlinks: readVisibleHyperlinks,
248
+ onResize: () => streamPresentation?.noteImmediatePresentation(),
249
+ onHyperlinkCleanupRequired: () => runtime?.requestRender(true),
250
+ });
251
+ return damageTerminal;
252
+ },
253
+ ...(inputPresentation?.coordination === false ? {} : {
254
+ inputCoordination: {
255
+ classify: (data, focusedOverlay) => classifyPiTuiInput(data, focusedOverlay ?? this.root.inputCoordinationSurface()),
256
+ onReceipt: () => streamPresentation?.noteImmediatePresentation(),
257
+ ...(inputPresentation?.scheduler === undefined
258
+ ? {}
259
+ : { scheduler: inputPresentation.scheduler }),
260
+ },
261
+ }),
262
+ } : { layoutRoot: this.root.layoutRoot() }),
263
+ ...(inputPresentation?.onEvent === undefined ? {} : {
264
+ inputDiagnostics: {
265
+ onEvent: inputPresentation.onEvent,
266
+ ...(inputPresentation.now === undefined ? {} : { now: inputPresentation.now }),
267
+ },
268
+ }),
269
+ ...(terminal === undefined ? {} : { terminal: terminal }),
270
+ hardwareCursor: this.backend.view().terminal.hardwareCursor,
271
+ };
272
+ runtime = new PiTuiRuntimeAdapter(runtimeOptions);
273
+ this.runtime = runtime;
274
+ this.#damageTerminal = damageTerminal ?? null;
275
+ this.#quitOutro = quitOutro;
276
+ this.#reloadPresentation = reloadPresentation;
277
+ const presentationInterval = streamPresentationOptions?.intervalMs ?? STREAM_PRESENTATION_INTERVAL_MS;
278
+ streamPresentation = streamPresentationOptions?.scheduler === undefined
279
+ ? new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval)
280
+ : new StreamPresentationCoalescer(() => this.runtime.requestRender(), presentationInterval, streamPresentationOptions.scheduler);
281
+ this.#streamPresentation = streamPresentation;
282
+ const promptSuggestionOptions = this.#customViewport ? options.suggestions : undefined;
283
+ promptSuggestionController = promptSuggestionOptions === undefined ? null : new ContextualPromptSuggestionController({
284
+ generator: promptSuggestionOptions.generator,
285
+ enabled: promptSuggestionOptions.enabled(),
286
+ ...(promptSuggestionOptions.diagnostics === undefined ? {} : { diagnostics: promptSuggestionOptions.diagnostics }),
287
+ surface: {
288
+ canPresent: identity => this.#promptSuggestionPresentationBlockReason(identity) === null,
289
+ presentationBlockReason: identity => this.#promptSuggestionPresentationBlockReason(identity),
290
+ present: text => {
291
+ if (!this.root.canPresentPromptSuggestion())
292
+ return false;
293
+ this.root.setPromptSuggestion(text);
294
+ return true;
295
+ },
296
+ clear: () => this.root.setPromptSuggestion(null),
297
+ requestRender: () => this.runtime.requestRender(),
298
+ },
299
+ });
300
+ this.#promptSuggestions = promptSuggestionController;
301
+ this.#unsubscribePromptSuggestions = promptSuggestionOptions === undefined
302
+ ? () => { }
303
+ : promptSuggestionOptions.onChange(enabled => this.#promptSuggestions?.setEnabled(enabled));
304
+ // Rationale: the same listener refreshes the menu for the A1 presentation choice and for the engine's
305
+ // skill-command registration, both of which the owned settings manager reports through one change.
306
+ this.#unsubscribeSkills = this.#skills === null ? () => { } : this.#skills.onChange(() => {
307
+ // Invariant: reinstalling drops extension provider wrappers, so an unrelated setting change leaves the list alone.
308
+ if (this.#disposed || this.#commandListSignature() === this.#installedCommandSignature)
309
+ return;
310
+ this.#installAutocompleteCommands();
311
+ this.runtime.requestRender();
312
+ });
313
+ const initialPiSettings = this.backend.pinnedSettingsSnapshot();
314
+ this.runtime.setHardwareCursor(initialPiSettings.showHardwareCursor);
315
+ this.runtime.setClearOnShrink(initialPiSettings.clearOnShrink);
316
+ this.#terminalProgressEnabled = initialPiSettings.showTerminalProgress;
317
+ this.#fullscreenExitOutput = initialPiSettings.fullscreenExitOutput;
318
+ // Invariant: bare A1 prints only the resume hint at exit, so the pinned exit-output
319
+ // choice is hidden there and cannot be bound; the comparison profile binds and honors it.
320
+ this.#unbindShutdownSettings = this.backend.settingsProductMode === "bare" ? () => { } : this.backend.bindSettingsOwner("shutdown", {
321
+ fullscreenExitOutput: { apply() { } },
322
+ });
323
+ this.#unbindTerminalSettings = this.backend.bindSettingsOwner("terminal", {
324
+ showHardwareCursor: { apply: value => {
325
+ if (typeof value !== "boolean")
326
+ throw new TypeError("Hardware cursor setting is invalid");
327
+ this.runtime.setHardwareCursor(value);
328
+ } },
329
+ clearOnShrink: { apply: value => {
330
+ if (typeof value !== "boolean")
331
+ throw new TypeError("Clear-on-shrink setting is invalid");
332
+ this.runtime.setClearOnShrink(value);
333
+ } },
334
+ showTerminalProgress: { apply: value => {
335
+ if (typeof value !== "boolean")
336
+ throw new TypeError("Terminal progress setting is invalid");
337
+ this.#terminalProgressEnabled = value;
338
+ this.#syncTerminalProgress(this.view());
339
+ } },
340
+ });
341
+ this.#removeViewportPreInput = this.#customViewport
342
+ ? this.runtime.addPreInputListener(data => {
343
+ if (inputPresentation?.coordination === false)
344
+ this.#streamPresentation.noteImmediatePresentation();
345
+ // Compatibility: Pi's fullscreen renderer also intercepts plain Home/End.
346
+ // Deliver them to the focused owned input before that outer scroll handler;
347
+ // overlays retain Pi's normal dispatch, and comparison profiles never enter here.
348
+ if (!this.runtime.hasOverlay() && (this.root.editor.matchesTerminalKey(data, "home")
349
+ || this.root.editor.matchesTerminalKey(data, "end"))) {
350
+ if (this.root.usesDefaultInputSurface())
351
+ this.root.handleViewportPreInput(data, true);
352
+ this.root.handleInput(data);
353
+ this.runtime.requestRender();
354
+ return { consume: true };
355
+ }
356
+ // Invariant: geometry must belong to the painted frame, including newly opened/nested
357
+ // surfaces. Steady pointer input does not trigger a synchronous composition.
358
+ const viewport = this.runtime.viewport();
359
+ if (data.includes("\u001b[<") && !this.root.viewportInputGeometryReady(viewport.columns, viewport.rows)) {
360
+ this.runtime.renderNow();
361
+ }
362
+ const routed = this.root.handleViewportPreInput(data, true, Date.now(), this.root.usesDefaultInputSurface() && !this.runtime.hasFocusedOverlay());
363
+ if (routed.copySelection !== undefined) {
364
+ const snapshot = routed.copySelection;
365
+ const acknowledgement = copyAcknowledgement(snapshot);
366
+ const intent = ++this.#copyIntentSequence;
367
+ void this.#responseCopy?.submit(snapshot, pendingClipboardWrite).then(result => {
368
+ if (this.#disposed || !runtime.active || intent !== this.#copyIntentSequence
369
+ || result.outcome !== "delivered" && result.outcome !== "submitted-unverified")
370
+ return;
371
+ if (acknowledgement.hasNonWhitespace) {
372
+ this.root.showCopyAcknowledgement(`copied ${acknowledgement.characters} chars to clipboard`);
373
+ }
374
+ });
375
+ }
376
+ if (!routed.consumed)
377
+ return routed.data === data ? undefined : { data: routed.data };
378
+ return routed.data.length === 0 ? { consume: true } : { data: routed.data };
379
+ })
380
+ : () => { };
381
+ const applyViewportSettings = () => {
382
+ const snapshot = viewportSettings?.snapshot();
383
+ this.root.setViewportConfig(snapshot ?? {
384
+ scrollbarAppearance: "auto",
385
+ scrollbarStyle: "thin",
386
+ scrollbarSpeed: "normal",
387
+ });
388
+ };
389
+ applyViewportSettings();
390
+ this.#unsubscribeSettings = this.#customViewport && viewportSettings
391
+ ? viewportSettings.onChange(settings => this.root.setViewportConfig(settings))
392
+ : () => { };
393
+ this.root.setEditorPaddingX(initialPiSettings.editorPaddingX);
394
+ this.root.setAutocompleteMaxVisible(initialPiSettings.autocompleteMaxVisible);
395
+ this.root.setOutputPad(initialPiSettings.outputPad);
396
+ this.root.setFullscreenCopyOnSelect(initialPiSettings.fullscreenCopyOnSelect);
397
+ this.root.setHideThinkingBlock(initialPiSettings.hideThinkingBlock);
398
+ this.root.setMermaidRenderingMode(initialPiSettings.mermaidRenderingMode);
399
+ this.#showImages = initialPiSettings.showImages;
400
+ this.#imageWidthCells = initialPiSettings.imageWidthCells;
401
+ this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
402
+ this.#unbindPiSettings = this.backend.bindSettingsOwner("shell", {
403
+ editorPaddingX: { apply: value => {
404
+ if (typeof value !== "number")
405
+ throw new TypeError("Editor padding is invalid");
406
+ this.root.setEditorPaddingX(value);
407
+ } },
408
+ autocompleteMaxVisible: { apply: value => {
409
+ if (typeof value !== "number")
410
+ throw new TypeError("Autocomplete maximum is invalid");
411
+ this.root.setAutocompleteMaxVisible(value);
412
+ } },
413
+ outputPad: { apply: value => {
414
+ if (value !== 0 && value !== 1)
415
+ throw new TypeError("Output padding is invalid");
416
+ this.root.setOutputPad(value);
417
+ } },
418
+ hideThinkingBlock: { apply: value => {
419
+ if (typeof value !== "boolean")
420
+ throw new TypeError("Thinking-block visibility is invalid");
421
+ this.root.setHideThinkingBlock(value);
422
+ } },
423
+ mermaidRenderingMode: { apply: value => {
424
+ if (value !== "off" && value !== "final" && value !== "streaming")
425
+ throw new TypeError("Mermaid mode is invalid");
426
+ this.root.setMermaidRenderingMode(value);
427
+ } },
428
+ showImages: { apply: value => {
429
+ if (typeof value !== "boolean")
430
+ throw new TypeError("Image visibility is invalid");
431
+ this.#showImages = value;
432
+ this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
433
+ } },
434
+ imageWidthCells: { apply: value => {
435
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
436
+ throw new TypeError("Image width is invalid");
437
+ this.#imageWidthCells = value;
438
+ this.root.setImagePresentation(this.#showImages, this.#imageWidthCells);
439
+ } },
440
+ ...(this.#customViewport ? { fullscreenCopyOnSelect: { apply: (value) => {
441
+ if (typeof value !== "boolean")
442
+ throw new TypeError("Fullscreen copy-on-select setting is invalid");
443
+ this.root.setFullscreenCopyOnSelect(value);
444
+ } } } : {}),
445
+ });
446
+ if (this.#customViewport && promptHistory !== undefined) {
447
+ this.#promptHistoryImageSidecar = promptHistory.imageSidecar;
448
+ const sidecar = this.#promptHistoryImageSidecar;
449
+ this.#promptHistory = new PromptHistoryController({
450
+ editor: this.root.editor,
451
+ store: promptHistory.store,
452
+ limit: promptHistory.limit,
453
+ fallback: this.view().transcript.flatMap(block => block.kind === "user" ? [block.text] : []),
454
+ active: () => this.root.usesDefaultInputSurface(),
455
+ render: () => this.runtime.requestRender(),
456
+ rehydrate: value => this.root.rehydrateHistoryText(value, id => sidecar?.readAttachment(id) ?? null),
457
+ });
458
+ }
459
+ this.#extensionBridge = createPiExtensionUiBridge({
460
+ runtime: {
461
+ getColumns: () => this.runtime.viewport().columns,
462
+ getRows: () => this.runtime.viewport().rows,
463
+ requestRender: () => this.runtime.requestRender(),
464
+ },
465
+ agentDir: this.backend.agentDir,
466
+ setInputSurface: component => this.root.setInputSurface(component, true, "opaque"),
467
+ showOverlay: (component, overlayOptions) => this.runtime.showOverlay(component, overlayOptions),
468
+ listenInput: handler => this.runtime.addInputListener(handler),
469
+ replaceWidget: (key, component, placement) => this.root.setExtensionWidget(key, component, placement),
470
+ replaceHeader: component => this.root.setExtensionHeader(component),
471
+ replaceFooter: component => this.root.setExtensionFooter(component),
472
+ setStatus: (key, text) => this.root.setExtensionStatus(key, text),
473
+ setWorking: (message, visible) => this.root.setExtensionWorking(message, visible),
474
+ notify: (message, type) => this.root.addExtensionNotification(message, type),
475
+ setTitle: title => this.runtime.setTitle(title),
476
+ getEditorText: () => this.root.editor.getText(),
477
+ setEditorText: text => this.root.editor.setText(text),
478
+ pasteToEditor: text => this.root.editor.insertText(text),
479
+ addAutocompleteProvider: factory => this.root.editor.addAutocompleteProvider(factory),
480
+ setCustomEditor: component => this.root.setInputSurface(component, true, "opaque"),
481
+ getFooterData: () => this.root.extensionFooterData(),
482
+ getToolsExpanded: () => this.root.toolsExpanded,
483
+ setToolsExpanded: expanded => this.root.setToolsExpanded(expanded),
484
+ });
485
+ this.backend.setWorkflowInteractionHost({
486
+ startLogin: request => this.#startWorkflowLogin(request),
487
+ prompt: request => this.#requestWorkflowInput(request),
488
+ notify: event => this.#notifyWorkflowLogin(event),
489
+ publish: message => {
490
+ this.root.appendWorkflowMessage(message);
491
+ this.runtime.requestRender();
492
+ },
493
+ finishLogin: () => this.#finishWorkflowLogin(),
494
+ });
495
+ this.#installAutocompleteCommands();
496
+ this.#unsubscribe = this.backend.onEvent(event => {
497
+ // Performance: a streamed chunk names one block, and touching only that block is what keeps the
498
+ // cost of a chunk the same in a long session as in a new one. Everything else
499
+ // resynchronizes the view, which is cheap next to re-reading the transcript.
500
+ if (event.type === "agent-run-started") {
501
+ this.#promptSuggestions?.invalidate();
502
+ this.root.resumeViewportFollowing();
503
+ }
504
+ if (event.type === "assistant-message-completed") {
505
+ this.root.noteCompletedAssistantMessage();
506
+ const identity = {
507
+ sessionId: event.sessionId,
508
+ sessionGeneration: event.sessionGeneration,
509
+ runSequence: event.runSequence,
510
+ responseSequence: event.responseSequence,
511
+ model: event.model,
512
+ };
513
+ if (event.model === null)
514
+ this.#promptSuggestions?.skip(identity, "no-model");
515
+ else
516
+ this.#promptSuggestions?.consider({ ...identity, model: event.model }, !event.successful ? "failed-response"
517
+ : event.toolContinuation || event.stopReason === "toolUse" ? "tool-continuation"
518
+ : event.stopReason !== "stop" ? "incomplete-response"
519
+ : event.assistantMessageCount < 2 ? "early-conversation"
520
+ : this.root.promptSuggestionPrepareBlockReason());
521
+ }
522
+ const semanticOnly = event.type === "agent-run-started" || event.type === "assistant-message-completed";
523
+ const view = event.type === "transcript-block" && this.#sessionGeneration === this.backend.sessionGeneration
524
+ ? this.#syncBlock(event.block)
525
+ : semanticOnly ? this.view() : this.#syncView();
526
+ this.#syncTerminalProgress(view);
527
+ const currentModelKey = modelKey(view);
528
+ if (this.backend.sessionGeneration !== this.#sessionGeneration || currentModelKey !== this.#suggestionModelKey) {
529
+ this.#promptSuggestions?.invalidate();
530
+ this.#suggestionModelKey = currentModelKey;
531
+ }
532
+ if (event.type === "status" && /^(Retrying|Compacting)/.test(event.status.workingMessage ?? "")) {
533
+ this.#promptSuggestions?.invalidate();
534
+ }
535
+ if (event.type === "agent-run-settled" && event.model !== null) {
536
+ this.#promptSuggestions?.settle({
537
+ sessionId: event.sessionId,
538
+ sessionGeneration: event.sessionGeneration,
539
+ runSequence: event.runSequence,
540
+ responseSequence: event.responseSequence,
541
+ model: event.model,
542
+ });
543
+ }
544
+ if (event.type === "session-lifecycle" && event.lifecycle === "stopped")
545
+ this.#settleStoppedLifecycle();
546
+ });
547
+ this.#unbindClipboardWriter = this.#responseCopy === null ? () => { } : this.backend.bindClipboardWriter(async (text) => {
548
+ const result = await this.#responseCopy.submitText(text);
549
+ if (result.outcome === "delivered")
550
+ return true;
551
+ if (result.outcome === "submitted-unverified")
552
+ return false;
553
+ throw new Error(result.outcome === "timed-out" ? "Clipboard delivery timed out" : "Clipboard delivery could not be completed");
554
+ });
555
+ if (this.backend.view().lifecycle === "stopped")
556
+ this.#resolveStopped?.();
557
+ }
558
+ view() {
559
+ return this.backend.view();
560
+ }
561
+ #promptSuggestionPresentationBlockReason(identity) {
562
+ const view = this.view();
563
+ if (this.#disposed)
564
+ return "disposed";
565
+ if (identity.sessionId !== view.sessionId || identity.sessionGeneration !== this.backend.sessionGeneration
566
+ || modelKey(view) !== `${identity.model.providerId}/${identity.model.modelId}`)
567
+ return "stale-identity";
568
+ return this.root.promptSuggestionPresentationBlockReason();
569
+ }
570
+ damagePresentationDecision() {
571
+ return this.#damageTerminal?.lastDecision ?? null;
572
+ }
573
+ start() {
574
+ if (this.#started)
575
+ return;
576
+ this.#started = true;
577
+ this.runtime.start();
578
+ this.#promptHistory?.start();
579
+ this.#syncTerminalProgress(this.view());
580
+ if (this.#customViewport)
581
+ this.#setPointerReporting(true);
582
+ void this.backend.bindExtensionUi(this.#extensionBridge.context, () => { void this.shutdown(); });
583
+ this.#syncView();
584
+ // Performance: the spare clipboard helpers fork after the first frame is out, so startup never waits on them.
585
+ setImmediate(() => {
586
+ if (this.#disposed || !this.#customViewport)
587
+ return;
588
+ this.root.warmPastePreparation();
589
+ this.#copyExecutor?.warm();
590
+ });
591
+ }
592
+ onView(listener) {
593
+ this.#listeners.add(listener);
594
+ listener(this.view());
595
+ return () => this.#listeners.delete(listener);
596
+ }
597
+ waitUntilStopped() {
598
+ return this.#stopped;
599
+ }
600
+ async submit(text) {
601
+ return this.#submitWhenReady(text, () => this.#submit(text));
602
+ }
603
+ #submitWhenReady(draft, action) {
604
+ const previous = this.#waitingImages.get(draft);
605
+ if (previous !== undefined)
606
+ return previous.result;
607
+ if (!this.root.hasPendingPastes(draft))
608
+ return this.#guardSubmission(draft, action);
609
+ const controller = new AbortController();
610
+ const generation = this.backend.sessionGeneration;
611
+ const result = this.#guardSubmission(draft, async () => {
612
+ await this.root.waitForPromptPastes(draft, controller.signal);
613
+ if (controller.signal.aborted || this.#disposed || this.backend.sessionGeneration !== generation)
614
+ return rejected("image submission canceled");
615
+ return action();
616
+ }).finally(() => {
617
+ this.#waitingImages.delete(draft);
618
+ if (!this.#disposed)
619
+ this.#showWaitingImages();
620
+ });
621
+ this.#waitingImages.set(draft, { controller, result });
622
+ if (this.root.editor.getText() === draft)
623
+ this.root.editor.setText("");
624
+ this.#showWaitingImages();
625
+ return result;
626
+ }
627
+ #showWaitingImages() {
628
+ const count = this.#waitingImages.size;
629
+ this.root.setExtensionWidget("owned-image-preparation", count === 0 ? null : {
630
+ render: width => [...renderPiShellStatusText(`Waiting for images (${count} submission${count === 1 ? "" : "s"}) — Esc cancels; dequeue restores`, width)],
631
+ invalidate: () => { },
632
+ }, "aboveEditor");
633
+ this.runtime.requestRender();
634
+ }
635
+ #cancelWaitingImages() {
636
+ for (const item of this.#waitingImages.values())
637
+ item.controller.abort();
638
+ }
639
+ #rememberInput(text, kind) {
640
+ this.root.editor.addToHistory(text);
641
+ if (this.#promptHistory !== null) {
642
+ const reusable = this.root.prepareHistoryText(text);
643
+ if (reusable.length === 0)
644
+ this.#promptHistory.rememberRecovery(text);
645
+ else {
646
+ this.#persistImageSidecars(text);
647
+ this.#promptHistory.capture(reusable, kind, this.#cwd, this.backend.sessionId);
648
+ }
649
+ }
650
+ }
651
+ // Rationale: write the image chip payloads referenced by an editor draft to the sidecar
652
+ // directory before their history row commits. Missing sidecar dependency = silent skip; the
653
+ // recall path treats an absent sidecar the same as a corrupt one.
654
+ #persistImageSidecars(text) {
655
+ const sidecar = this.#promptHistoryImageSidecar;
656
+ if (sidecar === undefined)
657
+ return;
658
+ for (const record of this.root.imageChipAttachmentsFromEditor(text)) {
659
+ sidecar.write(record.id, { tag: record.tag, data: record.image.data, mimeType: record.image.mimeType, savedAt: new Date().toISOString() });
660
+ }
661
+ }
662
+ async #submit(text) {
663
+ this.#promptSuggestions?.invalidate();
664
+ const displayInput = text.trim();
665
+ if (!displayInput)
666
+ return { outcome: "completed", diagnostic: null };
667
+ if (displayInput.startsWith("/"))
668
+ return this.#slashCommand(displayInput);
669
+ const prepared = this.root.preparePromptSubmission(displayInput);
670
+ assertPromptImages(prepared.images);
671
+ const input = prepared.text.trim();
672
+ if (input.startsWith("!")) {
673
+ const excludeFromContext = input.startsWith("!!");
674
+ const command = input.slice(excludeFromContext ? 2 : 1).trim();
675
+ if (command) {
676
+ this.#rememberInput(displayInput, "bash");
677
+ try {
678
+ const result = await this.backend.executeBashWorkflow(command, excludeFromContext);
679
+ const workflow = {
680
+ command: "debug",
681
+ outcome: result.cancelled ? "cancelled" : result.exitCode === 0 || result.exitCode === undefined ? "completed" : "failed",
682
+ message: result.cancelled ? "Bash command cancelled" : `Bash exited ${result.exitCode ?? 0}: ${command}`,
683
+ ...(result.output ? { detail: result.output } : {}),
684
+ };
685
+ this.root.appendWorkflowResult(workflow);
686
+ this.runtime.requestRender();
687
+ return workflow.outcome === "failed" ? rejected(workflow.message) : { outcome: "completed", diagnostic: null };
688
+ }
689
+ catch (error) {
690
+ const message = `Bash command failed: ${error instanceof Error ? error.message : String(error)}`;
691
+ this.root.appendWorkflowResult({ command: "debug", outcome: "failed", message });
692
+ this.runtime.requestRender();
693
+ return rejected(message);
694
+ }
695
+ }
696
+ }
697
+ // Compatibility: match interactive Pi: input during compaction is queued steering; the engine
698
+ // shows it in the pending rows and delivers it when compaction ends.
699
+ const type = this.view().lifecycle === "busy" ? "steer" : "prompt";
700
+ this.#rememberInput(displayInput, type);
701
+ this.root.resumeViewportFollowing();
702
+ return this.#execute({
703
+ type,
704
+ correlationId: this.#correlation(type),
705
+ sessionId: this.backend.sessionId,
706
+ text: input,
707
+ ...(prepared.images.length === 0 ? {} : { images: prepared.images }),
708
+ }, displayInput);
709
+ }
710
+ async clearOrExit(now = Date.now()) {
711
+ this.#promptSuggestions?.abortPending();
712
+ if (now - this.#lastClearTime < 500)
713
+ return this.shutdown();
714
+ this.root.editor.setText("");
715
+ this.#lastClearTime = now;
716
+ this.runtime.requestRender();
717
+ return { outcome: "completed", diagnostic: null };
718
+ }
719
+ async interrupt(now = Date.now()) {
720
+ this.#promptSuggestions?.invalidate();
721
+ if (this.#waitingImages.size > 0) {
722
+ this.#cancelWaitingImages();
723
+ return { outcome: "completed", diagnostic: null };
724
+ }
725
+ if (this.view().lifecycle === "busy")
726
+ return this.abort();
727
+ if (this.root.editor.getText().trim().length > 0) {
728
+ this.root.editor.setText("");
729
+ return { outcome: "completed", diagnostic: null };
730
+ }
731
+ // Compatibility: match Pi: with an empty editor, two escapes inside 500 ms open the
732
+ // configured session navigator. The first escape intentionally does not
733
+ // interrupt or mutate the prompt.
734
+ const action = this.backend.pinnedSettingsSnapshot().doubleEscapeAction;
735
+ if (action === "none")
736
+ return { outcome: "rejected", diagnostic: "nothing to interrupt" };
737
+ if (now - this.#lastEscapeTime < 500) {
738
+ this.#lastEscapeTime = 0;
739
+ if (action === "tree")
740
+ await this.showTreeSelector();
741
+ else
742
+ this.showForkSelector();
743
+ return { outcome: "completed", diagnostic: null };
744
+ }
745
+ this.#lastEscapeTime = now;
746
+ return { outcome: "completed", diagnostic: null };
747
+ }
748
+ async abort() {
749
+ return this.#execute(this.#simple("abort"));
750
+ }
751
+ async retry() {
752
+ this.#promptSuggestions?.invalidate();
753
+ return this.#execute(this.#simple("retry"));
754
+ }
755
+ async compact() {
756
+ this.#promptSuggestions?.invalidate();
757
+ return this.#execute(this.#simple("compact"));
758
+ }
759
+ async newSession() {
760
+ this.#promptSuggestions?.invalidate();
761
+ return this.#execute(this.#simple("new-session"));
762
+ }
763
+ async resumeSession(sessionPath) {
764
+ this.#promptSuggestions?.invalidate();
765
+ return this.#execute({
766
+ type: "resume-session",
767
+ correlationId: this.#correlation("resume"),
768
+ sessionId: this.backend.sessionId,
769
+ sessionPath,
770
+ });
771
+ }
772
+ async setModel(providerId, modelId) {
773
+ this.#promptSuggestions?.invalidate();
774
+ return this.#execute({
775
+ type: "set-model",
776
+ correlationId: this.#correlation("model"),
777
+ sessionId: this.backend.sessionId,
778
+ model: { providerId, modelId, displayName: modelId },
779
+ });
780
+ }
781
+ async setThinkingLevel(thinkingLevel) {
782
+ return this.#execute({
783
+ type: "set-thinking-level",
784
+ correlationId: this.#correlation("thinking"),
785
+ sessionId: this.backend.sessionId,
786
+ thinkingLevel,
787
+ });
788
+ }
789
+ async cycleThinkingLevel() {
790
+ const levels = ["off", "minimal", "low", "medium", "high", "xhigh"];
791
+ const current = Math.max(0, levels.indexOf(this.view().thinkingLevel));
792
+ return this.setThinkingLevel(levels[(current + 1) % levels.length] ?? "off");
793
+ }
794
+ async cycleModel(direction) {
795
+ const result = await this.backend.cycleModelWorkflow(direction);
796
+ this.root.appendWorkflowResult(result);
797
+ if (result.outcome === "completed")
798
+ this.#showDaxnutsForActiveModel();
799
+ this.runtime.requestRender();
800
+ return workflowAdapterResult(result);
801
+ }
802
+ async queueFollowUp() {
803
+ const draft = this.root.editor.getText();
804
+ return this.#submitWhenReady(draft, () => this.#queueFollowUp(draft));
805
+ }
806
+ async #queueFollowUp(draft) {
807
+ const displayInput = draft.trim();
808
+ if (!displayInput)
809
+ return rejected("nothing to queue");
810
+ const prepared = this.root.preparePromptSubmission(displayInput);
811
+ assertPromptImages(prepared.images);
812
+ const text = prepared.text.trim();
813
+ this.#rememberInput(displayInput, "follow-up");
814
+ if (this.root.editor.getText() === draft)
815
+ this.root.editor.setText("");
816
+ this.root.resumeViewportFollowing();
817
+ return this.#execute({
818
+ type: "follow-up",
819
+ correlationId: this.#correlation("follow-up"),
820
+ sessionId: this.backend.sessionId,
821
+ text,
822
+ ...(prepared.images.length === 0 ? {} : { images: prepared.images }),
823
+ }, displayInput);
824
+ }
825
+ restoreQueuedInput() {
826
+ const queued = [...this.#waitingImages.keys(), ...this.backend.clearQueuedWorkflows()];
827
+ this.#cancelWaitingImages();
828
+ if (queued.length === 0)
829
+ return;
830
+ this.root.editor.setText(queued.join("\n"));
831
+ this.runtime.requestRender();
832
+ }
833
+ showSelector(title, options, onSelect, onCancel) {
834
+ this.#dialogHandle?.hide();
835
+ this.#dialogSource = "local";
836
+ this.#dialogId = undefined;
837
+ const component = createPiShellSelector({
838
+ title,
839
+ options,
840
+ onSelect: id => {
841
+ onSelect(id);
842
+ this.#dialogHandle?.hide();
843
+ this.#dialogHandle = undefined;
844
+ this.#dialogSource = undefined;
845
+ },
846
+ onCancel: () => {
847
+ this.#dialogHandle?.hide();
848
+ this.#dialogHandle = undefined;
849
+ this.#dialogSource = undefined;
850
+ onCancel?.();
851
+ },
852
+ });
853
+ const handle = this.runtime.showOverlay(component, {
854
+ width: "70%",
855
+ maxHeight: "80%",
856
+ anchor: "center",
857
+ inputCoordination: "owned",
858
+ });
859
+ this.#dialogHandle = handle;
860
+ return handle;
861
+ }
862
+ async showThinkingSelector() {
863
+ const snapshot = this.backend.pinnedSettingsSnapshot();
864
+ const close = () => {
865
+ this.root.setFooterLevel(true);
866
+ this.root.setInputSurface(null);
867
+ this.runtime.requestRender();
868
+ };
869
+ const select = (level, persist) => {
870
+ close();
871
+ void this.runWorkflow({ command: "thinking", argument: "", selection: level, ...(persist ? { persist: true } : {}) });
872
+ };
873
+ const { createPiShellThinkingSelector } = await import("../../integrations/pi/components/thinking-selector-dialog.js");
874
+ const component = createPiShellThinkingSelector(snapshot.thinkingLevel, snapshot.availableThinkingLevels, level => select(level, false), close, level => select(level, true), snapshot.defaultThinkingLevel, this.#customViewport ? {
875
+ profile: "bare",
876
+ cycleBinding: this.root.editor.keybindingConfig()["app.thinking.cycle"] ?? [],
877
+ } : undefined);
878
+ this.root.setFooterLevel(false);
879
+ this.root.setInputSurface(component);
880
+ this.runtime.requestRender();
881
+ }
882
+ /** The Skills dialog: a replacement input like the model selector, applying the chosen skill through the prompt path. */
883
+ showSkillsSelector(skills = this.#skillSummaries()) {
884
+ const close = () => {
885
+ this.root.setInputSurface(null);
886
+ this.runtime.requestRender();
887
+ };
888
+ const component = createPiShellSkillsSelector({
889
+ skills,
890
+ onSelect: name => {
891
+ close();
892
+ void this.#submitSkillPrompt(skillPrompt(name), skillPrompt(name)).catch(() => this.#reportSubmissionError());
893
+ },
894
+ onCancel: close,
895
+ });
896
+ this.root.setInputSurface(component);
897
+ this.runtime.requestRender();
898
+ }
899
+ showModelSelector(initialSearchInput) {
900
+ const context = this.backend.pinnedModelSelectorContext();
901
+ const close = () => {
902
+ this.root.setInputSurface(null);
903
+ this.runtime.requestRender();
904
+ };
905
+ const component = createPiShellModelSelector({
906
+ ...context,
907
+ runtime: {
908
+ getColumns: () => this.runtime.viewport().columns,
909
+ getRows: () => this.runtime.viewport().rows,
910
+ requestRender: () => this.runtime.requestRender(),
911
+ },
912
+ ...(initialSearchInput === undefined ? {} : { initialSearchInput }),
913
+ onSelect: model => {
914
+ close();
915
+ void this.runWorkflow({ command: "model", argument: "", selection: modelReference(model) });
916
+ },
917
+ onSelectAsDefault: model => {
918
+ close();
919
+ void this.runWorkflow({ command: "model", argument: "", selection: modelReference(model), persist: true });
920
+ },
921
+ onCancel: close,
922
+ });
923
+ this.root.setInputSurface(component);
924
+ this.runtime.requestRender();
925
+ }
926
+ showForkSelector() {
927
+ const options = this.backend.pinnedForkOptions();
928
+ if (options.length === 0) {
929
+ this.root.appendWorkflowResult({ command: "fork", outcome: "completed", message: "No messages to fork from", messageKind: "status" });
930
+ this.runtime.requestRender();
931
+ return;
932
+ }
933
+ const close = () => {
934
+ this.root.setInputSurface(null);
935
+ this.runtime.requestRender();
936
+ };
937
+ const component = createPiShellUserMessageSelector(options, selection => {
938
+ close();
939
+ void this.runWorkflow({ command: "fork", argument: "", selection });
940
+ }, close);
941
+ this.root.setInputSurface(component);
942
+ this.runtime.requestRender();
943
+ }
944
+ async showLogoutSelector() {
945
+ let options;
946
+ try {
947
+ options = await this.backend.pinnedLogoutOptions();
948
+ }
949
+ catch (error) {
950
+ this.root.appendWorkflowResult({
951
+ command: "logout",
952
+ outcome: "failed",
953
+ message: `Could not read stored credentials: ${error instanceof Error ? error.message : String(error)}`,
954
+ });
955
+ this.runtime.requestRender();
956
+ return;
957
+ }
958
+ if (options.length === 0) {
959
+ this.root.appendWorkflowStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");
960
+ this.runtime.requestRender();
961
+ return;
962
+ }
963
+ const close = () => {
964
+ this.root.setInputSurface(null);
965
+ this.runtime.requestRender();
966
+ };
967
+ const component = createPiShellAuthProviderSelector("logout", options, selection => {
968
+ close();
969
+ void this.runWorkflow({ command: "logout", argument: "", selection });
970
+ }, close);
971
+ this.root.setInputSurface(component);
972
+ this.runtime.requestRender();
973
+ }
974
+ showLoginMethodSelector(providerReference) {
975
+ const method = this.backend.pinnedLoginMethodOptions(providerReference);
976
+ if (method.options.length === 0) {
977
+ this.showLoginProviderSelector(undefined, providerReference);
978
+ return;
979
+ }
980
+ if (method.options.length === 1) {
981
+ const selection = method.options[0]?.id;
982
+ if (selection)
983
+ void this.runWorkflow({ command: "login", argument: "", selection });
984
+ return;
985
+ }
986
+ const close = () => {
987
+ this.root.setInputSurface(null);
988
+ this.runtime.requestRender();
989
+ };
990
+ const labels = method.options.map(option => option.label);
991
+ const component = createPiShellExtensionSelector(method.title, labels, label => {
992
+ const selection = method.options.find(option => option.label === label)?.id;
993
+ if (!selection)
994
+ return;
995
+ close();
996
+ void this.runWorkflow({ command: "login", argument: "", selection });
997
+ }, close);
998
+ this.root.setInputSurface(component);
999
+ this.runtime.requestRender();
1000
+ }
1001
+ async showTreeSelector(initialSelectedId) {
1002
+ const context = this.backend.pinnedTreeSelectorContext();
1003
+ if (context.tree.length === 0) {
1004
+ this.root.appendWorkflowStatus("No entries in session");
1005
+ this.runtime.requestRender();
1006
+ return;
1007
+ }
1008
+ const close = () => {
1009
+ this.root.setInputSurface(null);
1010
+ this.runtime.requestRender();
1011
+ };
1012
+ const component = await createPiShellTreeSelector({
1013
+ tree: context.tree,
1014
+ currentLeafId: context.currentLeafId,
1015
+ terminalHeight: this.runtime.viewport().rows,
1016
+ initialFilterMode: context.filterMode,
1017
+ ...(initialSelectedId === undefined ? {} : { initialSelectedId }),
1018
+ onLabelChange: context.appendLabelChange,
1019
+ onCopy: text => {
1020
+ if (!text) {
1021
+ this.root.appendWorkflowResult({ command: "tree", outcome: "failed", message: "Selected entry has no text to copy" });
1022
+ this.runtime.requestRender();
1023
+ return;
1024
+ }
1025
+ const generation = this.backend.sessionBindingGeneration;
1026
+ void this.backend.copyWorkflowText(text).then(acknowledged => {
1027
+ if (this.#disposed || generation !== this.backend.sessionBindingGeneration)
1028
+ return;
1029
+ this.root.appendWorkflowStatus(acknowledged ? "Copied selected message to clipboard" : "Submitted selected message to clipboard");
1030
+ this.runtime.requestRender();
1031
+ }).catch(error => {
1032
+ if (this.#disposed || generation !== this.backend.sessionBindingGeneration)
1033
+ return;
1034
+ this.root.appendWorkflowResult({ command: "tree", outcome: "failed", message: error instanceof Error ? error.message : String(error) });
1035
+ this.runtime.requestRender();
1036
+ });
1037
+ },
1038
+ onCancel: close,
1039
+ onSelect: entryId => {
1040
+ close();
1041
+ if (entryId === context.currentLeafId) {
1042
+ this.root.appendWorkflowStatus("Already at this point");
1043
+ this.runtime.requestRender();
1044
+ return;
1045
+ }
1046
+ void this.#completeTreeSelection(entryId, context.skipSummaryPrompt);
1047
+ },
1048
+ });
1049
+ this.root.setInputSurface(component);
1050
+ this.runtime.requestRender();
1051
+ }
1052
+ showLoginAuthTypeSelector() {
1053
+ const close = () => {
1054
+ this.root.setInputSurface(null);
1055
+ this.runtime.requestRender();
1056
+ };
1057
+ const labels = ["Sign in with an account", "Sign in with an API key"];
1058
+ const component = createPiShellExtensionSelector("Select authentication method:", labels, label => {
1059
+ close();
1060
+ this.showLoginProviderSelector(label === labels[0] ? "oauth" : "api_key");
1061
+ }, close);
1062
+ this.root.setInputSurface(component);
1063
+ this.runtime.requestRender();
1064
+ }
1065
+ showLoginProviderSelector(authType, initialSearchInput) {
1066
+ const options = this.backend.pinnedLoginOptions(authType);
1067
+ if (options.length === 0) {
1068
+ this.root.appendWorkflowStatus(authType === "oauth" ? "No subscription providers available." : authType === "api_key" ? "No API key providers available." : "No login providers available.");
1069
+ this.runtime.requestRender();
1070
+ return;
1071
+ }
1072
+ const close = () => {
1073
+ this.root.setInputSurface(null);
1074
+ this.runtime.requestRender();
1075
+ };
1076
+ const component = createPiShellAuthProviderSelector("login", options, id => {
1077
+ close();
1078
+ void this.runWorkflow({ command: "login", argument: "", selection: id });
1079
+ }, () => {
1080
+ close();
1081
+ if (authType !== undefined)
1082
+ this.showLoginAuthTypeSelector();
1083
+ }, initialSearchInput);
1084
+ this.root.setInputSurface(component);
1085
+ this.runtime.requestRender();
1086
+ }
1087
+ async showSessionSelector() {
1088
+ const context = this.backend.pinnedSessionSelectorContext();
1089
+ const close = () => {
1090
+ this.root.setInputSurface(null);
1091
+ this.runtime.requestRender();
1092
+ };
1093
+ const component = await createPiShellSessionSelector({
1094
+ currentSessionsLoader: context.loadCurrentSessions,
1095
+ allSessionsLoader: context.loadAllSessions,
1096
+ currentSessionFilePath: context.currentSessionFilePath,
1097
+ renameSession: context.renameSession,
1098
+ requestRender: () => this.runtime.requestRender(),
1099
+ onSelect: sessionPath => {
1100
+ close();
1101
+ void this.runWorkflow({ command: "resume", argument: sessionPath });
1102
+ },
1103
+ onCancel: close,
1104
+ onExit: () => {
1105
+ close();
1106
+ void this.shutdown();
1107
+ },
1108
+ });
1109
+ this.root.setInputSurface(component);
1110
+ this.runtime.requestRender();
1111
+ }
1112
+ showSettingsSelector() {
1113
+ const snapshot = this.backend.pinnedSettingsSnapshot();
1114
+ const close = () => {
1115
+ this.root.setInputSurface(null);
1116
+ this.runtime.requestRender();
1117
+ };
1118
+ const { currentModel, ...settingsSnapshot } = snapshot;
1119
+ const component = createPiShellSettingsSelector({
1120
+ config: {
1121
+ ...settingsSnapshot,
1122
+ availableThinkingLevels: [...snapshot.availableThinkingLevels],
1123
+ availableThemes: [...snapshot.availableThemes],
1124
+ warnings: { ...snapshot.warnings },
1125
+ modelThinkingLevels: { ...snapshot.modelThinkingLevels },
1126
+ ...(currentModel === undefined ? {} : { currentModel: currentModel }),
1127
+ availableDefaultModels: snapshot.availableDefaultModels,
1128
+ },
1129
+ onChange: (callback, value) => {
1130
+ if (callback === "onCancel") {
1131
+ close();
1132
+ return;
1133
+ }
1134
+ if (callback === "onTuiModeChange") {
1135
+ // Invariant: the custom bare-A1 surface is permanently fullscreen; this callback
1136
+ // remains available only to pinned comparison profiles.
1137
+ if (this.#customViewport)
1138
+ return;
1139
+ if (value !== "regular" && value !== "fullscreen")
1140
+ return;
1141
+ if (!this.runtime.switchMode(value)) {
1142
+ this.root.appendWorkflowStatus("Close active overlays before changing TUI mode");
1143
+ this.runtime.requestRender();
1144
+ return;
1145
+ }
1146
+ if (this.#customViewport) {
1147
+ this.#pointerReporting = false;
1148
+ this.#setPointerReporting(true);
1149
+ }
1150
+ }
1151
+ void this.backend.applyPinnedSettingValue(callback, value).then(result => {
1152
+ if (result.outcome === "failed")
1153
+ this.root.appendWorkflowResult(result);
1154
+ else if (callback === "onTuiModeChange")
1155
+ this.root.appendWorkflowStatus(`TUI mode: ${value}`);
1156
+ this.runtime.requestRender();
1157
+ });
1158
+ },
1159
+ onCancel: close,
1160
+ });
1161
+ this.root.setInputSurface(component);
1162
+ this.runtime.requestRender();
1163
+ }
1164
+ shutdown() {
1165
+ this.#shutdownPromise ??= this.#shutdown();
1166
+ return this.#shutdownPromise;
1167
+ }
1168
+ async #shutdown() {
1169
+ try {
1170
+ const result = await this.backend.executeWorkflow({ command: "quit", argument: "" });
1171
+ await this.dispose();
1172
+ return workflowAdapterResult(result);
1173
+ }
1174
+ finally {
1175
+ this.#resolveStoppedLifecycle();
1176
+ }
1177
+ }
1178
+ async runWorkflow(request) {
1179
+ if (request.command === "quit")
1180
+ return this.shutdown();
1181
+ const copyGeneration = request.command === "copy" ? this.backend.sessionBindingGeneration : undefined;
1182
+ if (request.command === "login" && request.selection !== undefined) {
1183
+ const setup = this.backend.pinnedAmbientAuthentication(request.selection);
1184
+ if (setup) {
1185
+ const close = () => {
1186
+ this.root.setInputSurface(null);
1187
+ this.runtime.requestRender();
1188
+ };
1189
+ const dialog = createPiShellLoginDialog({
1190
+ getColumns: () => this.runtime.viewport().columns,
1191
+ getRows: () => this.runtime.viewport().rows,
1192
+ requestRender: () => this.runtime.requestRender(),
1193
+ }, setup.providerId, close, setup.providerName, setup.title);
1194
+ dialog.showInfo(setup.message, [], true);
1195
+ this.root.setInputSurface(dialog);
1196
+ this.runtime.requestRender();
1197
+ return { outcome: "completed", diagnostic: null };
1198
+ }
1199
+ }
1200
+ if (request.command === "scoped-models" && request.selection === undefined && request.confirmed === undefined) {
1201
+ this.showScopedModelsSelector();
1202
+ return { outcome: "completed", diagnostic: null };
1203
+ }
1204
+ if (request.command === "models" && request.selection === undefined) {
1205
+ this.showModelsDialog(request.argument.trim() || undefined);
1206
+ return { outcome: "completed", diagnostic: null };
1207
+ }
1208
+ if (request.command === "model" && request.selection === undefined && request.confirmed === undefined && request.argument.trim().length === 0) {
1209
+ this.showModelSelector();
1210
+ return { outcome: "completed", diagnostic: null };
1211
+ }
1212
+ if (request.command === "fork" && request.selection === undefined && request.confirmed === undefined) {
1213
+ this.showForkSelector();
1214
+ return { outcome: "completed", diagnostic: null };
1215
+ }
1216
+ if (request.command === "thinking" && request.selection === undefined && request.argument.trim().length === 0) {
1217
+ await this.showThinkingSelector();
1218
+ return { outcome: "completed", diagnostic: null };
1219
+ }
1220
+ if (request.command === "trust" && request.selection === undefined && request.confirmed === undefined) {
1221
+ this.showTrustSelector();
1222
+ return { outcome: "completed", diagnostic: null };
1223
+ }
1224
+ if (request.command === "settings" && request.selection === undefined && request.confirmed === undefined) {
1225
+ this.showSettingsSelector();
1226
+ return { outcome: "completed", diagnostic: null };
1227
+ }
1228
+ if (request.command === "resume" && request.selection === undefined && request.confirmed === undefined && request.argument.trim().length === 0) {
1229
+ await this.showSessionSelector();
1230
+ return { outcome: "completed", diagnostic: null };
1231
+ }
1232
+ if (request.command === "login" && request.selection === undefined && request.confirmed === undefined) {
1233
+ if (request.argument.trim().length === 0)
1234
+ this.showLoginAuthTypeSelector();
1235
+ else
1236
+ this.showLoginMethodSelector(request.argument);
1237
+ return { outcome: "completed", diagnostic: null };
1238
+ }
1239
+ if (request.command === "logout" && request.selection === undefined && request.confirmed === undefined) {
1240
+ await this.showLogoutSelector();
1241
+ return { outcome: "completed", diagnostic: null };
1242
+ }
1243
+ if (request.command === "tree" && request.selection === undefined && request.confirmed === undefined && request.argument.trim().length === 0) {
1244
+ await this.showTreeSelector();
1245
+ return { outcome: "completed", diagnostic: null };
1246
+ }
1247
+ if (request.command === "reload") {
1248
+ const blocked = this.backend.reloadBlockedResult();
1249
+ if (blocked) {
1250
+ this.root.appendWorkflowResult(blocked);
1251
+ this.runtime.requestRender();
1252
+ return workflowAdapterResult(blocked);
1253
+ }
1254
+ this.root.resetExtensionUi();
1255
+ }
1256
+ const shareSurface = request.command === "share"
1257
+ ? createPiShellOperationLoader({
1258
+ getColumns: () => this.runtime.viewport().columns,
1259
+ getRows: () => this.runtime.viewport().rows,
1260
+ requestRender: () => this.runtime.requestRender(),
1261
+ }, "Creating gist...")
1262
+ : undefined;
1263
+ const operationSurface = shareSurface ?? (request.command === "reload" ? createPiShellReloadBox() : undefined);
1264
+ const now = this.#reloadPresentation?.now ?? Date.now;
1265
+ const shownAt = now();
1266
+ if (operationSurface) {
1267
+ this.root.setInputSurface(operationSurface);
1268
+ this.runtime.requestRender();
1269
+ }
1270
+ let result;
1271
+ try {
1272
+ result = await this.backend.executeWorkflow(shareSurface === undefined ? request : { ...request, signal: shareSurface.signal });
1273
+ }
1274
+ finally {
1275
+ if (operationSurface) {
1276
+ // Rationale: a near-instant reload would flash the box for a frame or skip it entirely; holding it
1277
+ // briefly keeps the reload legible regardless of how fast the resources actually load.
1278
+ if (request.command === "reload")
1279
+ await this.#holdReloadSurface(now() - shownAt);
1280
+ this.root.setInputSurface(null);
1281
+ this.runtime.requestRender();
1282
+ }
1283
+ }
1284
+ if (copyGeneration !== undefined && (this.#disposed || copyGeneration !== this.backend.sessionBindingGeneration)) {
1285
+ return workflowAdapterResult({ command: "copy", outcome: "cancelled", message: "" });
1286
+ }
1287
+ if (result.outcome === "requires-selection" && request.command === "model") {
1288
+ if (result.messages !== undefined) {
1289
+ for (const message of result.messages)
1290
+ this.root.appendWorkflowMessage(message);
1291
+ }
1292
+ this.showModelSelector((result.detail ?? request.argument.trim()) || undefined);
1293
+ return { outcome: "completed", diagnostic: null };
1294
+ }
1295
+ if (result.outcome === "requires-confirmation" && request.command === "resume") {
1296
+ const confirmed = await this.#extensionBridge.context.confirm("Session cwd not found", result.message);
1297
+ return this.runWorkflow({ ...request, confirmed: confirmed === true });
1298
+ }
1299
+ if (result.outcome === "requires-confirmation" && request.command === "import") {
1300
+ const recoveringCwd = result.detail !== undefined;
1301
+ const confirmed = await this.#extensionBridge.context.confirm(recoveringCwd ? "Session cwd not found" : "Import session", result.message);
1302
+ return this.runWorkflow({
1303
+ ...request,
1304
+ confirmed: confirmed === true,
1305
+ ...(confirmed === true && result.detail ? { cwdOverride: result.detail } : {}),
1306
+ });
1307
+ }
1308
+ if (result.outcome === "requires-selection" || result.outcome === "requires-confirmation") {
1309
+ this.root.appendWorkflowResult({ command: request.command, outcome: "failed", message: `Owned controller missing for ${request.command}` });
1310
+ this.runtime.requestRender();
1311
+ return { outcome: "failed", diagnostic: `Owned controller missing for ${request.command}` };
1312
+ }
1313
+ if (request.command === "reload" && result.outcome === "completed") {
1314
+ this.root.resetWorkflowPresentation();
1315
+ this.root.editor.reloadKeybindings();
1316
+ this.#installAutocompleteCommands();
1317
+ }
1318
+ this.root.appendWorkflowResult(result);
1319
+ if ((request.command === "model" || request.command === "models") && result.outcome === "completed")
1320
+ this.#showDaxnutsForActiveModel();
1321
+ this.runtime.requestRender();
1322
+ return workflowAdapterResult(result);
1323
+ }
1324
+ async #holdReloadSurface(visibleMs) {
1325
+ const minVisibleMs = this.#reloadPresentation?.minVisibleMs ?? RELOAD_SURFACE_MIN_VISIBLE_MS;
1326
+ const remaining = minVisibleMs - visibleMs;
1327
+ if (remaining <= 0 || this.#disposed)
1328
+ return;
1329
+ const sleep = this.#reloadPresentation?.sleep ?? ((ms) => new Promise(resolve => setTimeout(resolve, ms)));
1330
+ await sleep(remaining);
1331
+ }
1332
+ showTrustSelector() {
1333
+ const context = this.backend.pinnedProjectTrustContext();
1334
+ const close = () => {
1335
+ this.root.setInputSurface(null);
1336
+ this.runtime.requestRender();
1337
+ };
1338
+ const component = createPiShellTrustSelector({
1339
+ ...context,
1340
+ onSelect: selection => {
1341
+ try {
1342
+ this.backend.persistProjectTrust(selection.updates);
1343
+ close();
1344
+ this.root.appendWorkflowStatus(`Saved trust decision: ${selection.trusted ? "trusted" : "untrusted"}. Restart pi for this to take effect.`);
1345
+ }
1346
+ catch (error) {
1347
+ close();
1348
+ this.root.appendWorkflowResult({ command: "trust", outcome: "failed", message: error instanceof Error ? error.message : String(error) });
1349
+ }
1350
+ this.runtime.requestRender();
1351
+ },
1352
+ onCancel: close,
1353
+ });
1354
+ this.root.setInputSurface(component);
1355
+ this.runtime.requestRender();
1356
+ }
1357
+ showScopedModelsSelector() {
1358
+ const initial = this.backend.pinnedScopedModelsContext();
1359
+ let currentEnabledIds = initial.enabledModelIds === null ? null : [...initial.enabledModelIds];
1360
+ let selectionChanged = false;
1361
+ let disposed = false;
1362
+ let timedOut = false;
1363
+ const controller = new AbortController();
1364
+ const timeout = setTimeout(() => {
1365
+ timedOut = true;
1366
+ controller.abort();
1367
+ }, 15_000);
1368
+ const close = () => {
1369
+ disposed = true;
1370
+ clearTimeout(timeout);
1371
+ controller.abort();
1372
+ this.root.setInputSurface(null);
1373
+ this.runtime.requestRender();
1374
+ };
1375
+ const selector = createPiShellScopedModelsSelector({
1376
+ models: initial.models,
1377
+ enabledModelIds: currentEnabledIds,
1378
+ refreshStatus: "Refreshing model catalogs…",
1379
+ onChange: enabledIds => {
1380
+ selectionChanged = true;
1381
+ currentEnabledIds = enabledIds === null ? null : [...enabledIds];
1382
+ this.backend.updateScopedModels(currentEnabledIds);
1383
+ this.runtime.requestRender();
1384
+ },
1385
+ onPersist: enabledIds => {
1386
+ currentEnabledIds = enabledIds === null ? null : [...enabledIds];
1387
+ this.backend.persistScopedModels(currentEnabledIds);
1388
+ this.root.appendWorkflowStatus("Model selection saved to settings");
1389
+ this.runtime.requestRender();
1390
+ },
1391
+ onCancel: close,
1392
+ });
1393
+ const component = {
1394
+ ...selector,
1395
+ dispose: () => {
1396
+ disposed = true;
1397
+ clearTimeout(timeout);
1398
+ controller.abort();
1399
+ selector.dispose?.();
1400
+ },
1401
+ };
1402
+ this.root.setInputSurface(component);
1403
+ this.runtime.requestRender();
1404
+ void this.backend.refreshScopedModels(controller.signal).then(refreshed => {
1405
+ if (disposed)
1406
+ return;
1407
+ if (!selectionChanged) {
1408
+ currentEnabledIds = refreshed.enabledModelIds === null ? null : [...refreshed.enabledModelIds];
1409
+ component.updateModels(refreshed.models, currentEnabledIds);
1410
+ }
1411
+ else {
1412
+ component.updateModels(refreshed.models);
1413
+ this.backend.updateScopedModels(currentEnabledIds);
1414
+ }
1415
+ component.setRefreshStatus(timedOut ? "Model refresh timed out; showing cached models." : refreshed.status, timedOut ? "warning" : refreshed.statusKind);
1416
+ this.runtime.requestRender();
1417
+ }).catch(error => {
1418
+ if (disposed)
1419
+ return;
1420
+ component.setRefreshStatus(timedOut
1421
+ ? "Model refresh timed out; showing cached models."
1422
+ : `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`, "warning");
1423
+ this.runtime.requestRender();
1424
+ }).finally(() => clearTimeout(timeout));
1425
+ }
1426
+ // Invariant: bare A1 routes `models`; the comparison profile keeps the pinned `model`/`scoped-models` pair. Hidden routes are shared.
1427
+ #isWorkflowRoute(value) {
1428
+ return workflowCommandNames(this.#customViewport ? "bare" : "comparison").includes(value)
1429
+ || PINNED_PI_HIDDEN_COMMAND_NAMES.includes(value);
1430
+ }
1431
+ /** The bare-A1 unified Models dialog: switch on Enter, scope on Space, persist on Ctrl+S, all through the engine. */
1432
+ showModelsDialog(initialQuery) {
1433
+ const context = this.backend.modelsContext();
1434
+ const available = new Set(context.models.map(model => `${model.provider}/${model.id}`));
1435
+ const savedScopeIds = context.persistedScopeIds.filter(id => available.has(id));
1436
+ // Invariant: an explicit session scope wins; otherwise the dialog starts from what is persisted, never from "all rows scoped".
1437
+ const scopeIds = context.sessionScopeIds.length > 0 ? context.sessionScopeIds : savedScopeIds;
1438
+ let disposed = false;
1439
+ let timedOut = false;
1440
+ const controller = new AbortController();
1441
+ const timeout = setTimeout(() => {
1442
+ timedOut = true;
1443
+ controller.abort();
1444
+ }, 15_000);
1445
+ const close = () => {
1446
+ disposed = true;
1447
+ clearTimeout(timeout);
1448
+ controller.abort();
1449
+ this.root.setInputSurface(null);
1450
+ this.runtime.requestRender();
1451
+ };
1452
+ const dialog = createPiShellModelsDialog({
1453
+ models: context.models,
1454
+ activeModelId: context.activeModelId,
1455
+ scopeIds,
1456
+ savedScopeIds,
1457
+ ...(initialQuery === undefined ? {} : { initialQuery }),
1458
+ refreshStatus: "Refreshing model catalogs…",
1459
+ requestRender: () => this.runtime.requestRender(),
1460
+ onSelect: modelId => {
1461
+ void this.runWorkflow({ command: "models", argument: "", selection: modelId }).then(result => {
1462
+ if (!disposed && result.outcome === "completed")
1463
+ close();
1464
+ });
1465
+ },
1466
+ onScopeChange: ids => {
1467
+ this.backend.setSessionModelScope(ids);
1468
+ this.runtime.requestRender();
1469
+ },
1470
+ onSave: ids => {
1471
+ try {
1472
+ this.backend.persistModelScope(ids);
1473
+ }
1474
+ catch (error) {
1475
+ this.root.appendWorkflowResult({ command: "models", outcome: "failed", message: error instanceof Error ? error.message : String(error) });
1476
+ this.runtime.requestRender();
1477
+ throw error;
1478
+ }
1479
+ this.root.appendWorkflowStatus("Model selection saved to settings");
1480
+ this.runtime.requestRender();
1481
+ },
1482
+ onCancel: close,
1483
+ });
1484
+ const component = {
1485
+ ...dialog,
1486
+ dispose: () => {
1487
+ disposed = true;
1488
+ clearTimeout(timeout);
1489
+ controller.abort();
1490
+ dialog.dispose?.();
1491
+ },
1492
+ };
1493
+ this.root.setInputSurface(component);
1494
+ this.runtime.requestRender();
1495
+ void this.backend.refreshModels(controller.signal).then(refreshed => {
1496
+ if (disposed)
1497
+ return;
1498
+ component.updateModels(refreshed.models);
1499
+ component.setRefreshStatus(timedOut ? "Model refresh timed out; showing cached models." : refreshed.status, timedOut ? "warning" : refreshed.statusKind);
1500
+ this.runtime.requestRender();
1501
+ }).catch(error => {
1502
+ if (disposed)
1503
+ return;
1504
+ component.setRefreshStatus(timedOut
1505
+ ? "Model refresh timed out; showing cached models."
1506
+ : `Could not refresh model catalogs: ${error instanceof Error ? error.message : String(error)}`, "warning");
1507
+ this.runtime.requestRender();
1508
+ }).finally(() => clearTimeout(timeout));
1509
+ }
1510
+ #showDaxnutsForActiveModel() {
1511
+ const model = this.view().activeModel;
1512
+ if (model?.providerId === "opencode" && model.modelId.toLowerCase().includes("kimi-k2.5")) {
1513
+ this.root.appendDaxnuts();
1514
+ }
1515
+ }
1516
+ // Invariant: pointer reporting is disabled on every path that ends the owning screen.
1517
+ #setPointerReporting(enabled, forceOff = false) {
1518
+ const effective = forceOff ? false : this.#customViewport || enabled;
1519
+ if (this.#pointerReporting === effective)
1520
+ return;
1521
+ this.#pointerReporting = effective;
1522
+ if (!this.runtime.active)
1523
+ return;
1524
+ this.runtime.writeControl(effective ? MOUSE_TRACKING_ON : MOUSE_TRACKING_OFF);
1525
+ }
1526
+ dispose() {
1527
+ if (this.#disposePromise !== undefined)
1528
+ return this.#disposePromise;
1529
+ if (this.#disposed)
1530
+ return Promise.resolve();
1531
+ const pending = Promise.resolve().then(() => this.#dispose());
1532
+ this.#disposePromise = pending;
1533
+ const clear = () => { if (this.#disposePromise === pending)
1534
+ this.#disposePromise = undefined; };
1535
+ void pending.then(clear, clear);
1536
+ return pending;
1537
+ }
1538
+ async #dispose() {
1539
+ this.#disposed = true;
1540
+ this.#copyIntentSequence += 1;
1541
+ // Invariant: the outro frame is what the terminal shows now, before any cleanup writes.
1542
+ const outroFrame = this.#captureQuitOutroFrame();
1543
+ this.#responseCopy?.dispose();
1544
+ this.#copyExecutor?.dispose();
1545
+ this.#cancelWaitingImages();
1546
+ const failures = [];
1547
+ const attempt = (action) => { try {
1548
+ action();
1549
+ }
1550
+ catch (error) {
1551
+ failures.push(error);
1552
+ } };
1553
+ let pasteCleanup = Promise.resolve();
1554
+ let historyCleanup = Promise.resolve(true);
1555
+ attempt(() => { historyCleanup = this.#promptHistory?.close() ?? Promise.resolve(true); });
1556
+ attempt(() => { pasteCleanup = this.root.disposePendingPastes(); });
1557
+ attempt(() => this.root.clearViewportPointerState());
1558
+ attempt(() => this.#setPointerReporting(false, true));
1559
+ attempt(() => this.#removeViewportPreInput());
1560
+ attempt(() => this.#streamPresentation.dispose());
1561
+ attempt(() => this.#promptSuggestions?.dispose());
1562
+ attempt(() => this.#unsubscribePromptSuggestions());
1563
+ attempt(() => this.#unsubscribeSkills());
1564
+ attempt(() => this.#unsubscribeSettings());
1565
+ let fullscreenExitText = "";
1566
+ attempt(() => {
1567
+ const exitMode = this.backend.disposed ? this.#fullscreenExitOutput : this.backend.pinnedSettingsSnapshot().fullscreenExitOutput;
1568
+ const resume = this.backend.currentSessionResumeMetadata();
1569
+ const resumeHint = resume === null ? "" : `${dim("To resume this session:")} ${formatSessionResumeCommand(resume)}`;
1570
+ // Invariant: bare A1 leaves only the hint behind; the pinned comparison profile still
1571
+ // honors fullscreenExitOutput, including the styled transcript.
1572
+ fullscreenExitText = this.runtime.mode !== "fullscreen" ? ""
1573
+ : this.#customViewport || exitMode === "resume-hint" ? resumeHint
1574
+ : [this.root.exitTranscript(this.runtime.viewport().columns), resumeHint].filter(Boolean).join("\n\n");
1575
+ });
1576
+ attempt(() => this.#unbindClipboardWriter());
1577
+ attempt(() => this.#unbindPiSettings());
1578
+ attempt(() => this.#unbindTerminalSettings());
1579
+ attempt(() => this.#unbindShutdownSettings());
1580
+ attempt(() => this.#unsubscribe());
1581
+ attempt(() => this.#dialogHandle?.hide());
1582
+ attempt(() => this.#extensionBridge.dispose());
1583
+ // Invariant: from here to the leave nothing but the outro paints. A throttled frame the
1584
+ // renderer still has queued would otherwise land during the stop-time input drain and
1585
+ // flash the prompt and footer, whether or not an effect plays.
1586
+ attempt(() => this.#freezeQuitPresentation());
1587
+ await this.#playQuitOutro(outroFrame);
1588
+ // Invariant: terminal restoration precedes any potentially stalled backend teardown. The
1589
+ // fullscreen leave preserves the screen: the pinned runtime never dumps its final document
1590
+ // into the parent terminal, so only the configured exit text follows the leave.
1591
+ await this.runtime.dispose({ preserveScreen: this.runtime.mode === "fullscreen" }).catch(error => failures.push(error));
1592
+ await historyCleanup.catch(() => false); // Security: background durability outcomes never enter terminal output.
1593
+ await boundedCleanup(() => pasteCleanup).catch(error => failures.push(error));
1594
+ await boundedCleanup(() => this.backend.unbindExtensionUi()).catch(error => failures.push(error));
1595
+ if (failures.length > 0)
1596
+ throw new AggregateError(failures, "Owned UI disposal failed");
1597
+ if (fullscreenExitText.length > 0)
1598
+ this.runtime.writeAfterStop(`${fullscreenExitText}\n`);
1599
+ }
1600
+ // Invariant: the snapshot is synchronous; the outro module itself loads only at quit.
1601
+ #captureQuitOutroFrame() {
1602
+ const outro = this.#quitOutro;
1603
+ if (outro === undefined || !outro.interactive || !this.#customViewport || this.#damageTerminal === null)
1604
+ return null;
1605
+ if (!this.runtime.active || this.runtime.mode !== "fullscreen")
1606
+ return null;
1607
+ try {
1608
+ if (!outro.snapshot().enabled)
1609
+ return null;
1610
+ const viewport = this.runtime.viewport();
1611
+ return {
1612
+ rows: this.#damageTerminal.presentedRows(), columns: viewport.columns, height: viewport.rows,
1613
+ settings: { effect: QUIT_OUTRO_EFFECT, durationMs: QUIT_OUTRO_DURATION_MS },
1614
+ };
1615
+ }
1616
+ catch {
1617
+ return null;
1618
+ }
1619
+ }
1620
+ #freezeQuitPresentation() {
1621
+ if (!this.#customViewport || !this.runtime.active || this.runtime.mode !== "fullscreen")
1622
+ return;
1623
+ this.runtime.freezePresentation();
1624
+ }
1625
+ // Rationale: any failure here only skips the effect; restoration always follows.
1626
+ async #playQuitOutro(capture) {
1627
+ const outro = this.#quitOutro;
1628
+ if (capture === null || outro === undefined || !this.runtime.active)
1629
+ return;
1630
+ try {
1631
+ // Rationale: the effects stay off the startup graph; quit is the only time they load.
1632
+ const { captureQuitOutroFrame, playQuitOutro } = await import("./quit-outro.js");
1633
+ const frame = captureQuitOutroFrame(capture.rows, capture.columns, capture.height);
1634
+ if (frame === null || !this.runtime.active)
1635
+ return;
1636
+ await playQuitOutro(frame, capture.settings.effect, capture.settings.durationMs, {
1637
+ write: data => this.runtime.writeControl(data),
1638
+ ...(outro.now === undefined ? {} : { now: outro.now }),
1639
+ ...(outro.sleep === undefined ? {} : { sleep: outro.sleep }),
1640
+ ...(outro.seed === undefined ? {} : { seed: outro.seed }),
1641
+ });
1642
+ }
1643
+ catch {
1644
+ // Rationale: a failed or interrupted effect must never hold the terminal; restoration follows.
1645
+ }
1646
+ }
1647
+ #settleStoppedLifecycle() {
1648
+ void this.dispose().then(() => this.#resolveStoppedLifecycle(), () => this.#resolveStoppedLifecycle());
1649
+ }
1650
+ #resolveStoppedLifecycle() {
1651
+ const resolve = this.#resolveStopped;
1652
+ this.#resolveStopped = undefined;
1653
+ resolve?.();
1654
+ }
1655
+ // Invariant: incremental block updates notify listeners with the same complete view contract.
1656
+ #syncBlock(block) {
1657
+ this.root.applyTranscriptBlock(block);
1658
+ if (this.#customViewport && block.status === "live" && isCoalescedStreamBlock(block.kind)) {
1659
+ this.#streamPresentation.request();
1660
+ }
1661
+ else if (this.#streamPresentation.pending) {
1662
+ this.#streamPresentation.flush();
1663
+ }
1664
+ else {
1665
+ this.#streamPresentation.presentImmediate();
1666
+ }
1667
+ const view = this.view();
1668
+ for (const listener of this.#listeners)
1669
+ listener(view);
1670
+ return view;
1671
+ }
1672
+ #syncTerminalProgress(view) {
1673
+ if (!this.runtime.active)
1674
+ return;
1675
+ this.runtime.setTerminalProgress(this.#terminalProgressEnabled && view.lifecycle === "busy");
1676
+ }
1677
+ #syncView() {
1678
+ this.#streamPresentation.noteImmediatePresentation();
1679
+ const view = this.view();
1680
+ if (this.backend.sessionGeneration !== this.#sessionGeneration) {
1681
+ this.#copyIntentSequence += 1;
1682
+ this.#responseCopy?.reset();
1683
+ this.#cancelWaitingImages();
1684
+ this.root.resetPendingPastes();
1685
+ this.#promptSuggestions?.invalidate();
1686
+ this.#sessionGeneration = this.backend.sessionGeneration;
1687
+ // Invariant: delivery recovery invalidates callbacks, not same-session local recall or its draft.
1688
+ if (this.#sessionBindingGeneration !== this.backend.sessionBindingGeneration) {
1689
+ this.#sessionBindingGeneration = this.backend.sessionBindingGeneration;
1690
+ this.root.resetTranscript();
1691
+ this.#promptHistory?.reset(view.transcript.flatMap(block => block.kind === "user" ? [block.text] : []));
1692
+ }
1693
+ this.#activeLoginDialog = undefined;
1694
+ this.#extensionBridge.reset();
1695
+ // Invariant: a replaced session takes its transient viewport and owned-route state with it.
1696
+ this.root.resetViewport();
1697
+ this.#dialogHandle?.hide();
1698
+ this.#dialogHandle = undefined;
1699
+ this.#dialogId = undefined;
1700
+ this.#dialogSource = undefined;
1701
+ this.#setPointerReporting(false);
1702
+ this.root.setInputSurface(null);
1703
+ this.root.resetExtensionUi();
1704
+ this.root.resetWorkflowPresentation();
1705
+ }
1706
+ this.root.update(view);
1707
+ this.#syncDialog(view.dialog);
1708
+ this.#presentStartupChangelog(view);
1709
+ this.runtime.requestRender();
1710
+ for (const listener of this.#listeners)
1711
+ listener(view);
1712
+ return view;
1713
+ }
1714
+ // Rationale: release details stay one explicit command away; startup needs only the same quiet,
1715
+ // non-transcript acknowledgement that bare A1 uses for model and thinking changes.
1716
+ #presentStartupChangelog(view) {
1717
+ if (this.#startupChangelogHandled || !this.#customViewport)
1718
+ return;
1719
+ const diagnostic = view.diagnostics.find(candidate => candidate.code === "changelog-collapsed" || candidate.code === "changelog-expanded");
1720
+ // Invariant: a view synchronized before the runtime starts is not the moment of arrival; start() replays it.
1721
+ if (diagnostic === undefined || !this.runtime.active)
1722
+ return;
1723
+ this.#startupChangelogHandled = true;
1724
+ this.root.appendWorkflowStatus(STARTUP_CHANGELOG_NOTICE);
1725
+ }
1726
+ #openOwnedRoute(route, input) {
1727
+ const surface = this.#routeHost?.open(route, input) ?? null;
1728
+ if (surface === null)
1729
+ return { outcome: "failed", diagnostic: `route is unavailable: ${route}` };
1730
+ if (!this.runtime.active)
1731
+ return { outcome: "failed", diagnostic: "runtime is not active" };
1732
+ this.#dialogHandle?.hide();
1733
+ this.#dialogSource = "route";
1734
+ // Protocol: any-event reporting: hover and drag are what the screen is driven by, and
1735
+ // it also stops the terminal treating a drag as a text selection.
1736
+ this.#setPointerReporting(true);
1737
+ // Protocol: the interrupt chord is global, so it is watched on raw input rather than
1738
+ // through the overlay: the pinned shell handles that key before an overlay
1739
+ // ever sees it, which is why an owned screen must not rely on being asked.
1740
+ let armedAt = 0;
1741
+ const removeInterruptWatch = this.runtime.addInputListener(data => {
1742
+ if (!data.includes(INTERRUPT))
1743
+ return undefined;
1744
+ const now = Date.now();
1745
+ if (armedAt !== 0 && now - armedAt <= INTERRUPT_CHORD_MS) {
1746
+ armedAt = 0;
1747
+ closeSurface();
1748
+ void this.shutdown();
1749
+ return { consume: true };
1750
+ }
1751
+ armedAt = now;
1752
+ this.runtime.requestRender();
1753
+ // Invariant: the presented screen owns the chord, so the pinned shell never sees a
1754
+ // stray interrupt while it is up.
1755
+ return { consume: true };
1756
+ });
1757
+ let removeSurfacePreInput = () => { };
1758
+ const closeSurface = () => {
1759
+ removeSurfacePreInput();
1760
+ removeInterruptWatch();
1761
+ this.#setPointerReporting(false);
1762
+ this.#dialogHandle?.hide();
1763
+ this.#dialogHandle = undefined;
1764
+ this.#dialogId = undefined;
1765
+ this.#dialogSource = undefined;
1766
+ };
1767
+ // Compatibility: fullscreen Pi owns a fallback text-selection layer before focused overlay
1768
+ // components see pointer input. Route every mouse report to the owned screen
1769
+ // at the pre-input boundary so dropdowns, value hover, and numeric +/- work,
1770
+ // and consume even unhandled reports so settings content is never selected.
1771
+ removeSurfacePreInput = this.runtime.addPreInputListener(data => {
1772
+ const { events, rest } = parseMouseInput(data);
1773
+ if (events.length === 0)
1774
+ return undefined;
1775
+ for (const event of events)
1776
+ surface.handleMouse(event);
1777
+ if (surface.isClosed())
1778
+ closeSurface();
1779
+ else
1780
+ this.runtime.requestRender();
1781
+ return rest.length === 0 ? { consume: true } : { data: rest };
1782
+ });
1783
+ const rows = () => Math.max(1, this.runtime.viewport().rows);
1784
+ const component = {
1785
+ render: (width) => [...surface.render(Math.max(1, width), rows())],
1786
+ handleInput: (data) => {
1787
+ const { events, rest } = parseMouseInput(data);
1788
+ for (const event of events)
1789
+ surface.handleMouse(event);
1790
+ if (rest.length > 0)
1791
+ surface.handleInput(rest);
1792
+ if (surface.isClosed()) {
1793
+ closeSurface();
1794
+ return;
1795
+ }
1796
+ this.runtime.requestRender();
1797
+ },
1798
+ invalidate: () => this.runtime.requestRender(),
1799
+ };
1800
+ surface.onRenderRequested(() => this.runtime.requestRender());
1801
+ surface.onExitRequested(() => {
1802
+ closeSurface();
1803
+ void this.shutdown();
1804
+ });
1805
+ this.#dialogHandle = this.runtime.showOverlay(component, {
1806
+ width: "100%",
1807
+ maxHeight: "100%",
1808
+ anchor: "top-left",
1809
+ inputCoordination: "owned",
1810
+ });
1811
+ this.#dialogId = surface.id;
1812
+ return { outcome: "completed", diagnostic: null };
1813
+ }
1814
+ #syncDialog(dialog) {
1815
+ if (!this.runtime.active)
1816
+ return;
1817
+ if (dialog === null) {
1818
+ // Invariant: locally owned routes (notably /settings) are independent of backend
1819
+ // lifecycle/status events and remain open while an agent is working.
1820
+ if (this.#dialogSource !== "backend")
1821
+ return;
1822
+ this.#dialogHandle?.hide();
1823
+ this.#dialogHandle = undefined;
1824
+ this.#dialogId = undefined;
1825
+ this.#dialogSource = undefined;
1826
+ return;
1827
+ }
1828
+ if (this.#dialogSource === "backend" && this.#dialogId === dialog.id)
1829
+ return;
1830
+ this.#dialogHandle?.hide();
1831
+ this.#dialogSource = "backend";
1832
+ const component = createPiShellDialog(dialog, {
1833
+ onSelect: () => {
1834
+ this.#dialogHandle?.hide();
1835
+ this.#dialogHandle = undefined;
1836
+ this.#dialogId = undefined;
1837
+ this.#dialogSource = undefined;
1838
+ },
1839
+ onCancel: () => {
1840
+ this.#dialogHandle?.hide();
1841
+ this.#dialogHandle = undefined;
1842
+ this.#dialogId = undefined;
1843
+ this.#dialogSource = undefined;
1844
+ },
1845
+ });
1846
+ this.#dialogHandle = this.runtime.showOverlay(component, {
1847
+ width: "70%",
1848
+ maxHeight: "80%",
1849
+ anchor: "center",
1850
+ inputCoordination: "owned",
1851
+ });
1852
+ this.#dialogId = dialog.id;
1853
+ }
1854
+ hotkeysPresentation() {
1855
+ return this.root.hotkeysPresentation();
1856
+ }
1857
+ async #slashCommand(text) {
1858
+ const body = text.slice(1).trim();
1859
+ const separator = body.search(/\s/);
1860
+ const name = separator < 0 ? body : body.slice(0, separator);
1861
+ const argument = separator < 0 ? "" : body.slice(separator + 1).trimStart();
1862
+ if (this.#routeHost?.claims(name))
1863
+ return this.#openOwnedRoute(name);
1864
+ if (this.#isWorkflowRoute(name))
1865
+ return this.runWorkflow({ command: name, argument });
1866
+ if (this.#skillsCollapsed()) {
1867
+ if (name === SKILLS_COMMAND_NAME)
1868
+ return this.#runSkillsCommand(text, argument);
1869
+ const rewritten = rewriteSkillsTunnelSubmission(text);
1870
+ if (rewritten !== text)
1871
+ return this.#submitSkillPrompt(rewritten, text);
1872
+ }
1873
+ // Compatibility: unknown slash input, prompt templates, skills, and extension commands remain Pi prompt input.
1874
+ this.#rememberInput(text, "slash");
1875
+ this.root.resumeViewportFollowing();
1876
+ return this.#execute({
1877
+ type: this.view().lifecycle === "busy" ? "steer" : "prompt",
1878
+ correlationId: this.#correlation("prompt-command"),
1879
+ sessionId: this.backend.sessionId,
1880
+ text,
1881
+ });
1882
+ }
1883
+ #installAutocompleteCommands() {
1884
+ this.root.editor.setAutocompleteCommands(this.backend.workflowAutocompleteCommands());
1885
+ this.#installedCommandSignature = this.#commandListSignature();
1886
+ }
1887
+ #commandListSignature() {
1888
+ return JSON.stringify([this.#skills?.presentation() ?? "expand", this.backend.disposed ? [] : this.backend.workflowAutocompleteCommands().map(command => command.name)]);
1889
+ }
1890
+ // Invariant: collapse applies only while the engine registers skill commands; otherwise there is nothing to collapse.
1891
+ #skillsCollapsed() {
1892
+ return this.#skills !== null && this.#skills.presentation() === "collapse"
1893
+ && !this.backend.disposed && this.backend.pinnedSettingsSnapshot().enableSkillCommands;
1894
+ }
1895
+ #skillSummaries() {
1896
+ return skillsFromCommands(this.backend.workflowAutocompleteCommands());
1897
+ }
1898
+ // Protocol: bare "/skills" opens the dialog, "/skills <name> [args]" applies directly, and an unknown name is a command outcome.
1899
+ async #runSkillsCommand(text, argument) {
1900
+ const skills = this.#skillSummaries();
1901
+ const trimmed = argument.trim();
1902
+ if (trimmed.length === 0) {
1903
+ this.showSkillsSelector(skills);
1904
+ return { outcome: "completed", diagnostic: null };
1905
+ }
1906
+ const separator = trimmed.search(/\s/u);
1907
+ const token = separator < 0 ? trimmed : trimmed.slice(0, separator);
1908
+ const skill = findSkillByArgument(skills, token);
1909
+ if (skill === undefined) {
1910
+ const message = "Unknown skill: " + token;
1911
+ this.root.appendWorkflowMessage({ kind: "error", message });
1912
+ this.runtime.requestRender();
1913
+ return { outcome: "failed", diagnostic: message };
1914
+ }
1915
+ return this.#submitSkillPrompt(skillPrompt(skill.name, separator < 0 ? "" : trimmed.slice(separator + 1)), text);
1916
+ }
1917
+ // Rationale: the engine expands "/skill:<name> args" itself; history keeps the form the user typed so recall restores the invocation.
1918
+ #submitSkillPrompt(prompt, typed) {
1919
+ this.#rememberInput(typed, "slash");
1920
+ this.root.resumeViewportFollowing();
1921
+ return this.#execute({
1922
+ type: this.view().lifecycle === "busy" ? "steer" : "prompt",
1923
+ correlationId: this.#correlation("prompt-command"),
1924
+ sessionId: this.backend.sessionId,
1925
+ text: prompt,
1926
+ });
1927
+ }
1928
+ async #completeTreeSelection(entryId, skipSummaryPrompt) {
1929
+ let summarize = false;
1930
+ let customInstructions;
1931
+ if (!skipSummaryPrompt) {
1932
+ while (true) {
1933
+ const choice = await this.#extensionBridge.context.select("Summarize branch?", [
1934
+ "No summary",
1935
+ "Summarize",
1936
+ "Summarize with custom prompt",
1937
+ ]);
1938
+ if (choice === undefined) {
1939
+ await this.showTreeSelector(entryId);
1940
+ return;
1941
+ }
1942
+ summarize = choice !== "No summary";
1943
+ if (choice === "Summarize with custom prompt") {
1944
+ customInstructions = await this.#extensionBridge.context.editor("Custom summarization instructions", "");
1945
+ if (customInstructions === undefined)
1946
+ continue;
1947
+ }
1948
+ break;
1949
+ }
1950
+ }
1951
+ const result = await this.runWorkflow({
1952
+ command: "tree",
1953
+ argument: "",
1954
+ selection: entryId,
1955
+ treeSummary: {
1956
+ summarize,
1957
+ ...(customInstructions === undefined ? {} : { customInstructions }),
1958
+ },
1959
+ });
1960
+ if (result.diagnostic === "Branch summarization cancelled")
1961
+ await this.showTreeSelector(entryId);
1962
+ }
1963
+ #startWorkflowLogin(request) {
1964
+ this.#finishWorkflowLogin();
1965
+ const dialog = createPiShellLoginDialog({
1966
+ getColumns: () => this.runtime.viewport().columns,
1967
+ getRows: () => this.runtime.viewport().rows,
1968
+ requestRender: () => this.runtime.requestRender(),
1969
+ }, request.providerId, success => {
1970
+ if (!success)
1971
+ this.#finishWorkflowLogin();
1972
+ }, request.providerName);
1973
+ this.#activeLoginDialog = dialog;
1974
+ this.root.setInputSurface(dialog);
1975
+ this.runtime.requestRender();
1976
+ }
1977
+ #requestWorkflowInput(request) {
1978
+ const dialog = this.#activeLoginDialog;
1979
+ if (!dialog)
1980
+ return Promise.resolve(null);
1981
+ if (request.type === "select") {
1982
+ return new Promise(resolve => {
1983
+ const options = request.options ?? [];
1984
+ const labels = options.map(option => option.label);
1985
+ const restoreDialog = () => {
1986
+ if (this.#activeLoginDialog === dialog)
1987
+ this.root.setInputSurface(dialog);
1988
+ this.runtime.requestRender();
1989
+ };
1990
+ const selector = createPiShellExtensionSelector(request.message, labels, label => {
1991
+ const id = options.find(option => option.label === label)?.id;
1992
+ restoreDialog();
1993
+ resolve(id ?? null);
1994
+ }, () => {
1995
+ restoreDialog();
1996
+ resolve(null);
1997
+ });
1998
+ this.root.setInputSurface(selector, false);
1999
+ this.runtime.requestRender();
2000
+ });
2001
+ }
2002
+ const response = request.type === "manual-code"
2003
+ ? dialog.showManualInput(request.message)
2004
+ : dialog.showPrompt(request.message, request.placeholder);
2005
+ this.runtime.requestRender();
2006
+ return response.then(value => value, () => null);
2007
+ }
2008
+ #notifyWorkflowLogin(event) {
2009
+ const dialog = this.#activeLoginDialog;
2010
+ if (!dialog)
2011
+ return;
2012
+ if (event.type === "auth_url")
2013
+ dialog.showAuth(event.url, event.instructions);
2014
+ else if (event.type === "device_code") {
2015
+ dialog.showDeviceCode(event);
2016
+ dialog.showWaiting("Waiting for authentication...");
2017
+ }
2018
+ else if (event.type === "info")
2019
+ dialog.showInfo(event.message, event.links);
2020
+ else if (event.type === "waiting")
2021
+ dialog.showWaiting(event.message);
2022
+ else
2023
+ dialog.showProgress(event.message);
2024
+ this.runtime.requestRender();
2025
+ }
2026
+ #finishWorkflowLogin() {
2027
+ if (!this.#activeLoginDialog)
2028
+ return;
2029
+ this.#activeLoginDialog = undefined;
2030
+ this.root.setInputSurface(null);
2031
+ this.runtime.requestRender();
2032
+ }
2033
+ async #execute(command, draft) {
2034
+ if (draft === undefined)
2035
+ return this.backend.execute(command);
2036
+ const revision = this.#editorRevision;
2037
+ try {
2038
+ assertOwnedUiCommand(command);
2039
+ }
2040
+ catch (error) {
2041
+ return this.#recoverSubmission(draft, revision, error);
2042
+ }
2043
+ try {
2044
+ const result = await this.backend.execute(command);
2045
+ if (result.outcome === "rejected")
2046
+ return this.#recoverSubmission(draft, revision);
2047
+ return result;
2048
+ }
2049
+ catch {
2050
+ // Security: dispatch might already have reached the provider. Never retry automatically.
2051
+ this.root.editor.addToHistory(draft);
2052
+ this.#promptHistory?.rememberRecovery(draft);
2053
+ this.#reportSubmissionError(undefined, "Submission failed; delivery is uncertain. Check the conversation before retrying. Press Up to recover the draft.");
2054
+ return { outcome: "failed", diagnostic: "submission delivery is uncertain" };
2055
+ }
2056
+ }
2057
+ async #guardSubmission(draft, action) {
2058
+ const revision = this.#editorRevision;
2059
+ try {
2060
+ return await action();
2061
+ }
2062
+ catch (error) {
2063
+ if (error instanceof ImageAttachmentError && error.code === "image-canceled")
2064
+ return rejected("image submission canceled");
2065
+ return this.#recoverSubmission(draft, revision, error);
2066
+ }
2067
+ }
2068
+ #recoverSubmission(draft, revision, error) {
2069
+ this.root.editor.addToHistory(draft);
2070
+ this.#promptHistory?.rememberRecovery(draft);
2071
+ // Concurrency: never overwrite input typed (even typed and cleared) after this submission.
2072
+ if (revision === this.#editorRevision && this.root.editor.getText().length === 0)
2073
+ this.root.editor.setText(draft);
2074
+ const message = error instanceof ImageAttachmentError ? error.message : "Submission rejected. Check the prompt and attachments.";
2075
+ this.#reportSubmissionError(error, `${message} Press Up to recover the draft.`);
2076
+ return rejected(message);
2077
+ }
2078
+ #reportSubmissionError(error, message) {
2079
+ // Security: arbitrary provider/extension error messages can contain the entire request.
2080
+ try {
2081
+ this.root.appendWorkflowResult({ command: "debug", outcome: "failed", message: message
2082
+ ?? (error instanceof ImageAttachmentError ? error.message : "Submission failed. Check the prompt and try again.") });
2083
+ this.runtime.requestRender();
2084
+ }
2085
+ catch { /* Security: error presentation cannot create another rejected submission callback. */ }
2086
+ }
2087
+ #simple(type) {
2088
+ return { type, correlationId: this.#correlation(type), sessionId: this.backend.sessionId };
2089
+ }
2090
+ #correlation(prefix) {
2091
+ this.#sequence += 1;
2092
+ return `pi-shell-${prefix}-${this.#sequence}`;
2093
+ }
2094
+ }
2095
+ function isCoalescedStreamBlock(kind) {
2096
+ return kind === "assistant" || kind === "thinking" || kind === "tool-call" || kind === "tool-result";
2097
+ }
2098
+ function copyAcknowledgement(snapshot) {
2099
+ if (snapshot.literal !== true)
2100
+ return { characters: snapshot.sourceUnits, hasNonWhitespace: true };
2101
+ let characters = Math.max(0, snapshot.rows.length - 1);
2102
+ let hasNonWhitespace = false;
2103
+ for (const row of snapshot.rows) {
2104
+ characters += row.text.length;
2105
+ hasNonWhitespace ||= /\S/u.test(row.text);
2106
+ }
2107
+ return { characters, hasNonWhitespace };
2108
+ }
2109
+ export function formatSessionResumeCommand(metadata) {
2110
+ const args = [PRODUCT_TEXT.commandName];
2111
+ if (!metadata.usesDefaultSessionDir)
2112
+ args.push("--session-dir", quoteCommandArgument(metadata.sessionDir));
2113
+ args.push("--session", metadata.sessionId);
2114
+ return args.join(" ");
2115
+ }
2116
+ export function quoteCommandArgument(value) {
2117
+ if (value.length > 0 && !/[^a-zA-Z0-9_\-./~:@]/.test(value))
2118
+ return value;
2119
+ return `'${value.replaceAll("'", `'\\''`)}'`;
2120
+ }
2121
+ function dim(value) {
2122
+ return `\u001b[2m${value}\u001b[22m`;
2123
+ }
2124
+ function modelReference(model) {
2125
+ if (typeof model !== "object" || model === null)
2126
+ return "";
2127
+ const value = model;
2128
+ const provider = typeof value.provider === "string" ? value.provider : "";
2129
+ const id = typeof value.id === "string" ? value.id : typeof value.modelId === "string" ? value.modelId : "";
2130
+ return provider && id ? `${provider}/${id}` : "";
2131
+ }
2132
+ function rejected(diagnostic) {
2133
+ return { outcome: "rejected", diagnostic };
2134
+ }
2135
+ function modelKey(view) {
2136
+ return view.activeModel === null ? "" : `${view.activeModel.providerId}/${view.activeModel.modelId}`;
2137
+ }
2138
+ function workflowAdapterResult(result) {
2139
+ if (result.outcome === "completed")
2140
+ return { outcome: "completed", diagnostic: null };
2141
+ if (result.outcome === "failed")
2142
+ return { outcome: "failed", diagnostic: result.message };
2143
+ return { outcome: "rejected", diagnostic: result.message };
2144
+ }
2145
+ const INTERRUPT = "\u0003";
2146
+ const INTERRUPT_CHORD_MS = 1_500;
2147
+ const RELOAD_SURFACE_MIN_VISIBLE_MS = 400;
2148
+ const STARTUP_CHANGELOG_NOTICE = "Run /changelog to view the full release notes.";
2149
+ // Rationale: the outro is not configurable; the switch only decides whether this plan plays.
2150
+ const QUIT_OUTRO_EFFECT = "fall";
2151
+ const QUIT_OUTRO_DURATION_MS = 800;