@timurproko/a1 0.2.7-dev.1252 → 0.2.7-dev.1264

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 (296) hide show
  1. package/bin/ui.js +3 -3
  2. package/dist/app/session-shell/clipboard-diagnostics.d.ts +2 -2
  3. package/dist/app/session-shell/clipboard-image.d.ts +0 -1
  4. package/dist/app/session-shell/clipboard-image.js +1 -1
  5. package/dist/app/session-shell/dialog-coordinator.d.ts +6 -5
  6. package/dist/app/session-shell/dialog-coordinator.js +3 -4
  7. package/dist/app/session-shell/dock-chrome.d.ts +11 -6
  8. package/dist/app/session-shell/dock-chrome.js +5 -8
  9. package/dist/app/session-shell/editor-hyperlink-budget.d.ts +0 -2
  10. package/dist/app/session-shell/editor-hyperlink-budget.js +1 -1
  11. package/dist/app/session-shell/exit-notice.d.ts +2 -2
  12. package/dist/app/session-shell/exit-notice.js +1 -1
  13. package/dist/app/session-shell/extension-surface.d.ts +8 -7
  14. package/dist/app/session-shell/helper-pool.d.ts +3 -4
  15. package/dist/app/session-shell/helper-pool.js +1 -1
  16. package/dist/app/session-shell/image-preparation-client.d.ts +4 -3
  17. package/dist/app/session-shell/image-preparation.d.ts +0 -2
  18. package/dist/app/session-shell/image-preparation.js +2 -2
  19. package/dist/app/session-shell/image-source.d.ts +2 -3
  20. package/dist/app/session-shell/image-source.js +2 -2
  21. package/dist/app/session-shell/input-surface-switch.d.ts +9 -7
  22. package/dist/app/session-shell/input-surface-switch.js +1 -2
  23. package/dist/app/session-shell/login-interaction.d.ts +5 -4
  24. package/dist/app/session-shell/login-interaction.js +2 -3
  25. package/dist/app/session-shell/paste-executor.d.ts +4 -8
  26. package/dist/app/session-shell/paste-executor.js +2 -2
  27. package/dist/app/session-shell/paste-protocol.d.ts +2 -2
  28. package/dist/app/session-shell/path-chip-presentation.d.ts +0 -5
  29. package/dist/app/session-shell/path-chip-presentation.js +3 -3
  30. package/dist/app/session-shell/prompt-chips.d.ts +8 -7
  31. package/dist/app/session-shell/prompt-history-controller.d.ts +3 -3
  32. package/dist/app/session-shell/prompt-submission.d.ts +5 -2
  33. package/dist/app/session-shell/prompt-submission.js +13 -14
  34. package/dist/app/session-shell/quit-outro-effects.d.ts +3 -3
  35. package/dist/app/session-shell/quit-outro-effects.js +1 -4
  36. package/dist/app/session-shell/quit-outro.d.ts +9 -12
  37. package/dist/app/session-shell/quit-outro.js +11 -11
  38. package/dist/app/session-shell/resource-labels.d.ts +2 -0
  39. package/dist/app/session-shell/resource-labels.js +158 -0
  40. package/dist/app/session-shell/response-copy-protocol.d.ts +3 -2
  41. package/dist/app/session-shell/response-copy-transport.d.ts +2 -14
  42. package/dist/app/session-shell/response-copy-transport.js +1 -1
  43. package/dist/app/session-shell/session-lifecycle.d.ts +2 -1
  44. package/dist/app/session-shell/session-prompt-history.d.ts +29 -0
  45. package/dist/app/session-shell/session-prompt-history.js +80 -0
  46. package/dist/app/session-shell/session-selectors.d.ts +46 -0
  47. package/dist/app/session-shell/session-selectors.js +269 -0
  48. package/dist/app/session-shell/session-shell-root.d.ts +76 -113
  49. package/dist/app/session-shell/session-shell-root.js +103 -329
  50. package/dist/app/session-shell/session-shell.d.ts +14 -37
  51. package/dist/app/session-shell/session-shell.js +177 -612
  52. package/dist/app/session-shell/session-viewport-controller.d.ts +9 -16
  53. package/dist/app/session-shell/session-viewport-controller.js +42 -320
  54. package/dist/app/session-shell/settings-bindings.d.ts +25 -3
  55. package/dist/app/session-shell/settings-bindings.js +26 -2
  56. package/dist/app/session-shell/share-operation.d.ts +3 -3
  57. package/dist/app/session-shell/share-operation.js +4 -6
  58. package/dist/app/session-shell/shell-clipboard.d.ts +59 -0
  59. package/dist/app/session-shell/shell-clipboard.js +119 -0
  60. package/dist/app/session-shell/shell-editor-factory.d.ts +8 -4
  61. package/dist/app/session-shell/shell-editor-factory.js +13 -15
  62. package/dist/app/session-shell/shell-host.d.ts +16 -17
  63. package/dist/app/session-shell/shell-host.js +18 -19
  64. package/dist/app/session-shell/shell-layout.d.ts +2 -2
  65. package/dist/app/session-shell/shell-prompt-suggestions.d.ts +26 -0
  66. package/dist/app/session-shell/shell-prompt-suggestions.js +48 -0
  67. package/dist/app/session-shell/suggestion-surface.d.ts +1 -6
  68. package/dist/app/session-shell/suggestion-surface.js +1 -1
  69. package/dist/app/session-shell/system-clipboard.d.ts +2 -14
  70. package/dist/app/session-shell/system-clipboard.js +2 -7
  71. package/dist/app/session-shell/transcript-document.d.ts +11 -8
  72. package/dist/app/session-shell/transcript-document.js +13 -14
  73. package/dist/app/session-shell/viewport-layout.d.ts +2 -2
  74. package/dist/app/session-shell/viewport-pointer.d.ts +83 -0
  75. package/dist/app/session-shell/viewport-pointer.js +361 -0
  76. package/dist/app/session-shell/workflow-output.d.ts +5 -3
  77. package/dist/app/session-shell/workflow-output.js +13 -15
  78. package/dist/cli/package-messages.d.ts +0 -1
  79. package/dist/cli/package-messages.js +1 -1
  80. package/dist/cli/session-context.d.ts +1 -1
  81. package/dist/cli/uninstall.d.ts +3 -2
  82. package/dist/composition/owned-settings.d.ts +2 -1
  83. package/dist/composition/owned-settings.js +0 -3
  84. package/dist/composition/owned-ui.d.ts +1 -1
  85. package/dist/composition/owned-ui.js +77 -73
  86. package/dist/composition/reference-selection-options.d.ts +1 -1
  87. package/dist/composition/reference-selection-options.js +1 -1
  88. package/dist/composition/session-runtime-registry.d.ts +2 -1
  89. package/dist/composition/settings-route-host.js +3 -10
  90. package/dist/composition/settings-search-input.d.ts +2 -1
  91. package/dist/composition/startup-route.d.ts +2 -2
  92. package/dist/composition/startup-route.js +2 -2
  93. package/dist/contracts/owned-ui/extension-ui.d.ts +2 -1
  94. package/dist/contracts/owned-ui/index.d.ts +2 -1
  95. package/dist/contracts/owned-ui/index.js +1 -1
  96. package/dist/contracts/owned-ui/session-presenters.d.ts +3 -0
  97. package/dist/contracts/owned-ui/shell-components.d.ts +543 -0
  98. package/dist/contracts/owned-ui/validation.d.ts +1 -11
  99. package/dist/contracts/owned-ui/validation.js +8 -104
  100. package/dist/contracts/presentation/component.d.ts +17 -0
  101. package/dist/contracts/presentation/component.js +8 -0
  102. package/dist/contracts/presentation/index.d.ts +6 -15
  103. package/dist/contracts/presentation/index.js +2 -0
  104. package/dist/contracts/presentation/terminal.d.ts +284 -0
  105. package/dist/contracts/presentation/terminal.js +1 -0
  106. package/dist/contracts/presentation/theme.d.ts +46 -0
  107. package/dist/contracts/presentation/theme.js +1 -0
  108. package/dist/features/launch/development-launch.js +1 -1
  109. package/dist/features/launch/runtime-selection.d.ts +2 -2
  110. package/dist/features/launch/runtime-selection.js +2 -2
  111. package/dist/features/owned-ui/project-trust-prompt.d.ts +2 -2
  112. package/dist/features/owned-ui/project-trust-prompt.js +1 -1
  113. package/dist/features/owned-ui/release-note-state.d.ts +2 -1
  114. package/dist/features/owned-ui/settings-app.js +49 -425
  115. package/dist/features/owned-ui/settings-edits.d.ts +31 -0
  116. package/dist/features/owned-ui/settings-edits.js +139 -0
  117. package/dist/features/owned-ui/settings-model-dialog.d.ts +41 -0
  118. package/dist/features/owned-ui/settings-model-dialog.js +194 -0
  119. package/dist/features/owned-ui/settings-scroll-rail.d.ts +29 -0
  120. package/dist/features/owned-ui/settings-scroll-rail.js +79 -0
  121. package/dist/features/owned-ui/settings-search-input.d.ts +2 -1
  122. package/dist/features/prompt-history/service.d.ts +3 -2
  123. package/dist/foundation/lifecycle/claim-gate.d.ts +2 -1
  124. package/dist/foundation/release/automatic-update.d.ts +5 -14
  125. package/dist/foundation/release/automatic-update.js +15 -22
  126. package/dist/foundation/release/bootstrap.js +4 -4
  127. package/dist/foundation/release/dependency-certification.d.ts +0 -1
  128. package/dist/foundation/release/dependency-certification.js +1 -1
  129. package/dist/foundation/release/dependency-layer.js +3 -3
  130. package/dist/foundation/release/early-accent.d.ts +2 -2
  131. package/dist/foundation/release/early-accent.js +1 -1
  132. package/dist/foundation/release/index.d.ts +2 -2
  133. package/dist/foundation/release/index.js +1 -1
  134. package/dist/foundation/release/latest-release.d.ts +3 -18
  135. package/dist/foundation/release/latest-release.js +11 -11
  136. package/dist/foundation/release/managed-path.d.ts +10 -0
  137. package/dist/foundation/release/managed-path.js +26 -0
  138. package/dist/foundation/release/ordinary-launch-selection.d.ts +1 -1
  139. package/dist/foundation/release/ordinary-launch-selection.js +1 -1
  140. package/dist/foundation/release/release-gc.d.ts +3 -3
  141. package/dist/foundation/release/release-gc.js +10 -12
  142. package/dist/foundation/release/{cohort-state.d.ts → release-state.d.ts} +23 -23
  143. package/dist/foundation/release/{cohort-state.js → release-state.js} +8 -8
  144. package/dist/foundation/release/restart-certification.js +3 -4
  145. package/dist/foundation/release/update-activation.js +3 -3
  146. package/dist/foundation/release/update-execution-lease.d.ts +2 -3
  147. package/dist/foundation/release/update-execution-lease.js +2 -8
  148. package/dist/foundation/release/update-installer.d.ts +45 -0
  149. package/dist/foundation/release/update-installer.js +57 -0
  150. package/dist/foundation/release/update-launch.d.ts +2 -2
  151. package/dist/foundation/release/update-recovery.js +2 -9
  152. package/dist/foundation/release/update.d.ts +4 -25
  153. package/dist/foundation/release/update.js +164 -183
  154. package/dist/foundation/startup/startup-budget.d.ts +5 -5
  155. package/dist/foundation/startup/startup-budget.js +2 -2
  156. package/dist/integrations/pi/components/bracketed-paste.d.ts +33 -0
  157. package/dist/integrations/pi/components/bracketed-paste.js +123 -0
  158. package/dist/integrations/pi/components/editor-interaction.d.ts +4 -12
  159. package/dist/integrations/pi/components/index.d.ts +15 -9
  160. package/dist/integrations/pi/components/index.js +9 -5
  161. package/dist/integrations/pi/components/lazy-selectors.d.ts +2 -10
  162. package/dist/integrations/pi/components/lazy-selectors.js +1 -1
  163. package/dist/integrations/pi/components/modal-frame.d.ts +5 -22
  164. package/dist/integrations/pi/components/modal-frame.js +3 -23
  165. package/dist/integrations/pi/components/owned-editor-ux.d.ts +4 -3
  166. package/dist/integrations/pi/components/owned-editor-ux.js +46 -140
  167. package/dist/integrations/pi/components/prompt-input-port.d.ts +2 -19
  168. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -1
  169. package/dist/integrations/pi/components/shell-editor-autocomplete.d.ts +3 -2
  170. package/dist/integrations/pi/components/shell-footer-status.d.ts +2 -2
  171. package/dist/integrations/pi/components/shell-footer-status.js +3 -2
  172. package/dist/integrations/pi/components/shell-presenters-info.d.ts +6 -5
  173. package/dist/integrations/pi/components/shell-presenters-info.js +2 -1
  174. package/dist/integrations/pi/components/shell-session-info-reference.d.ts +2 -1
  175. package/dist/integrations/pi/components/shell-shared-facade.d.ts +33 -227
  176. package/dist/integrations/pi/components/shell-shared-facade.js +8 -1
  177. package/dist/integrations/pi/components/skills-command.d.ts +1 -9
  178. package/dist/integrations/pi/components/skills-command.js +5 -5
  179. package/dist/integrations/pi/components/theme.d.ts +9 -2
  180. package/dist/integrations/pi/components/theme.js +17 -2
  181. package/dist/integrations/pi/components/thinking-selector-dialog.d.ts +2 -1
  182. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +2 -2
  183. package/dist/integrations/pi/engine/adapter.d.ts +4 -13
  184. package/dist/integrations/pi/engine/adapter.js +9 -61
  185. package/dist/integrations/pi/engine/changelog.d.ts +2 -2
  186. package/dist/integrations/pi/engine/changelog.js +3 -3
  187. package/dist/integrations/pi/engine/compaction-progress.d.ts +2 -3
  188. package/dist/integrations/pi/engine/compaction-progress.js +1 -1
  189. package/dist/integrations/pi/engine/conformance.d.ts +2 -1
  190. package/dist/integrations/pi/engine/default-model-setting.d.ts +0 -2
  191. package/dist/integrations/pi/engine/default-model-setting.js +1 -2
  192. package/dist/integrations/pi/engine/event-delivery.d.ts +2 -1
  193. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -1
  194. package/dist/integrations/pi/engine/host.js +3 -3
  195. package/dist/integrations/pi/engine/message-values.d.ts +0 -1
  196. package/dist/integrations/pi/engine/message-values.js +1 -1
  197. package/dist/integrations/pi/engine/pending-delivery.d.ts +0 -4
  198. package/dist/integrations/pi/engine/pending-delivery.js +3 -3
  199. package/dist/integrations/pi/engine/ports.d.ts +7 -1
  200. package/dist/integrations/pi/engine/ports.js +4 -0
  201. package/dist/integrations/pi/engine/project-trust-preflight.d.ts +2 -1
  202. package/dist/integrations/pi/engine/prompt-suggestions.d.ts +3 -2
  203. package/dist/integrations/pi/engine/provider-authentication.d.ts +1 -1
  204. package/dist/integrations/pi/engine/public-main-entry.d.ts +1 -5
  205. package/dist/integrations/pi/engine/public-main-entry.js +1 -1
  206. package/dist/integrations/pi/engine/repository-metadata.d.ts +49 -0
  207. package/dist/integrations/pi/engine/repository-metadata.js +189 -0
  208. package/dist/integrations/pi/engine/repository-pr-rest.d.ts +1 -9
  209. package/dist/integrations/pi/engine/repository-pr-rest.js +2 -2
  210. package/dist/integrations/pi/engine/repository-pr.d.ts +1 -3
  211. package/dist/integrations/pi/engine/repository-pr.js +1 -1
  212. package/dist/integrations/pi/engine/resource-catalog.d.ts +2 -1
  213. package/dist/integrations/pi/engine/session-integration.d.ts +1 -1
  214. package/dist/integrations/pi/engine/session-runtime.d.ts +7 -12
  215. package/dist/integrations/pi/engine/session-runtime.js +21 -178
  216. package/dist/integrations/pi/engine/settings-bridge.d.ts +0 -2
  217. package/dist/integrations/pi/engine/settings-bridge.js +1 -1
  218. package/dist/integrations/pi/engine/settings-port.d.ts +3 -2
  219. package/dist/integrations/pi/engine/transcript-projection.d.ts +2 -1
  220. package/dist/integrations/pi/engine/view-state.d.ts +21 -2
  221. package/dist/integrations/pi/engine/view-state.js +129 -1
  222. package/dist/integrations/pi/engine/workflow-contexts.d.ts +1 -1
  223. package/dist/integrations/pi/engine/workflow-runner.d.ts +1 -2
  224. package/dist/integrations/pi/engine/workflow-runner.js +254 -365
  225. package/dist/integrations/pi/engine/workflow-share.d.ts +9 -0
  226. package/dist/integrations/pi/engine/workflow-share.js +168 -0
  227. package/dist/integrations/pi/engine/workflow-support.d.ts +0 -20
  228. package/dist/integrations/pi/engine/workflow-support.js +4 -65
  229. package/dist/integrations/pi/engine/workflows.d.ts +5 -5
  230. package/dist/integrations/pi/session-presenters/components.d.ts +3 -0
  231. package/dist/integrations/pi/session-presenters/components.js +75 -0
  232. package/dist/integrations/pi/session-presenters/index.d.ts +1 -0
  233. package/dist/integrations/pi/session-presenters/index.js +1 -0
  234. package/dist/integrations/pi/session-presenters/presentation.d.ts +3 -0
  235. package/dist/integrations/pi/session-presenters/presentation.js +10 -0
  236. package/dist/integrations/pi/session-presenters/presenters.d.ts +2 -1
  237. package/dist/integrations/pi/session-presenters/presenters.js +3 -1
  238. package/dist/integrations/pi/tui-runtime/adapter.d.ts +9 -19
  239. package/dist/integrations/pi/tui-runtime/adapter.js +56 -174
  240. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +9 -44
  241. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  242. package/dist/integrations/pi/tui-runtime/index.js +1 -0
  243. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +4 -6
  244. package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +4 -10
  245. package/dist/integrations/pi/tui-runtime/overlay-geometry.js +3 -9
  246. package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +2 -2
  247. package/dist/integrations/pi/tui-runtime/runtime-factory.d.ts +3 -0
  248. package/dist/integrations/pi/tui-runtime/runtime-factory.js +11 -0
  249. package/dist/ui/components/index.d.ts +2 -2
  250. package/dist/ui/components/index.js +1 -1
  251. package/dist/ui/components/selection-copy.d.ts +0 -1
  252. package/dist/ui/components/selection-copy.js +0 -12
  253. package/dist/ui/components/theme.d.ts +4 -19
  254. package/dist/ui/components/theme.js +6 -0
  255. package/dist/ui/components/transcript-viewport-frame.d.ts +120 -0
  256. package/dist/ui/components/transcript-viewport-frame.js +314 -0
  257. package/dist/ui/components/transcript-viewport-types.d.ts +147 -0
  258. package/dist/ui/components/transcript-viewport-types.js +1 -0
  259. package/dist/ui/components/transcript-viewport.d.ts +2 -147
  260. package/dist/ui/components/transcript-viewport.js +87 -315
  261. package/dist/ui/settings/declarations.d.ts +2 -3
  262. package/dist/ui/settings/declarations.js +2 -3
  263. package/dist/ui/settings/early-accent.js +1 -1
  264. package/dist/ui/settings/index.d.ts +3 -5
  265. package/dist/ui/settings/index.js +2 -3
  266. package/dist/ui/settings/manager.d.ts +0 -4
  267. package/dist/ui/settings/manager.js +6 -62
  268. package/dist/ui/settings/resolution.d.ts +6 -18
  269. package/dist/ui/settings/resolution.js +4 -103
  270. package/dist/ui/settings/sections.d.ts +0 -4
  271. package/dist/ui/settings/sections.js +1 -1
  272. package/docs/architecture/boundaries.md +2 -2
  273. package/docs/architecture/internal-naming.md +2 -0
  274. package/docs/architecture/project-structure.md +4 -2
  275. package/docs/validation.md +1 -1
  276. package/package.json +3 -4
  277. package/dist/integrations/pi/components/components.d.ts +0 -4
  278. package/dist/integrations/pi/components/components.js +0 -48
  279. package/dist/integrations/pi/components/conformance.d.ts +0 -18
  280. package/dist/integrations/pi/components/conformance.js +0 -70
  281. package/dist/integrations/pi/components/shell-components.d.ts +0 -7
  282. package/dist/integrations/pi/components/shell-components.js +0 -7
  283. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +0 -33
  284. package/dist/integrations/pi/components/upstream/theme/theme-controller.js +0 -114
  285. package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -9
  286. package/dist/integrations/pi/engine/diagnostics-state.js +0 -34
  287. package/dist/integrations/pi/engine/usage-view.d.ts +0 -4
  288. package/dist/integrations/pi/engine/usage-view.js +0 -56
  289. package/dist/integrations/pi/tui-runtime/contracts.d.ts +0 -166
  290. package/dist/ui/settings/migrations.d.ts +0 -19
  291. package/dist/ui/settings/migrations.js +0 -225
  292. package/dist/ui/settings/progress-palette.generated.d.ts +0 -139
  293. package/dist/ui/settings/progress-palette.generated.js +0 -139
  294. /package/dist/{integrations/pi/tui-runtime/contracts.js → contracts/owned-ui/shell-components.js} +0 -0
  295. /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.d.ts +0 -0
  296. /package/dist/{foundation/release → contracts/presentation}/progress-palette.generated.js +0 -0
@@ -1,14 +1,8 @@
1
- import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
2
1
  import { promptArrow } from "../../ui/components/prompt-input.js";
3
2
  import { composeSubmittedPromptRows, submittedPromptLayout, } from "../../ui/components/submitted-prompt.js";
4
3
  import { nativeHyperlinkStyle } from "../../ui/components/spans.js";
5
4
  import { paintTextSelection } from "../../ui/components/text-selection.js";
6
5
  import { progressStatusFrame, progressStatusText } from "../../ui/components/progress-status.js";
7
- import { createPiQueuedInputStatus, createPiShellFooter, createPiShellHeader, createPiShellLoadedResources, createPiShellStatus, } from "../../integrations/pi/components/shell-footer-status.js";
8
- import { createPiShellTranscriptComponent, } from "../../integrations/pi/components/shell-presenters-transcript.js";
9
- import { onPiThemeChange, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
10
- import { piShellTruncateToWidth, } from "../../integrations/pi/components/shell-shared-facade.js";
11
- import {} from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
12
6
  import { PromptChipStore } from "./prompt-chips.js";
13
7
  import { SessionViewportController } from "./session-viewport-controller.js";
14
8
  import { createShellEditor } from "./shell-editor-factory.js";
@@ -18,14 +12,15 @@ import { WorkflowOutput } from "./workflow-output.js";
18
12
  import { InputSurfaceSwitch } from "./input-surface-switch.js";
19
13
  import { PinnedLayout } from "./shell-layout.js";
20
14
  import { ViewportLayout } from "./viewport-layout.js";
21
- import { nativeTranscriptLinkColor, TranscriptDocument } from "./transcript-document.js";
15
+ import { transcriptLinkColor, TranscriptDocument } from "./transcript-document.js";
22
16
  /** Composes session state into the owned transcript, viewport, editor, and dock. */
23
17
  export class OwnedUiSessionShellRoot {
24
18
  editor;
25
19
  header;
26
20
  resources;
27
21
  #cwd;
28
- #document;
22
+ /** The transcript's semantic rows, caches, and engine-backed block renderers. */
23
+ transcript;
29
24
  #themeUnsubscribe;
30
25
  #view;
31
26
  #status;
@@ -33,11 +28,11 @@ export class OwnedUiSessionShellRoot {
33
28
  #queued;
34
29
  #extensionRenderers;
35
30
  #imageAssets;
36
- #promptChips;
31
+ promptChips;
37
32
  #pasteDiagnosticId = 0;
38
33
  #customViewport;
39
34
  #submittedPromptComposer;
40
- #viewportController;
35
+ viewport;
41
36
  #onPromptSuggestionEligibilityChanged;
42
37
  #componentRuntime;
43
38
  #toolsExpanded = false;
@@ -47,11 +42,13 @@ export class OwnedUiSessionShellRoot {
47
42
  #showImages = true;
48
43
  #imageWidthCells = 80;
49
44
  #outputPad = 1;
50
- #workflowOutput;
45
+ /** Workflow results, messages, and status lines appended to the transcript. */
46
+ workflow;
51
47
  #input;
52
48
  #layout;
53
49
  #extensions = new ExtensionSurface();
54
- #dockChrome;
50
+ /** The dock's notices, copy acknowledgement, and release banner. */
51
+ chrome;
55
52
  #imageSubmissionsSending = 0;
56
53
  constructor(view, cwd, handlers, startup = {}, agentDir, extensionRenderers = {
57
54
  getMessageRenderer: () => undefined,
@@ -60,57 +57,57 @@ export class OwnedUiSessionShellRoot {
60
57
  }, sessionLayout = "pinned", imageAssets) {
61
58
  this.#view = view;
62
59
  this.#customViewport = sessionLayout === "custom-viewport";
63
- this.#promptChips = new PromptChipStore({ isolated: this.#customViewport,
60
+ this.promptChips = new PromptChipStore({ isolated: this.#customViewport,
64
61
  ...(handlers.pasteDiagnostics === undefined ? {} : { onEvent: handlers.pasteDiagnostics }),
65
62
  ...(handlers.pastePreparation === undefined ? {} : { preparation: handlers.pastePreparation }),
66
63
  ...(handlers.promptImageLimit === undefined ? {} : { imageLimit: handlers.promptImageLimit }) });
67
- this.#submittedPromptComposer = this.#customViewport ? this.#createSubmittedPromptComposer() : undefined;
64
+ this.#submittedPromptComposer = this.#customViewport ? this.#createSubmittedPromptComposer(handlers.presentation.theme) : undefined;
68
65
  this.#cwd = cwd;
69
- this.#document = this.#createDocument(cwd);
66
+ this.transcript = this.#createDocument(cwd, handlers.presentation.theme, handlers.components);
70
67
  this.#extensionRenderers = extensionRenderers;
71
68
  this.#imageAssets = imageAssets;
72
69
  this.#componentRuntime = handlers;
73
70
  this.#onPromptSuggestionEligibilityChanged = handlers.onPromptSuggestionEligibilityChanged;
74
- this.header = createPiShellHeader({
71
+ this.header = handlers.components.chrome.header({
75
72
  ...startup,
76
73
  ...(this.#customViewport ? { getKeybindings: () => this.editor.keybindingConfig() } : {}),
77
74
  });
78
- this.resources = createPiShellLoadedResources(startup.resources ?? [], startup.expanded ?? false);
79
- this.#status = createPiShellStatus(view, {
75
+ this.resources = handlers.components.chrome.loadedResources(startup.resources ?? [], startup.expanded ?? false);
76
+ this.#status = handlers.components.chrome.status(view, {
80
77
  text: (message, mode) => progressStatusText(message, mode === "custom-viewport" ? "…" : "..."),
81
78
  frame: progressStatusFrame,
82
79
  }, handlers);
83
80
  this.#status.setProgressPresentation(this.#customViewport ? "custom-viewport" : "pinned");
84
- this.#footer = createPiShellFooter(this.#extensions.withStatuses(view), cwd, this.#customViewport ? "a1" : "pi", () => this.#footerLevel);
81
+ this.#footer = handlers.components.chrome.footer(this.#extensions.withStatuses(view), cwd, this.#customViewport ? "a1" : "pi", () => this.#footerLevel);
85
82
  this.editor = createShellEditor({
86
- handlers,
83
+ handlers, theme: handlers.presentation.theme, components: handlers.components,
87
84
  customViewport: this.#customViewport,
88
85
  cwd,
89
86
  ...(agentDir === undefined ? {} : { agentDir }),
90
- promptChips: this.#promptChips,
91
- editorPointerSelecting: () => this.#viewportController.editorPointerSelecting,
87
+ promptChips: this.promptChips,
88
+ editorPointerSelecting: () => this.viewport.editorPointerSelecting,
92
89
  nextPasteDiagnosticRequest: () => --this.#pasteDiagnosticId,
93
90
  toggleToolsExpanded: () => this.#setToolsExpanded(!this.#toolsExpanded),
94
91
  });
95
- this.#queued = createPiQueuedInputStatus(view.editor.queuedSubmissions, this.#customViewport ? "custom-viewport" : "pinned", this.#customViewport ? () => this.editor.keybindingConfig() : undefined);
96
- this.#viewportController = new SessionViewportController({
92
+ this.#queued = handlers.components.chrome.queuedInput(view.editor.queuedSubmissions, this.#customViewport ? "custom-viewport" : "pinned", this.#customViewport ? () => this.editor.keybindingConfig() : undefined);
93
+ this.viewport = new SessionViewportController({
97
94
  enabled: this.#customViewport,
98
95
  editor: this.editor,
99
96
  requestRender: force => this.#componentRuntime.requestRender(force),
100
97
  requestHyperlinkCleanup: rows => handlers.requestHyperlinkCleanup?.(rows),
101
- hasEditorLinks: () => this.#promptChips.hyperlinkRanges(this.editor.getText()).length > 0,
98
+ hasEditorLinks: () => this.promptChips.hyperlinkRanges(this.editor.getText()).length > 0,
102
99
  ...(handlers.pasteDiagnostics === undefined ? {} : { pasteDiagnostics: handlers.pasteDiagnostics }),
103
100
  nextPasteDiagnosticRequest: () => --this.#pasteDiagnosticId,
104
101
  });
105
- this.#dockChrome = new DockChrome({
102
+ this.chrome = new DockChrome({ theme: handlers.presentation.theme, outputPad: handlers.presentation.pinnedOutputPad, components: handlers.components,
106
103
  invalidateChrome: () => this.#invalidateChrome(),
107
104
  requestRender: () => this.#componentRuntime.requestRender(),
108
- viewport: this.#viewportController,
105
+ viewport: this.viewport,
109
106
  });
110
- this.#workflowOutput = new WorkflowOutput({
111
- customViewport: this.#customViewport,
112
- document: this.#document,
113
- dock: this.#dockChrome,
107
+ this.workflow = new WorkflowOutput({
108
+ customViewport: this.#customViewport, components: handlers.components,
109
+ document: this.transcript,
110
+ dock: this.chrome,
114
111
  transcriptLength: () => this.#view.transcript.length,
115
112
  outputPad: () => this.#outputPad,
116
113
  hotkeysPresentation: () => this.hotkeysPresentation(),
@@ -119,26 +116,27 @@ export class OwnedUiSessionShellRoot {
119
116
  });
120
117
  this.editor.setThinkingLevel(view.thinkingLevel);
121
118
  this.#input = new InputSurfaceSwitch(this.editor, {
122
- dockInputReuse: this.#customViewport && (handlers.enableDockInputReuse ?? true),
123
- viewport: this.#viewportController,
119
+ dockInputReuse: this.#customViewport && (handlers.enableDockInputReuse ?? true), classifyInput: handlers.presentation.terminalRuntime.classifyInput,
120
+ viewport: this.viewport,
124
121
  ...(handlers.onInputSurfaceChanged === undefined ? {} : { onChanged: handlers.onInputSurfaceChanged }),
125
122
  });
126
- this.#layout = this.#createLayout(handlers.onViewportFrame);
123
+ this.#layout = this.#createLayout(handlers.onViewportFrame, createViewportTheme(handlers.presentation.theme));
127
124
  for (const block of view.transcript) {
128
125
  if (block.kind === "user")
129
126
  this.editor.addToHistory(block.text);
130
127
  }
131
- this.#document.sync(view.transcript);
128
+ this.transcript.sync(view.transcript);
132
129
  // Invariant: rendered rows expire when
133
130
  // their active theme changes.
134
- this.#themeUnsubscribe = onPiThemeChange(() => {
131
+ this.#themeUnsubscribe = handlers.presentation.theme.onChange(() => {
135
132
  this.invalidate();
136
133
  this.#componentRuntime.requestRender(true);
137
134
  });
138
135
  }
139
136
  // Invariant: the document reads the shell's chrome lazily, so it may be built before the header and viewport.
140
- #createDocument(cwd) {
137
+ #createDocument(cwd, theme, components) {
141
138
  return new TranscriptDocument({
139
+ theme, components,
142
140
  customViewport: this.#customViewport,
143
141
  cwd,
144
142
  mount: block => this.#mountTranscript(block),
@@ -153,33 +151,34 @@ export class OwnedUiSessionShellRoot {
153
151
  });
154
152
  }
155
153
  // Invariant: one layout per root; the render path never consults the layout mode again.
156
- #createLayout(onFrame) {
154
+ #createLayout(onFrame, theme) {
157
155
  const ports = {
158
- viewport: this.#viewportController,
156
+ viewport: this.viewport,
159
157
  input: this.#input,
160
158
  editor: this.editor,
161
- promptChips: this.#promptChips,
162
- dockChrome: this.#dockChrome,
163
- theme: VIEWPORT_THEME,
159
+ promptChips: this.promptChips,
160
+ dockChrome: this.chrome,
161
+ theme,
164
162
  ...(onFrame === undefined ? {} : { onFrame }),
165
163
  rows: () => this.#componentRuntime.getRows(),
166
164
  dock: width => this.#renderDockLayout(width),
167
- document: width => this.#document.layout(width),
165
+ document: width => this.transcript.layout(width),
168
166
  queued: width => this.#renderQueued(width),
169
167
  liveStatus: width => this.#renderStatus(width),
170
168
  diagnostics: () => this.#view.diagnostics,
171
169
  };
172
170
  return this.#customViewport ? new ViewportLayout(ports) : new PinnedLayout(ports);
173
171
  }
174
- #createSubmittedPromptComposer() {
172
+ #createSubmittedPromptComposer(theme) {
173
+ const linkColor = transcriptLinkColor(theme);
175
174
  return {
176
175
  layout: width => submittedPromptLayout(width),
177
- compose: (rows, width, style) => composeSubmittedPromptRows(rows, width, { ...style, prefix: text => promptArrow(text, piTheme()) }).map(row => nativeHyperlinkStyle(row, nativeTranscriptLinkColor)),
176
+ compose: (rows, width, style) => composeSubmittedPromptRows(rows, width, { ...style, prefix: text => promptArrow(text, theme.current()) }).map(row => nativeHyperlinkStyle(row, linkColor)),
178
177
  };
179
178
  }
180
179
  setEditorPaddingX(padding) {
181
180
  this.editor.setPaddingX(padding);
182
- this.#document.invalidate("editor-padding");
181
+ this.transcript.invalidate("editor-padding");
183
182
  }
184
183
  setAutocompleteMaxVisible(maxVisible) {
185
184
  this.editor.setAutocompleteMaxVisible(maxVisible);
@@ -189,7 +188,7 @@ export class OwnedUiSessionShellRoot {
189
188
  return;
190
189
  this.#outputPad = padding;
191
190
  this.#status.setOutputPad(padding);
192
- for (const component of this.#document.components())
191
+ for (const component of this.transcript.components())
193
192
  component.setOutputPad(padding);
194
193
  this.#invalidateTranscriptPresentation();
195
194
  }
@@ -197,7 +196,7 @@ export class OwnedUiSessionShellRoot {
197
196
  if (this.#thinkingVisible === !hidden)
198
197
  return;
199
198
  this.#thinkingVisible = !hidden;
200
- for (const component of this.#document.components())
199
+ for (const component of this.transcript.components())
201
200
  component.setHideThinkingBlock(hidden);
202
201
  this.#invalidateTranscriptPresentation();
203
202
  }
@@ -205,7 +204,7 @@ export class OwnedUiSessionShellRoot {
205
204
  if (this.#mermaidRenderingMode === mode)
206
205
  return;
207
206
  this.#mermaidRenderingMode = mode;
208
- for (const component of this.#document.components())
207
+ for (const component of this.transcript.components())
209
208
  component.setMermaidRenderingMode(mode);
210
209
  this.#invalidateTranscriptPresentation();
211
210
  }
@@ -214,44 +213,26 @@ export class OwnedUiSessionShellRoot {
214
213
  return;
215
214
  this.#showImages = showImages;
216
215
  this.#imageWidthCells = imageWidthCells;
217
- for (const component of this.#document.components())
216
+ for (const component of this.transcript.components())
218
217
  component.setImagePresentation(showImages, imageWidthCells);
219
218
  this.#invalidateTranscriptPresentation();
220
219
  }
221
- prepareHistoryText(text) {
222
- return this.#promptChips.prepareHistoryText(text);
223
- }
224
- omitUnsentPromptImages(text) {
225
- return this.#promptChips.omitUnsentImages(text);
226
- }
227
- rehydrateHistoryText(text, resolveImage) {
228
- return this.#promptChips.rehydrateHistoryText(text, resolveImage);
229
- }
230
- imageChipAttachmentsFromEditor(text) {
231
- return this.#promptChips.imageChipAttachments(text);
232
- }
233
- preparePromptSubmission(text) {
234
- return this.#promptChips.prepareSubmission(text);
235
- }
236
220
  reconcilePromptImageLimitNotice(text = this.editor.getText()) {
237
- if (this.#dockChrome.notice?.errorCode !== "image-count" || !this.#promptChips.imageLimitState(text).corrected)
221
+ if (this.chrome.notice?.errorCode !== "image-count" || !this.promptChips.imageLimitState(text).corrected)
238
222
  return false;
239
- this.dismissNotice();
223
+ this.chrome.dismissNotice();
240
224
  return true;
241
225
  }
242
- hasPendingPastes(text) { return this.#promptChips.hasPending(text); }
243
226
  waitForPromptPastes(text, signal) {
244
- return this.#promptChips.waitForPastes(text, signal, () => this.editor.getText());
227
+ return this.promptChips.waitForPastes(text, signal, () => this.editor.getText());
245
228
  }
246
229
  resetPendingPastes() {
247
230
  this.editor.cancelPendingPastes?.();
248
- this.editor.setText(this.#promptChips.resetPastes(this.editor.getText()));
231
+ this.editor.setText(this.promptChips.resetPastes(this.editor.getText()));
249
232
  }
250
- /** Forks the spare paste helper so the first paste of the session takes a live child. */
251
- warmPastePreparation() { this.#promptChips.warm(); }
252
233
  disposePendingPastes() {
253
234
  this.resetPendingPastes();
254
- return this.#promptChips.dispose();
235
+ return this.promptChips.dispose();
255
236
  }
256
237
  promptSuggestionPrepareBlockReason() {
257
238
  if (!this.usesDefaultInputSurface())
@@ -262,7 +243,6 @@ export class OwnedUiSessionShellRoot {
262
243
  return "draft";
263
244
  return null;
264
245
  }
265
- canPreparePromptSuggestion() { return this.promptSuggestionPrepareBlockReason() === null; }
266
246
  promptSuggestionPresentationBlockReason() {
267
247
  const reason = this.promptSuggestionPrepareBlockReason();
268
248
  if (reason !== null)
@@ -280,14 +260,14 @@ export class OwnedUiSessionShellRoot {
280
260
  const becameReady = this.#view.lifecycle !== "ready" && view.lifecycle === "ready";
281
261
  if (view.diagnostics.length !== this.#view.diagnostics.length
282
262
  || view.diagnostics.some((diagnostic, index) => diagnostic.sequence !== this.#view.diagnostics[index]?.sequence)) {
283
- this.#document.invalidate("diagnostics");
263
+ this.transcript.invalidate("diagnostics");
284
264
  }
285
265
  const promptAccepted = this.#view.lifecycle !== "busy" && view.lifecycle === "busy";
286
266
  this.#view = view;
287
267
  // Invariant: the idle new-session confirmation yields to the first truthful live status;
288
268
  // ordinary dock notices deliberately remain visible below Working during a run.
289
- if (promptAccepted && this.#dockChrome.notice?.kind === "new-session")
290
- this.#dockChrome.forgetNotice();
269
+ if (promptAccepted && this.chrome.notice?.kind === "new-session")
270
+ this.chrome.forgetNotice();
291
271
  if (promptAccepted && this.#imageSubmissionsSending > 0) {
292
272
  this.#imageSubmissionsSending = 0;
293
273
  this.#syncWorkingOverride();
@@ -295,7 +275,7 @@ export class OwnedUiSessionShellRoot {
295
275
  this.#status.update(view);
296
276
  this.#footer.update(this.#extensions.withStatuses(view));
297
277
  this.#queued.update(view.editor.queuedSubmissions);
298
- this.#document.sync(view.transcript);
278
+ this.transcript.sync(view.transcript);
299
279
  this.editor.setSubmitEnabled(view.lifecycle !== "stopping" && view.lifecycle !== "stopped" && view.lifecycle !== "failed");
300
280
  this.editor.setThinkingLevel(view.thinkingLevel);
301
281
  // Performance: semantic updates already invalidate affected transcript blocks. Chrome is a separate authority.
@@ -303,23 +283,15 @@ export class OwnedUiSessionShellRoot {
303
283
  if (becameReady)
304
284
  this.#onPromptSuggestionEligibilityChanged?.();
305
285
  }
306
- /**
307
- * Applies one block: its component is created or updated in place and the order grows
308
- * only when the block is new. A streamed chunk costs one component update rather than a
309
- * walk of the whole transcript.
310
- */
311
- applyTranscriptBlock(block) {
312
- this.#document.apply(block);
313
- }
314
286
  #mountTranscript(block) {
315
287
  // Invariant: the notice answers the reader's last command, so only their next prompt or
316
288
  // shell command retires it; assistant, tool, and compaction blocks streaming in keep it.
317
289
  if (block.kind === "user" || block.kind === "bash")
318
- this.dismissNotice();
319
- const created = createPiShellTranscriptComponent(block, this.#cwd, this.#extensionRenderers, this.#submittedPromptComposer, this.#outputPad, !this.#thinkingVisible, this.#mermaidRenderingMode, this.#showImages, this.#imageWidthCells, this.#imageAssets, { ...this.#componentRuntime, changed: () => {
320
- if (this.#document.component(block.id) !== created)
290
+ this.chrome.dismissNotice();
291
+ const created = this.#componentRuntime.components.transcript.component(block, this.#cwd, this.#extensionRenderers, this.#submittedPromptComposer, this.#outputPad, !this.#thinkingVisible, this.#mermaidRenderingMode, this.#showImages, this.#imageWidthCells, this.#imageAssets, { ...this.#componentRuntime, changed: () => {
292
+ if (this.transcript.component(block.id) !== created)
321
293
  return;
322
- this.#document.blockChanged(block.id);
294
+ this.transcript.blockChanged(block.id);
323
295
  this.#layout.invalidate();
324
296
  this.#input.clearDockInputCandidate();
325
297
  this.#componentRuntime.requestRender();
@@ -331,18 +303,18 @@ export class OwnedUiSessionShellRoot {
331
303
  return this.#layout.render(width);
332
304
  }
333
305
  viewportFrameDescriptor() {
334
- return this.#viewportController.frame?.descriptor ?? null;
306
+ return this.viewport.frame?.descriptor ?? null;
335
307
  }
336
308
  /** Read-only, payload-free evidence; observing a pending frame must never render or repair it. */
337
309
  viewportPresentationEvidence() {
338
- const frame = this.#viewportController.frame;
310
+ const frame = this.viewport.frame;
339
311
  const snapshot = this.#layout.composed();
340
312
  return {
341
313
  candidate: this.#input.dockInputCandidate,
342
314
  candidateRevision: this.#input.dockInputCandidate ? this.#input.dockInputRevision ?? null : null,
343
- currentRevision: this.#viewportController.presentationRevision,
315
+ currentRevision: this.viewport.presentationRevision,
344
316
  composedRevision: snapshot?.viewportRevision ?? null,
345
- currentPointer: this.#viewportController.pointerPosition ?? null,
317
+ currentPointer: this.viewport.pointerPosition ?? null,
346
318
  composedPointer: snapshot?.pointerPosition ?? null,
347
319
  frameId: frame?.descriptor.frameId ?? null,
348
320
  bottom: frame?.hits.bottom ?? null,
@@ -354,53 +326,28 @@ export class OwnedUiSessionShellRoot {
354
326
  }
355
327
  /** Visible non-persistent Steering, alignment, and Working rows, for rendering evidence. */
356
328
  viewportTransientTailRowCount() {
357
- return this.#viewportController.frame?.hits.transientTail.length ?? 0;
329
+ return this.viewport.frame?.hits.transientTail.length ?? 0;
358
330
  }
359
331
  hasActiveSelection() {
360
- return this.#viewportController.hasSelection || this.editor.hasSelection();
332
+ return this.viewport.hasSelection || this.editor.hasSelection();
361
333
  }
362
334
  setViewportConfig(config) {
363
- if (this.#viewportController.setConfig(config)) {
364
- this.#document.invalidate("viewport-config");
335
+ if (this.viewport.setConfig(config)) {
336
+ this.transcript.invalidate("viewport-config");
365
337
  this.#layout.invalidate();
366
338
  }
367
339
  }
368
- setFullscreenCopyOnSelect(enabled) {
369
- this.#viewportController.setCopyOnSelect(enabled);
370
- }
371
- showCopyAcknowledgement(message) {
372
- this.#dockChrome.showCopyAcknowledgement(message);
373
- }
374
- resumeViewportFollowing() {
375
- this.#viewportController.resumeFollowing();
376
- }
377
- noteCompletedAssistantMessage() {
378
- this.#viewportController.noteCompletedAssistantMessage();
379
- }
380
- /** A new session binding owns new mounts even when it reuses semantic invocation ids. */
381
- resetTranscript() {
382
- this.#document.reset();
383
- }
384
- resetViewport() {
385
- this.#viewportController.reset();
386
- }
387
- clearViewportPointerState() {
388
- this.#viewportController.clearPointerState();
389
- }
390
- setViewportOverlaySurfaces(surfaces) {
391
- this.#viewportController.setOverlaySurfaces(surfaces);
392
- }
393
340
  viewportInputGeometryReady(width, height) {
394
- const frame = this.#viewportController.frame;
395
- return this.#viewportController.inputGeometryReady && frame?.descriptor.width === width && frame.descriptor.height === height;
341
+ const frame = this.viewport.frame;
342
+ return this.viewport.inputGeometryReady && frame?.descriptor.width === width && frame.descriptor.height === height;
396
343
  }
397
344
  handleViewportPreInput(data, allowWheel = true, now = Date.now(), editorActive = this.usesDefaultInputSurface()) {
398
- return this.#viewportController.handlePreInput(data, allowWheel, now, editorActive);
345
+ return this.viewport.handlePreInput(data, allowWheel, now, editorActive);
399
346
  }
400
347
  #renderDockLayout(width) {
401
348
  const queued = this.#customViewport ? [] : this.#renderQueued(width);
402
349
  const statusRows = this.#customViewport ? this.#status.renderDock(width) : this.#renderStatus(width);
403
- const noticeRows = this.#dockChrome.renderNotice(width, this.#outputPad);
350
+ const noticeRows = this.chrome.renderNotice(width, this.#outputPad);
404
351
  const transientRows = [...queued, ...statusRows, ...noticeRows];
405
352
  const messageStart = queued.length;
406
353
  const copyableMessageRows = Array.from({ length: statusRows.length + noticeRows.length }, (_value, index) => ({ row: messageStart + index }));
@@ -420,9 +367,6 @@ export class OwnedUiSessionShellRoot {
420
367
  copyableMessageRows,
421
368
  };
422
369
  }
423
- dismissNotice() {
424
- this.#dockChrome.dismissNotice();
425
- }
426
370
  #renderQueued(width) {
427
371
  return this.#view.editor.queuedSubmissions.length === 0 ? [] : this.#queued.render(width);
428
372
  }
@@ -439,22 +383,7 @@ export class OwnedUiSessionShellRoot {
439
383
  };
440
384
  }
441
385
  #renderDocument(width) {
442
- return this.#document.layout(width).rows;
443
- }
444
- transcriptComponent(id) {
445
- return this.#document.component(id);
446
- }
447
- exitTranscript(width) {
448
- return this.#document.exitTranscript(width);
449
- }
450
- appendWorkflowStatus(message) {
451
- this.#workflowOutput.appendStatus(message);
452
- }
453
- appendWorkflowMessage(message, errorCode) {
454
- this.#workflowOutput.appendMessage(message, errorCode);
455
- }
456
- appendWorkflowResult(result, errorCode) {
457
- this.#workflowOutput.appendResult(result, errorCode);
386
+ return this.transcript.layout(width).rows;
458
387
  }
459
388
  toggleThinkingVisibility() {
460
389
  this.setHideThinkingBlock(this.#thinkingVisible);
@@ -471,7 +400,7 @@ export class OwnedUiSessionShellRoot {
471
400
  }
472
401
  setExtensionHeader(component) {
473
402
  this.#extensions.replaceHeader(component);
474
- this.#document.invalidate("extension-header");
403
+ this.transcript.invalidate("extension-header");
475
404
  this.invalidate();
476
405
  }
477
406
  setExtensionFooter(component) {
@@ -516,9 +445,9 @@ export class OwnedUiSessionShellRoot {
516
445
  };
517
446
  }
518
447
  resetWorkflowPresentation() {
519
- this.#dockChrome.forgetNotice();
520
- this.#dockChrome.clearCopyAcknowledgement(false);
521
- this.#workflowOutput.reset();
448
+ this.chrome.forgetNotice();
449
+ this.chrome.clearCopyAcknowledgement(false);
450
+ this.workflow.reset();
522
451
  this.invalidate();
523
452
  }
524
453
  resetExtensionUi() {
@@ -526,15 +455,15 @@ export class OwnedUiSessionShellRoot {
526
455
  this.#syncWorkingOverride();
527
456
  this.#footer.update(this.#extensions.withStatuses(this.#view));
528
457
  // Invariant: an extension renderer may have drawn transcript blocks that are now unrendered by it.
529
- this.#document.invalidate("extension-renderers");
458
+ this.transcript.invalidate("extension-renderers");
530
459
  this.invalidate();
531
460
  }
532
461
  addExtensionNotification(message, type) {
533
462
  if (type === "info") {
534
- this.appendWorkflowStatus(message);
463
+ this.workflow.appendStatus(message);
535
464
  return;
536
465
  }
537
- this.appendWorkflowMessage({ kind: type, message });
466
+ this.workflow.appendMessage({ kind: type, message });
538
467
  }
539
468
  extensionFooterData() {
540
469
  return {
@@ -554,7 +483,7 @@ export class OwnedUiSessionShellRoot {
554
483
  return this.#layout.compositions();
555
484
  }
556
485
  transcriptRenderCount() {
557
- return this.#document.renderCount;
486
+ return this.transcript.renderCount;
558
487
  }
559
488
  setFooterLevel(visible) { this.#footerLevel = visible; }
560
489
  setInputSurface(component, disposePrevious = true, coordination = "owned") {
@@ -565,7 +494,7 @@ export class OwnedUiSessionShellRoot {
565
494
  this.#input.handleInput(data);
566
495
  }
567
496
  invalidate() {
568
- this.#document.invalidate("repaint");
497
+ this.transcript.invalidate("repaint");
569
498
  this.#invalidateChrome();
570
499
  }
571
500
  #invalidateChrome() {
@@ -585,12 +514,12 @@ export class OwnedUiSessionShellRoot {
585
514
  this.#onPromptSuggestionEligibilityChanged?.();
586
515
  }
587
516
  dispose() {
588
- this.#dockChrome.clearCopyAcknowledgement(false);
589
- this.clearViewportPointerState();
517
+ this.chrome.clearCopyAcknowledgement(false);
518
+ this.viewport.clearPointerState();
590
519
  this.#themeUnsubscribe();
591
520
  this.header.dispose?.();
592
521
  this.resources.dispose?.();
593
- this.#document.dispose();
522
+ this.transcript.dispose();
594
523
  this.#layout.invalidate();
595
524
  this.#input.dispose();
596
525
  this.#extensions.dispose();
@@ -600,7 +529,7 @@ export class OwnedUiSessionShellRoot {
600
529
  this.#queued.dispose?.();
601
530
  }
602
531
  #invalidateTranscriptPresentation() {
603
- this.#document.invalidate("block-presentation");
532
+ this.transcript.invalidate("block-presentation");
604
533
  this.invalidate();
605
534
  }
606
535
  #renderStatus(width) {
@@ -611,16 +540,16 @@ export class OwnedUiSessionShellRoot {
611
540
  if (!this.#customViewport)
612
541
  return footer.render(width);
613
542
  width = Math.max(0, width - 2);
614
- return footer.render(width).map(row => ` ${piShellTruncateToWidth(row, width)}`);
543
+ return footer.render(width).map(row => ` ${this.#componentRuntime.components.text.truncateToWidth(row, width)}`);
615
544
  }
616
545
  #setToolsExpanded(expanded) {
617
546
  this.#toolsExpanded = expanded;
618
547
  this.header.setExpanded(expanded);
619
548
  this.resources.setExpanded(expanded);
620
- for (const component of this.#document.components())
549
+ for (const component of this.transcript.components())
621
550
  component.setExpanded(expanded);
622
551
  // Invariant: expansion changes what a block draws without changing its revision.
623
- this.#document.invalidate("tools-expanded");
552
+ this.transcript.invalidate("tools-expanded");
624
553
  this.invalidate();
625
554
  }
626
555
  }
@@ -634,7 +563,7 @@ function withoutTerminalBackground(text) {
634
563
  * The pinned-profile screen: a followed transcript scroll above the dock. The runtime mounts one such layout,
635
564
  * so its single `transcript` scroll view is shared by whichever session the parts currently resolve to.
636
565
  */
637
- export function pinnedLayoutRoot(parts) {
566
+ export function pinnedLayoutRoot(parts, theme) {
638
567
  return {
639
568
  type: "stack",
640
569
  direction: "vertical",
@@ -651,8 +580,8 @@ export function pinnedLayoutRoot(parts) {
651
580
  primary: true,
652
581
  overscroll: "chain",
653
582
  scrollbar: "auto",
654
- scrollbarTrackStyle: text => piTheme().fg("scrollbarTrack", text),
655
- scrollbarThumbStyle: text => piTheme().fg("scrollbarThumb", text),
583
+ scrollbarTrackStyle: text => theme.current().fg("scrollbarTrack", text),
584
+ scrollbarThumbStyle: text => theme.current().fg("scrollbarThumb", text),
656
585
  child: { type: "component", component: parts.document },
657
586
  },
658
587
  },
@@ -684,168 +613,13 @@ function layoutPort(render, invalidate, handleInput) {
684
613
  ...(handleInput === undefined ? {} : { handleInput }),
685
614
  };
686
615
  }
687
- export function shellResourceEntries(backend) {
688
- const resources = backend.extensions.nonVisualResources().map(resource => ({
689
- section: resource.kind === "skill"
690
- ? "Skills"
691
- : resource.kind === "prompt-template"
692
- ? "Prompts"
693
- : resource.kind === "theme"
694
- ? "Themes"
695
- : "Context",
696
- label: resource.kind === "prompt-template"
697
- ? `/${resource.label}`
698
- : resource.kind === "agent-context" || resource.kind === "system-prompt"
699
- ? compactResourceLabel(resource.sourcePath ?? resource.label)
700
- : resource.label,
701
- sourcePath: resource.sourcePath,
702
- diagnostic: resource.diagnostic,
703
- }));
704
- const extensions = backend.extensions.extensionResources().filter(extension => !extension.hidden);
705
- const loadedExtensions = extensions.filter(extension => extension.diagnostic === null);
706
- const extensionLabels = compactExtensionLabels(loadedExtensions);
707
- for (const extension of extensions) {
708
- const labelIndex = loadedExtensions.indexOf(extension);
709
- resources.push({
710
- section: "Extensions",
711
- label: extensionLabels[labelIndex] ?? compactResourceLabel(extension.sourcePath ?? extension.resolvedPath ?? "extension"),
712
- sourcePath: extension.sourcePath ?? extension.resolvedPath,
713
- diagnostic: extension.diagnostic,
714
- });
715
- }
716
- return resources;
717
- }
718
- function compactResourceLabel(path) {
719
- const segments = compactPathSegments(path);
720
- const leaf = segments.at(-1) ?? path;
721
- if ((leaf === "index.ts" || leaf === "index.js") && segments.length > 1)
722
- return segments.at(-2) ?? leaf;
723
- return leaf;
724
- }
725
- /**
726
- * Pinned from InteractiveMode's compact extension-label helpers at Pi commit
727
- * 914cf1472e715297caa30db4b9535d534a9eb718. The source metadata crosses an
728
- * A1-owned boundary first; the owned shell never inspects Pi's private root.
729
- */
730
- function compactExtensionLabels(extensions) {
731
- const localExtensions = extensions
732
- .filter(extension => !isPackageExtensionSource(extension.sourceInfo))
733
- .map(extension => {
734
- const path = extension.sourcePath ?? extension.resolvedPath ?? "extension";
735
- const segments = compactPathSegments(path);
736
- if (segments.length > 1 && (segments.at(-1) === "index.ts" || segments.at(-1) === "index.js"))
737
- segments.pop();
738
- return { extension, segments };
739
- });
740
- return extensions.map(extension => {
741
- const resourcePath = extension.sourcePath ?? extension.resolvedPath ?? "extension";
742
- if (isPackageExtensionSource(extension.sourceInfo)) {
743
- return compactPackageExtensionLabel(resourcePath, extension.sourceInfo);
744
- }
745
- const localIndex = localExtensions.findIndex(item => item.extension === extension);
746
- const segments = localExtensions[localIndex]?.segments;
747
- if (!segments || segments.length === 0)
748
- return compactResourceLabel(resourcePath);
749
- for (let count = 1; count <= segments.length; count += 1) {
750
- const candidate = segments.slice(-count).join("/");
751
- if (localExtensions.every((item, itemIndex) => itemIndex === localIndex || item.segments.slice(-count).join("/") !== candidate)) {
752
- return candidate;
753
- }
754
- }
755
- return segments.join("/");
756
- });
757
- }
758
- function compactPackageExtensionLabel(resourcePath, sourceInfo) {
759
- const sourceLabel = compactPackageSourceLabel(sourceInfo.source);
760
- if (!sourceLabel)
761
- return compactResourceLabel(resourcePath);
762
- const shortPath = shortPackagePath(resourcePath, sourceInfo).replaceAll("\\", "/");
763
- const packagePath = shortPath.startsWith("extensions/") ? shortPath.slice("extensions/".length) : shortPath;
764
- const slash = packagePath.lastIndexOf("/");
765
- const fileName = slash < 0 ? packagePath : packagePath.slice(slash + 1);
766
- const directory = slash < 0 ? "" : packagePath.slice(0, slash);
767
- const extension = fileName.lastIndexOf(".");
768
- const name = extension <= 0 ? fileName : fileName.slice(0, extension);
769
- if (name === "index")
770
- return !directory || directory === "." ? sourceLabel : `${sourceLabel}:${directory}`;
771
- return `${sourceLabel}:${packagePath}`;
772
- }
773
- function compactPackageSourceLabel(source) {
774
- if (source.startsWith("npm:"))
775
- return source.slice("npm:".length) || source;
776
- if (!source.startsWith("git:"))
777
- return source;
778
- const gitSource = source.slice("git:".length).trim();
779
- let repositoryPath;
780
- const scpLike = gitSource.match(/^git@[^:]+:(.+)$/);
781
- if (scpLike?.[1]) {
782
- repositoryPath = scpLike[1];
783
- }
784
- else if (/^[a-z]+:\/\//i.test(gitSource)) {
785
- try {
786
- repositoryPath = new URL(gitSource).pathname.replace(/^\/+/, "");
787
- }
788
- catch {
789
- return source;
790
- }
791
- }
792
- else {
793
- const slash = gitSource.indexOf("/");
794
- if (slash >= 0)
795
- repositoryPath = gitSource.slice(slash + 1);
796
- }
797
- if (!repositoryPath)
798
- return source;
799
- const ref = repositoryPath.indexOf("@");
800
- const withoutRef = ref < 0 ? repositoryPath : repositoryPath.slice(0, ref);
801
- return withoutRef.replace(/\.git$/, "") || source;
802
- }
803
- function shortPackagePath(resourcePath, sourceInfo) {
804
- const fullPath = normalizeResourcePath(resourcePath);
805
- const baseDir = sourceInfo.baseDir === null ? undefined : normalizeResourcePath(sourceInfo.baseDir).replace(/\/$/, "");
806
- if (baseDir) {
807
- const npmRoot = baseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
808
- if (npmRoot?.[1] && fullPath.startsWith(`${npmRoot[1]}/`))
809
- return relativeResourcePath(baseDir, fullPath);
810
- if (fullPath === baseDir)
811
- return ".";
812
- if (fullPath.startsWith(`${baseDir}/`))
813
- return fullPath.slice(baseDir.length + 1);
814
- }
815
- const npmMatch = fullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
816
- if (npmMatch?.[2] && sourceInfo.source.startsWith("npm:"))
817
- return npmMatch[2];
818
- const gitMatch = fullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
819
- if (gitMatch?.[1] && sourceInfo.source.startsWith("git:"))
820
- return gitMatch[1];
821
- return resourcePath;
822
- }
823
- function relativeResourcePath(from, to) {
824
- const fromSegments = from.split("/").filter(Boolean);
825
- const toSegments = to.split("/").filter(Boolean);
826
- let common = 0;
827
- while (common < fromSegments.length && common < toSegments.length
828
- && fromSegments[common]?.toLowerCase() === toSegments[common]?.toLowerCase())
829
- common += 1;
830
- return [...fromSegments.slice(common).map(() => ".."), ...toSegments.slice(common)].join("/") || ".";
831
- }
832
- function compactPathSegments(path) {
833
- return normalizeResourcePath(path).split("/").filter(segment => segment.length > 0 && segment !== "~");
834
- }
835
- function normalizeResourcePath(path) {
836
- return path.replaceAll("\\", "/");
837
- }
838
- function isPackageExtensionSource(sourceInfo) {
839
- const source = sourceInfo?.source ?? "";
840
- return source.startsWith("npm:") || source.startsWith("git:");
616
+ function createViewportTheme(source) {
617
+ return {
618
+ track: text => `${SCROLLBAR_CELL_RESET}${source.current().fg("dim", text)}`,
619
+ thumb: text => `${SCROLLBAR_CELL_RESET}${source.current().fg("accent", text)}`,
620
+ sticky: (text, hovered) => source.current().background(hovered ? "selectedBg" : "toolPendingBg", source.current().fg("text", withoutTerminalBackground(text))),
621
+ quietSticky: text => `\u001b[2m${text.replace(/\u001b\[(?:0|22)m/g, "$&\u001b[2m")}\u001b[22m`,
622
+ bottomControl: (text, hovered) => source.current().background(hovered ? "selectedBg" : "toolPendingBg", source.current().fg("text", text)),
623
+ selection: paintTextSelection,
624
+ };
841
625
  }
842
- // Performance: stable painter identities let the neutral viewport retain row-level
843
- // selection variants while each callback still resolves the live Pi theme.
844
- const VIEWPORT_THEME = {
845
- track: text => `${SCROLLBAR_CELL_RESET}${piTheme().fg("dim", text)}`,
846
- thumb: text => `${SCROLLBAR_CELL_RESET}${piTheme().fg("accent", text)}`,
847
- sticky: (text, hovered) => piTheme().bg(hovered ? "selectedBg" : "toolPendingBg", piTheme().fg("text", withoutTerminalBackground(text))),
848
- quietSticky: text => `\u001b[2m${text.replace(/\u001b\[(?:0|22)m/g, "$&\u001b[2m")}\u001b[22m`,
849
- bottomControl: (text, hovered) => piTheme().bg(hovered ? "selectedBg" : "toolPendingBg", piTheme().fg("text", text)),
850
- selection: paintTextSelection,
851
- };