@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
@@ -5,11 +5,6 @@ import { assertSourceBytes } from "./image-source.js";
5
5
  const MAX_CLIPBOARD_BYTES = 16 * 1024 * 1024;
6
6
  let nativeClipboardPromise;
7
7
  let pendingClipboardWrite = Promise.resolve();
8
- /** Load the native adapter during shell startup so the first paste is warm. */
9
- export function preloadSystemClipboard() {
10
- if (process.platform === "win32" || process.platform === "darwin")
11
- void nativeClipboard();
12
- }
13
8
  /**
14
9
  * Reads plain text through platform clipboard commands without importing Pi's
15
10
  * private clipboard module. Failures are deliberately non-fatal: a denied or
@@ -38,7 +33,7 @@ export async function readSystemClipboardContent(signal, strict = false) {
38
33
  const text = await readSystemClipboardText(signal, strict);
39
34
  return text === null ? null : { kind: "text", text };
40
35
  }
41
- export async function readSystemClipboardImage(reader) {
36
+ async function readSystemClipboardImage(reader) {
42
37
  if (!reader.hasImage())
43
38
  return null;
44
39
  if (reader.getImageBinary !== undefined) {
@@ -74,7 +69,7 @@ export async function readSystemClipboardImage(reader) {
74
69
  }
75
70
  return null;
76
71
  }
77
- export async function readSystemClipboardText(signal, strict = false) {
72
+ async function readSystemClipboardText(signal, strict = false) {
78
73
  // Concurrency: Ctrl+C/Ctrl+X and Ctrl+V can arrive in adjacent input turns. Serialize the
79
74
  // read behind our native write so paste never observes the previous value.
80
75
  await pendingClipboardWrite;
@@ -1,6 +1,7 @@
1
+ import type { OwnedUiShellComponents, OwnedUiShellTranscriptComponentPort } from "../../contracts/owned-ui/index.js";
1
2
  import type { OwnedUiSessionViewModel } from "../../contracts/owned-ui/index.js";
3
+ import type { ThemeSource } from "../../contracts/presentation/index.js";
2
4
  import type { TranscriptPromptAnchor } from "../../ui/components/transcript-viewport.js";
3
- import type { PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
4
5
  type TranscriptBlock = OwnedUiSessionViewModel["transcript"][number];
5
6
  export interface TranscriptDocumentLayout {
6
7
  readonly rows: readonly string[];
@@ -13,7 +14,7 @@ export interface TranscriptDocumentLayout {
13
14
  */
14
15
  export type TranscriptInvalidation = "editor-padding" | "diagnostics" | "workflow-status" | "extension-header" | "viewport-config" | "extension-renderers" | "block-presentation" | "tools-expanded" | "repaint";
15
16
  /** What the document reads from the shell around it on every uncached layout. */
16
- export interface TranscriptDocumentChrome {
17
+ interface TranscriptDocumentChrome {
17
18
  diagnostics(): OwnedUiSessionViewModel["diagnostics"];
18
19
  /** The extension header's rows when one is set, else the built-in header's rows for this layout. */
19
20
  headerRows(width: number): readonly string[];
@@ -23,11 +24,13 @@ export interface TranscriptDocumentChrome {
23
24
  hasExtensionHeader(): boolean;
24
25
  thinkingVisible(): boolean;
25
26
  }
26
- export interface TranscriptDocumentOptions {
27
+ interface TranscriptDocumentOptions {
28
+ readonly theme: ThemeSource;
29
+ readonly components: Pick<OwnedUiShellComponents, "info" | "transcript">;
27
30
  readonly customViewport: boolean;
28
31
  readonly cwd: string;
29
32
  /** Creates the component for a newly seen block; its change callback should call `blockChanged`. */
30
- mount(block: TranscriptBlock): PiShellTranscriptComponentPort;
33
+ mount(block: TranscriptBlock): OwnedUiShellTranscriptComponentPort;
31
34
  readonly chrome: TranscriptDocumentChrome;
32
35
  }
33
36
  /**
@@ -40,8 +43,8 @@ export declare class TranscriptDocument {
40
43
  /** Block component renders since construction, for rendering evidence. */
41
44
  get renderCount(): number;
42
45
  get lastId(): string | undefined;
43
- component(id: string): PiShellTranscriptComponentPort | undefined;
44
- components(): IterableIterator<PiShellTranscriptComponentPort>;
46
+ component(id: string): OwnedUiShellTranscriptComponentPort | undefined;
47
+ components(): IterableIterator<OwnedUiShellTranscriptComponentPort>;
45
48
  anchorOf(id: string): number | undefined;
46
49
  /**
47
50
  * Applies one block: its component is created or updated in place and the order grows
@@ -52,7 +55,7 @@ export declare class TranscriptDocument {
52
55
  /** Replaces the whole transcript with the view's blocks, keeping anchored workflow output in place. */
53
56
  sync(blocks: OwnedUiSessionViewModel["transcript"]): void;
54
57
  /** Appends workflow output anchored after the transcript's first `anchor` blocks. */
55
- appendAnchored(id: string, component: PiShellTranscriptComponentPort, anchor: number): void;
58
+ appendAnchored(id: string, component: OwnedUiShellTranscriptComponentPort, anchor: number): void;
56
59
  /** Disposes every anchored workflow output and drops it from the order. */
57
60
  removeAnchored(): void;
58
61
  /** One block's component drew something new: drop its rows and every layout that contains them. */
@@ -73,5 +76,5 @@ export declare function parseReleaseUpdateDiagnostic(message: string): {
73
76
  changelogUrl: string | null;
74
77
  } | null;
75
78
  /** Web URLs use link blue; file targets retain A1's cyan interactive accent. */
76
- export declare function nativeTranscriptLinkColor(text: string, target: string): string;
79
+ export declare function transcriptLinkColor(theme: ThemeSource): (text: string, target: string) => string;
77
80
  export {};
@@ -1,8 +1,5 @@
1
1
  import { acceptsTranscriptUpdate } from "../../contracts/owned-ui/index.js";
2
2
  import { nativeHyperlinkStyle } from "../../ui/components/spans.js";
3
- import { createPiShellChangelog, createPiShellCollapsedChangelog, renderPiShellPackageUpdateNotice, renderPiShellReleaseUpdateNotice, } from "../../integrations/pi/components/shell-presenters-info.js";
4
- import { isPiPromptStyleCompaction, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
5
- import { piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
6
3
  const LAYOUT_ONLY = new Set(["editor-padding", "diagnostics", "workflow-status", "extension-header"]);
7
4
  const WORKFLOW_STATUS_PREFIX = "workflow-status-";
8
5
  /**
@@ -19,8 +16,10 @@ export class TranscriptDocument {
19
16
  // Performance: document layouts are shared by wheel, rail, jump, and selection frames.
20
17
  #layouts = new Map();
21
18
  #renders = 0;
19
+ #linkColor;
22
20
  constructor(options) {
23
21
  this.#options = options;
22
+ this.#linkColor = transcriptLinkColor(options.theme);
24
23
  }
25
24
  /** Block component renders since construction, for rendering evidence. */
26
25
  get renderCount() {
@@ -171,7 +170,7 @@ export class TranscriptDocument {
171
170
  // bare A1 presents them in its prompt-adjacent notice dock instead.
172
171
  .filter(diagnostic => diagnostic.code === "engine-startup"
173
172
  || !customViewport && diagnostic.code === "project-trust")
174
- .flatMap(diagnostic => renderPiShellStartupDiagnostic(diagnostic, width));
173
+ .flatMap(diagnostic => this.#options.components.transcript.renderStartupDiagnostic(diagnostic, width));
175
174
  const resourceRows = [...chrome.resourceRows(width)];
176
175
  if (resourceRows.at(-1) === "")
177
176
  resourceRows.pop();
@@ -191,7 +190,7 @@ export class TranscriptDocument {
191
190
  if (!thinkingVisible && block?.kind === "thinking")
192
191
  continue;
193
192
  const promptLike = block !== undefined
194
- && (block.kind === "user" || customViewport && isPiPromptStyleCompaction(block));
193
+ && (block.kind === "user" || customViewport && this.#options.components.transcript.isPromptStyleCompaction(block));
195
194
  // Invariant: the custom viewport has already removed its rail gutter from this width.
196
195
  // Prompt-like and ordinary blocks therefore share one right content edge.
197
196
  const blockWidth = width;
@@ -240,11 +239,11 @@ export class TranscriptDocument {
240
239
  .filter(diagnostic => !customViewport && diagnostic.code === "release-update")
241
240
  .flatMap(diagnostic => {
242
241
  const release = parseReleaseUpdateDiagnostic(diagnostic.message);
243
- return release === null ? [] : renderPiShellReleaseUpdateNotice(release, width);
242
+ return release === null ? [] : this.#options.components.info.releaseUpdateNotice(release, width);
244
243
  }));
245
244
  rows.push(...diagnostics
246
245
  .filter(diagnostic => diagnostic.code === "package-updates")
247
- .flatMap(diagnostic => renderPiShellPackageUpdateNotice(diagnostic.message.split("\n").filter(line => line.startsWith("- ")).map(line => line.slice(2)), width)));
246
+ .flatMap(diagnostic => this.#options.components.info.packageUpdateNotice(diagnostic.message.split("\n").filter(line => line.startsWith("- ")).map(line => line.slice(2)), width)));
248
247
  rows.push(...diagnostics
249
248
  .filter(diagnostic => diagnostic.code === "changelog-collapsed" || diagnostic.code === "changelog-expanded")
250
249
  // Rationale: bare A1 translates either startup diagnostic into transient dock chrome;
@@ -252,8 +251,8 @@ export class TranscriptDocument {
252
251
  .flatMap(diagnostic => customViewport
253
252
  ? []
254
253
  : diagnostic.code === "changelog-collapsed"
255
- ? createPiShellCollapsedChangelog().render(width)
256
- : createPiShellChangelog(diagnostic.message).render(width)));
254
+ ? this.#options.components.info.collapsedChangelog().render(width)
255
+ : this.#options.components.info.changelog(diagnostic.message).render(width)));
257
256
  rows.push(...diagnostics
258
257
  .filter(diagnostic => diagnostic.code !== "engine-startup" && diagnostic.code !== "project-trust"
259
258
  && diagnostic.code !== "release-update" && diagnostic.code !== "release-update-installed"
@@ -261,7 +260,7 @@ export class TranscriptDocument {
261
260
  && diagnostic.code !== "package-updates" && diagnostic.code !== "changelog-collapsed"
262
261
  && diagnostic.code !== "changelog-expanded")
263
262
  .slice(-3)
264
- .flatMap(diagnostic => renderPiShellTranscriptBlock({
263
+ .flatMap(diagnostic => this.#options.components.transcript.renderBlock({
265
264
  id: `diagnostic-${diagnostic.sequence}`,
266
265
  kind: diagnostic.severity === "error" ? "error" : "system",
267
266
  status: "finalized",
@@ -280,7 +279,7 @@ export class TranscriptDocument {
280
279
  const block = this.#blocks.get(id);
281
280
  if (block === undefined || (!thinkingVisible && block.kind === "thinking"))
282
281
  continue;
283
- if (rows.length > 0 && (block.kind === "user" || this.#options.customViewport && isPiPromptStyleCompaction(block)))
282
+ if (rows.length > 0 && (block.kind === "user" || this.#options.customViewport && this.#options.components.transcript.isPromptStyleCompaction(block)))
284
283
  rows.push("");
285
284
  rows.push(...this.#blockRows(id, block, width).map(sanitizeExitTranscriptRow));
286
285
  }
@@ -298,7 +297,7 @@ export class TranscriptDocument {
298
297
  const rows = component.render(width);
299
298
  if (!this.#options.customViewport || block?.kind === "user")
300
299
  return rows;
301
- return rows.map(row => nativeHyperlinkStyle(row, nativeTranscriptLinkColor));
300
+ return rows.map(row => nativeHyperlinkStyle(row, this.#linkColor));
302
301
  };
303
302
  if (block === undefined || block.status !== "finalized")
304
303
  return render();
@@ -336,6 +335,6 @@ function sanitizeExitTranscriptRow(row) {
336
335
  return row.replace(KITTY_IMAGE_CONTROL, "").replace(ITERM_IMAGE_CONTROL, "");
337
336
  }
338
337
  /** Web URLs use link blue; file targets retain A1's cyan interactive accent. */
339
- export function nativeTranscriptLinkColor(text, target) {
340
- return piTheme().fg(/^file:/iu.test(target) ? "accent" : "mdLink", text);
338
+ export function transcriptLinkColor(theme) {
339
+ return (text, target) => theme.current().fg(/^file:/iu.test(target) ? "accent" : "mdLink", text);
341
340
  }
@@ -1,5 +1,5 @@
1
+ import type { OwnedUiShellComponentPort } from "../../contracts/owned-ui/index.js";
1
2
  import type { TranscriptPromptAnchor, TranscriptViewportFrameInput } from "../../ui/components/transcript-viewport.js";
2
- import type { PiShellComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
3
3
  import type { ShellLayout, ShellLayoutPorts } from "./shell-layout.js";
4
4
  interface VisibleViewportSnapshot {
5
5
  readonly width: number;
@@ -8,7 +8,7 @@ interface VisibleViewportSnapshot {
8
8
  readonly transientSignature: string;
9
9
  readonly promptAnchors: readonly TranscriptPromptAnchor[];
10
10
  readonly dockLength: number;
11
- readonly inputSurface: PiShellComponentPort;
11
+ readonly inputSurface: OwnedUiShellComponentPort;
12
12
  readonly viewportRevision: number;
13
13
  readonly selectionRevision: number;
14
14
  readonly pointerPosition: TranscriptViewportFrameInput["pointerPosition"];
@@ -0,0 +1,83 @@
1
+ import type { OwnedUiShellEditorPort, OwnedUiViewportSettings } from "../../contracts/owned-ui/index.js";
2
+ import type { TerminalPointerSurface } from "../../contracts/presentation/index.js";
3
+ import { type RoutedMouseInput } from "../../ui/components/mouse.js";
4
+ import type { SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
5
+ import type { TranscriptViewport, TranscriptViewportFrame } from "../../ui/components/transcript-viewport.js";
6
+ /** One-based, inclusive terminal cells of a clickable viewport-tail control. */
7
+ export interface TailControlRegion {
8
+ readonly rowStart: number;
9
+ readonly rowEnd: number;
10
+ readonly columnStart: number;
11
+ readonly columnEnd: number;
12
+ }
13
+ export type TailControl = TailControlRegion & {
14
+ readonly activate: () => void;
15
+ };
16
+ export declare function withinTailControl(region: TailControlRegion, column: number, row: number): boolean;
17
+ export interface ViewportPointerPorts {
18
+ readonly viewport: TranscriptViewport;
19
+ readonly editor: OwnedUiShellEditorPort;
20
+ config(): OwnedUiViewportSettings;
21
+ copyOnSelect(): boolean;
22
+ /** False while replacement input or overlay bounds have not been painted yet. */
23
+ inputGeometryReady(): boolean;
24
+ /** The topmost overlay or input surface under a cell. */
25
+ modalAt(column: number, row: number): TerminalPointerSurface | undefined;
26
+ /** The editor rows of the most recent composition. */
27
+ editorFrame(): {
28
+ readonly rowStart: number;
29
+ readonly rowEnd: number;
30
+ } | undefined;
31
+ tailControl(): TailControl | undefined;
32
+ clearTailControl(): void;
33
+ requestRender(): void;
34
+ requestHyperlinkCleanup(rows?: readonly number[]): void;
35
+ updateSelectionAutoScroll(column: number, row: number, viewportHeight: number, frameHeight: number): void;
36
+ stopSelectionAutoScroll(): void;
37
+ /** A right-click on the editor pastes the clipboard. */
38
+ pasteFromPointer(): void;
39
+ }
40
+ /** How one input chunk's mouse reports changed the viewport. */
41
+ export interface ViewportPointerOutcome {
42
+ repaint: boolean;
43
+ forceRepaint: boolean;
44
+ activity: boolean;
45
+ completedCopy: SelectionCopySnapshot | undefined;
46
+ }
47
+ interface PointerCall {
48
+ readonly allowWheel: boolean;
49
+ readonly now: number;
50
+ readonly editorActive: boolean;
51
+ }
52
+ /**
53
+ * The pointer gestures of the session viewport: which surface a gesture is latched to, the
54
+ * suppression of a gesture begun on the dock or a control, the editor click that waits for drag
55
+ * or release, the rail drag offset, the pointer position and the hovered link. Each report is
56
+ * routed in the same order of checks, and its effect is reported as an outcome.
57
+ */
58
+ export declare class ViewportPointerGestures {
59
+ #private;
60
+ constructor(ports: ViewportPointerPorts);
61
+ get position(): {
62
+ readonly column: number;
63
+ readonly row: number;
64
+ } | undefined;
65
+ get editorSelecting(): boolean;
66
+ /** A gesture is latched to a surface or a selection is being dragged. */
67
+ get held(): boolean;
68
+ /** No pointer position or hovered link is remembered. */
69
+ get idle(): boolean;
70
+ /** Forget every latch. */
71
+ clear(): void;
72
+ /** Swallow the rest of a held gesture until its release. */
73
+ drain(): void;
74
+ /** Before the first paint, a left press and its motion and release belong to no surface. */
75
+ routeUnpainted(data: string): RoutedMouseInput;
76
+ route(data: string, frame: TranscriptViewportFrame, call: PointerCall): {
77
+ readonly routed: RoutedMouseInput;
78
+ readonly outcome: ViewportPointerOutcome;
79
+ };
80
+ /** A newly composed frame may move a link away from a stationary pointer. */
81
+ refreshHover(frame: TranscriptViewportFrame): void;
82
+ }
83
+ export {};
@@ -0,0 +1,361 @@
1
+ import { routeMouseInput } from "../../ui/components/mouse.js";
2
+ import { scrollForThumbRow, scrollForTrackPage, scrollbarWheelRows } from "../../ui/components/scrollbar.js";
3
+ import { readVisibleHyperlinks } from "../../ui/components/visible-hyperlinks.js";
4
+ export function withinTailControl(region, column, row) {
5
+ return row >= region.rowStart && row <= region.rowEnd && column >= region.columnStart && column <= region.columnEnd;
6
+ }
7
+ /**
8
+ * The pointer gestures of the session viewport: which surface a gesture is latched to, the
9
+ * suppression of a gesture begun on the dock or a control, the editor click that waits for drag
10
+ * or release, the rail drag offset, the pointer position and the hovered link. Each report is
11
+ * routed in the same order of checks, and its effect is reported as an outcome.
12
+ */
13
+ export class ViewportPointerGestures {
14
+ #ports;
15
+ #dragGrabOffset = null;
16
+ #owner;
17
+ // Invariant: a right-click editor gesture remains owned by the dock.
18
+ #dockSuppressed = false;
19
+ // Invariant: a gesture begun on an explicit control remains owned by that control.
20
+ #tailSuppressed = false;
21
+ // Invariant: editor selection remains true only while its left button is held.
22
+ #editorSelecting = false;
23
+ // Invariant: no-drag editor presses replay on release; distinct motion promotes frame selection.
24
+ #pendingEditorClick;
25
+ #position;
26
+ #hoveredHyperlinkKey;
27
+ constructor(ports) {
28
+ this.#ports = ports;
29
+ }
30
+ get position() {
31
+ return this.#position;
32
+ }
33
+ get editorSelecting() {
34
+ return this.#editorSelecting;
35
+ }
36
+ /** A gesture is latched to a surface or a selection is being dragged. */
37
+ get held() {
38
+ return this.#owner !== undefined || this.#ports.viewport.selectionActive || this.#editorSelecting;
39
+ }
40
+ /** No pointer position or hovered link is remembered. */
41
+ get idle() {
42
+ return this.#position === undefined && this.#hoveredHyperlinkKey === undefined;
43
+ }
44
+ /** Forget every latch. */
45
+ clear() {
46
+ this.#dragGrabOffset = null;
47
+ this.#dockSuppressed = false;
48
+ this.#tailSuppressed = false;
49
+ this.#editorSelecting = false;
50
+ this.#pendingEditorClick = undefined;
51
+ this.#position = undefined;
52
+ this.#hoveredHyperlinkKey = undefined;
53
+ this.#owner = undefined;
54
+ }
55
+ /** Swallow the rest of a held gesture until its release. */
56
+ drain() {
57
+ this.#owner = "drain";
58
+ }
59
+ /** Before the first paint, a left press and its motion and release belong to no surface. */
60
+ routeUnpainted(data) {
61
+ // Invariant: a not-yet-painted A1 screen is not Pi's selection surface.
62
+ return routeMouseInput(data, event => {
63
+ if (event.kind === "press" && event.button === 0)
64
+ this.#tailSuppressed = true;
65
+ if (event.kind === "release")
66
+ this.#tailSuppressed = false;
67
+ return event.kind === "motion" || event.kind === "release" || (event.kind === "press" && event.button === 0);
68
+ });
69
+ }
70
+ route(data, frame, call) {
71
+ const outcome = { repaint: false, forceRepaint: false, activity: false, completedCopy: undefined };
72
+ const routed = routeMouseInput(data, (event, report) => this.#report(event, report, frame, call, outcome));
73
+ return { routed, outcome };
74
+ }
75
+ /** A newly composed frame may move a link away from a stationary pointer. */
76
+ refreshHover(frame) {
77
+ const pointer = this.#position;
78
+ if (pointer === undefined || this.#ports.viewport.selectionActive || this.#editorSelecting)
79
+ return;
80
+ const next = hyperlinkKeyAt(frame, pointer.column, pointer.row);
81
+ if (this.#hoveredHyperlinkKey !== undefined && next !== this.#hoveredHyperlinkKey) {
82
+ // Platform: Windows Terminal can leave its solid native-hover underline behind
83
+ // when a following viewport moves the link away from a stationary pointer.
84
+ this.#ports.requestHyperlinkCleanup([pointer.row]);
85
+ this.#ports.requestRender();
86
+ }
87
+ this.#hoveredHyperlinkKey = next;
88
+ }
89
+ #report(event, report, frame, call, outcome) {
90
+ const viewport = this.#ports.viewport;
91
+ const hits = frame.hits;
92
+ const overModal = this.#ports.modalAt(event.column, event.row);
93
+ const wheel = event.kind === "wheel-up" || event.kind === "wheel-down";
94
+ // Invariant: latch each gesture to one surface.
95
+ if (this.#owner === "drain" || !this.#ports.inputGeometryReady()) {
96
+ if (event.kind === "release")
97
+ this.#owner = undefined;
98
+ else if (event.kind === "press")
99
+ this.#owner = "drain";
100
+ return true;
101
+ }
102
+ const owner = !wheel && this.#owner !== undefined ? this.#owner : overModal;
103
+ if (owner !== undefined && owner !== "viewport") {
104
+ if (event.kind === "press")
105
+ this.#owner = owner;
106
+ if (event.kind === "release")
107
+ this.#owner = undefined;
108
+ if (event.kind === "press" && viewport.clearSelection())
109
+ outcome.repaint = true;
110
+ viewport.setRailHovered(false);
111
+ viewport.setStickyHovered(false);
112
+ this.#position = undefined;
113
+ owner.component.handleInput?.(report);
114
+ outcome.repaint = true;
115
+ return true;
116
+ }
117
+ if (event.kind === "press")
118
+ this.#owner = "viewport";
119
+ if (event.kind === "release")
120
+ this.#owner = undefined;
121
+ const tailControl = this.#ports.tailControl();
122
+ const target = {
123
+ frame,
124
+ overRail: overModal === undefined && hits.rail !== null
125
+ && event.column === hits.rail.column
126
+ && event.row >= hits.rail.rowStart
127
+ && event.row < hits.rail.rowStart + hits.rail.trackHeight,
128
+ overSticky: overModal === undefined && hits.sticky !== null && event.row === hits.sticky.row && event.column <= hits.sticky.width,
129
+ overBottom: overModal === undefined && hits.bottom !== null && event.row === hits.bottom.row
130
+ && event.column >= hits.bottom.columnStart && event.column <= hits.bottom.columnEnd,
131
+ tailControl,
132
+ overTailControl: overModal === undefined && tailControl !== undefined
133
+ && withinTailControl(tailControl, event.column, event.row),
134
+ };
135
+ this.#track(event, target, outcome);
136
+ switch (event.kind) {
137
+ case "motion": return this.#motion(event, target, call, outcome);
138
+ case "wheel-up":
139
+ case "wheel-down": return this.#wheel(event, frame, call, outcome);
140
+ case "press": return this.#press(event, target, call, outcome);
141
+ case "release": return this.#release(event, call, outcome);
142
+ }
143
+ }
144
+ // Rationale: every report updates the pointer position, the hover of the bottom and tail controls, and the hovered link.
145
+ #track(event, target, outcome) {
146
+ const hits = target.frame.hits;
147
+ const tailControl = target.tailControl;
148
+ const previousPointer = this.#position;
149
+ const wasOverBottom = hits.bottom !== null && previousPointer !== undefined
150
+ && previousPointer.row === hits.bottom.row
151
+ && previousPointer.column >= hits.bottom.columnStart && previousPointer.column <= hits.bottom.columnEnd;
152
+ // Invariant: every report updates the pointer position.
153
+ this.#position = { column: event.column, row: event.row };
154
+ outcome.repaint ||= wasOverBottom !== target.overBottom;
155
+ const wasOverTailControl = tailControl !== undefined && previousPointer !== undefined
156
+ && withinTailControl(tailControl, previousPointer.column, previousPointer.row);
157
+ outcome.repaint ||= wasOverTailControl !== target.overTailControl;
158
+ if (!this.#ports.viewport.selectionActive && !this.#editorSelecting) {
159
+ const nextHyperlink = hyperlinkKeyAt(target.frame, event.column, event.row);
160
+ if (this.#hoveredHyperlinkKey !== undefined && nextHyperlink !== this.#hoveredHyperlinkKey) {
161
+ // Platform: overwrite Windows Terminal's cached native-hover underline exactly once.
162
+ this.#ports.requestHyperlinkCleanup(previousPointer === undefined ? undefined : [previousPointer.row]);
163
+ outcome.repaint = true;
164
+ }
165
+ this.#hoveredHyperlinkKey = nextHyperlink;
166
+ }
167
+ }
168
+ #motion(event, target, call, outcome) {
169
+ const viewport = this.#ports.viewport;
170
+ const { frame } = target;
171
+ const hits = frame.hits;
172
+ viewport.setRailHovered(target.overRail);
173
+ viewport.setStickyHovered(target.overSticky);
174
+ outcome.repaint = true;
175
+ const editorFrame = this.#ports.editorFrame();
176
+ if (call.editorActive && this.#editorSelecting && editorFrame !== undefined) {
177
+ this.#ports.editor.handlePointer({
178
+ kind: "motion",
179
+ button: event.button,
180
+ column: event.column,
181
+ row: event.row - editorFrame.rowStart + 1,
182
+ });
183
+ return true;
184
+ }
185
+ if (this.#dockSuppressed || this.#tailSuppressed)
186
+ return true;
187
+ const pendingEditorClick = this.#pendingEditorClick;
188
+ if (pendingEditorClick !== undefined) {
189
+ if (event.column === pendingEditorClick.column && event.row === pendingEditorClick.row)
190
+ return true;
191
+ this.#pendingEditorClick = undefined;
192
+ const activeEditorFrame = call.editorActive ? editorFrame : undefined;
193
+ if (activeEditorFrame !== undefined && this.#ports.editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: pendingEditorClick.row - activeEditorFrame.rowStart + 1 })) {
194
+ this.#editorSelecting = true;
195
+ this.#ports.editor.handlePointer({ kind: "motion", button: event.button, column: event.column, row: event.row - activeEditorFrame.rowStart + 1 });
196
+ return true;
197
+ }
198
+ viewport.pressSelection(pendingEditorClick.column, pendingEditorClick.row, call.now, { continueMultiClick: false });
199
+ viewport.extendSelection(event.column, event.row, call.now, false);
200
+ this.#ports.updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
201
+ outcome.activity = true;
202
+ return true;
203
+ }
204
+ if (viewport.selectionActive) {
205
+ viewport.extendSelection(event.column, event.row, call.now, false);
206
+ this.#ports.updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
207
+ outcome.activity = true;
208
+ return true;
209
+ }
210
+ if (this.#dragGrabOffset !== null && hits.rail !== null) {
211
+ const scroll = scrollForThumbRow(hits.rail.geometry, event.row - hits.rail.rowStart - this.#dragGrabOffset);
212
+ viewport.scrollTo(scroll, call.now);
213
+ outcome.activity = true;
214
+ return true;
215
+ }
216
+ return target.overRail || target.overSticky || target.overBottom || target.overTailControl;
217
+ }
218
+ #wheel(event, frame, call, outcome) {
219
+ if (!call.allowWheel || event.row < 1 || event.row > frame.hits.viewportHeight)
220
+ return false;
221
+ const distance = scrollbarWheelRows(this.#ports.config().scrollbarSpeed);
222
+ this.#ports.viewport.scrollBy(event.kind === "wheel-up" ? -distance : distance, call.now);
223
+ outcome.activity = true;
224
+ outcome.repaint = true;
225
+ outcome.forceRepaint = true;
226
+ return true;
227
+ }
228
+ #press(event, target, call, outcome) {
229
+ const viewport = this.#ports.viewport;
230
+ const { frame } = target;
231
+ const hits = frame.hits;
232
+ const editorFrame = call.editorActive ? this.#ports.editorFrame() : undefined;
233
+ if (event.button === 2 && editorFrame !== undefined
234
+ && event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
235
+ this.#ports.stopSelectionAutoScroll();
236
+ if (viewport.clearSelection())
237
+ outcome.repaint = true;
238
+ this.#ports.pasteFromPointer();
239
+ this.#dockSuppressed = true;
240
+ outcome.repaint = true;
241
+ return true;
242
+ }
243
+ if (event.button !== 0)
244
+ return false;
245
+ this.#dockSuppressed = false;
246
+ this.#tailSuppressed = false;
247
+ this.#pendingEditorClick = undefined;
248
+ this.#ports.stopSelectionAutoScroll();
249
+ if (viewport.clearSelection())
250
+ outcome.repaint = true;
251
+ if (target.overTailControl && target.tailControl !== undefined) {
252
+ this.#ports.clearTailControl();
253
+ target.tailControl.activate();
254
+ this.#tailSuppressed = true;
255
+ outcome.repaint = true;
256
+ return true;
257
+ }
258
+ if (target.overBottom) {
259
+ viewport.scrollToEnd(call.now);
260
+ this.#tailSuppressed = true;
261
+ outcome.activity = true;
262
+ outcome.repaint = true;
263
+ return true;
264
+ }
265
+ if (target.overSticky && hits.sticky !== null) {
266
+ viewport.scrollTo(hits.sticky.target, call.now);
267
+ this.#tailSuppressed = true;
268
+ outcome.activity = true;
269
+ outcome.repaint = true;
270
+ return true;
271
+ }
272
+ if (target.overRail && hits.rail !== null) {
273
+ const trackRow = event.row - hits.rail.rowStart;
274
+ const geometry = hits.rail.geometry;
275
+ if (trackRow >= geometry.thumbTop && trackRow < geometry.thumbTop + geometry.thumbHeight) {
276
+ this.#dragGrabOffset = trackRow - geometry.thumbTop;
277
+ viewport.setRailDragging(true);
278
+ }
279
+ else {
280
+ viewport.scrollTo(scrollForTrackPage(geometry, trackRow, frame.scrollTop, hits.viewportHeight), call.now);
281
+ this.#tailSuppressed = true;
282
+ }
283
+ outcome.activity = true;
284
+ outcome.repaint = true;
285
+ return true;
286
+ }
287
+ if (event.row >= 1 && event.row <= frame.rows.length && event.column <= frame.descriptor.width) {
288
+ if (editorFrame !== undefined && event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
289
+ // Invariant: no-drag clicks remain editor-owned; first motion latches an editor drag.
290
+ this.#pendingEditorClick = { column: event.column, row: event.row };
291
+ }
292
+ else {
293
+ viewport.pressSelection(event.column, event.row, call.now);
294
+ }
295
+ outcome.repaint = true;
296
+ return true;
297
+ }
298
+ this.#tailSuppressed = true;
299
+ return true;
300
+ }
301
+ #release(event, call, outcome) {
302
+ const viewport = this.#ports.viewport;
303
+ const editorFrame = this.#ports.editorFrame();
304
+ if (call.editorActive && this.#editorSelecting && editorFrame !== undefined) {
305
+ this.#ports.editor.handlePointer({
306
+ kind: "release",
307
+ button: event.button,
308
+ column: event.column,
309
+ row: event.row - editorFrame.rowStart + 1,
310
+ });
311
+ this.#editorSelecting = false;
312
+ outcome.forceRepaint = true;
313
+ outcome.repaint = true;
314
+ return true;
315
+ }
316
+ const pendingEditorClick = this.#pendingEditorClick;
317
+ if (pendingEditorClick !== undefined) {
318
+ this.#pendingEditorClick = undefined;
319
+ if (editorFrame !== undefined) {
320
+ const editorRow = pendingEditorClick.row - editorFrame.rowStart + 1;
321
+ this.#ports.editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: editorRow });
322
+ this.#ports.editor.handlePointer({ kind: "release", button: 0, column: pendingEditorClick.column, row: editorRow });
323
+ }
324
+ outcome.forceRepaint = true;
325
+ outcome.repaint = true;
326
+ return true;
327
+ }
328
+ if (viewport.releaseSelection()) {
329
+ this.#ports.stopSelectionAutoScroll();
330
+ if (this.#ports.copyOnSelect())
331
+ outcome.completedCopy = viewport.captureSelectedText() ?? undefined;
332
+ // Platform: restore OSC 8 links only after the held-button selection paint has
333
+ // ended, then overwrite any terminal-cached hover cells immediately.
334
+ outcome.forceRepaint = true;
335
+ outcome.repaint = true;
336
+ return true;
337
+ }
338
+ if (this.#dragGrabOffset !== null) {
339
+ this.#dragGrabOffset = null;
340
+ viewport.setRailDragging(false);
341
+ outcome.repaint = true;
342
+ return true;
343
+ }
344
+ if (this.#dockSuppressed) {
345
+ this.#dockSuppressed = false;
346
+ return true;
347
+ }
348
+ if (this.#tailSuppressed) {
349
+ this.#tailSuppressed = false;
350
+ return true;
351
+ }
352
+ return false;
353
+ }
354
+ }
355
+ function hyperlinkKeyAt(frame, column, row) {
356
+ if (row < 1 || row > frame.rows.length || column < 1)
357
+ return undefined;
358
+ const range = readVisibleHyperlinks(frame.rows[row - 1] ?? "").ranges
359
+ .find(candidate => column - 1 >= candidate.from && column - 1 < candidate.to);
360
+ return range === undefined ? undefined : JSON.stringify([row, range]);
361
+ }