@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.
- package/README.md +4 -2
- package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
- package/dist/app/session-shell/dialog-coordinator.js +133 -0
- package/dist/app/session-shell/dock-chrome.d.ts +34 -0
- package/dist/app/session-shell/dock-chrome.js +109 -0
- package/dist/app/session-shell/exit-notice.d.ts +1 -1
- package/dist/app/session-shell/exit-notice.js +1 -1
- package/dist/app/session-shell/extension-surface.d.ts +30 -0
- package/dist/app/session-shell/extension-surface.js +105 -0
- package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
- package/dist/app/session-shell/input-surface-switch.js +85 -0
- package/dist/app/session-shell/login-interaction.d.ts +27 -0
- package/dist/app/session-shell/login-interaction.js +91 -0
- package/dist/app/session-shell/prompt-submission.d.ts +48 -0
- package/dist/app/session-shell/prompt-submission.js +276 -0
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +41 -0
- package/dist/app/session-shell/resident-tab-coordinator.js +120 -0
- package/dist/app/session-shell/response-copy-transport.d.ts +13 -0
- package/dist/app/session-shell/response-copy-transport.js +16 -7
- package/dist/app/session-shell/session-concern.d.ts +22 -0
- package/dist/app/session-shell/session-concern.js +29 -0
- package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
- package/dist/app/session-shell/session-lifecycle.js +49 -0
- package/dist/app/session-shell/session-shell-root.d.ts +1 -1
- package/dist/app/session-shell/session-shell-root.js +182 -931
- package/dist/app/session-shell/session-shell.d.ts +2 -8
- package/dist/app/session-shell/session-shell.js +202 -901
- package/dist/app/session-shell/settings-bindings.d.ts +17 -0
- package/dist/app/session-shell/settings-bindings.js +91 -0
- package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
- package/dist/app/session-shell/shell-editor-factory.js +102 -0
- package/dist/app/session-shell/shell-host.d.ts +6 -0
- package/dist/app/session-shell/shell-host.js +8 -0
- package/dist/app/session-shell/shell-layout.d.ts +64 -0
- package/dist/app/session-shell/shell-layout.js +18 -0
- package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
- package/dist/app/session-shell/suggestion-surface.js +63 -0
- package/dist/app/session-shell/transcript-document.d.ts +78 -0
- package/dist/app/session-shell/transcript-document.js +365 -0
- package/dist/app/session-shell/viewport-layout.d.ts +31 -0
- package/dist/app/session-shell/viewport-layout.js +160 -0
- package/dist/app/session-shell/workflow-output.d.ts +33 -0
- package/dist/app/session-shell/workflow-output.js +174 -0
- package/dist/app/session-shell/workflow-router.d.ts +25 -0
- package/dist/app/session-shell/workflow-router.js +39 -0
- package/dist/composition/owned-ui.d.ts +4 -25
- package/dist/composition/owned-ui.js +26 -270
- package/dist/composition/resident-tab-bridge.d.ts +16 -0
- package/dist/composition/resident-tab-bridge.js +159 -0
- package/dist/composition/session-backend.d.ts +19 -0
- package/dist/composition/session-backend.js +1 -0
- package/dist/composition/session-runtime-registry.d.ts +20 -0
- package/dist/composition/session-runtime-registry.js +85 -0
- package/dist/composition/startup-route.d.ts +32 -0
- package/dist/composition/startup-route.js +72 -0
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.js +2 -2
- package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +1 -1
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -4
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +77 -98
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.js +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +4 -77
- package/dist/integrations/pi/engine/adapter.js +85 -393
- package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
- package/dist/integrations/pi/engine/command-dispatch.js +57 -0
- package/dist/integrations/pi/engine/host.js +2 -2
- package/dist/integrations/pi/engine/ports.d.ts +56 -0
- package/dist/integrations/pi/engine/ports.js +89 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/view-state.d.ts +42 -0
- package/dist/integrations/pi/engine/view-state.js +126 -0
- package/dist/integrations/pi/startup-public.js +164 -150
- package/dist/integrations/pi/startup-public.manifest.json +351 -310
- package/dist/integrations/pi/tui-runtime/adapter.js +4 -0
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +1 -1
- package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/runtime-payload-inventory.json +5181 -5369
- package/dist/ui/components/transcript-viewport.js +10 -19
- package/docs/architecture/boundaries.md +14 -0
- package/docs/architecture/resident-tabs.md +8 -8
- package/docs/architecture/response-copy-delivery.md +1 -1
- package/docs/architecture/toolchain.md +2 -2
- package/package.json +5 -5
|
@@ -2,7 +2,7 @@ import { PiTranscriptProjection } from "./transcript-projection.js";
|
|
|
2
2
|
import { isRecord, readModel, readStringArray, readThinkingLevel, stringProperty } from "./message-values.js";
|
|
3
3
|
import { getAgentDir } from "../startup-public.js";
|
|
4
4
|
import { assertOwnedUiSnapshot, } from "../../../contracts/owned-ui/index.js";
|
|
5
|
-
import { PiCommandDispatch } from "./command-dispatch.js";
|
|
5
|
+
import { PiCommandDispatch, performEngineCommand } from "./command-dispatch.js";
|
|
6
6
|
import { PiEventDelivery } from "./event-delivery.js";
|
|
7
7
|
import { PiExtensionUiBinding } from "./extension-ui-binding.js";
|
|
8
8
|
import { PiPromptSuggestions } from "./prompt-suggestions.js";
|
|
@@ -15,16 +15,12 @@ import { readUsageView } from "./usage-view.js";
|
|
|
15
15
|
import { PiWorkflowContexts } from "./workflow-contexts.js";
|
|
16
16
|
import { PiWorkflowRunner } from "./workflow-runner.js";
|
|
17
17
|
import { defaultWorkflowHost } from "./workflow-support.js";
|
|
18
|
+
import { EngineViewState } from "./view-state.js";
|
|
19
|
+
import { createEnginePorts } from "./ports.js";
|
|
18
20
|
/** Explicit flush failure when required delivery was interrupted rather than completed. */
|
|
19
21
|
export class EngineDeliveryError extends Error {
|
|
20
22
|
constructor() { super("Engine delivery did not complete"); this.name = "EngineDeliveryError"; }
|
|
21
23
|
}
|
|
22
|
-
const DEFAULT_SURFACE = {
|
|
23
|
-
columns: 100,
|
|
24
|
-
rows: 32,
|
|
25
|
-
focusedRegion: "editor",
|
|
26
|
-
hardwareCursor: false,
|
|
27
|
-
};
|
|
28
24
|
/** Owns the pinned Pi session lifecycle and serves it to the owned shell as the neutral session backend. */
|
|
29
25
|
export class PiEngineAdapter {
|
|
30
26
|
#agentDir;
|
|
@@ -38,31 +34,11 @@ export class PiEngineAdapter {
|
|
|
38
34
|
#resources;
|
|
39
35
|
#settings;
|
|
40
36
|
#suggestions;
|
|
41
|
-
#
|
|
42
|
-
#lifecycle = "starting";
|
|
43
|
-
#editor = {
|
|
44
|
-
text: "",
|
|
45
|
-
queuedSubmissions: [],
|
|
46
|
-
selection: null,
|
|
47
|
-
cursorOffset: 0,
|
|
48
|
-
historyRevision: 0,
|
|
49
|
-
submitEnabled: false,
|
|
50
|
-
};
|
|
51
|
-
#status = {
|
|
52
|
-
title: "Pi",
|
|
53
|
-
workingMessage: null,
|
|
54
|
-
diagnostics: [],
|
|
55
|
-
badges: [],
|
|
56
|
-
};
|
|
57
|
-
#terminal = DEFAULT_SURFACE;
|
|
58
|
-
#activeModel = null;
|
|
59
|
-
#thinkingLevel = "medium";
|
|
37
|
+
#state = new EngineViewState();
|
|
60
38
|
#projection = new PiTranscriptProjection({
|
|
61
39
|
retryAttempt: () => this.#engine.session?.retryAttempt ?? 0,
|
|
62
40
|
blockChanged: block => this.#emitEvent({ type: "transcript-block", block }),
|
|
63
41
|
});
|
|
64
|
-
#usageCache;
|
|
65
|
-
#diagnostics = [];
|
|
66
42
|
// Invariant: every port closes over adapter state read at call time, so delivery is built before a session binds.
|
|
67
43
|
#delivery = new PiEventDelivery({
|
|
68
44
|
sessionId: () => this.#sessionId,
|
|
@@ -80,36 +56,30 @@ export class PiEngineAdapter {
|
|
|
80
56
|
#events = new PiSessionEvents(this.#projection, {
|
|
81
57
|
sessionGeneration: () => this.#engine.generation,
|
|
82
58
|
sessionMessages: () => this.#engine.session?.messages ?? [],
|
|
83
|
-
activeModel: () => this.#activeModel,
|
|
59
|
+
activeModel: () => this.#state.activeModel,
|
|
84
60
|
replaceTranscript: blocks => { this.#setTranscript(blocks); },
|
|
85
61
|
emit: value => { this.#emitEvent(value); },
|
|
86
62
|
emitView: () => { this.#emitView(); },
|
|
87
63
|
enterWork: message => {
|
|
88
|
-
|
|
89
|
-
this.#lifecycle = "busy";
|
|
90
|
-
this.#status = { ...this.#status, workingMessage: message, workingProgress: null };
|
|
91
|
-
if (!wasBusy)
|
|
64
|
+
if (!this.#state.enterWork(message))
|
|
92
65
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "busy", reason: null });
|
|
93
|
-
this.#emitEvent({ type: "status", status: this.#status });
|
|
66
|
+
this.#emitEvent({ type: "status", status: this.#state.status });
|
|
94
67
|
},
|
|
95
68
|
leaveWork: () => {
|
|
96
|
-
this.#
|
|
97
|
-
this.#status = { ...this.#status, workingMessage: null, workingProgress: null };
|
|
69
|
+
this.#state.leaveWork();
|
|
98
70
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "ready", reason: null });
|
|
99
|
-
this.#emitEvent({ type: "status", status: this.#status });
|
|
71
|
+
this.#emitEvent({ type: "status", status: this.#state.status });
|
|
100
72
|
},
|
|
101
73
|
workProgress: percent => {
|
|
102
|
-
if (this.#
|
|
103
|
-
|
|
104
|
-
this.#status = { ...this.#status, workingProgress: percent };
|
|
105
|
-
this.#emitEvent({ type: "status", status: this.#status });
|
|
74
|
+
if (this.#state.setWorkProgress(percent))
|
|
75
|
+
this.#emitEvent({ type: "status", status: this.#state.status });
|
|
106
76
|
},
|
|
107
77
|
queueChanged: queuedSubmissions => {
|
|
108
|
-
this.#
|
|
109
|
-
this.#emitEvent({ type: "editor-state", editor: this.#editor });
|
|
78
|
+
this.#state.setQueuedSubmissions(queuedSubmissions);
|
|
79
|
+
this.#emitEvent({ type: "editor-state", editor: this.#state.editor });
|
|
110
80
|
},
|
|
111
|
-
thinkingLevelChanged: level => { this.#thinkingLevel = level; },
|
|
112
|
-
usageInvalidated: () => { this.#
|
|
81
|
+
thinkingLevelChanged: level => { this.#state.thinkingLevel = level; },
|
|
82
|
+
usageInvalidated: () => { this.#state.invalidateUsage(); },
|
|
113
83
|
compactionStarted: () => { this.#engine.compactionStarted(); },
|
|
114
84
|
compactionEnded: () => { this.#engine.compactionEnded(); },
|
|
115
85
|
deliverQueuedAfterCompaction: () => { this.#engine.deliverQueuedAfterCompaction(); },
|
|
@@ -146,10 +116,7 @@ export class PiEngineAdapter {
|
|
|
146
116
|
}, {
|
|
147
117
|
disposed: () => this.#disposed,
|
|
148
118
|
started: runtime => {
|
|
149
|
-
this.#
|
|
150
|
-
...this.#terminal,
|
|
151
|
-
hardwareCursor: runtime.services.settingsManager?.getShowHardwareCursor?.() ?? this.#terminal.hardwareCursor,
|
|
152
|
-
};
|
|
119
|
+
this.#state.setHardwareCursor(runtime.services.settingsManager?.getShowHardwareCursor?.() ?? this.#state.terminal.hardwareCursor);
|
|
153
120
|
const httpIdleTimeoutMs = runtime.services.settingsManager?.getHttpIdleTimeoutMs?.();
|
|
154
121
|
if (typeof httpIdleTimeoutMs === "number")
|
|
155
122
|
this.#engineHost.httpPolicyLoaded(httpIdleTimeoutMs, this.#sessionId);
|
|
@@ -168,7 +135,7 @@ export class PiEngineAdapter {
|
|
|
168
135
|
session: () => this.#engine.session,
|
|
169
136
|
runtime: () => this.#engine.runtime,
|
|
170
137
|
disposed: () => this.#disposed,
|
|
171
|
-
activeModel: () => this.#activeModel,
|
|
138
|
+
activeModel: () => this.#state.activeModel,
|
|
172
139
|
emitView: () => { this.#emitView(); },
|
|
173
140
|
});
|
|
174
141
|
this.#workflows = new PiWorkflowRunner({ agentDir: this.#agentDir, host: this.#workflowHost, contexts: this.#contexts }, {
|
|
@@ -181,10 +148,10 @@ export class PiEngineAdapter {
|
|
|
181
148
|
pendingCommandCount: () => this.#commands.pendingCount,
|
|
182
149
|
beginRunning: () => { this.#runningCommands++; },
|
|
183
150
|
endRunning: () => { this.#runningCommands--; },
|
|
184
|
-
activeModel: () => this.#activeModel,
|
|
185
|
-
setActiveModel: model => { this.#activeModel = model; },
|
|
186
|
-
thinkingLevel: () => this.#thinkingLevel,
|
|
187
|
-
setThinkingLevel: level => { this.#thinkingLevel = level; },
|
|
151
|
+
activeModel: () => this.#state.activeModel,
|
|
152
|
+
setActiveModel: model => { this.#state.activeModel = model; },
|
|
153
|
+
thinkingLevel: () => this.#state.thinkingLevel,
|
|
154
|
+
setThinkingLevel: level => { this.#state.thinkingLevel = level; },
|
|
188
155
|
emitView: () => { this.#emitView(); },
|
|
189
156
|
reconcileActiveModelAvailability: () => { this.#reconcileActiveModelAvailability(); },
|
|
190
157
|
bindExtensionUiToSession: () => this.#extensions.rebind(),
|
|
@@ -200,7 +167,7 @@ export class PiEngineAdapter {
|
|
|
200
167
|
sessionGeneration: () => this.#engine.generation,
|
|
201
168
|
beginRunning: () => { this.#runningCommands++; },
|
|
202
169
|
endRunning: () => { this.#runningCommands--; },
|
|
203
|
-
perform: command => this.#
|
|
170
|
+
perform: command => performEngineCommand(command, this.#commandContext()),
|
|
204
171
|
emit: value => { this.#emitEvent(value); },
|
|
205
172
|
emitView: () => { this.#emitView(); },
|
|
206
173
|
diagnostic: (severity, code, message, recoverable) => { this.#addDiagnostic(severity, code, message, recoverable); },
|
|
@@ -212,14 +179,14 @@ export class PiEngineAdapter {
|
|
|
212
179
|
this.#settings = new PiEngineSettings({ availableThemes: options.availableThemes ?? null, productMode: options.settingsProductMode ?? "bare" }, {
|
|
213
180
|
runtime: () => this.#engine.runtime,
|
|
214
181
|
requireSession: () => this.#requireWorkflowSession(),
|
|
215
|
-
thinkingLevelChanged: level => { this.#thinkingLevel = level; this.#emitView(); },
|
|
182
|
+
thinkingLevelChanged: level => { this.#state.thinkingLevel = level; this.#emitView(); },
|
|
216
183
|
httpPolicyChanged: timeoutMs => { this.#engineHost.httpPolicyChanged(timeoutMs, this.#sessionId); },
|
|
217
184
|
emitView: () => { this.#emitView(); },
|
|
218
185
|
});
|
|
219
186
|
this.#suggestions = new PiPromptSuggestions({
|
|
220
187
|
session: () => this.#engine.session,
|
|
221
188
|
runtime: () => this.#engine.runtime,
|
|
222
|
-
activeModel: () => this.#activeModel,
|
|
189
|
+
activeModel: () => this.#state.activeModel,
|
|
223
190
|
identity: () => ({ sessionId: this.#sessionId, sessionGeneration: this.#engine.generation, runSequence: this.#events.runSequence, responseSequence: this.#events.responseSequence }),
|
|
224
191
|
unavailable: () => this.#disposed || this.#delivery.overloaded || this.#admissionStopped,
|
|
225
192
|
});
|
|
@@ -236,38 +203,12 @@ export class PiEngineAdapter {
|
|
|
236
203
|
setWorkflowInteractionHost(interaction) {
|
|
237
204
|
this.#workflowInteraction = interaction;
|
|
238
205
|
}
|
|
239
|
-
|
|
240
|
-
return this.#sessionId;
|
|
241
|
-
}
|
|
242
|
-
get sessionGeneration() {
|
|
243
|
-
return this.#engine.generation;
|
|
244
|
-
}
|
|
245
|
-
/** Actual session replacements, excluding delivery-only invalidation of callbacks. */
|
|
246
|
-
get sessionBindingGeneration() { return this.#engine.bindingGeneration; }
|
|
247
|
-
get cwd() {
|
|
248
|
-
return this.#engine.cwd;
|
|
249
|
-
}
|
|
250
|
-
get agentDir() {
|
|
251
|
-
return this.#agentDir;
|
|
252
|
-
}
|
|
253
|
-
resolveTranscriptImage(assetId) {
|
|
206
|
+
#resolveTranscriptImage(assetId) {
|
|
254
207
|
return this.#projection.assets.resolve(assetId);
|
|
255
208
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
currentSessionResumeMetadata() {
|
|
260
|
-
return this.#engine.currentSessionResumeMetadata();
|
|
261
|
-
}
|
|
262
|
-
get disposed() {
|
|
263
|
-
return this.#disposed;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Report a newer A1 release found by the startup check. The shell renders the diagnostic as
|
|
267
|
-
* pinned Pi's `Update Available` notice; it arrives whenever the check resolves, so a late
|
|
268
|
-
* result is appended to the transcript like Pi's own fire-and-forget version check.
|
|
269
|
-
*/
|
|
270
|
-
announceReleaseUpdate(release) {
|
|
209
|
+
// Rationale: the startup check's newer release becomes pinned Pi's `Update Available` notice; it arrives
|
|
210
|
+
// whenever the check resolves, so a late result is appended like Pi's own fire-and-forget version check.
|
|
211
|
+
#announceReleaseUpdate(release) {
|
|
271
212
|
if (this.#disposed)
|
|
272
213
|
return;
|
|
273
214
|
const changelog = release.changelogUrl === null ? "" : `\nChangelog: ${release.changelogUrl}`;
|
|
@@ -287,12 +228,11 @@ export class PiEngineAdapter {
|
|
|
287
228
|
if (this.#engine.started)
|
|
288
229
|
return this.view();
|
|
289
230
|
await this.#engine.start().catch(error => {
|
|
290
|
-
this.#lifecycle = "failed";
|
|
231
|
+
this.#state.lifecycle = "failed";
|
|
291
232
|
this.#addDiagnostic("error", "engine-startup", error instanceof Error ? error.message : String(error), false);
|
|
292
233
|
throw error;
|
|
293
234
|
});
|
|
294
|
-
this.#
|
|
295
|
-
this.#editor = { ...this.#editor, submitEnabled: true };
|
|
235
|
+
this.#state.markReady();
|
|
296
236
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "ready", reason: null });
|
|
297
237
|
this.#emitView();
|
|
298
238
|
return this.view();
|
|
@@ -315,94 +255,14 @@ export class PiEngineAdapter {
|
|
|
315
255
|
async flushEvents() {
|
|
316
256
|
const failed = this.#delivery.failed;
|
|
317
257
|
await this.#delivery.settle();
|
|
318
|
-
if (failed || this.#delivery.failed || this.#disposed && this.#lifecycle !== "stopped") {
|
|
258
|
+
if (failed || this.#delivery.failed || this.#disposed && this.#state.lifecycle !== "stopped") {
|
|
319
259
|
this.#delivery.clearFailure();
|
|
320
260
|
throw new EngineDeliveryError();
|
|
321
261
|
}
|
|
322
262
|
}
|
|
323
|
-
nonVisualResources() {
|
|
324
|
-
return this.#resources.nonVisualResources();
|
|
325
|
-
}
|
|
326
|
-
extensionResources() {
|
|
327
|
-
return this.#resources.extensionResources();
|
|
328
|
-
}
|
|
329
|
-
workflowAutocompleteCommands() {
|
|
330
|
-
return this.#resources.workflowAutocompleteCommands();
|
|
331
|
-
}
|
|
332
|
-
visualExtensionSupport() {
|
|
333
|
-
return this.#extensions.support();
|
|
334
|
-
}
|
|
335
|
-
bindExtensionUi(ui, shutdown) {
|
|
336
|
-
return this.#extensions.bind(ui, shutdown);
|
|
337
|
-
}
|
|
338
|
-
unbindExtensionUi() {
|
|
339
|
-
return this.#extensions.unbind();
|
|
340
|
-
}
|
|
341
|
-
async cycleModelWorkflow(direction) {
|
|
342
|
-
return this.#workflows.cycleModelWorkflow(direction);
|
|
343
|
-
}
|
|
344
|
-
pinnedProjectTrustContext() {
|
|
345
|
-
return this.#contexts.pinnedProjectTrustContext();
|
|
346
|
-
}
|
|
347
|
-
persistProjectTrust(updates) {
|
|
348
|
-
this.#contexts.persistProjectTrust(updates);
|
|
349
|
-
}
|
|
350
|
-
pinnedScopedModelsContext() {
|
|
351
|
-
return this.#contexts.pinnedScopedModelsContext();
|
|
352
|
-
}
|
|
353
|
-
updateScopedModels(enabledModelIds) {
|
|
354
|
-
this.#contexts.updateScopedModels(enabledModelIds);
|
|
355
|
-
}
|
|
356
|
-
persistScopedModels(enabledModelIds) {
|
|
357
|
-
this.#contexts.persistScopedModels(enabledModelIds);
|
|
358
|
-
}
|
|
359
|
-
refreshScopedModels(signal) {
|
|
360
|
-
return this.#contexts.refreshScopedModels(signal);
|
|
361
|
-
}
|
|
362
|
-
modelsContext() {
|
|
363
|
-
return this.#contexts.modelsContext();
|
|
364
|
-
}
|
|
365
|
-
setSessionModelScope(scopeIds) {
|
|
366
|
-
this.#contexts.setSessionModelScope(scopeIds);
|
|
367
|
-
}
|
|
368
|
-
persistModelScope(scopeIds) {
|
|
369
|
-
this.#contexts.persistModelScope(scopeIds);
|
|
370
|
-
}
|
|
371
|
-
refreshModels(signal) {
|
|
372
|
-
return this.#contexts.refreshModels(signal);
|
|
373
|
-
}
|
|
374
|
-
pinnedLoginOptions(authType) {
|
|
375
|
-
return this.#contexts.loginOptions(authType);
|
|
376
|
-
}
|
|
377
|
-
pinnedLoginMethodOptions(providerReference) {
|
|
378
|
-
return this.#contexts.pinnedLoginMethodOptions(providerReference);
|
|
379
|
-
}
|
|
380
|
-
pinnedAmbientAuthentication(selection) {
|
|
381
|
-
return this.#contexts.pinnedAmbientAuthentication(selection);
|
|
382
|
-
}
|
|
383
|
-
pinnedLogoutOptions() {
|
|
384
|
-
return this.#contexts.logoutOptions();
|
|
385
|
-
}
|
|
386
|
-
pinnedForkOptions() {
|
|
387
|
-
return this.#contexts.pinnedForkOptions();
|
|
388
|
-
}
|
|
389
|
-
/** Bind the owned UI's clipboard lifecycle without changing the comparison host. True means acknowledged delivery. */
|
|
390
|
-
bindClipboardWriter(writer) {
|
|
391
|
-
return this.#workflows.bindClipboardWriter(writer);
|
|
392
|
-
}
|
|
393
|
-
/** Workflow and tree copying share the active owner's write fence and delivery acknowledgment. */
|
|
394
|
-
copyWorkflowText(text) {
|
|
395
|
-
return this.#workflows.copyWorkflowText(text);
|
|
396
|
-
}
|
|
397
263
|
abortBashWorkflow() {
|
|
398
264
|
this.#workflows.abortBashWorkflow();
|
|
399
265
|
}
|
|
400
|
-
executeBashWorkflow(command, excludeFromContext) {
|
|
401
|
-
return this.#workflows.executeBashWorkflow(command, excludeFromContext);
|
|
402
|
-
}
|
|
403
|
-
reloadBlockedResult() {
|
|
404
|
-
return this.#workflows.reloadBlockedResult();
|
|
405
|
-
}
|
|
406
266
|
async executeWorkflow(request) {
|
|
407
267
|
const result = await this.#workflows.executeWorkflow(request);
|
|
408
268
|
if (request.command === "tree" && result.outcome === "completed" && request.selection !== undefined) {
|
|
@@ -417,40 +277,13 @@ export class PiEngineAdapter {
|
|
|
417
277
|
configuredTheme() {
|
|
418
278
|
return this.#settings.configuredTheme();
|
|
419
279
|
}
|
|
420
|
-
/** Persist the global thinking default without changing the live session level. */
|
|
421
|
-
setDefaultThinkingLevel(level) {
|
|
422
|
-
this.#settings.setDefaultThinkingLevel(level);
|
|
423
|
-
}
|
|
424
280
|
/** Settings port for the live runtime, or null before the runtime is available. */
|
|
425
281
|
settingsPort() {
|
|
426
282
|
return this.#settings.settingsPort();
|
|
427
283
|
}
|
|
428
|
-
/** Which settings surface this adapter serves; hidden-in-bare effects are unbindable in bare mode. */
|
|
429
|
-
get settingsProductMode() {
|
|
430
|
-
return this.#settings.productMode;
|
|
431
|
-
}
|
|
432
|
-
bindSettingsOwner(owner, handlers) {
|
|
433
|
-
return this.#settings.bindSettingsOwner(owner, handlers);
|
|
434
|
-
}
|
|
435
284
|
pinnedSettingsSnapshot() {
|
|
436
285
|
return this.#settings.pinnedSettingsSnapshot();
|
|
437
286
|
}
|
|
438
|
-
#pinnedMessageRenderer(customType) {
|
|
439
|
-
return this.#requireWorkflowSession().extensionRunner?.getMessageRenderer?.(customType);
|
|
440
|
-
}
|
|
441
|
-
#pinnedShortcutDescriptions(bindings) {
|
|
442
|
-
const shortcuts = this.#requireWorkflowSession().extensionRunner?.getShortcuts?.(bindings);
|
|
443
|
-
return shortcuts === undefined ? [] : [...shortcuts].map(([key, shortcut]) => ({ key, description: shortcut.description ?? shortcut.extensionPath }));
|
|
444
|
-
}
|
|
445
|
-
#pinnedToolRenderers(toolName) {
|
|
446
|
-
const runner = this.#requireWorkflowSession().extensionRunner;
|
|
447
|
-
if (runner === undefined)
|
|
448
|
-
return undefined;
|
|
449
|
-
if (typeof runner.resolveToolRenderers === "function") {
|
|
450
|
-
return runner.resolveToolRenderers(toolName, () => runner.getToolDefinition?.(toolName));
|
|
451
|
-
}
|
|
452
|
-
return runner.getToolDefinition?.(toolName);
|
|
453
|
-
}
|
|
454
287
|
clearQueuedWorkflows() {
|
|
455
288
|
const session = this.#requireWorkflowSession();
|
|
456
289
|
const result = session.clearQueue?.();
|
|
@@ -465,15 +298,15 @@ export class PiEngineAdapter {
|
|
|
465
298
|
return {
|
|
466
299
|
contractVersion: 1,
|
|
467
300
|
sessionId: this.#sessionId,
|
|
468
|
-
revision: this.#
|
|
469
|
-
lifecycle: this.#lifecycle,
|
|
301
|
+
revision: this.#state.revision,
|
|
302
|
+
lifecycle: this.#state.lifecycle,
|
|
470
303
|
transcript: this.#projection.snapshot(),
|
|
471
|
-
editor: { ...this.#editor, queuedSubmissions: [...this.#editor.queuedSubmissions] },
|
|
304
|
+
editor: { ...this.#state.editor, queuedSubmissions: [...this.#state.editor.queuedSubmissions] },
|
|
472
305
|
status: {
|
|
473
|
-
...this.#status,
|
|
474
|
-
diagnostics: [...this.#status.diagnostics],
|
|
475
|
-
badges: [...this.#status.badges],
|
|
476
|
-
usage: this.#
|
|
306
|
+
...this.#state.status,
|
|
307
|
+
diagnostics: [...this.#state.status.diagnostics],
|
|
308
|
+
badges: [...this.#state.status.badges],
|
|
309
|
+
usage: this.#state.usage(() => readUsageView(this.#engine.session, this.#engine.runtime, this.#state.activeModel)),
|
|
477
310
|
footer: {
|
|
478
311
|
branch: this.#engine.gitBranch,
|
|
479
312
|
repositoryPath: this.#engine.repositoryCwd,
|
|
@@ -483,24 +316,24 @@ export class PiEngineAdapter {
|
|
|
483
316
|
extensionStatuses: [],
|
|
484
317
|
},
|
|
485
318
|
},
|
|
486
|
-
terminal: { ...this.#terminal },
|
|
487
|
-
activeModel: this.#activeModel === null ? null : { ...this.#activeModel },
|
|
319
|
+
terminal: { ...this.#state.terminal },
|
|
320
|
+
activeModel: this.#state.activeModel === null ? null : { ...this.#state.activeModel },
|
|
488
321
|
routedModel: routedModel === null ? null : {
|
|
489
322
|
model: routedModel,
|
|
490
323
|
...(routed?.thinkingLevel === undefined ? {} : { thinkingLevel: readThinkingLevel(routed.thinkingLevel) }),
|
|
491
324
|
},
|
|
492
|
-
thinkingLevel: this.#thinkingLevel,
|
|
325
|
+
thinkingLevel: this.#state.thinkingLevel,
|
|
493
326
|
activeCommandIds: [...this.#commands.activeCommandIds],
|
|
494
327
|
dialog: null,
|
|
495
328
|
overlay: null,
|
|
496
329
|
customizations: [],
|
|
497
|
-
diagnostics: this.#diagnostics.map(diagnostic => ({ ...diagnostic })),
|
|
330
|
+
diagnostics: this.#state.diagnostics.map(diagnostic => ({ ...diagnostic })),
|
|
498
331
|
};
|
|
499
332
|
}
|
|
500
333
|
snapshot() {
|
|
501
334
|
const snapshot = {
|
|
502
335
|
contractVersion: 1,
|
|
503
|
-
snapshotId: `snapshot-${this.#
|
|
336
|
+
snapshotId: `snapshot-${this.#state.revision}`,
|
|
504
337
|
sessionId: this.#sessionId,
|
|
505
338
|
sequence: this.#delivery.sequence,
|
|
506
339
|
view: this.view(),
|
|
@@ -520,10 +353,10 @@ export class PiEngineAdapter {
|
|
|
520
353
|
this.#workflows.cancelPending("quit");
|
|
521
354
|
this.#projection.assets.clear();
|
|
522
355
|
await this.#extensions.unbind();
|
|
523
|
-
this.#lifecycle = "stopping";
|
|
356
|
+
this.#state.lifecycle = "stopping";
|
|
524
357
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "stopping", reason: null });
|
|
525
358
|
await this.#engine.dispose();
|
|
526
|
-
this.#lifecycle = "stopped";
|
|
359
|
+
this.#state.lifecycle = "stopped";
|
|
527
360
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "stopped", reason: null });
|
|
528
361
|
this.#emitView();
|
|
529
362
|
try {
|
|
@@ -534,28 +367,17 @@ export class PiEngineAdapter {
|
|
|
534
367
|
throw error;
|
|
535
368
|
}
|
|
536
369
|
}
|
|
537
|
-
// Invariant: every
|
|
370
|
+
// Invariant: every port member delegates at call time, so ports built once follow session replacement.
|
|
538
371
|
#createPorts() {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
return {
|
|
549
|
-
identity: {
|
|
550
|
-
sessionId,
|
|
551
|
-
agentDir,
|
|
552
|
-
get cwd() { return engine.cwd; },
|
|
553
|
-
get sessionGeneration() { return engine.generation; },
|
|
554
|
-
get sessionBindingGeneration() { return engine.bindingGeneration; },
|
|
555
|
-
get disposed() { return isDisposed(); },
|
|
556
|
-
currentSessionResumeMetadata: () => engine.currentSessionResumeMetadata(),
|
|
557
|
-
currentSessionFile: () => engine.currentSessionFile(),
|
|
558
|
-
},
|
|
372
|
+
return createEnginePorts({
|
|
373
|
+
sessionId: this.#sessionId,
|
|
374
|
+
agentDir: this.#agentDir,
|
|
375
|
+
engine: this.#engine,
|
|
376
|
+
contexts: this.#contexts,
|
|
377
|
+
workflows: this.#workflows,
|
|
378
|
+
settings: this.#settings,
|
|
379
|
+
resources: this.#resources,
|
|
380
|
+
extensions: this.#extensions,
|
|
559
381
|
session: {
|
|
560
382
|
start: () => this.start(),
|
|
561
383
|
view: () => this.view(),
|
|
@@ -565,67 +387,22 @@ export class PiEngineAdapter {
|
|
|
565
387
|
flushEvents: () => this.flushEvents(),
|
|
566
388
|
dispose: () => this.dispose(),
|
|
567
389
|
},
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
},
|
|
585
|
-
bindOwner: (owner, handlers) => settings.bindSettingsOwner(owner, handlers),
|
|
586
|
-
setDefaultThinkingLevel: level => { settings.setDefaultThinkingLevel(level); },
|
|
587
|
-
configuredTheme: () => settings.configuredTheme(),
|
|
588
|
-
},
|
|
589
|
-
catalog: {
|
|
590
|
-
modelsContext: () => contexts.modelsContext(),
|
|
591
|
-
setSessionModelScope: scopeIds => { contexts.setSessionModelScope(scopeIds); },
|
|
592
|
-
persistModelScope: scopeIds => { contexts.persistModelScope(scopeIds); },
|
|
593
|
-
refreshModels: signal => contexts.refreshModels(signal),
|
|
594
|
-
pinnedScopedModelsContext: () => contexts.pinnedScopedModelsContext(),
|
|
595
|
-
updateScopedModels: enabledModelIds => { contexts.updateScopedModels(enabledModelIds); },
|
|
596
|
-
persistScopedModels: enabledModelIds => { contexts.persistScopedModels(enabledModelIds); },
|
|
597
|
-
refreshScopedModels: signal => contexts.refreshScopedModels(signal),
|
|
598
|
-
pinnedProjectTrustContext: () => contexts.pinnedProjectTrustContext(),
|
|
599
|
-
persistProjectTrust: updates => { contexts.persistProjectTrust(updates); },
|
|
600
|
-
pinnedLoginOptions: authType => contexts.loginOptions(authType),
|
|
601
|
-
pinnedLoginMethodOptions: providerReference => contexts.pinnedLoginMethodOptions(providerReference),
|
|
602
|
-
pinnedAmbientAuthentication: selection => contexts.pinnedAmbientAuthentication(selection),
|
|
603
|
-
pinnedLogoutOptions: () => contexts.logoutOptions(),
|
|
604
|
-
pinnedForkOptions: () => contexts.pinnedForkOptions(),
|
|
605
|
-
},
|
|
606
|
-
extensions: {
|
|
607
|
-
nonVisualResources: () => resources.nonVisualResources(),
|
|
608
|
-
extensionResources: () => resources.extensionResources(),
|
|
609
|
-
resolveTranscriptImage: assetId => this.resolveTranscriptImage(assetId),
|
|
610
|
-
visualExtensionSupport: () => extensions.support(),
|
|
611
|
-
bindExtensionUi: (ui, shutdown) => extensions.bind(ui, shutdown),
|
|
612
|
-
unbindExtensionUi: () => extensions.unbind(),
|
|
613
|
-
bindClipboardWriter: writer => workflows.bindClipboardWriter(writer),
|
|
614
|
-
announceReleaseUpdate: release => { this.announceReleaseUpdate(release); },
|
|
615
|
-
},
|
|
616
|
-
presentation: {
|
|
617
|
-
pinnedModelSelectorContext: () => contexts.pinnedModelSelectorContext(),
|
|
618
|
-
pinnedSessionSelectorContext: () => contexts.pinnedSessionSelectorContext(),
|
|
619
|
-
pinnedTreeSelectorContext: () => contexts.pinnedTreeSelectorContext(),
|
|
620
|
-
pinnedMessageRenderer: customType => this.#pinnedMessageRenderer(customType),
|
|
621
|
-
pinnedToolRenderers: toolName => this.#pinnedToolRenderers(toolName),
|
|
622
|
-
pinnedShortcutDescriptions: bindings => this.#pinnedShortcutDescriptions(bindings),
|
|
623
|
-
pinnedSettingsModels: () => {
|
|
624
|
-
const { currentModel, availableDefaultModels } = settings.pinnedSettingsSnapshot();
|
|
625
|
-
return { ...(currentModel === undefined ? {} : { currentModel }), availableDefaultModels };
|
|
626
|
-
},
|
|
627
|
-
applyPinnedSettingValue: (callback, value) => settings.applyPinnedSettingValue(callback, value),
|
|
628
|
-
},
|
|
390
|
+
disposed: () => this.#disposed,
|
|
391
|
+
executeWorkflow: request => this.executeWorkflow(request),
|
|
392
|
+
clearQueuedWorkflows: () => this.clearQueuedWorkflows(),
|
|
393
|
+
setWorkflowInteractionHost: interaction => { this.setWorkflowInteractionHost(interaction); },
|
|
394
|
+
announceReleaseUpdate: release => { this.#announceReleaseUpdate(release); },
|
|
395
|
+
resolveTranscriptImage: assetId => this.#resolveTranscriptImage(assetId),
|
|
396
|
+
extensionRunner: () => this.#requireWorkflowSession().extensionRunner,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
#commandContext() {
|
|
400
|
+
return {
|
|
401
|
+
engine: this.#engine,
|
|
402
|
+
state: this.#state,
|
|
403
|
+
admissionOpen: () => !this.#delivery.overloaded && !this.#admissionStopped,
|
|
404
|
+
emit: value => { this.#emitEvent(value); },
|
|
405
|
+
dispose: () => this.dispose(),
|
|
629
406
|
};
|
|
630
407
|
}
|
|
631
408
|
#requireWorkflowSession() {
|
|
@@ -633,75 +410,16 @@ export class PiEngineAdapter {
|
|
|
633
410
|
throw new Error("engine adapter is not running");
|
|
634
411
|
return this.#engine.session;
|
|
635
412
|
}
|
|
636
|
-
async #perform(command) {
|
|
637
|
-
const runtime = this.#engine.runtime;
|
|
638
|
-
const session = this.#engine.session;
|
|
639
|
-
const generation = this.#engine.generation;
|
|
640
|
-
if (!runtime || !session)
|
|
641
|
-
throw new Error("engine session is unavailable");
|
|
642
|
-
switch (command.type) {
|
|
643
|
-
case "prompt":
|
|
644
|
-
case "steer":
|
|
645
|
-
case "follow-up":
|
|
646
|
-
case "abort":
|
|
647
|
-
case "retry":
|
|
648
|
-
case "compact": {
|
|
649
|
-
const result = await this.#engine.sessionCommands?.execute(command.type === "prompt" || command.type === "steer" || command.type === "follow-up"
|
|
650
|
-
? {
|
|
651
|
-
type: command.type,
|
|
652
|
-
text: command.text,
|
|
653
|
-
...(command.images === undefined ? {} : { images: [...command.images] }),
|
|
654
|
-
}
|
|
655
|
-
: { type: command.type });
|
|
656
|
-
if (!result || result.outcome === "rejected" || result.outcome === "failed") {
|
|
657
|
-
throw new Error(command.type === "retry" ? "no previous prompt is available to retry" : `Pi session command failed: ${command.type}`);
|
|
658
|
-
}
|
|
659
|
-
return;
|
|
660
|
-
}
|
|
661
|
-
case "set-model": {
|
|
662
|
-
const model = runtime.services.modelRuntime.getModel(command.model.providerId, command.model.modelId);
|
|
663
|
-
if (!model) {
|
|
664
|
-
throw new Error(`model is unavailable: ${command.model.providerId}/${command.model.modelId}`);
|
|
665
|
-
}
|
|
666
|
-
await session.setModel(model);
|
|
667
|
-
if (generation === this.#engine.generation && !this.#delivery.overloaded && !this.#admissionStopped)
|
|
668
|
-
this.#activeModel = { ...command.model };
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
case "set-thinking-level":
|
|
672
|
-
session.setThinkingLevel(command.thinkingLevel);
|
|
673
|
-
this.#thinkingLevel = command.thinkingLevel;
|
|
674
|
-
return;
|
|
675
|
-
case "new-session":
|
|
676
|
-
await runtime.newSession();
|
|
677
|
-
return;
|
|
678
|
-
case "resume-session":
|
|
679
|
-
await runtime.switchSession(command.sessionPath);
|
|
680
|
-
return;
|
|
681
|
-
case "resize-surface":
|
|
682
|
-
this.#terminal = { ...command.surface };
|
|
683
|
-
this.#emitEvent({ type: "terminal-surface", surface: this.#terminal });
|
|
684
|
-
return;
|
|
685
|
-
case "shutdown":
|
|
686
|
-
await this.dispose();
|
|
687
|
-
return;
|
|
688
|
-
case "set-setting":
|
|
689
|
-
case "apply-customization":
|
|
690
|
-
case "remove-customization":
|
|
691
|
-
throw new Error("owned UI state commands belong to the owned UI layer, not the Pi engine adapter");
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
413
|
// Invariant: in-place tree navigation rebuilds derived content without clearing the editor draft.
|
|
695
414
|
#refreshNavigatedSession(editorText) {
|
|
696
415
|
const session = this.#engine.session;
|
|
697
416
|
if (!session)
|
|
698
417
|
return;
|
|
699
|
-
if (editorText
|
|
700
|
-
this.#
|
|
701
|
-
|
|
702
|
-
this.#activeModel = readModel(session.model);
|
|
418
|
+
if (editorText)
|
|
419
|
+
this.#state.offerEditorText(editorText);
|
|
420
|
+
this.#state.activeModel = readModel(session.model);
|
|
703
421
|
this.#reconcileActiveModelAvailability();
|
|
704
|
-
this.#thinkingLevel = readThinkingLevel(session.thinkingLevel);
|
|
422
|
+
this.#state.thinkingLevel = readThinkingLevel(session.thinkingLevel);
|
|
705
423
|
this.#projection.assets.clear();
|
|
706
424
|
this.#setTranscript(this.#projection.rebuild(session.messages, "finalized"));
|
|
707
425
|
this.#emitView();
|
|
@@ -710,19 +428,11 @@ export class PiEngineAdapter {
|
|
|
710
428
|
#sessionReplaced(session) {
|
|
711
429
|
this.#delivery.discardObsolete(this.#engine.generation);
|
|
712
430
|
this.#commands.reset();
|
|
713
|
-
this.#
|
|
714
|
-
text: "",
|
|
715
|
-
queuedSubmissions: [],
|
|
716
|
-
selection: null,
|
|
717
|
-
cursorOffset: 0,
|
|
718
|
-
historyRevision: this.#editor.historyRevision + 1,
|
|
719
|
-
submitEnabled: true,
|
|
720
|
-
};
|
|
721
|
-
this.#status = { ...this.#status, workingMessage: null, workingProgress: null, badges: [] };
|
|
431
|
+
this.#state.replaceSession();
|
|
722
432
|
this.#events.reset();
|
|
723
|
-
this.#activeModel = readModel(session.model);
|
|
433
|
+
this.#state.activeModel = readModel(session.model);
|
|
724
434
|
this.#reconcileActiveModelAvailability();
|
|
725
|
-
this.#thinkingLevel = readThinkingLevel(session.thinkingLevel);
|
|
435
|
+
this.#state.thinkingLevel = readThinkingLevel(session.thinkingLevel);
|
|
726
436
|
this.#projection.assets.clear();
|
|
727
437
|
// Invariant: a new binding cannot inherit arguments/results from a reused invocation id.
|
|
728
438
|
this.#setTranscript([]);
|
|
@@ -733,17 +443,17 @@ export class PiEngineAdapter {
|
|
|
733
443
|
#reconcileActiveModelAvailability() {
|
|
734
444
|
const modelRuntime = this.#engine.runtime?.services.modelRuntime;
|
|
735
445
|
if (!modelRuntime) {
|
|
736
|
-
this.#activeModel = null;
|
|
446
|
+
this.#state.activeModel = null;
|
|
737
447
|
return;
|
|
738
448
|
}
|
|
739
449
|
const available = modelRuntime.getAvailableSnapshot?.() ?? [];
|
|
740
450
|
const sessionModel = readModel(this.#engine.session?.model);
|
|
741
|
-
const authoritative = this.#activeModel ?? sessionModel;
|
|
451
|
+
const authoritative = this.#state.activeModel ?? sessionModel;
|
|
742
452
|
if (authoritative === null)
|
|
743
453
|
return;
|
|
744
454
|
const remainsAvailable = available.some(model => stringProperty(model, "provider") === authoritative.providerId
|
|
745
455
|
&& stringProperty(model, "id") === authoritative.modelId);
|
|
746
|
-
this.#activeModel = remainsAvailable ? authoritative : null;
|
|
456
|
+
this.#state.activeModel = remainsAvailable ? authoritative : null;
|
|
747
457
|
}
|
|
748
458
|
#setTranscript(blocks) {
|
|
749
459
|
// Invariant: lazy delivery snapshots must freeze before their authoritative source can be removed.
|
|
@@ -758,13 +468,12 @@ export class PiEngineAdapter {
|
|
|
758
468
|
this.#emitEvent({ type: "diagnostic", diagnostic });
|
|
759
469
|
}
|
|
760
470
|
#emitView() {
|
|
761
|
-
this.#
|
|
762
|
-
this.#viewRevision += 1;
|
|
471
|
+
this.#state.invalidate();
|
|
763
472
|
this.#emitEvent({ type: "session-view", view: this.view() });
|
|
764
473
|
}
|
|
765
474
|
#emitEvent(value) {
|
|
766
475
|
if (value.type !== "session-view")
|
|
767
|
-
this.#
|
|
476
|
+
this.#state.advance();
|
|
768
477
|
this.#delivery.emit(value);
|
|
769
478
|
}
|
|
770
479
|
// Concurrency: cancellation runs synchronously so the overload reservation already guards reentrant outcomes.
|
|
@@ -779,10 +488,7 @@ export class PiEngineAdapter {
|
|
|
779
488
|
this.#admissionStopped = !canResume;
|
|
780
489
|
this.#engine.suspend();
|
|
781
490
|
this.#events.abandonRun();
|
|
782
|
-
this.#
|
|
783
|
-
this.#lifecycle = this.#disposed ? "stopped" : canResume ? "ready" : "failed";
|
|
784
|
-
this.#editor = { ...this.#editor, submitEnabled: canResume && !this.#disposed };
|
|
785
|
-
this.#viewRevision += 1;
|
|
491
|
+
this.#state.settleOverload(canResume, this.#disposed);
|
|
786
492
|
// Invariant: overload publishes one authoritative view; settle tool phases before finalizing other live blocks.
|
|
787
493
|
this.#projection.settleFailedDeclarations({ role: "assistant", stopReason: cancelled ? "aborted" : "error",
|
|
788
494
|
errorMessage: "Tool result unavailable after UI delivery overload" });
|
|
@@ -799,21 +505,7 @@ export class PiEngineAdapter {
|
|
|
799
505
|
this.#engine.resume();
|
|
800
506
|
}
|
|
801
507
|
#recordDiagnostic(severity, code, message, recoverable) {
|
|
802
|
-
|
|
803
|
-
sequence: this.#diagnostics.length,
|
|
804
|
-
code,
|
|
805
|
-
severity,
|
|
806
|
-
message,
|
|
807
|
-
recoverable,
|
|
808
|
-
};
|
|
809
|
-
this.#diagnostics.push(diagnostic);
|
|
810
|
-
if (this.#diagnostics.length > 100)
|
|
811
|
-
this.#diagnostics.shift();
|
|
812
|
-
this.#status = {
|
|
813
|
-
...this.#status,
|
|
814
|
-
diagnostics: [...this.#status.diagnostics, message].slice(-8),
|
|
815
|
-
};
|
|
816
|
-
return diagnostic;
|
|
508
|
+
return this.#state.recordDiagnostic(severity, code, message, recoverable);
|
|
817
509
|
}
|
|
818
510
|
}
|
|
819
511
|
export async function createPiEngineAdapter(options) {
|