@timurproko/a1 0.2.7-dev.808 → 0.2.7-dev.810

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 (141) hide show
  1. package/README.md +4 -2
  2. package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
  3. package/dist/app/session-shell/dialog-coordinator.js +133 -0
  4. package/dist/app/session-shell/dock-chrome.d.ts +34 -0
  5. package/dist/app/session-shell/dock-chrome.js +109 -0
  6. package/dist/app/session-shell/exit-notice.d.ts +1 -1
  7. package/dist/app/session-shell/exit-notice.js +1 -1
  8. package/dist/app/session-shell/extension-surface.d.ts +30 -0
  9. package/dist/app/session-shell/extension-surface.js +105 -0
  10. package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
  11. package/dist/app/session-shell/input-surface-switch.js +85 -0
  12. package/dist/app/session-shell/login-interaction.d.ts +27 -0
  13. package/dist/app/session-shell/login-interaction.js +91 -0
  14. package/dist/app/session-shell/prompt-submission.d.ts +48 -0
  15. package/dist/app/session-shell/prompt-submission.js +276 -0
  16. package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
  17. package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
  18. package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
  19. package/dist/app/session-shell/response-copy-transport.js +16 -7
  20. package/dist/app/session-shell/session-concern.d.ts +22 -0
  21. package/dist/app/session-shell/session-concern.js +29 -0
  22. package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
  23. package/dist/app/session-shell/session-lifecycle.js +49 -0
  24. package/dist/app/session-shell/session-shell-root.d.ts +1 -1
  25. package/dist/app/session-shell/session-shell-root.js +182 -931
  26. package/dist/app/session-shell/session-shell.d.ts +2 -8
  27. package/dist/app/session-shell/session-shell.js +202 -901
  28. package/dist/app/session-shell/settings-bindings.d.ts +17 -0
  29. package/dist/app/session-shell/settings-bindings.js +91 -0
  30. package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
  31. package/dist/app/session-shell/shell-editor-factory.js +102 -0
  32. package/dist/app/session-shell/shell-host.d.ts +6 -0
  33. package/dist/app/session-shell/shell-host.js +8 -0
  34. package/dist/app/session-shell/shell-layout.d.ts +64 -0
  35. package/dist/app/session-shell/shell-layout.js +18 -0
  36. package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
  37. package/dist/app/session-shell/suggestion-surface.js +63 -0
  38. package/dist/app/session-shell/transcript-document.d.ts +78 -0
  39. package/dist/app/session-shell/transcript-document.js +365 -0
  40. package/dist/app/session-shell/viewport-layout.d.ts +31 -0
  41. package/dist/app/session-shell/viewport-layout.js +160 -0
  42. package/dist/app/session-shell/workflow-output.d.ts +33 -0
  43. package/dist/app/session-shell/workflow-output.js +174 -0
  44. package/dist/app/session-shell/workflow-router.d.ts +25 -0
  45. package/dist/app/session-shell/workflow-router.js +39 -0
  46. package/dist/composition/owned-ui.d.ts +4 -25
  47. package/dist/composition/owned-ui.js +26 -270
  48. package/dist/composition/resident-tab-bridge.d.ts +16 -0
  49. package/dist/composition/resident-tab-bridge.js +159 -0
  50. package/dist/composition/session-backend.d.ts +19 -0
  51. package/dist/composition/session-backend.js +1 -0
  52. package/dist/composition/session-runtime-registry.d.ts +20 -0
  53. package/dist/composition/session-runtime-registry.js +85 -0
  54. package/dist/composition/startup-route.d.ts +32 -0
  55. package/dist/composition/startup-route.js +72 -0
  56. package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
  57. package/dist/foundation/release/progress-palette.generated.js +2 -2
  58. package/dist/foundation/startup/startup-descriptor.js +2 -2
  59. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
  60. package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
  61. package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
  62. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  63. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
  64. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  65. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  66. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  67. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  68. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  69. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  70. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  71. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  72. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
  73. package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
  74. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  75. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
  76. package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
  77. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  78. package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
  79. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  80. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  81. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
  82. package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
  83. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  84. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  85. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
  86. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
  87. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
  88. package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
  89. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
  90. package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
  91. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  92. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  93. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
  94. package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
  95. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  96. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  97. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  98. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  99. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  100. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  101. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  102. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  103. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  104. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  105. package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
  106. package/dist/integrations/pi/engine/adapter.d.ts +4 -77
  107. package/dist/integrations/pi/engine/adapter.js +85 -393
  108. package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
  109. package/dist/integrations/pi/engine/command-dispatch.js +57 -0
  110. package/dist/integrations/pi/engine/host.js +2 -2
  111. package/dist/integrations/pi/engine/ports.d.ts +56 -0
  112. package/dist/integrations/pi/engine/ports.js +89 -0
  113. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  114. package/dist/integrations/pi/engine/view-state.d.ts +42 -0
  115. package/dist/integrations/pi/engine/view-state.js +126 -0
  116. package/dist/integrations/pi/startup-public.js +164 -150
  117. package/dist/integrations/pi/startup-public.manifest.json +351 -310
  118. package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
  119. package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
  120. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
  121. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
  122. package/dist/native/darwin-arm64/manifest.json +1 -1
  123. package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
  124. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  125. package/dist/native/darwin-x64/manifest.json +1 -1
  126. package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
  127. package/dist/native/darwin-x64/terminal-host.node +0 -0
  128. package/dist/native/linux-x64/manifest.json +1 -1
  129. package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
  130. package/dist/native/linux-x64/terminal-host.node +0 -0
  131. package/dist/native/win32-x64/manifest.json +2 -2
  132. package/dist/native/win32-x64/process-guardian.node +0 -0
  133. package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
  134. package/dist/native/win32-x64/terminal-host.node +0 -0
  135. package/dist/runtime-payload-inventory.json +5181 -5369
  136. package/dist/ui/components/transcript-viewport.js +10 -19
  137. package/docs/architecture/boundaries.md +14 -0
  138. package/docs/architecture/resident-tabs.md +8 -8
  139. package/docs/architecture/response-copy-delivery.md +1 -1
  140. package/docs/architecture/toolchain.md +2 -2
  141. package/package.json +5 -5
@@ -1,5 +1,7 @@
1
1
  import { type OwnedUiCommand, type OwnedUiCommandResult, type OwnedUiDiagnostics } from "../../../contracts/owned-ui/index.js";
2
2
  import type { PiEmittedEvent } from "./event-delivery.js";
3
+ import type { PiEngineRuntime } from "./session-runtime.js";
4
+ import type { EngineViewState } from "./view-state.js";
3
5
  export type AdapterCommandResult = OwnedUiCommandResult;
4
6
  export interface PiCommandDispatchPorts {
5
7
  sessionId(): string;
@@ -36,3 +38,14 @@ export declare class PiCommandDispatch {
36
38
  reset(): void;
37
39
  execute(command: OwnedUiCommand): Promise<AdapterCommandResult>;
38
40
  }
41
+ /** What carrying out a command reaches: the running engine, the view state it updates, and disposal. */
42
+ export interface EngineCommandContext {
43
+ readonly engine: Pick<PiEngineRuntime, "runtime" | "session" | "generation" | "sessionCommands">;
44
+ readonly state: Pick<EngineViewState, "activeModel" | "thinkingLevel" | "setTerminal" | "terminal">;
45
+ /** False while delivery is overloaded or admission is stopped; a late model change then stays unpublished. */
46
+ admissionOpen(): boolean;
47
+ emit(value: PiEmittedEvent): void;
48
+ dispose(): Promise<void>;
49
+ }
50
+ /** Carries out one admitted command against the running engine; throws when no session runs or the command fails. */
51
+ export declare function performEngineCommand(command: OwnedUiCommand, context: EngineCommandContext): Promise<void>;
@@ -123,3 +123,60 @@ export class PiCommandDispatch {
123
123
  return { outcome, diagnostic };
124
124
  }
125
125
  }
126
+ // Invariant: prompt input and session controls run through the engine's own session commands, which own queuing and images.
127
+ async function runSessionCommand(request, context) {
128
+ const result = await context.engine.sessionCommands?.execute(request);
129
+ if (!result || result.outcome === "rejected" || result.outcome === "failed") {
130
+ throw new Error(request.type === "retry" ? "no previous prompt is available to retry" : `Pi session command failed: ${request.type}`);
131
+ }
132
+ }
133
+ function runPromptCommand(command, context) {
134
+ return runSessionCommand({
135
+ type: command.type,
136
+ text: command.text,
137
+ ...(command.images === undefined ? {} : { images: [...command.images] }),
138
+ }, context);
139
+ }
140
+ const ownedUiStateCommand = () => {
141
+ throw new Error("owned UI state commands belong to the owned UI layer, not the Pi engine adapter");
142
+ };
143
+ // Invariant: one handler per command type; the table is exhaustive, so a new command type cannot be silently ignored.
144
+ const ENGINE_COMMANDS = {
145
+ "prompt": (command, context) => runPromptCommand(command, context),
146
+ "steer": (command, context) => runPromptCommand(command, context),
147
+ "follow-up": (command, context) => runPromptCommand(command, context),
148
+ "abort": (_command, context) => runSessionCommand({ type: "abort" }, context),
149
+ "retry": (_command, context) => runSessionCommand({ type: "retry" }, context),
150
+ "compact": (_command, context) => runSessionCommand({ type: "compact" }, context),
151
+ "set-model": async (command, context, { runtime, session, generation }) => {
152
+ const model = runtime.services.modelRuntime.getModel(command.model.providerId, command.model.modelId);
153
+ if (!model)
154
+ throw new Error(`model is unavailable: ${command.model.providerId}/${command.model.modelId}`);
155
+ await session.setModel(model);
156
+ if (generation === context.engine.generation && context.admissionOpen())
157
+ context.state.activeModel = { ...command.model };
158
+ },
159
+ "set-thinking-level": (command, context, { session }) => {
160
+ session.setThinkingLevel(command.thinkingLevel);
161
+ context.state.thinkingLevel = command.thinkingLevel;
162
+ },
163
+ "new-session": async (_command, _context, { runtime }) => { await runtime.newSession(); },
164
+ "resume-session": async (command, _context, { runtime }) => { await runtime.switchSession(command.sessionPath); },
165
+ "resize-surface": (command, context) => {
166
+ context.state.setTerminal(command.surface);
167
+ context.emit({ type: "terminal-surface", surface: context.state.terminal });
168
+ },
169
+ "shutdown": (_command, context) => context.dispose(),
170
+ "set-setting": ownedUiStateCommand,
171
+ "apply-customization": ownedUiStateCommand,
172
+ "remove-customization": ownedUiStateCommand,
173
+ };
174
+ /** Carries out one admitted command against the running engine; throws when no session runs or the command fails. */
175
+ export async function performEngineCommand(command, context) {
176
+ const { runtime, session, generation } = context.engine;
177
+ if (!runtime || !session)
178
+ throw new Error("engine session is unavailable");
179
+ // Invariant: the table maps each type to the handler for exactly that command, so the command fits its own handler.
180
+ const handler = ENGINE_COMMANDS[command.type];
181
+ await handler(command, context, { runtime, session, generation });
182
+ }
@@ -86,7 +86,7 @@ class ProcessPiEngineHost {
86
86
  return;
87
87
  this.#disposed = true;
88
88
  this.#abort.abort();
89
- const live = [...this.#sessions.values()].filter(session => !session.disposed);
89
+ const live = [...this.#sessions.values()].filter(session => !session.identity.disposed);
90
90
  this.#sessions.clear();
91
91
  await Promise.all(live.map(session => session.dispose()));
92
92
  }
@@ -107,7 +107,7 @@ class ProcessPiEngineHost {
107
107
  }
108
108
  #forgetDisposedSessions() {
109
109
  for (const [sessionId, session] of this.#sessions)
110
- if (session.disposed)
110
+ if (session.identity.disposed)
111
111
  this.#sessions.delete(sessionId);
112
112
  }
113
113
  // Rationale: the profile's timeout is installed once, by whichever session loads it first; a written
@@ -0,0 +1,56 @@
1
+ import type { AgentSession } from "../startup-public.js";
2
+ import type { OwnedUiExtensionPort, OwnedUiImageAttachment, OwnedUiReleaseUpdate, OwnedUiSessionCatalogPort, OwnedUiSessionIdentityPort, OwnedUiSessionPort, OwnedUiSessionSettingsPort, OwnedUiWorkflowPort } from "../../../contracts/owned-ui/index.js";
3
+ import type { PiPinnedSettingsCallback, PiPinnedSettingsSnapshot, PiSessionSelectorContext, PiTreeSelectorContext, PiWorkflowInteractionHost, PiWorkflowRequest, PiWorkflowResult } from "./workflows.js";
4
+ import type { PiExtensionUiBinding } from "./extension-ui-binding.js";
5
+ import type { PiResourceCatalog } from "./resource-catalog.js";
6
+ import type { PiEngineRuntime } from "./session-runtime.js";
7
+ import type { PiEngineSettings } from "./settings-port.js";
8
+ import type { PiWorkflowContexts } from "./workflow-contexts.js";
9
+ import type { PiWorkflowRunner } from "./workflow-runner.js";
10
+ /**
11
+ * The Pi objects pinned selectors and transcript renderers are built from. They are not part of the
12
+ * session backend contract; only the session presenters owner reads them.
13
+ */
14
+ export interface PiSessionPresentationSource {
15
+ pinnedModelSelectorContext(): ReturnType<PiWorkflowContexts["pinnedModelSelectorContext"]>;
16
+ pinnedSessionSelectorContext(): PiSessionSelectorContext;
17
+ pinnedTreeSelectorContext(): PiTreeSelectorContext;
18
+ pinnedMessageRenderer(customType: string): unknown;
19
+ pinnedToolRenderers(toolName: string): unknown;
20
+ pinnedShortcutDescriptions(bindings: Parameters<AgentSession["extensionRunner"]["getShortcuts"]>[0]): readonly {
21
+ readonly key: string;
22
+ readonly description: string;
23
+ }[];
24
+ pinnedSettingsModels(): Pick<PiPinnedSettingsSnapshot, "currentModel" | "availableDefaultModels">;
25
+ applyPinnedSettingValue(callback: PiPinnedSettingsCallback, value: unknown): Promise<PiWorkflowResult>;
26
+ }
27
+ export interface PiEngineAdapterPorts {
28
+ readonly identity: OwnedUiSessionIdentityPort;
29
+ readonly session: OwnedUiSessionPort;
30
+ readonly workflows: OwnedUiWorkflowPort;
31
+ readonly settings: OwnedUiSessionSettingsPort;
32
+ readonly catalog: OwnedUiSessionCatalogPort;
33
+ readonly extensions: OwnedUiExtensionPort;
34
+ readonly presentation: PiSessionPresentationSource;
35
+ }
36
+ /** The adapter's collaborators and its own session operations, which every port member reaches at call time. */
37
+ export interface EnginePortParts {
38
+ readonly sessionId: string;
39
+ readonly agentDir: string;
40
+ readonly engine: Pick<PiEngineRuntime, "cwd" | "generation" | "bindingGeneration" | "currentSessionResumeMetadata" | "currentSessionFile">;
41
+ readonly contexts: PiWorkflowContexts;
42
+ readonly workflows: PiWorkflowRunner;
43
+ readonly settings: PiEngineSettings;
44
+ readonly resources: PiResourceCatalog;
45
+ readonly extensions: PiExtensionUiBinding;
46
+ readonly session: OwnedUiSessionPort;
47
+ disposed(): boolean;
48
+ executeWorkflow(request: PiWorkflowRequest): Promise<PiWorkflowResult>;
49
+ clearQueuedWorkflows(): readonly string[];
50
+ setWorkflowInteractionHost(interaction: PiWorkflowInteractionHost): void;
51
+ announceReleaseUpdate(release: OwnedUiReleaseUpdate): void;
52
+ resolveTranscriptImage(assetId: string): OwnedUiImageAttachment | null;
53
+ /** The running session's extension runner; throws when no session runs. */
54
+ extensionRunner(): AgentSession["extensionRunner"] | undefined;
55
+ }
56
+ export declare function createEnginePorts(parts: EnginePortParts): PiEngineAdapterPorts;
@@ -0,0 +1,89 @@
1
+ // Invariant: every port member delegates at call time, so ports built once follow session replacement.
2
+ export function createEnginePorts(parts) {
3
+ const { engine, contexts, workflows, settings, resources, extensions } = parts;
4
+ return {
5
+ identity: {
6
+ sessionId: parts.sessionId,
7
+ agentDir: parts.agentDir,
8
+ get cwd() { return engine.cwd; },
9
+ get sessionGeneration() { return engine.generation; },
10
+ get sessionBindingGeneration() { return engine.bindingGeneration; },
11
+ get disposed() { return parts.disposed(); },
12
+ currentSessionResumeMetadata: () => engine.currentSessionResumeMetadata(),
13
+ currentSessionFile: () => engine.currentSessionFile(),
14
+ },
15
+ session: parts.session,
16
+ workflows: {
17
+ executeWorkflow: request => parts.executeWorkflow(request),
18
+ executeBashWorkflow: (command, excludeFromContext) => workflows.executeBashWorkflow(command, excludeFromContext),
19
+ cycleModelWorkflow: direction => workflows.cycleModelWorkflow(direction),
20
+ workflowAutocompleteCommands: () => resources.workflowAutocompleteCommands(),
21
+ clearQueuedWorkflows: () => parts.clearQueuedWorkflows(),
22
+ reloadBlockedResult: () => workflows.reloadBlockedResult(),
23
+ copyWorkflowText: text => workflows.copyWorkflowText(text),
24
+ setWorkflowInteractionHost: interaction => { parts.setWorkflowInteractionHost(interaction); },
25
+ },
26
+ settings: {
27
+ get productMode() { return settings.productMode; },
28
+ snapshot: () => {
29
+ // Invariant: the selector-only model values travel on the presentation source, not in the neutral snapshot.
30
+ const { currentModel: _currentModel, availableDefaultModels: _availableDefaultModels, ...snapshot } = settings.pinnedSettingsSnapshot();
31
+ return snapshot;
32
+ },
33
+ bindOwner: (owner, handlers) => settings.bindSettingsOwner(owner, handlers),
34
+ setDefaultThinkingLevel: level => { settings.setDefaultThinkingLevel(level); },
35
+ configuredTheme: () => settings.configuredTheme(),
36
+ },
37
+ catalog: {
38
+ modelsContext: () => contexts.modelsContext(),
39
+ setSessionModelScope: scopeIds => { contexts.setSessionModelScope(scopeIds); },
40
+ persistModelScope: scopeIds => { contexts.persistModelScope(scopeIds); },
41
+ refreshModels: signal => contexts.refreshModels(signal),
42
+ pinnedScopedModelsContext: () => contexts.pinnedScopedModelsContext(),
43
+ updateScopedModels: enabledModelIds => { contexts.updateScopedModels(enabledModelIds); },
44
+ persistScopedModels: enabledModelIds => { contexts.persistScopedModels(enabledModelIds); },
45
+ refreshScopedModels: signal => contexts.refreshScopedModels(signal),
46
+ pinnedProjectTrustContext: () => contexts.pinnedProjectTrustContext(),
47
+ persistProjectTrust: updates => { contexts.persistProjectTrust(updates); },
48
+ pinnedLoginOptions: authType => contexts.loginOptions(authType),
49
+ pinnedLoginMethodOptions: providerReference => contexts.pinnedLoginMethodOptions(providerReference),
50
+ pinnedAmbientAuthentication: selection => contexts.pinnedAmbientAuthentication(selection),
51
+ pinnedLogoutOptions: () => contexts.logoutOptions(),
52
+ pinnedForkOptions: () => contexts.pinnedForkOptions(),
53
+ },
54
+ extensions: {
55
+ nonVisualResources: () => resources.nonVisualResources(),
56
+ extensionResources: () => resources.extensionResources(),
57
+ resolveTranscriptImage: assetId => parts.resolveTranscriptImage(assetId),
58
+ visualExtensionSupport: () => extensions.support(),
59
+ bindExtensionUi: (ui, shutdown) => extensions.bind(ui, shutdown),
60
+ unbindExtensionUi: () => extensions.unbind(),
61
+ bindClipboardWriter: writer => workflows.bindClipboardWriter(writer),
62
+ announceReleaseUpdate: release => { parts.announceReleaseUpdate(release); },
63
+ },
64
+ presentation: {
65
+ pinnedModelSelectorContext: () => contexts.pinnedModelSelectorContext(),
66
+ pinnedSessionSelectorContext: () => contexts.pinnedSessionSelectorContext(),
67
+ pinnedTreeSelectorContext: () => contexts.pinnedTreeSelectorContext(),
68
+ pinnedMessageRenderer: customType => parts.extensionRunner()?.getMessageRenderer?.(customType),
69
+ pinnedToolRenderers: toolName => {
70
+ const runner = parts.extensionRunner();
71
+ if (runner === undefined)
72
+ return undefined;
73
+ if (typeof runner.resolveToolRenderers === "function") {
74
+ return runner.resolveToolRenderers(toolName, () => runner.getToolDefinition?.(toolName));
75
+ }
76
+ return runner.getToolDefinition?.(toolName);
77
+ },
78
+ pinnedShortcutDescriptions: bindings => {
79
+ const shortcuts = parts.extensionRunner()?.getShortcuts?.(bindings);
80
+ return shortcuts === undefined ? [] : [...shortcuts].map(([key, shortcut]) => ({ key, description: shortcut.description ?? shortcut.extensionPath }));
81
+ },
82
+ pinnedSettingsModels: () => {
83
+ const { currentModel, availableDefaultModels } = settings.pinnedSettingsSnapshot();
84
+ return { ...(currentModel === undefined ? {} : { currentModel }), availableDefaultModels };
85
+ },
86
+ applyPinnedSettingValue: (callback, value) => settings.applyPinnedSettingValue(callback, value),
87
+ },
88
+ };
89
+ }