@timurproko/a1 0.2.6-dev.717 → 0.2.6-dev.734

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 (213) hide show
  1. package/bin/cli.js +13 -2
  2. package/bin/ui.js +13 -0
  3. package/dist/app/session-shell/clipboard-services.d.ts +19 -0
  4. package/dist/app/session-shell/clipboard-services.js +7 -0
  5. package/dist/app/session-shell/exit-notice.d.ts +9 -5
  6. package/dist/app/session-shell/exit-notice.js +5 -5
  7. package/dist/app/session-shell/index.d.ts +3 -1
  8. package/dist/app/session-shell/index.js +1 -0
  9. package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
  10. package/dist/app/session-shell/paste-preparation-client.js +5 -2
  11. package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
  12. package/dist/app/session-shell/path-chip-presentation.js +48 -6
  13. package/dist/app/session-shell/prompt-chips.js +30 -4
  14. package/dist/app/session-shell/prompt-suggestion-controller.d.ts +5 -4
  15. package/dist/app/session-shell/prompt-suggestion-controller.js +148 -58
  16. package/dist/app/session-shell/quit-outro.d.ts +3 -1
  17. package/dist/app/session-shell/quit-outro.js +23 -8
  18. package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
  19. package/dist/app/session-shell/response-copy-transport.js +8 -2
  20. package/dist/app/session-shell/session-shell-root.d.ts +22 -11
  21. package/dist/app/session-shell/session-shell-root.js +19 -12
  22. package/dist/app/session-shell/session-shell.d.ts +19 -21
  23. package/dist/app/session-shell/session-shell.js +678 -840
  24. package/dist/app/session-shell/session-viewport-controller.js +33 -21
  25. package/dist/cli/dispatch.js +5 -3
  26. package/dist/cli/session-context.d.ts +5 -1
  27. package/dist/cli/session-context.js +25 -8
  28. package/dist/composition/owned-ui.d.ts +23 -2
  29. package/dist/composition/owned-ui.js +124 -33
  30. package/dist/composition/session-info-reference.d.ts +2 -2
  31. package/dist/composition/session-info-reference.js +2 -2
  32. package/dist/composition/settings-route-host.js +2 -1
  33. package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
  34. package/dist/contracts/agent-engine/capability-ports.js +1 -35
  35. package/dist/contracts/agent-engine/index.d.ts +1 -7
  36. package/dist/contracts/agent-engine/index.js +0 -4
  37. package/dist/contracts/owned-ui/index.d.ts +9 -3
  38. package/dist/contracts/owned-ui/index.js +2 -1
  39. package/dist/contracts/owned-ui/model.d.ts +10 -0
  40. package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
  41. package/dist/contracts/owned-ui/session-presenters.d.ts +55 -0
  42. package/dist/contracts/owned-ui/session-presenters.js +1 -0
  43. package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
  44. package/dist/contracts/owned-ui/session-workflows.js +30 -0
  45. package/dist/contracts/owned-ui/suggestion-diagnostics.d.ts +5 -1
  46. package/dist/contracts/owned-ui/suggestion-diagnostics.js +3 -1
  47. package/dist/contracts/owned-ui/validation.js +7 -0
  48. package/dist/features/launch/index.d.ts +1 -1
  49. package/dist/features/launch/session-context.d.ts +17 -2
  50. package/dist/features/launch/session-context.js +9 -5
  51. package/dist/features/owned-ui/settings-app.js +56 -54
  52. package/dist/features/prompt-suggestions/diagnostics.js +4 -1
  53. package/dist/foundation/lifecycle/index.d.ts +2 -2
  54. package/dist/foundation/lifecycle/index.js +1 -1
  55. package/dist/foundation/lifecycle/session-repository-context.d.ts +19 -2
  56. package/dist/foundation/lifecycle/session-repository-context.js +434 -66
  57. package/dist/foundation/process-containment/index.d.ts +1 -0
  58. package/dist/foundation/process-containment/index.js +1 -0
  59. package/dist/foundation/process-containment/native-process-inspector.d.ts +3 -0
  60. package/dist/foundation/process-containment/native-process-inspector.js +21 -0
  61. package/dist/foundation/release/bootstrap.js +1 -2
  62. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  63. package/dist/foundation/release/progress-palette.generated.js +2 -2
  64. package/dist/foundation/release/release-gc.js +1 -1
  65. package/dist/foundation/release/update.js +0 -4
  66. package/dist/foundation/startup/startup-descriptor.js +2 -2
  67. package/dist/foundation/storage/control-store.js +0 -12
  68. package/dist/integrations/pi/components/components.js +2 -18
  69. package/dist/integrations/pi/components/index.d.ts +4 -4
  70. package/dist/integrations/pi/components/index.js +2 -2
  71. package/dist/integrations/pi/components/modal-frame.js +3 -4
  72. package/dist/integrations/pi/components/models-dialog.js +6 -35
  73. package/dist/integrations/pi/components/prompt-input-port.d.ts +1 -0
  74. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  75. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  76. package/dist/integrations/pi/components/share-operation-dialog.js +3 -3
  77. package/dist/integrations/pi/components/shell-editor-autocomplete.js +19 -16
  78. package/dist/integrations/pi/components/shell-extension-ui.d.ts +5 -3
  79. package/dist/integrations/pi/components/shell-extension-ui.js +26 -12
  80. package/dist/integrations/pi/components/shell-hotkey-sections.js +2 -2
  81. package/dist/integrations/pi/components/shell-presenters-info.js +10 -10
  82. package/dist/integrations/pi/components/shell-presenters-transcript.js +13 -13
  83. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -6
  84. package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
  85. package/dist/integrations/pi/components/shell-shared-facade.js +19 -3
  86. package/dist/integrations/pi/components/skills-dialog.js +3 -3
  87. package/dist/integrations/pi/components/submitted-prompt-adapter.js +2 -3
  88. package/dist/integrations/pi/components/theme.d.ts +9 -0
  89. package/dist/integrations/pi/components/theme.js +30 -0
  90. package/dist/integrations/pi/components/tool-result-adapter.js +6 -1
  91. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  92. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  93. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  94. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  95. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  96. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  97. package/dist/integrations/pi/components/upstream/components/extension-editor.js +6 -6
  98. package/dist/integrations/pi/components/upstream/components/extension-input.js +4 -4
  99. package/dist/integrations/pi/components/upstream/components/extension-selector.js +4 -4
  100. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  101. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +5 -5
  102. package/dist/integrations/pi/components/upstream/components/owned-editor.js +8 -5
  103. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  104. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  105. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +3 -3
  106. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  107. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  108. package/dist/integrations/pi/components/upstream/components/session-selector.js +9 -9
  109. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +3 -2
  110. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +6 -3
  111. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  112. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  113. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  114. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  115. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  116. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +2 -2
  117. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +4 -0
  118. package/dist/integrations/pi/components/upstream/components/tool-execution.js +11 -1
  119. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +2 -2
  120. package/dist/integrations/pi/components/upstream/components/tree-selector.js +27 -18
  121. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  122. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  123. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +4 -4
  124. package/dist/integrations/pi/components/upstream/history/editor-core.js +11 -7
  125. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  126. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  127. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  128. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  129. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  130. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  131. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  132. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  133. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +31 -0
  134. package/dist/integrations/pi/components/upstream/program-status-reporter.js +89 -0
  135. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  136. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +22 -1
  137. package/dist/integrations/pi/components/upstream/theme/theme.js +225 -10
  138. package/dist/integrations/pi/engine/adapter.d.ts +44 -24
  139. package/dist/integrations/pi/engine/adapter.js +130 -22
  140. package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
  141. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
  142. package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
  143. package/dist/integrations/pi/engine/host-ports.js +13 -0
  144. package/dist/integrations/pi/engine/host.d.ts +70 -0
  145. package/dist/integrations/pi/engine/host.js +147 -0
  146. package/dist/integrations/pi/engine/index.d.ts +8 -4
  147. package/dist/integrations/pi/engine/index.js +3 -1
  148. package/dist/integrations/pi/engine/pi-settings-metadata.json +1 -1
  149. package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
  150. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  151. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
  152. package/dist/integrations/pi/engine/runtime-integration.js +12 -7
  153. package/dist/integrations/pi/engine/session-events.js +10 -2
  154. package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
  155. package/dist/integrations/pi/engine/session-integration.js +0 -49
  156. package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
  157. package/dist/integrations/pi/engine/session-runtime.js +18 -7
  158. package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
  159. package/dist/integrations/pi/engine/settings-bridge.js +0 -2
  160. package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
  161. package/dist/integrations/pi/engine/settings-port.js +3 -5
  162. package/dist/integrations/pi/engine/transcript-projection.js +2 -1
  163. package/dist/integrations/pi/engine/workflows.d.ts +33 -260
  164. package/dist/integrations/pi/engine/workflows.js +6 -28
  165. package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
  166. package/dist/integrations/pi/session-presenters/index.js +1 -0
  167. package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
  168. package/dist/integrations/pi/session-presenters/presenters.js +341 -0
  169. package/dist/integrations/pi/startup-public.js +306 -290
  170. package/dist/integrations/pi/startup-public.manifest.json +289 -265
  171. package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -1
  172. package/dist/integrations/pi/tui-runtime/adapter.js +7 -2
  173. package/dist/integrations/pi/tui-runtime/contracts.d.ts +3 -1
  174. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +8 -1
  175. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +67 -2
  176. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  177. package/dist/integrations/pi/tui-runtime/index.js +1 -1
  178. package/dist/native/darwin-arm64/manifest.json +1 -1
  179. package/dist/native/linux-x64/manifest.json +1 -1
  180. package/dist/native/win32-x64/manifest.json +2 -2
  181. package/dist/native/win32-x64/process-guardian.exe +0 -0
  182. package/dist/product-identity.d.ts +2 -2
  183. package/dist/product-identity.js +2 -2
  184. package/dist/product-identity.json +3 -1
  185. package/dist/runtime-payload-inventory.json +3092 -2878
  186. package/dist/ui/components/prompt-input.d.ts +2 -0
  187. package/dist/ui/components/prompt-input.js +5 -1
  188. package/dist/ui/components/text-selection.d.ts +1 -1
  189. package/dist/ui/components/text-selection.js +3 -1
  190. package/dist/ui/components/theme.d.ts +2 -0
  191. package/dist/ui/components/transcript-viewport.d.ts +6 -4
  192. package/dist/ui/components/transcript-viewport.js +94 -16
  193. package/dist/ui/components/value-menu.d.ts +2 -0
  194. package/dist/ui/components/value-menu.js +13 -8
  195. package/dist/ui/settings/declarations.d.ts +38 -14
  196. package/dist/ui/settings/declarations.js +35 -11
  197. package/dist/ui/settings/migrations.js +23 -0
  198. package/docs/architecture/boundaries.md +9 -1
  199. package/docs/architecture/project-structure.md +7 -5
  200. package/docs/architecture/prompt-suggestions.md +14 -10
  201. package/docs/local-worktree-cleanup.md +11 -5
  202. package/docs/openspec-archive-automation.md +6 -5
  203. package/package.json +3 -3
  204. package/dist/contracts/agent-engine/model.d.ts +0 -78
  205. package/dist/contracts/agent-engine/model.js +0 -1
  206. package/dist/contracts/agent-engine/ports.d.ts +0 -18
  207. package/dist/contracts/agent-engine/serialization.d.ts +0 -7
  208. package/dist/contracts/agent-engine/serialization.js +0 -58
  209. package/dist/contracts/agent-engine/validation.d.ts +0 -5
  210. package/dist/contracts/agent-engine/validation.js +0 -128
  211. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
  212. package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
  213. /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
@@ -306,14 +306,14 @@ export class SessionViewportController {
306
306
  if (this.#viewport.clearSelection())
307
307
  this.#requestRender();
308
308
  }
309
- else {
309
+ else if (this.#viewport.hasSelection) {
310
310
  const copySelection = this.#viewport.captureSelectedText();
311
- if (copySelection !== null) {
312
- this.#viewport.clearSelection();
313
- this.#stopSelectionAutoScroll();
314
- this.#requestRender();
315
- return { data: "", consumed: true, copySelection };
316
- }
311
+ this.#viewport.clearSelection();
312
+ this.#stopSelectionAutoScroll();
313
+ this.#requestRender();
314
+ return copySelection === null
315
+ ? { data: "", consumed: true }
316
+ : { data: "", consumed: true, copySelection };
317
317
  }
318
318
  }
319
319
  const previousPrompt = SHIFT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
@@ -412,12 +412,19 @@ export class SessionViewportController {
412
412
  }
413
413
  if (this.#dockPointerSuppressed || this.#tailPointerSuppressed)
414
414
  return true;
415
+ const pendingEditorClick = this.#pendingEditorClick;
416
+ if (pendingEditorClick !== undefined) {
417
+ if (event.column === pendingEditorClick.column && event.row === pendingEditorClick.row)
418
+ return true;
419
+ this.#pendingEditorClick = undefined;
420
+ this.#viewport.pressSelection(pendingEditorClick.column, pendingEditorClick.row, now, { continueMultiClick: false });
421
+ this.#viewport.extendSelection(event.column, event.row, now, false);
422
+ this.#updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
423
+ activity = true;
424
+ return true;
425
+ }
415
426
  if (this.#viewport.selectionActive) {
416
427
  this.#viewport.extendSelection(event.column, event.row, now, false);
417
- if (this.#pendingEditorClick !== undefined
418
- && (event.column !== this.#pendingEditorClick.column || event.row !== this.#pendingEditorClick.row)) {
419
- this.#pendingEditorClick = undefined;
420
- }
421
428
  this.#updateSelectionAutoScroll(event.column, event.row, hits.viewportHeight, frame.rows.length);
422
429
  activity = true;
423
430
  return true;
@@ -500,11 +507,13 @@ export class SessionViewportController {
500
507
  }
501
508
  if (event.row >= 1 && event.row <= frame.rows.length && event.column <= frame.descriptor.width) {
502
509
  if (editorFrame !== undefined && event.row >= editorFrame.rowStart && event.row <= editorFrame.rowEnd) {
510
+ // Invariant: no-drag prompt clicks remain visually editor-owned. Distinct
511
+ // motion promotes from this exact origin into complete-frame selection.
503
512
  this.#pendingEditorClick = { column: event.column, row: event.row };
504
513
  }
505
- // Invariant: frame selection includes transient and dock rows without changing
506
- // semantic ownership; no-drag editor presses replay on release.
507
- this.#viewport.pressSelection(event.column, event.row, now);
514
+ else {
515
+ this.#viewport.pressSelection(event.column, event.row, now);
516
+ }
508
517
  repaint = true;
509
518
  return true;
510
519
  }
@@ -525,19 +534,22 @@ export class SessionViewportController {
525
534
  repaint = true;
526
535
  return true;
527
536
  }
528
- if (this.#viewport.releaseSelection()) {
529
- this.#stopSelectionAutoScroll();
530
- const pendingEditorClick = this.#pendingEditorClick;
537
+ const pendingEditorClick = this.#pendingEditorClick;
538
+ if (pendingEditorClick !== undefined) {
531
539
  this.#pendingEditorClick = undefined;
532
- if (pendingEditorClick !== undefined && this.#editorPointerFrame !== undefined) {
533
- this.#viewport.clearSelection();
540
+ if (this.#editorPointerFrame !== undefined) {
534
541
  const editorRow = pendingEditorClick.row - this.#editorPointerFrame.rowStart + 1;
535
542
  this.#editor.handlePointer({ kind: "press", button: 0, column: pendingEditorClick.column, row: editorRow });
536
543
  this.#editor.handlePointer({ kind: "release", button: 0, column: pendingEditorClick.column, row: editorRow });
537
544
  }
538
- else if (this.#copyOnSelect) {
545
+ forceRepaint = true;
546
+ repaint = true;
547
+ return true;
548
+ }
549
+ if (this.#viewport.releaseSelection()) {
550
+ this.#stopSelectionAutoScroll();
551
+ if (this.#copyOnSelect)
539
552
  completedCopy = this.#viewport.captureSelectedText() ?? undefined;
540
- }
541
553
  // Platform: restore OSC 8 links only after the held-button selection paint has
542
554
  // ended, then overwrite any terminal-cached hover cells immediately.
543
555
  forceRepaint = true;
@@ -18,6 +18,7 @@ export function cliUsage(capabilities) {
18
18
  "remove <source>",
19
19
  "uninstall <source>",
20
20
  "list",
21
+ "session worktrees",
21
22
  "session link-worktree <path>",
22
23
  "session unlink-worktree",
23
24
  ]);
@@ -47,6 +48,7 @@ export function cliHelp(capabilities) {
47
48
  ` ${command} list`,
48
49
  "",
49
50
  "Session context:",
51
+ ` ${command} session worktrees`,
50
52
  ` ${command} session link-worktree <path>`,
51
53
  ` ${command} session unlink-worktree`,
52
54
  "",
@@ -127,12 +129,12 @@ function parseSessionContext(rest) {
127
129
  return { kind: "error", message: PRODUCT_TEXT.diagnostic("session link-worktree accepts one path.") };
128
130
  return { kind: "session-context", request: { action, path: value } };
129
131
  }
130
- if (action === "unlink-worktree") {
132
+ if (action === "unlink-worktree" || action === "worktrees") {
131
133
  if (value !== undefined)
132
- return { kind: "error", message: PRODUCT_TEXT.diagnostic("session unlink-worktree does not accept arguments.") };
134
+ return { kind: "error", message: PRODUCT_TEXT.diagnostic(`session ${action} does not accept arguments.`) };
133
135
  return { kind: "session-context", request: { action } };
134
136
  }
135
- return { kind: "error", message: PRODUCT_TEXT.diagnostic("session accepts link-worktree <path> or unlink-worktree.") };
137
+ return { kind: "error", message: PRODUCT_TEXT.diagnostic("session accepts worktrees, link-worktree <path>, or unlink-worktree.") };
136
138
  }
137
139
  /**
138
140
  * Stable update is the empty form. `--develop` selects the moving development
@@ -2,8 +2,12 @@ import { type SessionContextRequest } from "../features/launch/index.js";
2
2
  export type { SessionContextRequest } from "../features/launch/index.js";
3
3
  export interface SessionContextCommandOptions {
4
4
  readonly environment?: NodeJS.ProcessEnv;
5
+ readonly inspectProcess?: (pid: number) => Promise<{
6
+ readonly pid: number;
7
+ readonly startIdentity: string;
8
+ } | null>;
5
9
  readonly stdout?: (message: string) => void;
6
10
  readonly stderr?: (message: string) => void;
7
11
  }
8
- /** Apply repository presentation context only when invoked by an active Pi session shell tool. */
12
+ /** Apply repository context only when invoked by an exact live A1 shell-tool runtime. */
9
13
  export declare function runSessionContextCommand(request: SessionContextRequest, options?: SessionContextCommandOptions): Promise<number>;
@@ -1,29 +1,46 @@
1
1
  import { updateSessionRepositoryContext, } from "../features/launch/index.js";
2
- import { PRODUCT_TEXT } from "../product-identity.js";
3
- /** Apply repository presentation context only when invoked by an active Pi session shell tool. */
2
+ import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../product-identity.js";
3
+ /** Apply repository context only when invoked by an exact live A1 shell-tool runtime. */
4
4
  export async function runSessionContextCommand(request, options = {}) {
5
5
  const environment = options.environment ?? process.env;
6
6
  const stdout = options.stdout ?? (message => process.stdout.write(message));
7
7
  const stderr = options.stderr ?? (message => process.stderr.write(message));
8
8
  const identity = readIdentity(environment);
9
9
  if (identity === null) {
10
- stderr(`${PRODUCT_TEXT.diagnostic("session context requires an active A1 shell-tool session.")}\n`);
10
+ stderr(`${PRODUCT_TEXT.diagnostic("session context requires an active A1 shell-tool session runtime.")}\n`);
11
11
  return 2;
12
12
  }
13
13
  try {
14
- const cwd = await updateSessionRepositoryContext(identity, request);
15
- stdout(cwd === null ? "Session worktree context cleared.\n" : `Session worktree context linked: ${cwd}\n`);
14
+ if (options.inspectProcess === undefined)
15
+ throw Object.assign(new Error("native process identity inspection is unavailable"), { code: "process-inspection-unavailable" });
16
+ const outcome = await updateSessionRepositoryContext({ sessionId: identity.sessionId, sessionFile: identity.sessionFile }, request, { runtimeId: identity.runtimeId, inspectProcess: options.inspectProcess });
17
+ if (outcome.kind === "unlinked")
18
+ stdout("Session worktree context cleared.\n");
19
+ if (outcome.kind === "linked")
20
+ stdout(`Session worktree context linked: ${outcome.cwd}\n`);
21
+ if (outcome.kind === "worktrees") {
22
+ for (const entry of outcome.entries)
23
+ stdout(`${entry.status}: ${entry.cwd} (${entry.branch})\n`);
24
+ }
16
25
  return 0;
17
26
  }
18
27
  catch (error) {
19
- stderr(`${PRODUCT_TEXT.diagnostic(`could not update session context: ${error instanceof Error ? error.message : String(error)}`)}\n`);
28
+ const code = errorCode(error);
29
+ const detail = error instanceof Error ? error.message : String(error);
30
+ stderr(`${PRODUCT_TEXT.diagnostic(`could not update session context${code === null ? "" : ` (${code})`}: ${detail}`)}\n`);
20
31
  return 1;
21
32
  }
22
33
  }
23
34
  function readIdentity(environment) {
24
35
  const sessionId = environment.PI_SESSION_ID;
25
36
  const sessionFile = environment.PI_SESSION_FILE;
26
- if (!sessionId || !sessionFile)
37
+ const runtimeId = environment[PRODUCT_IDENTITY.environment.sessionRuntimeId];
38
+ if (!sessionId || !sessionFile || !runtimeId)
27
39
  return null;
28
- return { sessionId, sessionFile };
40
+ return { sessionId, sessionFile, runtimeId };
41
+ }
42
+ function errorCode(error) {
43
+ if (error instanceof Error && "code" in error && typeof error.code === "string")
44
+ return error.code;
45
+ return null;
29
46
  }
@@ -1,15 +1,34 @@
1
1
  import type { AvailableRelease, StartupReleaseCheckOptions } from "../foundation/release/latest-release.js";
2
+ import type { NativeProcessIdentity } from "../foundation/lifecycle/model.js";
2
3
  import type { SessionSelection } from "../foundation/lifecycle/session-selection.js";
3
- import type { PiEngineAdapter } from "../integrations/pi/engine/adapter.js";
4
+ import { type PiEngineHostOptions, type PiEngineSessionRequest } from "../integrations/pi/engine/host.js";
5
+ import { type PiSessionPresenterBackend } from "../integrations/pi/session-presenters/index.js";
4
6
  import type { PiProjectTrustPreflightPrompt } from "../integrations/pi/engine/project-trust-preflight.js";
5
7
  import type { PiSessionForkPrompt } from "../integrations/pi/engine/session-selection.js";
6
8
  import { OwnedSettingsManager } from "../ui/settings/manager.js";
7
9
  import type { OwnedUiApplicationPort, PresentationTerminalPort } from "../contracts/presentation/index.js";
10
+ import type { AgentSettingsPort } from "../contracts/agent-engine/index.js";
11
+ import type { OwnedUiPromptSuggestionGeneratorPort, UiAccentColor } from "../contracts/owned-ui/index.js";
8
12
  import type { ReleaseNoteCatalog } from "../features/owned-ui/release-notes.js";
13
+ /**
14
+ * The session backend composition wires: the owned-UI port, the prompt-suggestion generator, and
15
+ * the agent settings port. `settingsPort` stays outside the owned-UI contract because its type
16
+ * belongs to the agent-engine contracts, which the owned-UI contract may not import.
17
+ */
18
+ export interface ComposedSessionBackend extends PiSessionPresenterBackend, OwnedUiPromptSuggestionGeneratorPort {
19
+ settingsPort(): AgentSettingsPort | null;
20
+ }
21
+ /** The process-level engine host as composition drives it: sessions, the live accent, and disposal. */
22
+ export interface ComposedEngineHost {
23
+ create(request: PiEngineSessionRequest): Promise<ComposedSessionBackend>;
24
+ setAccentColor(color: UiAccentColor): void;
25
+ dispose(): Promise<void>;
26
+ }
9
27
  export interface OwnedUiCompositionOptions {
10
28
  readonly cwd?: string;
11
29
  readonly terminal?: PresentationTerminalPort;
12
- readonly createPiAdapter?: () => Promise<PiEngineAdapter>;
30
+ /** Test seam standing in for the Pi engine host; receives the options composition resolved. */
31
+ readonly createEngineHost?: (options: PiEngineHostOptions) => Promise<ComposedEngineHost>;
13
32
  /** Explicit file selection retained for SDK callers. Public CLI uses sessionSelection. */
14
33
  readonly sessionPath?: string;
15
34
  readonly sessionSelection?: SessionSelection;
@@ -34,6 +53,8 @@ export interface OwnedUiCompositionOptions {
34
53
  readonly releaseNotes?: ReleaseNoteCatalog;
35
54
  /** Startup release-availability seam; defaults to the throttled registry check. */
36
55
  readonly checkForNewerRelease?: (options: StartupReleaseCheckOptions) => Promise<AvailableRelease | null>;
56
+ /** Exact native process inspection injected by the shipped entry; absent SDK seams do not publish claims. */
57
+ readonly inspectProcess?: (pid: number) => Promise<NativeProcessIdentity | null>;
37
58
  }
38
59
  export interface OwnedUiComposition {
39
60
  readonly application: OwnedUiApplicationPort;
@@ -6,47 +6,108 @@ import { PromptImageSidecar } from "../features/prompt-history/image-sidecar.js"
6
6
  import { resolvePromptHistoryPath } from "../features/prompt-history/paths.js";
7
7
  import { resolvePromptHistoryDataDir } from "../features/launch/profile-paths.js";
8
8
  import { resolveProductPaths } from "../foundation/lifecycle/paths.js";
9
- import { readSessionRepositoryContext } from "../foundation/lifecycle/session-repository-context.js";
10
- import { applyConfiguredPiTheme, getAvailablePiThemes } from "../integrations/pi/components/upstream/theme/theme.js";
11
- import { createPiEngineAdapter } from "../integrations/pi/engine/adapter.js";
9
+ import { applyConfiguredPiTheme, getAvailablePiThemes, setPiAccentColor, setPiPackageBorderProjectionEnabled } from "../integrations/pi/components/upstream/theme/theme.js";
10
+ import { createPiEngineHost } from "../integrations/pi/engine/host.js";
11
+ import { createPiSessionPresenters } from "../integrations/pi/session-presenters/index.js";
12
12
  import { ClipboardDiagnosticCapture } from "../app/session-shell/clipboard-diagnostics.js";
13
+ import { createOwnedUiClipboardServices } from "../app/session-shell/clipboard-services.js";
14
+ import { createPiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
13
15
  import { OwnedUiSessionShell } from "../app/session-shell/session-shell.js";
14
16
  import { OwnedSettingsManager } from "../ui/settings/manager.js";
15
17
  import { createPiTerminalBridge } from "../integrations/pi/tui-runtime/presentation-adapter.js";
16
18
  import { createOwnedRouteHost } from "./settings-route-host.js";
17
19
  import { renderPiShellChangelogLines } from "../integrations/pi/components/shell-presenters-info.js";
18
20
  import { nativeHyperlinkStyle } from "../ui/components/spans.js";
21
+ const SESSION_RUNTIME_REFRESH_MS = 30_000;
19
22
  export async function composeOwnedUiApplication(options = {}) {
20
23
  return (await composeOwnedUi(options)).application;
21
24
  }
22
25
  export async function composeOwnedUi(options = {}) {
23
26
  const cwd = options.cwd ?? process.cwd();
24
27
  const ownedSurfaces = options.ownedSurfaces !== "off";
25
- const adapter = options.createPiAdapter
26
- ? await options.createPiAdapter()
27
- : await createPiEngineAdapter({
28
- cwd,
29
- availableThemes: () => getAvailablePiThemes().map(theme => theme.name),
30
- settingsProductMode: ownedSurfaces ? "bare" : "comparison",
31
- announceStartupChangelog: !ownedSurfaces,
32
- ...(ownedSurfaces ? {
33
- repositoryContextReader: async (sessionId, sessionFile, signal) => await readSessionRepositoryContext({ sessionId, sessionFile }, { signal }),
34
- } : {}),
35
- ...(options.sessionPath === undefined ? {} : { sessionPath: options.sessionPath }),
36
- ...(options.sessionSelection === undefined ? {} : { sessionSelection: options.sessionSelection }),
37
- ...(options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: options.sessionForkPrompt }),
38
- ...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
39
- });
28
+ const sessionRuntimeId = ownedSurfaces ? process.env[PRODUCT_IDENTITY.environment.sessionRuntimeId] : undefined;
29
+ const inspectSessionProcess = options.inspectProcess;
30
+ let sessionRuntimeIdentity = null;
31
+ let activeSessionIdentity = null;
32
+ let sessionRuntimeRefreshTimer = null;
33
+ let sessionRuntimeRefresh = Promise.resolve();
34
+ let sessionRuntimeDisposed = false;
35
+ const runtimeIdentity = async () => {
36
+ if (sessionRuntimeId === undefined || inspectSessionProcess === undefined)
37
+ return null;
38
+ sessionRuntimeIdentity ??= inspectSessionProcess(process.pid).catch(() => null);
39
+ return await sessionRuntimeIdentity;
40
+ };
41
+ const queueSessionRuntimeRefresh = () => {
42
+ if (sessionRuntimeDisposed || activeSessionIdentity === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
43
+ return;
44
+ sessionRuntimeRefresh = sessionRuntimeRefresh.then(async () => {
45
+ const identity = activeSessionIdentity;
46
+ if (sessionRuntimeDisposed || identity === null)
47
+ return;
48
+ const owner = await runtimeIdentity();
49
+ if (owner === null)
50
+ return;
51
+ const { registerSessionRepositoryRuntime } = await import("../foundation/lifecycle/session-repository-context.js");
52
+ await registerSessionRepositoryRuntime(identity, sessionRuntimeId, owner, { inspectProcess: inspectSessionProcess });
53
+ }).catch(() => undefined);
54
+ };
55
+ const armSessionRuntimeRefresh = () => {
56
+ if (sessionRuntimeRefreshTimer !== null)
57
+ return;
58
+ sessionRuntimeRefreshTimer = setInterval(queueSessionRuntimeRefresh, SESSION_RUNTIME_REFRESH_MS);
59
+ sessionRuntimeRefreshTimer.unref();
60
+ };
40
61
  const productPaths = resolveProductPaths();
62
+ // Rationale: the manager reads the engine's settings port lazily, after the session exists.
63
+ let backend;
41
64
  const settings = options.profileId === undefined
42
65
  ? null
43
66
  : new OwnedSettingsManager({
44
67
  configDir: resolveProductPaths().configDir,
45
68
  profileId: options.profileId,
46
- agentProvider: () => adapter.settingsPort(),
69
+ agentProvider: () => backend.settingsPort(),
47
70
  hiddenAgentSettingIds: ["fullscreenWheelScrollLines"],
48
71
  agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
49
72
  });
73
+ // Invariant: process-wide engine state has one owner. The host installs the HTTP dispatcher, applies
74
+ // the theme singletons, and announces startup notices once; every session is created through it.
75
+ const host = await (options.createEngineHost ?? (async (hostOptions) => createPiEngineHost(hostOptions)))({
76
+ productMode: ownedSurfaces ? "bare" : "comparison",
77
+ availableThemes: () => getAvailablePiThemes().map(theme => theme.name),
78
+ announceStartupChangelog: !ownedSurfaces,
79
+ theme: {
80
+ base: ownedSurfaces ? "dark" : "engine-configured",
81
+ accentColor: settings !== null && ownedSurfaces ? settings.value("accentColor") : "purple",
82
+ packageBorderProjection: ownedSurfaces,
83
+ apply: { base: applyConfiguredPiTheme, accentColor: setPiAccentColor, packageBorderProjection: setPiPackageBorderProjectionEnabled },
84
+ },
85
+ ...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
86
+ });
87
+ try {
88
+ backend = await host.create({
89
+ cwd,
90
+ ...(ownedSurfaces ? {
91
+ repositoryContextReader: async (sessionId, sessionFile, signal) => {
92
+ const owner = await runtimeIdentity();
93
+ if (owner === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
94
+ return null;
95
+ activeSessionIdentity = { sessionId, sessionFile };
96
+ const { activateSessionRepositoryContext } = await import("../foundation/lifecycle/session-repository-context.js");
97
+ const context = await activateSessionRepositoryContext(activeSessionIdentity, sessionRuntimeId, owner, { signal, inspectProcess: inspectSessionProcess });
98
+ armSessionRuntimeRefresh();
99
+ return context;
100
+ },
101
+ } : {}),
102
+ ...(options.sessionPath === undefined ? {} : { sessionPath: options.sessionPath }),
103
+ ...(options.sessionSelection === undefined ? {} : { sessionSelection: options.sessionSelection }),
104
+ ...(options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: options.sessionForkPrompt }),
105
+ });
106
+ }
107
+ catch (error) {
108
+ await host.dispose();
109
+ throw error;
110
+ }
50
111
  let releaseNotes = null;
51
112
  let releaseNotesFailure;
52
113
  if (ownedSurfaces) {
@@ -67,10 +128,9 @@ export async function composeOwnedUi(options = {}) {
67
128
  : await import("../features/owned-ui/release-note-state.js").then(module => module.claimReleaseNote({
68
129
  configDir: productPaths.configDir, profileId: options.profileId, version: currentReleaseNote.version,
69
130
  }));
70
- // Compatibility: bare A1 intentionally ships one visual target while its UI is being completed:
71
- // dark, regardless of terminal detection or a previously stored Pi theme. The
72
- // comparison profile keeps Pi's configured theme behavior and settings surface.
73
- applyConfiguredPiTheme(ownedSurfaces ? "dark" : adapter.configuredTheme());
131
+ const unsubscribeAccent = settings === null || !ownedSurfaces
132
+ ? () => { }
133
+ : settings.onChange(current => host.setAccentColor(current.value("accentColor")));
74
134
  // Rationale: Routes open only after shell construction.
75
135
  const references = {
76
136
  changelog: async (input) => {
@@ -84,19 +144,24 @@ export async function composeOwnedUi(options = {}) {
84
144
  const { renderPiShellHotkeySections } = await import("../integrations/pi/components/shell-hotkey-sections.js");
85
145
  return { sections: width => renderPiShellHotkeySections(presentation, width) };
86
146
  },
87
- session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(adapter)),
147
+ session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(backend)),
88
148
  };
89
149
  const routeHost = settings === null || !ownedSurfaces ? null : createOwnedRouteHost(settings, references);
90
150
  const viewportSettings = settings === null || !ownedSurfaces ? null : {
91
151
  snapshot: () => viewportSettingsSnapshot(settings),
92
152
  onChange: listener => settings.onChange(() => listener(viewportSettingsSnapshot(settings))),
93
153
  };
154
+ const backgroundSettings = settings === null || !ownedSurfaces ? null : {
155
+ snapshot: () => settings.value("backgroundStyle"),
156
+ // Rationale: one manager notification also recomputes an accent-derived canvas after accentColor changes.
157
+ onChange: listener => settings.onChange(current => listener(current.value("backgroundStyle"))),
158
+ };
94
159
  const diagnosticDestination = options.suggestionDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.suggestionDiagnostics];
95
160
  const suggestionDiagnostics = settings !== null && ownedSurfaces && diagnosticDestination?.trim()
96
161
  ? new SuggestionDiagnosticCapture({ enabled: true, destination: diagnosticDestination }) : null;
97
162
  const promptSuggestions = settings === null || !ownedSurfaces ? null : {
98
163
  ...(suggestionDiagnostics === null ? {} : { diagnostics: suggestionDiagnostics }),
99
- generator: adapter,
164
+ generator: backend,
100
165
  enabled: () => settings.value("promptSuggestions"),
101
166
  onChange: (listener) => settings.onChange(() => listener(settings.value("promptSuggestions"))),
102
167
  };
@@ -112,12 +177,12 @@ export async function composeOwnedUi(options = {}) {
112
177
  const historyLimit = settings?.value("promptHistoryMaxItems");
113
178
  const historyProfileLocation = settings === null || !ownedSurfaces || !settings.value("promptHistoryEnabled")
114
179
  ? null
115
- : resolvePromptHistoryPath(resolvePromptHistoryDataDir(), adapter.agentDir);
180
+ : resolvePromptHistoryPath(resolvePromptHistoryDataDir(), backend.identity.agentDir);
116
181
  const promptHistory = historyProfileLocation === null ? null : {
117
182
  limit: typeof historyLimit === "number" ? historyLimit : 100,
118
183
  store: new PromptHistoryService({
119
184
  dataDir: resolvePromptHistoryDataDir(),
120
- profileRoot: adapter.agentDir,
185
+ profileRoot: backend.identity.agentDir,
121
186
  limit: typeof historyLimit === "number" ? historyLimit : 100,
122
187
  }),
123
188
  imageSidecar: new PromptImageSidecar(historyProfileLocation.imagesDir),
@@ -125,13 +190,18 @@ export async function composeOwnedUi(options = {}) {
125
190
  const clipboardDestination = options.clipboardDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.clipboardDiagnostics];
126
191
  const clipboardDiagnostics = settings !== null && ownedSurfaces && clipboardDestination?.trim()
127
192
  ? new ClipboardDiagnosticCapture(clipboardDestination) : null;
193
+ // Invariant: process-wide services are created once here and borrowed by every session shell. The
194
+ // keybinding registry is applied before any presenter is built, so none of them reads Pi's defaults.
195
+ const keybindings = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
196
+ const clipboardServices = ownedSurfaces ? createOwnedUiClipboardServices() : null;
128
197
  let shell;
129
198
  let releaseNoteAcknowledgement = null;
130
199
  try {
131
200
  shell = new OwnedUiSessionShell({
201
+ presenters: createPiSessionPresenters(backend),
132
202
  engine: {
133
- backend: adapter,
134
- cwd: adapter.cwd,
203
+ backend,
204
+ cwd: backend.identity.cwd,
135
205
  ...(routeHost === null ? {} : { routeHost }),
136
206
  ...(currentReleaseNote === null || releaseNoteClaim === null ? {} : {
137
207
  startupRoute: {
@@ -149,6 +219,7 @@ export async function composeOwnedUi(options = {}) {
149
219
  ...(options.terminal === undefined ? {} : { terminal: createPiTerminalBridge(options.terminal) }),
150
220
  ...(clipboardDiagnostics === null ? {} : { input: { onEvent: event => clipboardDiagnostics.runtime(event) } }),
151
221
  ...(viewportSettings === null ? {} : { viewportSettings }),
222
+ ...(backgroundSettings === null ? {} : { backgroundSettings }),
152
223
  ...(settings === null || !ownedSurfaces ? {} : {
153
224
  quitOutro: { snapshot: () => quitOutroSettingsSnapshot(settings), interactive: process.stdout.isTTY === true },
154
225
  }),
@@ -160,6 +231,7 @@ export async function composeOwnedUi(options = {}) {
160
231
  ...(promptSuggestions === null ? {} : { suggestions: promptSuggestions }),
161
232
  ...(promptImages === null ? {} : { promptImages }),
162
233
  ...(skills === null ? {} : { skills }),
234
+ shared: { keybindings, ...(clipboardServices === null ? {} : { clipboard: clipboardServices }) },
163
235
  ...(promptHistory === null ? {} : { history: {
164
236
  ...promptHistory,
165
237
  editor: await import("../integrations/pi/components/history-editor-loader.js").then(module => module.loadHistoryEditor()),
@@ -167,9 +239,12 @@ export async function composeOwnedUi(options = {}) {
167
239
  });
168
240
  }
169
241
  catch (error) {
242
+ unsubscribeAccent();
170
243
  await releaseNoteClaim?.release();
171
244
  clipboardDiagnostics?.dispose();
172
245
  suggestionDiagnostics?.dispose();
246
+ clipboardServices?.dispose();
247
+ await host.dispose();
173
248
  throw error;
174
249
  }
175
250
  // Rationale: pinned Pi's version check is unreachable because the owned shell never runs its
@@ -185,23 +260,23 @@ export async function composeOwnedUi(options = {}) {
185
260
  ...(settings === null || !ownedSurfaces ? {} : { settingEnabled: settings.value("updateCheck") }),
186
261
  });
187
262
  if (release !== null)
188
- adapter.announceReleaseUpdate(release);
263
+ backend.extensions.announceReleaseUpdate(release);
189
264
  };
190
265
  const exitNoticePath = process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
191
266
  // Security: tools the agent runs must never see, or rewrite, this instance's notice.
192
267
  delete process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
193
268
  let exitNotice = Promise.resolve(null);
194
269
  const application = {
195
- get disposed() { return adapter.disposed; },
270
+ get disposed() { return backend.identity.disposed; },
196
271
  start: () => {
197
272
  // Performance: the guardian notice loads beside first paint, never on the startup path.
198
273
  if (exitNoticePath)
199
274
  exitNotice = import("../app/session-shell/exit-notice.js")
200
- .then(module => module.armExitNotice(adapter, exitNoticePath), () => null);
275
+ .then(module => module.armExitNotice(backend, exitNoticePath), () => null);
201
276
  shell.start();
202
277
  void announceNewerRelease().catch(() => undefined);
203
278
  },
204
- flush: () => adapter.flushEvents(),
279
+ flush: () => backend.session.flushEvents(),
205
280
  waitUntilStopped: () => shell.waitUntilStopped(),
206
281
  dispose: async () => {
207
282
  try {
@@ -211,9 +286,25 @@ export async function composeOwnedUi(options = {}) {
211
286
  await releaseNoteAcknowledgement?.catch(() => undefined);
212
287
  }
213
288
  finally {
289
+ // Invariant: the shared spares outlive every shell and stop only after the last one is disposed.
290
+ clipboardServices?.dispose();
291
+ unsubscribeAccent();
292
+ sessionRuntimeDisposed = true;
293
+ if (sessionRuntimeRefreshTimer !== null)
294
+ clearInterval(sessionRuntimeRefreshTimer);
295
+ sessionRuntimeRefreshTimer = null;
296
+ await sessionRuntimeRefresh;
297
+ const owner = await runtimeIdentity();
298
+ if (sessionRuntimeId !== undefined && owner !== null) {
299
+ await import("../foundation/lifecycle/session-repository-context.js")
300
+ .then(module => module.releaseSessionRepositoryRuntime(sessionRuntimeId, owner))
301
+ .catch(() => undefined);
302
+ }
214
303
  await releaseNoteClaim?.release();
215
304
  suggestionDiagnostics?.dispose();
216
305
  clipboardDiagnostics?.dispose();
306
+ // Invariant: the host outlives the application; disposing it cancels host-level probes last.
307
+ await host.dispose();
217
308
  }
218
309
  },
219
310
  };
@@ -1,4 +1,4 @@
1
1
  import type { ReferenceDocumentProvider } from "../features/owned-ui/reference-screen-app.js";
2
- import type { PiEngineAdapter } from "../integrations/pi/engine/adapter.js";
2
+ import type { OwnedUiSessionBackend } from "../contracts/owned-ui/index.js";
3
3
  /** Captures one current session snapshot and adapts it to the neutral reference document. */
4
- export declare function loadSessionInfoReference(adapter: PiEngineAdapter): Promise<ReferenceDocumentProvider>;
4
+ export declare function loadSessionInfoReference(backend: OwnedUiSessionBackend): Promise<ReferenceDocumentProvider>;
@@ -1,7 +1,7 @@
1
1
  import { renderPiShellSessionInfoReferenceDocument } from "../integrations/pi/components/shell-session-info-reference.js";
2
2
  /** Captures one current session snapshot and adapts it to the neutral reference document. */
3
- export async function loadSessionInfoReference(adapter) {
4
- const result = await adapter.executeWorkflow({ command: "session", argument: "" });
3
+ export async function loadSessionInfoReference(backend) {
4
+ const result = await backend.workflows.executeWorkflow({ command: "session", argument: "" });
5
5
  if (result.outcome !== "completed")
6
6
  throw new Error(result.message);
7
7
  if (result.presentation?.kind !== "session-info")
@@ -1,6 +1,6 @@
1
1
  import { CHANGELOG_ROUTE, HOTKEYS_ROUTE, HOTKEYS_TITLE } from "../features/owned-ui/reference-routes.js";
2
2
  import { SETTINGS_APP_ID, SETTINGS_ROUTE } from "../features/owned-ui/settings-route.js";
3
- import { piTheme } from "../integrations/pi/components/upstream/theme/theme.js";
3
+ import { piTheme, renderPiAccentPreview } from "../integrations/pi/components/upstream/theme/theme.js";
4
4
  import { faint } from "../ui/components/text.js";
5
5
  /** Declares settings and lazy document routes. */
6
6
  export function createOwnedRouteHost(settings, references) {
@@ -130,6 +130,7 @@ function pinnedTheme() {
130
130
  fg: (token, text) => piTheme().fg(token, text),
131
131
  bold: (text) => piTheme().bold(text),
132
132
  plain: (text) => text,
133
+ accentPreview: (color, text) => renderPiAccentPreview(color, text),
133
134
  disabled: (text) => faint(piTheme().fg("dim", text)),
134
135
  highlight: (text) => piTheme().bg("selectedBg", text),
135
136
  panel: (text) => `\u001b[48;2;55;55;55m${text}\u001b[49m`,