@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,10 +1,10 @@
1
+ import type { OwnedUiShellEditorPort } from "../../contracts/owned-ui/index.js";
1
2
  import { type PromptHistoryKind, type PromptHistoryPort } from "../../contracts/owned-ui/index.js";
2
- import type { PiShellEditorPort } from "../../integrations/pi/components/index.js";
3
3
  /** Merges bounded recall snapshots; the editor alone owns browsing, draft, cursor, and undo state. */
4
4
  export declare class PromptHistoryController {
5
5
  #private;
6
6
  readonly options: {
7
- editor: PiShellEditorPort;
7
+ editor: OwnedUiShellEditorPort;
8
8
  store: PromptHistoryPort;
9
9
  limit: number;
10
10
  fallback: readonly string[];
@@ -16,7 +16,7 @@ export declare class PromptHistoryController {
16
16
  rehydrate?: (text: string) => string;
17
17
  };
18
18
  constructor(options: {
19
- editor: PiShellEditorPort;
19
+ editor: OwnedUiShellEditorPort;
20
20
  store: PromptHistoryPort;
21
21
  limit: number;
22
22
  fallback: readonly string[];
@@ -1,13 +1,15 @@
1
+ import type { OwnedUiShellComponents } from "../../contracts/owned-ui/index.js";
1
2
  import type { OwnedUiCommand, OwnedUiCommandResult, OwnedUiSessionBackend, OwnedUiSessionViewModel, PromptHistoryImageSidecarPort } from "../../contracts/owned-ui/index.js";
2
3
  import type { PromptHistoryController } from "./prompt-history-controller.js";
3
4
  import type { SessionConcern } from "./session-concern.js";
4
5
  import type { OwnedUiSessionShellRoot } from "./session-shell-root.js";
5
6
  import type { OwnedUiPresenterTerminal } from "./shell-host.js";
6
- export interface PromptSubmissionPorts {
7
+ interface PromptSubmissionPorts {
7
8
  readonly backend: Pick<OwnedUiSessionBackend, "session" | "identity" | "workflows">;
8
- readonly root: Pick<OwnedUiSessionShellRoot, "editor" | "hasPendingPastes" | "waitForPromptPastes" | "setExtensionWidget" | "prepareHistoryText" | "imageChipAttachmentsFromEditor" | "preparePromptSubmission" | "omitUnsentPromptImages" | "resumeViewportFollowing" | "beginImageSubmissionStatus" | "appendWorkflowResult">;
9
+ readonly root: Pick<OwnedUiSessionShellRoot, "editor" | "promptChips" | "viewport" | "waitForPromptPastes" | "setExtensionWidget" | "beginImageSubmissionStatus" | "workflow">;
9
10
  readonly terminal: Pick<OwnedUiPresenterTerminal, "requestRender">;
10
11
  readonly cwd: string;
12
+ readonly statusText: OwnedUiShellComponents["info"]["statusText"];
11
13
  promptHistory(): PromptHistoryController | null;
12
14
  imageSidecar(): PromptHistoryImageSidecarPort | undefined;
13
15
  disposed(): boolean;
@@ -44,3 +46,4 @@ export declare class PromptSubmission implements SessionConcern {
44
46
  onSessionReplaced(): void;
45
47
  dispose(): void;
46
48
  }
49
+ export {};
@@ -1,5 +1,4 @@
1
1
  import { assertOwnedUiCommand, assertPromptImages, ImageAttachmentError, } from "../../contracts/owned-ui/index.js";
2
- import { renderPiShellStatusText } from "../../integrations/pi/components/shell-presenters-info.js";
3
2
  const rejected = (diagnostic) => ({ outcome: "rejected", diagnostic });
4
3
  /**
5
4
  * Turns editor input into engine commands: prompts, steering, follow-ups, and bash, each recorded
@@ -43,7 +42,7 @@ export class PromptSubmission {
43
42
  /** Sends slash text the shell does not own as engine prompt input; history keeps what was typed. */
44
43
  sendSlashPrompt(text, typed = text) {
45
44
  this.#rememberInput(typed, "slash");
46
- this.#ports.root.resumeViewportFollowing();
45
+ this.#ports.root.viewport.resumeFollowing();
47
46
  return this.execute({
48
47
  type: this.#ports.lifecycle() === "busy" ? "steer" : "prompt",
49
48
  correlationId: this.#ports.correlation("prompt-command"),
@@ -80,7 +79,7 @@ export class PromptSubmission {
80
79
  reportError(error, message) {
81
80
  // Security: arbitrary provider/extension error messages can contain the entire request.
82
81
  try {
83
- this.#ports.root.appendWorkflowResult({ command: "debug", outcome: "failed", message: message
82
+ this.#ports.root.workflow.appendResult({ command: "debug", outcome: "failed", message: message
84
83
  ?? (error instanceof ImageAttachmentError ? error.message : "Submission failed. Check the prompt and try again.") }, error instanceof ImageAttachmentError ? error.code : undefined);
85
84
  this.#ports.terminal.requestRender();
86
85
  }
@@ -97,7 +96,7 @@ export class PromptSubmission {
97
96
  const previous = this.#waiting.get(draft);
98
97
  if (previous !== undefined)
99
98
  return previous.result;
100
- if (!root.hasPendingPastes(draft))
99
+ if (!root.promptChips.hasPending(draft))
101
100
  return this.#guard(draft, action);
102
101
  const controller = new AbortController();
103
102
  const generation = backend.identity.sessionGeneration;
@@ -120,7 +119,7 @@ export class PromptSubmission {
120
119
  #showWaiting() {
121
120
  const count = this.#waiting.size;
122
121
  this.#ports.root.setExtensionWidget("owned-image-preparation", count === 0 ? null : {
123
- render: width => [...renderPiShellStatusText(`Waiting for images (${count} submission${count === 1 ? "" : "s"}) — Esc cancels; dequeue restores`, width)],
122
+ render: width => [...this.#ports.statusText(`Waiting for images (${count} submission${count === 1 ? "" : "s"}) — Esc cancels; dequeue restores`, width)],
124
123
  invalidate: () => { },
125
124
  }, "aboveEditor");
126
125
  this.#ports.terminal.requestRender();
@@ -155,7 +154,7 @@ export class PromptSubmission {
155
154
  const history = this.#ports.promptHistory();
156
155
  if (history === null)
157
156
  return;
158
- const reusable = root.prepareHistoryText(text);
157
+ const reusable = root.promptChips.prepareHistoryText(text);
159
158
  if (reusable.length === 0) {
160
159
  history.rememberRecovery(text);
161
160
  return;
@@ -165,7 +164,7 @@ export class PromptSubmission {
165
164
  // recall path treats an absent sidecar the same as a corrupt one.
166
165
  const sidecar = this.#ports.imageSidecar();
167
166
  if (sidecar !== undefined) {
168
- for (const record of root.imageChipAttachmentsFromEditor(text)) {
167
+ for (const record of root.promptChips.imageChipAttachments(text)) {
169
168
  sidecar.write(record.id, { tag: record.tag, data: record.image.data, mimeType: record.image.mimeType, savedAt: new Date().toISOString() });
170
169
  }
171
170
  }
@@ -179,7 +178,7 @@ export class PromptSubmission {
179
178
  if (displayInput.startsWith("/"))
180
179
  return this.#ports.slashCommand(displayInput);
181
180
  const { root, backend } = this.#ports;
182
- const prepared = root.preparePromptSubmission(displayInput);
181
+ const prepared = root.promptChips.prepareSubmission(displayInput);
183
182
  assertPromptImages(prepared.images);
184
183
  const input = prepared.text.trim();
185
184
  if (input.startsWith("!")) {
@@ -190,8 +189,8 @@ export class PromptSubmission {
190
189
  // Compatibility: match interactive Pi: input during compaction is queued steering; the engine
191
190
  // shows it in the pending rows and delivers it when compaction ends.
192
191
  const type = this.#ports.lifecycle() === "busy" ? "steer" : "prompt";
193
- this.#rememberInput(root.omitUnsentPromptImages(displayInput).trim(), type);
194
- root.resumeViewportFollowing();
192
+ this.#rememberInput(root.promptChips.omitUnsentImages(displayInput).trim(), type);
193
+ root.viewport.resumeFollowing();
195
194
  const command = {
196
195
  type,
197
196
  correlationId: this.#ports.correlation(type),
@@ -222,13 +221,13 @@ export class PromptSubmission {
222
221
  message: result.cancelled ? "Bash command cancelled" : `Bash exited ${result.exitCode ?? 0}: ${command}`,
223
222
  ...(result.output ? { detail: result.output } : {}),
224
223
  };
225
- this.#ports.root.appendWorkflowResult(workflow);
224
+ this.#ports.root.workflow.appendResult(workflow);
226
225
  this.#ports.terminal.requestRender();
227
226
  return workflow.outcome === "failed" ? rejected(workflow.message) : { outcome: "completed", diagnostic: null };
228
227
  }
229
228
  catch (error) {
230
229
  const message = `Bash command failed: ${error instanceof Error ? error.message : String(error)}`;
231
- this.#ports.root.appendWorkflowResult({ command: "debug", outcome: "failed", message });
230
+ this.#ports.root.workflow.appendResult({ command: "debug", outcome: "failed", message });
232
231
  this.#ports.terminal.requestRender();
233
232
  return rejected(message);
234
233
  }
@@ -238,13 +237,13 @@ export class PromptSubmission {
238
237
  const displayInput = draft.trim();
239
238
  if (!displayInput)
240
239
  return rejected("nothing to queue");
241
- const prepared = root.preparePromptSubmission(displayInput);
240
+ const prepared = root.promptChips.prepareSubmission(displayInput);
242
241
  assertPromptImages(prepared.images);
243
242
  const text = prepared.text.trim();
244
243
  this.#rememberInput(displayInput, "follow-up");
245
244
  if (root.editor.getText() === draft)
246
245
  root.editor.setText("");
247
- root.resumeViewportFollowing();
246
+ root.viewport.resumeFollowing();
248
247
  return this.execute({
249
248
  type: "follow-up",
250
249
  correlationId: this.#ports.correlation("follow-up"),
@@ -16,14 +16,14 @@ export interface QuitOutroCell {
16
16
  readonly glyph: string;
17
17
  readonly color: string;
18
18
  }
19
- export interface QuitOutroPlan {
19
+ interface QuitOutroPlan {
20
20
  /** Sorted by `start`. */
21
21
  readonly sparkles: readonly QuitOutroCell[];
22
22
  /** Sorted by `end`. */
23
23
  readonly clears: readonly QuitOutroCell[];
24
24
  }
25
- export declare const QUIT_OUTRO_EFFECTS: readonly ["fall", "dissolve", "starburst", "waves"];
25
+ declare const QUIT_OUTRO_EFFECTS: readonly ["fall", "dissolve", "starburst", "waves"];
26
26
  export type QuitOutroEffect = (typeof QUIT_OUTRO_EFFECTS)[number];
27
- export declare function isQuitOutroEffect(value: unknown): value is QuitOutroEffect;
28
27
  /** Builds the selected effect's deterministic plan for the captured row widths. */
29
28
  export declare function createQuitOutroPlan(effect: QuitOutroEffect, rowWidths: readonly number[], seed: number): QuitOutroPlan;
29
+ export {};
@@ -6,10 +6,7 @@
6
6
  * cell from `start`, and clears blank a cell at `end`. The player consumes both
7
7
  * in order, so a fixed seed yields a byte-stable animation.
8
8
  */
9
- export const QUIT_OUTRO_EFFECTS = Object.freeze(["fall", "dissolve", "starburst", "waves"]);
10
- export function isQuitOutroEffect(value) {
11
- return typeof value === "string" && QUIT_OUTRO_EFFECTS.includes(value);
12
- }
9
+ const QUIT_OUTRO_EFFECTS = Object.freeze(["fall", "dissolve", "starburst", "waves"]);
13
10
  const WHITE = "\x1b[38;2;238;238;238m";
14
11
  const DUST_GLYPHS = [".", "·", "'", ":", "+", "°"];
15
12
  const FALL_GLYPHS = [".", ".", "·", "'", ":", "°"];
@@ -1,5 +1,5 @@
1
1
  import { type QuitOutroEffect } from "./quit-outro-effects.js";
2
- export interface QuitOutroFrame {
2
+ interface QuitOutroFrame {
3
3
  /** Row content as presented, truncated to `columns`; index 0 is the top row. */
4
4
  readonly lines: readonly string[];
5
5
  readonly columns: number;
@@ -7,7 +7,7 @@ export interface QuitOutroFrame {
7
7
  /** Visible width of each line, at most `columns`. */
8
8
  readonly rowWidths: readonly number[];
9
9
  }
10
- export interface QuitOutroPlayback {
10
+ interface QuitOutroPlayback {
11
11
  write(data: string): void;
12
12
  /** Monotonic clock seam; defaults to `Date.now`. */
13
13
  now?(): number;
@@ -16,25 +16,22 @@ export interface QuitOutroPlayback {
16
16
  /** Plan seed; defaults to a time- and geometry-derived value. */
17
17
  readonly seed?: number;
18
18
  /** Active bare-A1 canvas; omitted preserves transparent playback bytes. */
19
- readonly canvasBackgroundAnsi?: string;
19
+ readonly canvas?: QuitOutroCanvas;
20
+ }
21
+ /** A painted canvas: its background sequence and how to rebase a row's default background onto it. */
22
+ export interface QuitOutroCanvas {
23
+ readonly ansi: string;
24
+ readonly rebase: (content: string, backgroundAnsi: string) => string;
20
25
  }
21
- export declare const QUIT_OUTRO_MIN_MS = 300;
22
- export declare const QUIT_OUTRO_MAX_MS = 2000;
23
- /** Wall-clock allowance beyond the clamped duration before playback abandons remaining ticks. */
24
- export declare const QUIT_OUTRO_GUARD_MS = 500;
25
- /** Tick ceiling for a clock that stops advancing: the longest playback plus its guard at 30 fps. */
26
- export declare const QUIT_OUTRO_MAX_TICKS: number;
27
- export declare function clampQuitOutroDuration(durationMs: number): number;
28
26
  /**
29
27
  * Captures the presented rows into an outro frame. Returns null when nothing is
30
28
  * visible, so a blank screen never animates.
31
29
  */
32
30
  export declare function captureQuitOutroFrame(presented: readonly string[], columns: number, rows: number): QuitOutroFrame | null;
33
- /** The clear-and-repaint block that seeds the animation surface with the captured frame. */
34
- export declare function createQuitOutroSurfaceFrame(frame: QuitOutroFrame, canvasBackgroundAnsi?: string): string;
35
31
  /**
36
32
  * Plays the effect over the frame. Resolves true when the plan was played to
37
33
  * completion or abandoned at its guard, false when there was nothing to play.
38
34
  * Write failures propagate so the caller can decide to continue restoration.
39
35
  */
40
36
  export declare function playQuitOutro(frame: QuitOutroFrame, effect: QuitOutroEffect, durationMs: number, playback: QuitOutroPlayback): Promise<boolean>;
37
+ export {};
@@ -6,22 +6,21 @@
6
6
  * terminal cannot delay restoration past the configured clamp.
7
7
  */
8
8
  import { displayWidth, truncateToWidth } from "../../ui/components/index.js";
9
- import { rebaseTerminalDefaultBackground } from "../../integrations/pi/tui-runtime/index.js";
10
9
  import { createQuitOutroPlan } from "./quit-outro-effects.js";
11
- export const QUIT_OUTRO_MIN_MS = 300;
12
- export const QUIT_OUTRO_MAX_MS = 2000;
10
+ const QUIT_OUTRO_MIN_MS = 300;
11
+ const QUIT_OUTRO_MAX_MS = 2000;
13
12
  /** Wall-clock allowance beyond the clamped duration before playback abandons remaining ticks. */
14
- export const QUIT_OUTRO_GUARD_MS = 500;
13
+ const QUIT_OUTRO_GUARD_MS = 500;
15
14
  const FRAME_MS = 1000 / 30;
16
15
  /** Tick ceiling for a clock that stops advancing: the longest playback plus its guard at 30 fps. */
17
- export const QUIT_OUTRO_MAX_TICKS = Math.ceil((QUIT_OUTRO_MAX_MS + QUIT_OUTRO_GUARD_MS) / FRAME_MS) + 1;
16
+ const QUIT_OUTRO_MAX_TICKS = Math.ceil((QUIT_OUTRO_MAX_MS + QUIT_OUTRO_GUARD_MS) / FRAME_MS) + 1;
18
17
  const SYNC_BEGIN = "\x1b[?2026h";
19
18
  const SYNC_END = "\x1b[?2026l";
20
19
  const RESET = "\x1b[0m";
21
20
  const CLEAR_SCREEN = "\x1b[2J";
22
21
  const HOME = "\x1b[H";
23
22
  const HIDE_CURSOR = "\x1b[?25l";
24
- export function clampQuitOutroDuration(durationMs) {
23
+ function clampQuitOutroDuration(durationMs) {
25
24
  if (!Number.isFinite(durationMs))
26
25
  return QUIT_OUTRO_MIN_MS;
27
26
  return Math.max(QUIT_OUTRO_MIN_MS, Math.min(QUIT_OUTRO_MAX_MS, Math.floor(durationMs)));
@@ -45,8 +44,8 @@ export function captureQuitOutroFrame(presented, columns, rows) {
45
44
  return { lines, columns: width, rows: height, rowWidths };
46
45
  }
47
46
  /** The clear-and-repaint block that seeds the animation surface with the captured frame. */
48
- export function createQuitOutroSurfaceFrame(frame, canvasBackgroundAnsi) {
49
- if (canvasBackgroundAnsi === undefined) {
47
+ function createQuitOutroSurfaceFrame(frame, canvas) {
48
+ if (canvas === undefined) {
50
49
  let output = `${SYNC_BEGIN}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME}${RESET}`;
51
50
  for (let row = 0; row < frame.rows; row++) {
52
51
  const line = frame.lines[row] ?? "";
@@ -55,12 +54,13 @@ export function createQuitOutroSurfaceFrame(frame, canvasBackgroundAnsi) {
55
54
  }
56
55
  return `${output}${SYNC_END}`;
57
56
  }
57
+ const canvasBackgroundAnsi = canvas.ansi;
58
58
  let output = `${SYNC_BEGIN}${HIDE_CURSOR}${RESET}${canvasBackgroundAnsi}${CLEAR_SCREEN}${HOME}`;
59
59
  for (let row = 0; row < frame.rows; row++) {
60
60
  const line = frame.lines[row] ?? "";
61
61
  if (frame.rowWidths[row] > 0) {
62
62
  output += `${cursorAt(row, 0)}${canvasBackgroundAnsi}`
63
- + `${rebaseTerminalDefaultBackground(line, canvasBackgroundAnsi)}${RESET}${canvasBackgroundAnsi}`;
63
+ + `${canvas.rebase(line, canvasBackgroundAnsi)}${RESET}${canvasBackgroundAnsi}`;
64
64
  }
65
65
  }
66
66
  return `${output}${RESET}${SYNC_END}`;
@@ -81,8 +81,8 @@ export async function playQuitOutro(frame, effect, durationMs, playback) {
81
81
  let sparkleIndex = 0;
82
82
  let clearIndex = 0;
83
83
  let ticks = 0;
84
- const canvas = playback.canvasBackgroundAnsi;
85
- playback.write(createQuitOutroSurfaceFrame(frame, canvas));
84
+ playback.write(createQuitOutroSurfaceFrame(frame, playback.canvas));
85
+ const canvas = playback.canvas?.ansi;
86
86
  const startedAt = now();
87
87
  for (;;) {
88
88
  ticks += 1;
@@ -0,0 +1,2 @@
1
+ import type { OwnedUiSessionBackend, OwnedUiShellResourceEntry } from "../../contracts/owned-ui/index.js";
2
+ export declare function shellResourceEntries(backend: OwnedUiSessionBackend): readonly OwnedUiShellResourceEntry[];
@@ -0,0 +1,158 @@
1
+ // Rationale: the startup header lists loaded resources with the shortest label that stays unambiguous.
2
+ export function shellResourceEntries(backend) {
3
+ const resources = backend.extensions.nonVisualResources().map(resource => ({
4
+ section: resource.kind === "skill"
5
+ ? "Skills"
6
+ : resource.kind === "prompt-template"
7
+ ? "Prompts"
8
+ : resource.kind === "theme"
9
+ ? "Themes"
10
+ : "Context",
11
+ label: resource.kind === "prompt-template"
12
+ ? `/${resource.label}`
13
+ : resource.kind === "agent-context" || resource.kind === "system-prompt"
14
+ ? compactResourceLabel(resource.sourcePath ?? resource.label)
15
+ : resource.label,
16
+ sourcePath: resource.sourcePath,
17
+ diagnostic: resource.diagnostic,
18
+ }));
19
+ const extensions = backend.extensions.extensionResources().filter(extension => !extension.hidden);
20
+ const loadedExtensions = extensions.filter(extension => extension.diagnostic === null);
21
+ const extensionLabels = compactExtensionLabels(loadedExtensions);
22
+ for (const extension of extensions) {
23
+ const labelIndex = loadedExtensions.indexOf(extension);
24
+ resources.push({
25
+ section: "Extensions",
26
+ label: extensionLabels[labelIndex] ?? compactResourceLabel(extension.sourcePath ?? extension.resolvedPath ?? "extension"),
27
+ sourcePath: extension.sourcePath ?? extension.resolvedPath,
28
+ diagnostic: extension.diagnostic,
29
+ });
30
+ }
31
+ return resources;
32
+ }
33
+ function compactResourceLabel(path) {
34
+ const segments = compactPathSegments(path);
35
+ const leaf = segments.at(-1) ?? path;
36
+ if ((leaf === "index.ts" || leaf === "index.js") && segments.length > 1)
37
+ return segments.at(-2) ?? leaf;
38
+ return leaf;
39
+ }
40
+ /**
41
+ * Pinned from InteractiveMode's compact extension-label helpers at Pi commit
42
+ * 914cf1472e715297caa30db4b9535d534a9eb718. The source metadata crosses an
43
+ * A1-owned boundary first; the owned shell never inspects Pi's private root.
44
+ */
45
+ function compactExtensionLabels(extensions) {
46
+ const localExtensions = extensions
47
+ .filter(extension => !isPackageExtensionSource(extension.sourceInfo))
48
+ .map(extension => {
49
+ const path = extension.sourcePath ?? extension.resolvedPath ?? "extension";
50
+ const segments = compactPathSegments(path);
51
+ if (segments.length > 1 && (segments.at(-1) === "index.ts" || segments.at(-1) === "index.js"))
52
+ segments.pop();
53
+ return { extension, segments };
54
+ });
55
+ return extensions.map(extension => {
56
+ const resourcePath = extension.sourcePath ?? extension.resolvedPath ?? "extension";
57
+ if (isPackageExtensionSource(extension.sourceInfo)) {
58
+ return compactPackageExtensionLabel(resourcePath, extension.sourceInfo);
59
+ }
60
+ const localIndex = localExtensions.findIndex(item => item.extension === extension);
61
+ const segments = localExtensions[localIndex]?.segments;
62
+ if (!segments || segments.length === 0)
63
+ return compactResourceLabel(resourcePath);
64
+ for (let count = 1; count <= segments.length; count += 1) {
65
+ const candidate = segments.slice(-count).join("/");
66
+ if (localExtensions.every((item, itemIndex) => itemIndex === localIndex || item.segments.slice(-count).join("/") !== candidate)) {
67
+ return candidate;
68
+ }
69
+ }
70
+ return segments.join("/");
71
+ });
72
+ }
73
+ function compactPackageExtensionLabel(resourcePath, sourceInfo) {
74
+ const sourceLabel = compactPackageSourceLabel(sourceInfo.source);
75
+ if (!sourceLabel)
76
+ return compactResourceLabel(resourcePath);
77
+ const shortPath = shortPackagePath(resourcePath, sourceInfo).replaceAll("\\", "/");
78
+ const packagePath = shortPath.startsWith("extensions/") ? shortPath.slice("extensions/".length) : shortPath;
79
+ const slash = packagePath.lastIndexOf("/");
80
+ const fileName = slash < 0 ? packagePath : packagePath.slice(slash + 1);
81
+ const directory = slash < 0 ? "" : packagePath.slice(0, slash);
82
+ const extension = fileName.lastIndexOf(".");
83
+ const name = extension <= 0 ? fileName : fileName.slice(0, extension);
84
+ if (name === "index")
85
+ return !directory || directory === "." ? sourceLabel : `${sourceLabel}:${directory}`;
86
+ return `${sourceLabel}:${packagePath}`;
87
+ }
88
+ function compactPackageSourceLabel(source) {
89
+ if (source.startsWith("npm:"))
90
+ return source.slice("npm:".length) || source;
91
+ if (!source.startsWith("git:"))
92
+ return source;
93
+ const gitSource = source.slice("git:".length).trim();
94
+ let repositoryPath;
95
+ const scpLike = gitSource.match(/^git@[^:]+:(.+)$/);
96
+ if (scpLike?.[1]) {
97
+ repositoryPath = scpLike[1];
98
+ }
99
+ else if (/^[a-z]+:\/\//i.test(gitSource)) {
100
+ try {
101
+ repositoryPath = new URL(gitSource).pathname.replace(/^\/+/, "");
102
+ }
103
+ catch {
104
+ return source;
105
+ }
106
+ }
107
+ else {
108
+ const slash = gitSource.indexOf("/");
109
+ if (slash >= 0)
110
+ repositoryPath = gitSource.slice(slash + 1);
111
+ }
112
+ if (!repositoryPath)
113
+ return source;
114
+ const ref = repositoryPath.indexOf("@");
115
+ const withoutRef = ref < 0 ? repositoryPath : repositoryPath.slice(0, ref);
116
+ return withoutRef.replace(/\.git$/, "") || source;
117
+ }
118
+ function shortPackagePath(resourcePath, sourceInfo) {
119
+ const fullPath = normalizeResourcePath(resourcePath);
120
+ const baseDir = sourceInfo.baseDir === null ? undefined : normalizeResourcePath(sourceInfo.baseDir).replace(/\/$/, "");
121
+ if (baseDir) {
122
+ const npmRoot = baseDir.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);
123
+ if (npmRoot?.[1] && fullPath.startsWith(`${npmRoot[1]}/`))
124
+ return relativeResourcePath(baseDir, fullPath);
125
+ if (fullPath === baseDir)
126
+ return ".";
127
+ if (fullPath.startsWith(`${baseDir}/`))
128
+ return fullPath.slice(baseDir.length + 1);
129
+ }
130
+ const npmMatch = fullPath.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);
131
+ if (npmMatch?.[2] && sourceInfo.source.startsWith("npm:"))
132
+ return npmMatch[2];
133
+ const gitMatch = fullPath.match(/git\/[^/]+\/[^/]+\/(.*)/);
134
+ if (gitMatch?.[1] && sourceInfo.source.startsWith("git:"))
135
+ return gitMatch[1];
136
+ return resourcePath;
137
+ }
138
+ function relativeResourcePath(from, to) {
139
+ const fromSegments = from.split("/").filter(Boolean);
140
+ const toSegments = to.split("/").filter(Boolean);
141
+ let common = 0;
142
+ while (common < fromSegments.length && common < toSegments.length
143
+ && fromSegments[common]?.toLowerCase() === toSegments[common]?.toLowerCase())
144
+ common += 1;
145
+ return [...fromSegments.slice(common).map(() => ".."), ...toSegments.slice(common)].join("/") || ".";
146
+ }
147
+ function compactPathSegments(path) {
148
+ return normalizeResourcePath(path).split("/").filter(segment => segment.length > 0 && segment !== "~");
149
+ }
150
+ function normalizeResourcePath(path) {
151
+ return path.replaceAll("\\", "/");
152
+ }
153
+ function isPackageExtensionSource(sourceInfo) {
154
+ const source = sourceInfo?.source ?? "";
155
+ return source.startsWith("npm:") || source.startsWith("git:");
156
+ }
157
+ // Performance: one painter set per root keeps identities stable, so the neutral viewport retains row-level
158
+ // selection variants while each callback still resolves the live theme.
@@ -4,8 +4,8 @@ export declare const COPY_CLEANUP_MS = 250;
4
4
  export declare const MAX_COPY_BYTES: number;
5
5
  export declare const MAX_COPY_CONTROL_BYTES: number;
6
6
  export declare const COPY_CHUNK_UNITS = 16384;
7
- export type CopyOutcome = "delivered" | "submitted-unverified" | "failed" | "timed-out" | "superseded" | "canceled";
8
- export type CopyFailure = "size" | "unavailable" | "denied" | "transport" | "unsafe";
7
+ type CopyOutcome = "delivered" | "submitted-unverified" | "failed" | "timed-out" | "superseded" | "canceled";
8
+ type CopyFailure = "size" | "unavailable" | "denied" | "transport" | "unsafe";
9
9
  export interface CopyResult {
10
10
  readonly outcome: CopyOutcome;
11
11
  readonly failure?: CopyFailure;
@@ -54,3 +54,4 @@ export type CopyHelperOutput = {
54
54
  readonly result: CopyResult;
55
55
  readonly control?: string;
56
56
  };
57
+ export {};
@@ -15,26 +15,13 @@ export interface OwnedResponseCopyExecutor extends ResponseCopyExecutor {
15
15
  dispose(): void;
16
16
  readonly warmed: boolean;
17
17
  }
18
- export interface ResponseCopyTerminal {
18
+ interface ResponseCopyTerminal {
19
19
  readonly maxBytes?: number;
20
20
  /** A supported non-blocking submission boundary, not clipboard acknowledgment. */
21
21
  submit(control: string, signal: AbortSignal): Promise<void>;
22
22
  }
23
23
  /** Never substitute a remote host's native clipboard for the terminal user's clipboard. */
24
24
  export declare function responseCopyDestination(env: NodeJS.ProcessEnv): "native" | "terminal";
25
- /**
26
- * Spawn options for one operating-system clipboard writer.
27
- * Platform: on POSIX the writer is detached into its own process group, as pinned Pi 1.4 does, so a writer
28
- * that daemonizes to keep serving the clipboard is not stopped when Ctrl+Z sends SIGTSTP to the shell's group.
29
- */
30
- export declare function platformClipboardWriteOptions(signal: AbortSignal, platform?: NodeJS.Platform): {
31
- signal: AbortSignal;
32
- windowsHide: boolean;
33
- timeout: number;
34
- killSignal: "SIGKILL";
35
- maxBuffer: number;
36
- detached: boolean;
37
- };
38
25
  /** Isolates preparation and native clipboard access; only the owner may submit terminal controls. */
39
26
  export declare function createResponseCopyExecutor(options?: {
40
27
  readonly terminal?: ResponseCopyTerminal;
@@ -52,3 +39,4 @@ export declare function createResponseCopyExecutor(options?: {
52
39
  }): OwnedResponseCopyExecutor;
53
40
  /** A spare-of-one pool of copy helpers; `createResponseCopyExecutor` takes its child and warms the next one after each copy. */
54
41
  export declare function createCopyHelperPool(helper?: URL, idleMs?: number): HelperPool;
42
+ export {};
@@ -25,7 +25,7 @@ function platformClipboardCommands() {
25
25
  * Platform: on POSIX the writer is detached into its own process group, as pinned Pi 1.4 does, so a writer
26
26
  * that daemonizes to keep serving the clipboard is not stopped when Ctrl+Z sends SIGTSTP to the shell's group.
27
27
  */
28
- export function platformClipboardWriteOptions(signal, platform = process.platform) {
28
+ function platformClipboardWriteOptions(signal, platform = process.platform) {
29
29
  return {
30
30
  signal,
31
31
  windowsHide: true,
@@ -5,7 +5,7 @@ export interface SessionResumeCommandMetadata {
5
5
  }
6
6
  export declare function formatSessionResumeCommand(metadata: SessionResumeCommandMetadata): string;
7
7
  export declare function quoteCommandArgument(value: string): string;
8
- export interface ExitTextInput {
8
+ interface ExitTextInput {
9
9
  readonly terminalMode: "regular" | "fullscreen";
10
10
  readonly customViewport: boolean;
11
11
  readonly exitMode: "transcript" | "resume-hint";
@@ -27,3 +27,4 @@ export declare class SessionStopLatch {
27
27
  /** The engine stopped on its own: dispose the shell, then resolve whether or not disposal failed. */
28
28
  settleAfter(dispose: () => Promise<void>): void;
29
29
  }
30
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { OwnedUiSessionViewModel, PromptHistoryImageSidecarAttachment, PromptHistoryImageSidecarPort } from "../../contracts/owned-ui/index.js";
2
+ import type { OwnedUiShellEditorPort } from "../../contracts/owned-ui/index.js";
3
+ import { PromptHistoryController } from "./prompt-history-controller.js";
4
+ import type { OwnedUiShellHistoryOptions } from "./session-shell-root.js";
5
+ type HistoryScope = "unique" | "shared";
6
+ /** What prompt history needs from the session: the editor, the transcript, and a render request. */
7
+ export interface SessionPromptHistoryPorts {
8
+ readonly editor: OwnedUiShellEditorPort;
9
+ usesDefaultInputSurface(): boolean;
10
+ rehydrate(text: string, resolveImage: (id: string) => PromptHistoryImageSidecarAttachment | null): string;
11
+ requestRender(): void;
12
+ transcript(): OwnedUiSessionViewModel["transcript"];
13
+ currentHistorySessionId(): string | null;
14
+ }
15
+ /**
16
+ * Binds persistent prompt history to the current session and scope, and replaces the store when either changes.
17
+ * Invariant: the controller is built in one place, so the initial and rebound histories behave the same.
18
+ */
19
+ export declare class SessionPromptHistory {
20
+ #private;
21
+ constructor(options: OwnedUiShellHistoryOptions, ports: SessionPromptHistoryPorts);
22
+ get controller(): PromptHistoryController | null;
23
+ get imageSidecar(): PromptHistoryImageSidecarPort | undefined;
24
+ start(): void;
25
+ synchronize(): void;
26
+ close(): Promise<boolean>;
27
+ rebind(replaced: boolean, scope?: HistoryScope): void;
28
+ }
29
+ export {};
@@ -0,0 +1,80 @@
1
+ import { PromptHistoryController } from "./prompt-history-controller.js";
2
+ /** The user prompts in a transcript, oldest first: the recall a store-less or replaced history starts from. */
3
+ function userTexts(transcript) {
4
+ return transcript.flatMap(block => block.kind === "user" ? [block.text] : []);
5
+ }
6
+ /**
7
+ * Binds persistent prompt history to the current session and scope, and replaces the store when either changes.
8
+ * Invariant: the controller is built in one place, so the initial and rebound histories behave the same.
9
+ */
10
+ export class SessionPromptHistory {
11
+ #options;
12
+ #ports;
13
+ #controller;
14
+ #scope;
15
+ #sessionId;
16
+ #imageSidecar;
17
+ #started = false;
18
+ constructor(options, ports) {
19
+ this.#options = options;
20
+ this.#ports = ports;
21
+ this.#scope = options.scope ?? "unique";
22
+ this.#sessionId = options.sessionId;
23
+ this.#imageSidecar = options.imageSidecar;
24
+ this.#controller = this.#createController(options.store, userTexts(ports.transcript()));
25
+ }
26
+ get controller() { return this.#controller; }
27
+ get imageSidecar() { return this.#imageSidecar; }
28
+ start() {
29
+ this.#started = true;
30
+ this.#controller?.start();
31
+ }
32
+ synchronize() { this.#controller?.synchronize(); }
33
+ close() { return this.#controller?.close() ?? Promise.resolve(true); }
34
+ // Invariant: delivery recovery does not replace a store; conversation or live scope changes can.
35
+ rebind(replaced, scope) {
36
+ if (this.#options.forSession !== undefined || this.#options.forScope !== undefined) {
37
+ const sessionId = this.#ports.currentHistorySessionId();
38
+ const selectedScope = scope ?? this.#scope;
39
+ if (selectedScope !== this.#scope || sessionId !== this.#sessionId) {
40
+ if (!replaced)
41
+ this.#ports.editor.recall?.restoreDraft?.();
42
+ const previous = this.#controller;
43
+ this.#controller = null;
44
+ this.#imageSidecar = undefined;
45
+ this.#scope = selectedScope;
46
+ this.#sessionId = sessionId ?? undefined;
47
+ void previous?.close().catch(() => false);
48
+ const destination = this.#options.forScope !== undefined
49
+ ? this.#options.forScope(selectedScope, sessionId)
50
+ : sessionId === null ? null : this.#options.forSession(sessionId);
51
+ if (destination !== null) {
52
+ this.#imageSidecar = destination.imageSidecar;
53
+ this.#controller = this.#createController(destination.store, replaced ? userTexts(this.#ports.transcript()) : []);
54
+ if (this.#started)
55
+ this.#controller.start();
56
+ }
57
+ else {
58
+ // Security: missing identity must not reopen Shared or retain another session's recall.
59
+ const fallback = replaced ? userTexts(this.#ports.transcript()).reverse() : [];
60
+ this.#ports.editor.recall?.reset();
61
+ this.#ports.editor.recall?.replace(fallback);
62
+ }
63
+ return;
64
+ }
65
+ }
66
+ if (replaced)
67
+ this.#controller?.reset(userTexts(this.#ports.transcript()));
68
+ }
69
+ #createController(store, fallback) {
70
+ return new PromptHistoryController({
71
+ editor: this.#ports.editor,
72
+ store,
73
+ limit: this.#options.limit,
74
+ fallback,
75
+ active: () => this.#ports.usesDefaultInputSurface(),
76
+ render: () => this.#ports.requestRender(),
77
+ rehydrate: value => this.#ports.rehydrate(value, id => this.#imageSidecar?.readAttachment(id) ?? null),
78
+ });
79
+ }
80
+ }