@timurproko/a1 0.2.6-dev.727 → 0.2.6-dev.736

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 (116) hide show
  1. package/dist/app/session-shell/clipboard-services.d.ts +19 -0
  2. package/dist/app/session-shell/clipboard-services.js +7 -0
  3. package/dist/app/session-shell/exit-notice.d.ts +9 -5
  4. package/dist/app/session-shell/exit-notice.js +5 -5
  5. package/dist/app/session-shell/index.d.ts +4 -2
  6. package/dist/app/session-shell/index.js +2 -1
  7. package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
  8. package/dist/app/session-shell/paste-preparation-client.js +5 -2
  9. package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
  10. package/dist/app/session-shell/path-chip-presentation.js +48 -6
  11. package/dist/app/session-shell/prompt-chips.js +30 -4
  12. package/dist/app/session-shell/quit-outro.d.ts +3 -1
  13. package/dist/app/session-shell/quit-outro.js +23 -8
  14. package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
  15. package/dist/app/session-shell/response-copy-transport.js +8 -2
  16. package/dist/app/session-shell/session-shell-root.d.ts +29 -11
  17. package/dist/app/session-shell/session-shell-root.js +62 -53
  18. package/dist/app/session-shell/session-shell.d.ts +55 -29
  19. package/dist/app/session-shell/session-shell.js +748 -1132
  20. package/dist/app/session-shell/shell-host.d.ts +105 -0
  21. package/dist/app/session-shell/shell-host.js +523 -0
  22. package/dist/cli/session-context.js +6 -3
  23. package/dist/composition/owned-ui.d.ts +20 -2
  24. package/dist/composition/owned-ui.js +107 -56
  25. package/dist/composition/session-info-reference.d.ts +2 -2
  26. package/dist/composition/session-info-reference.js +2 -2
  27. package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
  28. package/dist/contracts/agent-engine/capability-ports.js +1 -35
  29. package/dist/contracts/agent-engine/index.d.ts +1 -7
  30. package/dist/contracts/agent-engine/index.js +0 -4
  31. package/dist/contracts/owned-ui/index.d.ts +5 -1
  32. package/dist/contracts/owned-ui/index.js +1 -0
  33. package/dist/contracts/owned-ui/model.d.ts +6 -0
  34. package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
  35. package/dist/contracts/owned-ui/session-presenters.d.ts +82 -0
  36. package/dist/contracts/owned-ui/session-presenters.js +1 -0
  37. package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
  38. package/dist/contracts/owned-ui/session-workflows.js +30 -0
  39. package/dist/features/launch/index.d.ts +1 -1
  40. package/dist/features/launch/index.js +1 -1
  41. package/dist/features/launch/session-context.d.ts +1 -0
  42. package/dist/features/launch/session-context.js +1 -0
  43. package/dist/features/owned-ui/settings-app.js +35 -15
  44. package/dist/foundation/lifecycle/index.d.ts +1 -1
  45. package/dist/foundation/lifecycle/index.js +1 -1
  46. package/dist/foundation/lifecycle/session-repository-context.d.ts +8 -2
  47. package/dist/foundation/lifecycle/session-repository-context.js +200 -65
  48. package/dist/foundation/release/bootstrap.js +1 -2
  49. package/dist/foundation/release/release-gc.js +1 -1
  50. package/dist/foundation/release/update.js +0 -4
  51. package/dist/foundation/storage/control-store.js +0 -12
  52. package/dist/integrations/pi/components/components.js +0 -16
  53. package/dist/integrations/pi/components/index.d.ts +3 -3
  54. package/dist/integrations/pi/components/index.js +2 -2
  55. package/dist/integrations/pi/components/models-dialog.js +1 -30
  56. package/dist/integrations/pi/components/shell-editor-autocomplete.js +11 -9
  57. package/dist/integrations/pi/components/shell-extension-ui.d.ts +3 -3
  58. package/dist/integrations/pi/components/shell-extension-ui.js +6 -2
  59. package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -4
  60. package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
  61. package/dist/integrations/pi/components/shell-shared-facade.js +18 -2
  62. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -1
  63. package/dist/integrations/pi/components/upstream/theme/theme.js +20 -2
  64. package/dist/integrations/pi/engine/adapter.d.ts +44 -24
  65. package/dist/integrations/pi/engine/adapter.js +130 -22
  66. package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
  67. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
  68. package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
  69. package/dist/integrations/pi/engine/host-ports.js +13 -0
  70. package/dist/integrations/pi/engine/host.d.ts +70 -0
  71. package/dist/integrations/pi/engine/host.js +147 -0
  72. package/dist/integrations/pi/engine/index.d.ts +8 -4
  73. package/dist/integrations/pi/engine/index.js +3 -1
  74. package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
  75. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
  76. package/dist/integrations/pi/engine/runtime-integration.js +12 -7
  77. package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
  78. package/dist/integrations/pi/engine/session-integration.js +0 -49
  79. package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
  80. package/dist/integrations/pi/engine/session-runtime.js +18 -7
  81. package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
  82. package/dist/integrations/pi/engine/settings-bridge.js +0 -2
  83. package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
  84. package/dist/integrations/pi/engine/settings-port.js +3 -5
  85. package/dist/integrations/pi/engine/workflows.d.ts +33 -260
  86. package/dist/integrations/pi/engine/workflows.js +6 -28
  87. package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
  88. package/dist/integrations/pi/session-presenters/index.js +1 -0
  89. package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
  90. package/dist/integrations/pi/session-presenters/presenters.js +341 -0
  91. package/dist/integrations/pi/tui-runtime/adapter.js +0 -2
  92. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +18 -0
  93. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +84 -3
  94. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  95. package/dist/integrations/pi/tui-runtime/index.js +1 -1
  96. package/dist/native/darwin-arm64/manifest.json +1 -1
  97. package/dist/native/linux-x64/manifest.json +1 -1
  98. package/dist/native/win32-x64/manifest.json +2 -2
  99. package/dist/native/win32-x64/process-guardian.exe +0 -0
  100. package/dist/ui/settings/declarations.d.ts +13 -1
  101. package/dist/ui/settings/declarations.js +12 -1
  102. package/dist/ui/settings/migrations.js +7 -0
  103. package/docs/architecture/boundaries.md +9 -1
  104. package/docs/architecture/project-structure.md +3 -2
  105. package/docs/architecture/ui-reference-provenance.md +1 -1
  106. package/package.json +1 -1
  107. package/dist/contracts/agent-engine/model.d.ts +0 -78
  108. package/dist/contracts/agent-engine/model.js +0 -1
  109. package/dist/contracts/agent-engine/ports.d.ts +0 -18
  110. package/dist/contracts/agent-engine/serialization.d.ts +0 -7
  111. package/dist/contracts/agent-engine/serialization.js +0 -58
  112. package/dist/contracts/agent-engine/validation.d.ts +0 -5
  113. package/dist/contracts/agent-engine/validation.js +0 -128
  114. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
  115. package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
  116. /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
@@ -1,16 +1,34 @@
1
1
  import type { AvailableRelease, StartupReleaseCheckOptions } from "../foundation/release/latest-release.js";
2
2
  import type { NativeProcessIdentity } from "../foundation/lifecycle/model.js";
3
3
  import type { SessionSelection } from "../foundation/lifecycle/session-selection.js";
4
- 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";
5
6
  import type { PiProjectTrustPreflightPrompt } from "../integrations/pi/engine/project-trust-preflight.js";
6
7
  import type { PiSessionForkPrompt } from "../integrations/pi/engine/session-selection.js";
7
8
  import { OwnedSettingsManager } from "../ui/settings/manager.js";
8
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";
9
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
+ }
10
27
  export interface OwnedUiCompositionOptions {
11
28
  readonly cwd?: string;
12
29
  readonly terminal?: PresentationTerminalPort;
13
- 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>;
14
32
  /** Explicit file selection retained for SDK callers. Public CLI uses sessionSelection. */
15
33
  readonly sessionPath?: string;
16
34
  readonly sessionSelection?: SessionSelection;
@@ -7,9 +7,12 @@ 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
9
  import { applyConfiguredPiTheme, getAvailablePiThemes, setPiAccentColor, setPiPackageBorderProjectionEnabled } from "../integrations/pi/components/upstream/theme/theme.js";
10
- import { createPiEngineAdapter } from "../integrations/pi/engine/adapter.js";
10
+ import { createPiEngineHost } from "../integrations/pi/engine/host.js";
11
+ import { createPiSessionPresenters } from "../integrations/pi/session-presenters/index.js";
11
12
  import { ClipboardDiagnosticCapture } from "../app/session-shell/clipboard-diagnostics.js";
12
- import { OwnedUiSessionShell } from "../app/session-shell/session-shell.js";
13
+ import { createOwnedUiClipboardServices } from "../app/session-shell/clipboard-services.js";
14
+ import { createPiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
15
+ import { OwnedUiSessionPresenter, OwnedUiTerminalHost, sessionTerminalHostOptions, } from "../app/session-shell/session-shell.js";
13
16
  import { OwnedSettingsManager } from "../ui/settings/manager.js";
14
17
  import { createPiTerminalBridge } from "../integrations/pi/tui-runtime/presentation-adapter.js";
15
18
  import { createOwnedRouteHost } from "./settings-route-host.js";
@@ -25,7 +28,8 @@ export async function composeOwnedUi(options = {}) {
25
28
  const sessionRuntimeId = ownedSurfaces ? process.env[PRODUCT_IDENTITY.environment.sessionRuntimeId] : undefined;
26
29
  const inspectSessionProcess = options.inspectProcess;
27
30
  let sessionRuntimeIdentity = null;
28
- let activeSessionIdentity = null;
31
+ // Invariant: one entry per agent of this runtime; each agent holds its own claim, and the runtime's exit releases all.
32
+ const activeSessionIdentities = new Map();
29
33
  let sessionRuntimeRefreshTimer = null;
30
34
  let sessionRuntimeRefresh = Promise.resolve();
31
35
  let sessionRuntimeDisposed = false;
@@ -36,59 +40,86 @@ export async function composeOwnedUi(options = {}) {
36
40
  return await sessionRuntimeIdentity;
37
41
  };
38
42
  const queueSessionRuntimeRefresh = () => {
39
- if (sessionRuntimeDisposed || activeSessionIdentity === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
43
+ if (sessionRuntimeDisposed || activeSessionIdentities.size === 0 || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
40
44
  return;
41
45
  sessionRuntimeRefresh = sessionRuntimeRefresh.then(async () => {
42
- const identity = activeSessionIdentity;
43
- if (sessionRuntimeDisposed || identity === null)
46
+ if (sessionRuntimeDisposed)
44
47
  return;
45
48
  const owner = await runtimeIdentity();
46
49
  if (owner === null)
47
50
  return;
48
51
  const { registerSessionRepositoryRuntime } = await import("../foundation/lifecycle/session-repository-context.js");
49
- await registerSessionRepositoryRuntime(identity, sessionRuntimeId, owner, { inspectProcess: inspectSessionProcess });
52
+ for (const [agentId, identity] of activeSessionIdentities) {
53
+ if (sessionRuntimeDisposed)
54
+ return;
55
+ await registerSessionRepositoryRuntime(identity, sessionRuntimeId, owner, {
56
+ inspectProcess: inspectSessionProcess,
57
+ ...(agentId === undefined ? {} : { agentId }),
58
+ }).catch(() => undefined);
59
+ }
50
60
  }).catch(() => undefined);
51
61
  };
62
+ /** The repository context reader for one agent; undefined names the primary agent, the only one composed today. */
63
+ const repositoryContextReaderFor = (agentId) => async (sessionId, sessionFile, signal) => {
64
+ const owner = await runtimeIdentity();
65
+ if (owner === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
66
+ return null;
67
+ const identity = { sessionId, sessionFile };
68
+ activeSessionIdentities.set(agentId, identity);
69
+ const { activateSessionRepositoryContext } = await import("../foundation/lifecycle/session-repository-context.js");
70
+ const context = await activateSessionRepositoryContext(identity, sessionRuntimeId, owner, {
71
+ signal,
72
+ inspectProcess: inspectSessionProcess,
73
+ ...(agentId === undefined ? {} : { agentId }),
74
+ });
75
+ armSessionRuntimeRefresh();
76
+ return context;
77
+ };
52
78
  const armSessionRuntimeRefresh = () => {
53
79
  if (sessionRuntimeRefreshTimer !== null)
54
80
  return;
55
81
  sessionRuntimeRefreshTimer = setInterval(queueSessionRuntimeRefresh, SESSION_RUNTIME_REFRESH_MS);
56
82
  sessionRuntimeRefreshTimer.unref();
57
83
  };
58
- const adapter = options.createPiAdapter
59
- ? await options.createPiAdapter()
60
- : await createPiEngineAdapter({
61
- cwd,
62
- availableThemes: () => getAvailablePiThemes().map(theme => theme.name),
63
- settingsProductMode: ownedSurfaces ? "bare" : "comparison",
64
- announceStartupChangelog: !ownedSurfaces,
65
- ...(ownedSurfaces ? {
66
- repositoryContextReader: async (sessionId, sessionFile, signal) => {
67
- const owner = await runtimeIdentity();
68
- if (owner === null || sessionRuntimeId === undefined || inspectSessionProcess === undefined)
69
- return null;
70
- activeSessionIdentity = { sessionId, sessionFile };
71
- const { activateSessionRepositoryContext } = await import("../foundation/lifecycle/session-repository-context.js");
72
- const context = await activateSessionRepositoryContext(activeSessionIdentity, sessionRuntimeId, owner, { signal, inspectProcess: inspectSessionProcess });
73
- armSessionRuntimeRefresh();
74
- return context;
75
- },
76
- } : {}),
77
- ...(options.sessionPath === undefined ? {} : { sessionPath: options.sessionPath }),
78
- ...(options.sessionSelection === undefined ? {} : { sessionSelection: options.sessionSelection }),
79
- ...(options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: options.sessionForkPrompt }),
80
- ...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
81
- });
82
84
  const productPaths = resolveProductPaths();
85
+ // Rationale: the manager reads the engine's settings port lazily, after the session exists.
86
+ let backend;
83
87
  const settings = options.profileId === undefined
84
88
  ? null
85
89
  : new OwnedSettingsManager({
86
90
  configDir: resolveProductPaths().configDir,
87
91
  profileId: options.profileId,
88
- agentProvider: () => adapter.settingsPort(),
92
+ agentProvider: () => backend.settingsPort(),
89
93
  hiddenAgentSettingIds: ["fullscreenWheelScrollLines"],
90
94
  agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
91
95
  });
96
+ // Invariant: process-wide engine state has one owner. The host installs the HTTP dispatcher, applies
97
+ // the theme singletons, and announces startup notices once; every session is created through it.
98
+ const host = await (options.createEngineHost ?? (async (hostOptions) => createPiEngineHost(hostOptions)))({
99
+ productMode: ownedSurfaces ? "bare" : "comparison",
100
+ availableThemes: () => getAvailablePiThemes().map(theme => theme.name),
101
+ announceStartupChangelog: !ownedSurfaces,
102
+ theme: {
103
+ base: ownedSurfaces ? "dark" : "engine-configured",
104
+ accentColor: settings !== null && ownedSurfaces ? settings.value("accentColor") : "purple",
105
+ packageBorderProjection: ownedSurfaces,
106
+ apply: { base: applyConfiguredPiTheme, accentColor: setPiAccentColor, packageBorderProjection: setPiPackageBorderProjectionEnabled },
107
+ },
108
+ ...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
109
+ });
110
+ try {
111
+ backend = await host.create({
112
+ cwd,
113
+ ...(ownedSurfaces ? { repositoryContextReader: repositoryContextReaderFor(undefined) } : {}),
114
+ ...(options.sessionPath === undefined ? {} : { sessionPath: options.sessionPath }),
115
+ ...(options.sessionSelection === undefined ? {} : { sessionSelection: options.sessionSelection }),
116
+ ...(options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: options.sessionForkPrompt }),
117
+ });
118
+ }
119
+ catch (error) {
120
+ await host.dispose();
121
+ throw error;
122
+ }
92
123
  let releaseNotes = null;
93
124
  let releaseNotesFailure;
94
125
  if (ownedSurfaces) {
@@ -109,15 +140,9 @@ export async function composeOwnedUi(options = {}) {
109
140
  : await import("../features/owned-ui/release-note-state.js").then(module => module.claimReleaseNote({
110
141
  configDir: productPaths.configDir, profileId: options.profileId, version: currentReleaseNote.version,
111
142
  }));
112
- // Compatibility: bare A1 intentionally ships one base visual target while its UI is being completed:
113
- // dark, regardless of terminal detection or a previously stored Pi theme. Its owned accent projects
114
- // over that base; comparison keeps Pi's configured theme and unmodified semantic accent.
115
- setPiPackageBorderProjectionEnabled(ownedSurfaces);
116
- setPiAccentColor(settings !== null && ownedSurfaces ? settings.value("accentColor") : "purple");
117
- applyConfiguredPiTheme(ownedSurfaces ? "dark" : adapter.configuredTheme());
118
143
  const unsubscribeAccent = settings === null || !ownedSurfaces
119
144
  ? () => { }
120
- : settings.onChange(current => setPiAccentColor(current.value("accentColor")));
145
+ : settings.onChange(current => host.setAccentColor(current.value("accentColor")));
121
146
  // Rationale: Routes open only after shell construction.
122
147
  const references = {
123
148
  changelog: async (input) => {
@@ -127,23 +152,28 @@ export async function composeOwnedUi(options = {}) {
127
152
  return { rows: width => renderPiShellChangelogLines(markdown, width).map(row => nativeHyperlinkStyle(row)) };
128
153
  },
129
154
  hotkeys: async () => {
130
- const presentation = shell.hotkeysPresentation();
155
+ const presentation = presenter.hotkeysPresentation();
131
156
  const { renderPiShellHotkeySections } = await import("../integrations/pi/components/shell-hotkey-sections.js");
132
157
  return { sections: width => renderPiShellHotkeySections(presentation, width) };
133
158
  },
134
- session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(adapter)),
159
+ session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(backend)),
135
160
  };
136
161
  const routeHost = settings === null || !ownedSurfaces ? null : createOwnedRouteHost(settings, references);
137
162
  const viewportSettings = settings === null || !ownedSurfaces ? null : {
138
163
  snapshot: () => viewportSettingsSnapshot(settings),
139
164
  onChange: listener => settings.onChange(() => listener(viewportSettingsSnapshot(settings))),
140
165
  };
166
+ const backgroundSettings = settings === null || !ownedSurfaces ? null : {
167
+ snapshot: () => settings.value("backgroundStyle"),
168
+ // Rationale: one manager notification also recomputes an accent-derived canvas after accentColor changes.
169
+ onChange: listener => settings.onChange(current => listener(current.value("backgroundStyle"))),
170
+ };
141
171
  const diagnosticDestination = options.suggestionDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.suggestionDiagnostics];
142
172
  const suggestionDiagnostics = settings !== null && ownedSurfaces && diagnosticDestination?.trim()
143
173
  ? new SuggestionDiagnosticCapture({ enabled: true, destination: diagnosticDestination }) : null;
144
174
  const promptSuggestions = settings === null || !ownedSurfaces ? null : {
145
175
  ...(suggestionDiagnostics === null ? {} : { diagnostics: suggestionDiagnostics }),
146
- generator: adapter,
176
+ generator: backend,
147
177
  enabled: () => settings.value("promptSuggestions"),
148
178
  onChange: (listener) => settings.onChange(() => listener(settings.value("promptSuggestions"))),
149
179
  };
@@ -159,12 +189,12 @@ export async function composeOwnedUi(options = {}) {
159
189
  const historyLimit = settings?.value("promptHistoryMaxItems");
160
190
  const historyProfileLocation = settings === null || !ownedSurfaces || !settings.value("promptHistoryEnabled")
161
191
  ? null
162
- : resolvePromptHistoryPath(resolvePromptHistoryDataDir(), adapter.agentDir);
192
+ : resolvePromptHistoryPath(resolvePromptHistoryDataDir(), backend.identity.agentDir);
163
193
  const promptHistory = historyProfileLocation === null ? null : {
164
194
  limit: typeof historyLimit === "number" ? historyLimit : 100,
165
195
  store: new PromptHistoryService({
166
196
  dataDir: resolvePromptHistoryDataDir(),
167
- profileRoot: adapter.agentDir,
197
+ profileRoot: backend.identity.agentDir,
168
198
  limit: typeof historyLimit === "number" ? historyLimit : 100,
169
199
  }),
170
200
  imageSidecar: new PromptImageSidecar(historyProfileLocation.imagesDir),
@@ -172,13 +202,20 @@ export async function composeOwnedUi(options = {}) {
172
202
  const clipboardDestination = options.clipboardDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.clipboardDiagnostics];
173
203
  const clipboardDiagnostics = settings !== null && ownedSurfaces && clipboardDestination?.trim()
174
204
  ? new ClipboardDiagnosticCapture(clipboardDestination) : null;
175
- let shell;
205
+ // Invariant: process-wide services are created once here and borrowed by every session shell. The
206
+ // keybinding registry is applied before any presenter is built, so none of them reads Pi's defaults.
207
+ const keybindings = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
208
+ const clipboardServices = ownedSurfaces ? createOwnedUiClipboardServices() : null;
209
+ let createdTerminalHost;
210
+ let terminalHost;
211
+ let presenter;
176
212
  let releaseNoteAcknowledgement = null;
177
213
  try {
178
- shell = new OwnedUiSessionShell({
214
+ const presenterOptions = {
215
+ presenters: createPiSessionPresenters(backend),
179
216
  engine: {
180
- backend: adapter,
181
- cwd: adapter.cwd,
217
+ backend,
218
+ cwd: backend.identity.cwd,
182
219
  ...(routeHost === null ? {} : { routeHost }),
183
220
  ...(currentReleaseNote === null || releaseNoteClaim === null ? {} : {
184
221
  startupRoute: {
@@ -196,6 +233,7 @@ export async function composeOwnedUi(options = {}) {
196
233
  ...(options.terminal === undefined ? {} : { terminal: createPiTerminalBridge(options.terminal) }),
197
234
  ...(clipboardDiagnostics === null ? {} : { input: { onEvent: event => clipboardDiagnostics.runtime(event) } }),
198
235
  ...(viewportSettings === null ? {} : { viewportSettings }),
236
+ ...(backgroundSettings === null ? {} : { backgroundSettings }),
199
237
  ...(settings === null || !ownedSurfaces ? {} : {
200
238
  quitOutro: { snapshot: () => quitOutroSettingsSnapshot(settings), interactive: process.stdout.isTTY === true },
201
239
  }),
@@ -207,17 +245,26 @@ export async function composeOwnedUi(options = {}) {
207
245
  ...(promptSuggestions === null ? {} : { suggestions: promptSuggestions }),
208
246
  ...(promptImages === null ? {} : { promptImages }),
209
247
  ...(skills === null ? {} : { skills }),
248
+ shared: { keybindings, ...(clipboardServices === null ? {} : { clipboard: clipboardServices }) },
210
249
  ...(promptHistory === null ? {} : { history: {
211
250
  ...promptHistory,
212
251
  editor: await import("../integrations/pi/components/history-editor-loader.js").then(module => module.loadHistoryEditor()),
213
252
  } }),
214
- });
253
+ };
254
+ // Invariant: one terminal host owns the process terminal; the session presenter reaches it only through
255
+ // the host and paints once attached.
256
+ terminalHost = createdTerminalHost = new OwnedUiTerminalHost(sessionTerminalHostOptions(presenterOptions));
257
+ presenter = new OwnedUiSessionPresenter(terminalHost, presenterOptions);
258
+ terminalHost.attach(presenter);
215
259
  }
216
260
  catch (error) {
261
+ await createdTerminalHost?.dispose().catch(() => undefined);
217
262
  unsubscribeAccent();
218
263
  await releaseNoteClaim?.release();
219
264
  clipboardDiagnostics?.dispose();
220
265
  suggestionDiagnostics?.dispose();
266
+ clipboardServices?.dispose();
267
+ await host.dispose();
221
268
  throw error;
222
269
  }
223
270
  // Rationale: pinned Pi's version check is unreachable because the owned shell never runs its
@@ -233,32 +280,34 @@ export async function composeOwnedUi(options = {}) {
233
280
  ...(settings === null || !ownedSurfaces ? {} : { settingEnabled: settings.value("updateCheck") }),
234
281
  });
235
282
  if (release !== null)
236
- adapter.announceReleaseUpdate(release);
283
+ backend.extensions.announceReleaseUpdate(release);
237
284
  };
238
285
  const exitNoticePath = process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
239
286
  // Security: tools the agent runs must never see, or rewrite, this instance's notice.
240
287
  delete process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
241
288
  let exitNotice = Promise.resolve(null);
242
289
  const application = {
243
- get disposed() { return adapter.disposed; },
290
+ get disposed() { return backend.identity.disposed; },
244
291
  start: () => {
245
292
  // Performance: the guardian notice loads beside first paint, never on the startup path.
246
293
  if (exitNoticePath)
247
294
  exitNotice = import("../app/session-shell/exit-notice.js")
248
- .then(module => module.armExitNotice(adapter, exitNoticePath), () => null);
249
- shell.start();
295
+ .then(module => module.armExitNotice(backend, exitNoticePath), () => null);
296
+ presenter.start();
250
297
  void announceNewerRelease().catch(() => undefined);
251
298
  },
252
- flush: () => adapter.flushEvents(),
253
- waitUntilStopped: () => shell.waitUntilStopped(),
299
+ flush: () => backend.session.flushEvents(),
300
+ waitUntilStopped: () => presenter.waitUntilStopped(),
254
301
  dispose: async () => {
255
302
  try {
256
- await shell.dispose();
303
+ await terminalHost.dispose();
257
304
  // Invariant: cleared only once the terminal is restored; a failed dispose leaves it armed.
258
305
  (await exitNotice)?.clear();
259
306
  await releaseNoteAcknowledgement?.catch(() => undefined);
260
307
  }
261
308
  finally {
309
+ // Invariant: the shared spares outlive every shell and stop only after the last one is disposed.
310
+ clipboardServices?.dispose();
262
311
  unsubscribeAccent();
263
312
  sessionRuntimeDisposed = true;
264
313
  if (sessionRuntimeRefreshTimer !== null)
@@ -274,6 +323,8 @@ export async function composeOwnedUi(options = {}) {
274
323
  await releaseNoteClaim?.release();
275
324
  suggestionDiagnostics?.dispose();
276
325
  clipboardDiagnostics?.dispose();
326
+ // Invariant: the host outlives the application; disposing it cancels host-level probes last.
327
+ await host.dispose();
277
328
  }
278
329
  },
279
330
  };
@@ -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,24 +1,4 @@
1
- import type { AgentJsonValue, AgentModelDescriptor, AgentSettingChangeOutcome, AgentResourceDescriptor, AgentSettingDescriptor } from "./domain.js";
2
- export interface AgentModelPort {
3
- readonly capabilities: {
4
- readonly selection: boolean;
5
- readonly refresh: boolean;
6
- readonly scopedCatalog: boolean;
7
- };
8
- listModels(scope?: string): Promise<readonly AgentModelDescriptor[]>;
9
- currentModel(): Promise<AgentModelDescriptor | null>;
10
- selectModel?(providerId: string, modelId: string): Promise<void>;
11
- refreshModels?(): Promise<void>;
12
- }
13
- export interface AgentAuthenticationPort {
14
- readonly capabilities: {
15
- readonly login: boolean;
16
- readonly logout: boolean;
17
- };
18
- status(providerId: string): Promise<"authenticated" | "unauthenticated" | "unavailable">;
19
- login?(providerId: string, signal?: AbortSignal): Promise<void>;
20
- logout?(providerId: string): Promise<void>;
21
- }
1
+ import type { AgentJsonValue, AgentSettingChangeOutcome, AgentSettingDescriptor } from "./domain.js";
22
2
  export interface AgentSettingsPort {
23
3
  readonly capabilities: {
24
4
  readonly write: boolean;
@@ -29,67 +9,3 @@ export interface AgentSettingsPort {
29
9
  writeSetting?(key: string, value: AgentJsonValue): Promise<AgentSettingChangeOutcome>;
30
10
  flush?(): Promise<void>;
31
11
  }
32
- export interface AgentResourcesPort {
33
- readonly capabilities: {
34
- readonly reload: boolean;
35
- readonly extensionBinding: boolean;
36
- };
37
- discoverResources(): Promise<readonly AgentResourceDescriptor[]>;
38
- reload?(): Promise<void>;
39
- bindExtensions?(sessionId: string): Promise<AgentExtensionBinding>;
40
- }
41
- export interface AgentExtensionBinding {
42
- readonly sessionId: string;
43
- dispose(): Promise<void>;
44
- }
45
- export interface AgentExtensionCommand {
46
- readonly name: string;
47
- readonly description: string;
48
- }
49
- export interface AgentSessionMetadata {
50
- readonly sessionId: string;
51
- readonly sessionName: string | null;
52
- readonly sessionPath: string | null;
53
- readonly cwd: string;
54
- }
55
- export interface AgentExtensionFailure {
56
- readonly extensionPath: string | null;
57
- readonly operation: string;
58
- readonly message: string;
59
- readonly recoverable: boolean;
60
- }
61
- export interface AgentExtensionPort {
62
- readonly capabilities: {
63
- readonly reload: boolean;
64
- readonly binding: boolean;
65
- readonly renderers: boolean;
66
- };
67
- discoverCommands(): Promise<readonly AgentExtensionCommand[]>;
68
- sessionMetadata(): Promise<AgentSessionMetadata>;
69
- bind?(sessionId: string): Promise<AgentExtensionBinding>;
70
- reload?(): Promise<void>;
71
- resolveMessageRenderer?(customType: string): unknown;
72
- resolveToolRenderer?(toolName: string): unknown;
73
- subscribeFailures(listener: (failure: AgentExtensionFailure) => void): () => void;
74
- }
75
- export interface AgentWorkflowDescriptor {
76
- readonly id: string;
77
- readonly label: string;
78
- readonly requiredCommands: readonly string[];
79
- }
80
- export interface AgentWorkflowPort {
81
- readonly capabilities: {
82
- readonly execute: boolean;
83
- };
84
- listWorkflows(): Promise<readonly AgentWorkflowDescriptor[]>;
85
- executeWorkflow?(workflowId: string, input: AgentJsonValue, signal?: AbortSignal): Promise<AgentJsonValue>;
86
- }
87
- export interface AgentServicePorts {
88
- readonly models: AgentModelPort;
89
- readonly authentication: AgentAuthenticationPort;
90
- readonly settings: AgentSettingsPort;
91
- readonly resources: AgentResourcesPort;
92
- readonly extensions: AgentExtensionPort;
93
- readonly workflows: AgentWorkflowPort;
94
- }
95
- export declare function assertAgentServicePorts(ports: AgentServicePorts): void;
@@ -1,35 +1 @@
1
- export function assertAgentServicePorts(ports) {
2
- required(ports.models, ["listModels", "currentModel"], "model");
3
- advertised(ports.models, "selection", "selectModel", "model");
4
- advertised(ports.models, "refresh", "refreshModels", "model");
5
- required(ports.authentication, ["status"], "authentication");
6
- advertised(ports.authentication, "login", "login", "authentication");
7
- advertised(ports.authentication, "logout", "logout", "authentication");
8
- required(ports.settings, ["listSettings", "readSetting"], "settings");
9
- advertised(ports.settings, "write", "writeSetting", "settings");
10
- advertised(ports.settings, "flush", "flush", "settings");
11
- required(ports.resources, ["discoverResources"], "resources");
12
- advertised(ports.resources, "reload", "reload", "resources");
13
- advertised(ports.resources, "extensionBinding", "bindExtensions", "resources");
14
- required(ports.extensions, ["discoverCommands", "sessionMetadata", "subscribeFailures"], "extensions");
15
- advertised(ports.extensions, "reload", "reload", "extensions");
16
- advertised(ports.extensions, "binding", "bind", "extensions");
17
- advertised(ports.extensions, "renderers", "resolveMessageRenderer", "extensions");
18
- advertised(ports.extensions, "renderers", "resolveToolRenderer", "extensions");
19
- required(ports.workflows, ["listWorkflows"], "workflow");
20
- advertised(ports.workflows, "execute", "executeWorkflow", "workflow");
21
- }
22
- function required(port, operations, label) {
23
- if (!port || typeof port.capabilities !== "object")
24
- throw new TypeError(`${label} port and capabilities are required`);
25
- for (const operation of operations)
26
- if (typeof port[operation] !== "function")
27
- throw new TypeError(`${label} port requires ${operation}`);
28
- }
29
- function advertised(port, capability, operation, label) {
30
- const enabled = port.capabilities[capability];
31
- if (typeof enabled !== "boolean")
32
- throw new TypeError(`${label} capability ${capability} must be explicit`);
33
- if (enabled && typeof port[operation] !== "function")
34
- throw new TypeError(`${label} capability ${capability} requires ${operation}`);
35
- }
1
+ export {};
@@ -1,11 +1,5 @@
1
- export { assertAgentServicePorts } from "./capability-ports.js";
2
- export type { AgentAuthenticationPort, AgentExtensionBinding, AgentExtensionCommand, AgentExtensionFailure, AgentExtensionPort, AgentModelPort, AgentResourcesPort, AgentServicePorts, AgentSessionMetadata, AgentSettingsPort, AgentWorkflowDescriptor, AgentWorkflowPort, } from "./capability-ports.js";
1
+ export type { AgentSettingsPort } from "./capability-ports.js";
3
2
  export type { AgentDomainCapabilities, AgentFailure, AgentFailureCategory, AgentJsonValue, AgentMessage, AgentMessageContent, AgentModelDescriptor, AgentResourceDescriptor, AgentSettingApplicationBoundary, AgentSettingChangeOutcome, AgentSettingDescriptor, AgentSettingFlag, AgentSettingOwner, AgentThemeDescriptor, AgentToolDescriptor, AgentUiContribution, AgentUsage, } from "./domain.js";
4
3
  export { assertAgentDomainCapabilities, assertAgentFailure, assertAgentMessage, assertAgentMessageContent, assertAgentModelDescriptor, assertAgentResourceDescriptor, assertAgentSettingDescriptor, assertAgentThemeDescriptor, assertAgentToolDescriptor, assertAgentUiContribution, assertAgentUsage, } from "./domain-validation.js";
5
- export { AGENT_ENGINE_CONTRACT_VERSION } from "./model.js";
6
- export type { AgentCapabilityContract, AgentCommand, AgentCommandCapability, AgentCommandId, AgentCommandOutcome, AgentEvent, AgentEventCapability, AgentEventSequence, AgentSessionId, AgentSessionLifecycle, AgentSnapshot, } from "./model.js";
7
4
  export { agentPackageOutcome, assertAgentPackagesPort } from "./package-ports.js";
8
5
  export type { AgentPackageDescriptor, AgentPackageDiagnostic, AgentPackageOperation, AgentPackageOutcome, AgentPackageProgress, AgentPackageStatus, AgentPackagesPort, AgentPackagesPortInput, } from "./package-ports.js";
9
- export type { AgentEnginePort, AgentSessionPort } from "./ports.js";
10
- export { assertAgentCapabilityContract, assertAgentCommand, assertAgentEvent, assertAgentSnapshot } from "./validation.js";
11
- export { decodeAgentCommand, decodeAgentEvent, decodeAgentSnapshot, encodeAgentCommand, encodeAgentEvent, encodeAgentSnapshot } from "./serialization.js";
@@ -1,6 +1,2 @@
1
- export { assertAgentServicePorts } from "./capability-ports.js";
2
1
  export { assertAgentDomainCapabilities, assertAgentFailure, assertAgentMessage, assertAgentMessageContent, assertAgentModelDescriptor, assertAgentResourceDescriptor, assertAgentSettingDescriptor, assertAgentThemeDescriptor, assertAgentToolDescriptor, assertAgentUiContribution, assertAgentUsage, } from "./domain-validation.js";
3
- export { AGENT_ENGINE_CONTRACT_VERSION } from "./model.js";
4
2
  export { agentPackageOutcome, assertAgentPackagesPort } from "./package-ports.js";
5
- export { assertAgentCapabilityContract, assertAgentCommand, assertAgentEvent, assertAgentSnapshot } from "./validation.js";
6
- export { decodeAgentCommand, decodeAgentEvent, decodeAgentSnapshot, encodeAgentCommand, encodeAgentEvent, encodeAgentSnapshot } from "./serialization.js";
@@ -3,7 +3,11 @@ export type UiAccentColor = "purple" | "blue" | "cyan" | "green" | "orange" | "p
3
3
  export { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, assertOwnedUiExtensionUiPort, } from "./extension-ui.js";
4
4
  export type { OwnedUiExtensionAutocompleteItem, OwnedUiExtensionAutocompleteProvider, OwnedUiExtensionAutocompleteProviderFactory, OwnedUiExtensionAutocompleteSuggestions, OwnedUiExtensionComponent, OwnedUiExtensionComponentFactory, OwnedUiExtensionComponentFactoryContext, OwnedUiExtensionCustomFactory, OwnedUiExtensionCustomOptions, OwnedUiExtensionDialogOptions, OwnedUiExtensionEditorComponent, OwnedUiExtensionEditorFactory, OwnedUiExtensionEditorThemePort, OwnedUiExtensionEntryRenderInput, OwnedUiExtensionFooterDataPort, OwnedUiExtensionFooterFactory, OwnedUiExtensionInputListener, OwnedUiExtensionKeybindingsPort, OwnedUiExtensionMessageRenderInput, OwnedUiExtensionNotificationSeverity, OwnedUiExtensionOverlayAnchor, OwnedUiExtensionOverlayHandle, OwnedUiExtensionOverlayMargin, OwnedUiExtensionOverlayOptions, OwnedUiExtensionRenderCallback, OwnedUiExtensionRendererPort, OwnedUiExtensionRuntimePort, OwnedUiExtensionSelectListThemePort, OwnedUiExtensionSizeValue, OwnedUiExtensionTerminalPort, OwnedUiExtensionThemeBackground, OwnedUiExtensionThemeColor, OwnedUiExtensionThemeInfo, OwnedUiExtensionThemePort, OwnedUiExtensionToolRenderContext, OwnedUiExtensionUiCallback, OwnedUiExtensionUiPort, OwnedUiExtensionUiProperty, OwnedUiExtensionWidgetOptions, OwnedUiExtensionWidgetPlacement, OwnedUiExtensionWorkingIndicatorOptions, } from "./extension-ui.js";
5
5
  export { OWNED_UI_CONTRACT_VERSION } from "./model.js";
6
- export type { OwnedUiBlockStatus, OwnedUiCommand, OwnedUiCommandOutcome, OwnedUiCorrelationId, OwnedUiCustomization, OwnedUiDiagnostics, OwnedUiDialog, OwnedUiEditorState, OwnedUiEntityId, OwnedUiEvent, OwnedUiFooterView, OwnedUiImageAttachment, OwnedUiLifecycle, OwnedUiModelInfo, OwnedUiOverlay, OwnedUiPromptSuggestionGeneratorPort, OwnedUiPromptSuggestionIdentity, OwnedUiPromptSuggestionReasoning, OwnedUiPromptSuggestionRequest, OwnedUiPromptSuggestionResult, OwnedUiPromptSuggestionState, OwnedUiQuitOutroSettings, OwnedUiQuitOutroSettingsPort, OwnedUiSessionId, OwnedUiSessionViewModel, OwnedUiSeverity, OwnedUiSlotId, OwnedUiSnapshot, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiToolRendering, OwnedUiToolResultPart, OwnedUiToolState, OwnedUiTranscriptBlock, OwnedUiTranscriptBlockKind, OwnedUiTranscriptImageReference, OwnedUiUsageView, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, } from "./model.js";
6
+ export type { OwnedUiBackgroundSettingsPort, OwnedUiBackgroundStyle, OwnedUiBlockStatus, OwnedUiCommand, OwnedUiCommandOutcome, OwnedUiCorrelationId, OwnedUiCustomization, OwnedUiDiagnostics, OwnedUiDialog, OwnedUiEditorState, OwnedUiEntityId, OwnedUiEvent, OwnedUiFooterView, OwnedUiImageAttachment, OwnedUiLifecycle, OwnedUiModelInfo, OwnedUiOverlay, OwnedUiPromptSuggestionGeneratorPort, OwnedUiPromptSuggestionIdentity, OwnedUiPromptSuggestionReasoning, OwnedUiPromptSuggestionRequest, OwnedUiPromptSuggestionResult, OwnedUiPromptSuggestionState, OwnedUiQuitOutroSettings, OwnedUiQuitOutroSettingsPort, OwnedUiSessionId, OwnedUiSessionViewModel, OwnedUiSeverity, OwnedUiSlotId, OwnedUiSnapshot, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiToolRendering, OwnedUiToolResultPart, OwnedUiToolState, OwnedUiTranscriptBlock, OwnedUiTranscriptBlockKind, OwnedUiTranscriptImageReference, OwnedUiUsageView, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, } from "./model.js";
7
+ export type { OwnedUiExtensionPort, OwnedUiSessionBackend, OwnedUiSessionCatalogPort, OwnedUiSessionFactory, OwnedUiSessionIdentityPort, OwnedUiSessionPort, OwnedUiSessionRequest, OwnedUiSessionSettingsPort, OwnedUiWorkflowPort, } from "./session-backend.js";
8
+ export type { OwnedUiDialogHost, OwnedUiInputSurface, OwnedUiPresenterHost, OwnedUiSessionPresenter, OwnedUiSessionPresenters, OwnedUiShortcutDescription, OwnedUiTerminalHost, OwnedUiTranscriptRendererPort, } from "./session-presenters.js";
9
+ export { OWNED_UI_HIDDEN_COMMAND_NAMES, OWNED_UI_MODELS_COMMAND_NAME, OWNED_UI_WORKFLOW_COMMAND_NAMES, } from "./session-workflows.js";
10
+ export type { OwnedUiAmbientAuthentication, OwnedUiAuthenticationProviderOption, OwnedUiAuthenticationProviderStatus, OwnedUiBashWorkflowResult, OwnedUiCacheWarmingPresentation, OwnedUiCommandResult, OwnedUiExtensionResourceSummary, OwnedUiExtensionSourceSummary, OwnedUiHiddenWorkflowCommandName, OwnedUiJsonValue, OwnedUiModelsCommandName, OwnedUiModelsContext, OwnedUiModelsRefreshResult, OwnedUiProjectTrustContext, OwnedUiProjectTrustUpdate, OwnedUiReleaseUpdate, OwnedUiResourceSummary, OwnedUiScopedModelDescriptor, OwnedUiScopedModelsContext, OwnedUiScopedModelsRefreshResult, OwnedUiSessionInfoPresentation, OwnedUiSessionProductMode, OwnedUiSessionResumeMetadata, OwnedUiSessionSettingKey, OwnedUiSessionSettingsSnapshot, OwnedUiSettingEffectHandler, OwnedUiSettingOwner, OwnedUiSettingOwnerHandlers, OwnedUiSettingsThinkingLevel, OwnedUiVisualExtensionSupport, OwnedUiWorkflowAutocompleteCommand, OwnedUiWorkflowCommandName, OwnedUiWorkflowInteractionHost, OwnedUiWorkflowInteractionRequest, OwnedUiWorkflowLoginNotification, OwnedUiWorkflowLoginStart, OwnedUiWorkflowMessage, OwnedUiWorkflowMessageKind, OwnedUiWorkflowOption, OwnedUiWorkflowOutcome, OwnedUiWorkflowPresentation, OwnedUiWorkflowRequest, OwnedUiWorkflowResult, OwnedUiWorkflowRoute, } from "./session-workflows.js";
7
11
  export { acceptsTranscriptUpdate, transcriptToolState } from "./transcript-lifecycle.js";
8
12
  export { DEFAULT_PROMPT_IMAGE_LIMIT, ImageAttachmentError, MAX_CLIPBOARD_TEXT_BYTES, MAX_IMAGE_DATA_BYTES, MAX_PROMPT_IMAGES, assertImageEncodedSize, assertPromptImages, } from "./image-attachments.js";
9
13
  export { CONTEXTUAL_PROMPT_SUGGESTION_INSTRUCTION, normalizePromptSuggestionCandidate } from "./prompt-suggestions.js";
@@ -1,5 +1,6 @@
1
1
  export { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, assertOwnedUiExtensionUiPort, } from "./extension-ui.js";
2
2
  export { OWNED_UI_CONTRACT_VERSION } from "./model.js";
3
+ export { OWNED_UI_HIDDEN_COMMAND_NAMES, OWNED_UI_MODELS_COMMAND_NAME, OWNED_UI_WORKFLOW_COMMAND_NAMES, } from "./session-workflows.js";
3
4
  export { acceptsTranscriptUpdate, transcriptToolState } from "./transcript-lifecycle.js";
4
5
  export { DEFAULT_PROMPT_IMAGE_LIMIT, ImageAttachmentError, MAX_CLIPBOARD_TEXT_BYTES, MAX_IMAGE_DATA_BYTES, MAX_PROMPT_IMAGES, assertImageEncodedSize, assertPromptImages, } from "./image-attachments.js";
5
6
  export { CONTEXTUAL_PROMPT_SUGGESTION_INSTRUCTION, normalizePromptSuggestionCandidate } from "./prompt-suggestions.js";
@@ -64,6 +64,12 @@ export interface OwnedUiViewportSettingsPort {
64
64
  snapshot(): OwnedUiViewportSettings;
65
65
  onChange(listener: (settings: OwnedUiViewportSettings) => void): () => void;
66
66
  }
67
+ export type OwnedUiBackgroundStyle = "transparent" | "accent" | "dark";
68
+ /** Narrow live canvas setting supplied only to the bare-A1 fullscreen presentation. */
69
+ export interface OwnedUiBackgroundSettingsPort {
70
+ snapshot(): OwnedUiBackgroundStyle;
71
+ onChange(listener: (style: OwnedUiBackgroundStyle) => void): () => void;
72
+ }
67
73
  /** Profile-local quit outro choice, read at the moment bare A1 quits. */
68
74
  export interface OwnedUiQuitOutroSettings {
69
75
  /** False leaves the terminal immediately; true plays the shell's fixed effect. */