@timurproko/a1 0.1.8-dev.157 → 0.1.8-dev.214
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 +32 -0
- package/bin/cli.js +2 -2
- package/bin/sync-pi-tui-proxy.js +1 -1
- package/bin/ui.js +18 -3
- package/dist/cli/dispatch.js +3 -3
- package/dist/cli/packages.js +1 -1
- package/dist/cli/version-stats.js +3 -3
- package/dist/composition/owned-ui.d.ts +4 -1
- package/dist/composition/owned-ui.js +9 -6
- package/dist/composition/settings-route-host.js +6 -4
- package/dist/contracts/agent-engine/capability-ports.d.ts +2 -2
- package/dist/contracts/agent-engine/domain-validation.js +22 -4
- package/dist/contracts/agent-engine/domain.d.ts +17 -0
- package/dist/contracts/owned-ui/model.d.ts +8 -0
- package/dist/contracts/owned-ui/validation.js +11 -0
- package/dist/features/launch/development-launch.js +1 -1
- package/dist/features/owned-ui/customization.d.ts +2 -0
- package/dist/features/owned-ui/customization.js +2 -0
- package/dist/features/owned-ui/diagnostics.d.ts +1 -0
- package/dist/features/owned-ui/diagnostics.js +1 -0
- package/dist/features/owned-ui/index.d.ts +1 -0
- package/dist/features/owned-ui/index.js +1 -0
- package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
- package/dist/features/owned-ui/project-trust-prompt.js +149 -0
- package/dist/features/owned-ui/settings-app.js +69 -44
- package/dist/features/workspace/reducer.d.ts +1 -0
- package/dist/features/workspace/reducer.js +1 -0
- package/dist/features/workspace/router.d.ts +1 -0
- package/dist/features/workspace/router.js +1 -0
- package/dist/features/workspace/store.d.ts +1 -0
- package/dist/features/workspace/store.js +1 -0
- package/dist/foundation/launch-guardian/main.js +1 -1
- package/dist/foundation/native-host-protocol/codec.d.ts +2 -0
- package/dist/foundation/native-host-protocol/codec.js +2 -0
- package/dist/foundation/process-containment/linux-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/linux-process-inspector.js +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.d.ts +1 -0
- package/dist/foundation/process-containment/native-guardian-containment.js +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.d.ts +1 -0
- package/dist/foundation/process-containment/windows-process-inspector.js +1 -0
- package/dist/foundation/protocol/client.d.ts +1 -0
- package/dist/foundation/protocol/client.js +1 -0
- package/dist/foundation/protocol/messages.d.ts +1 -0
- package/dist/foundation/protocol/messages.js +1 -0
- package/dist/foundation/release/bootstrap.js +6 -6
- package/dist/foundation/release/cohort-state.d.ts +1 -0
- package/dist/foundation/release/cohort-state.js +1 -0
- package/dist/foundation/release/release-gc.js +1 -1
- package/dist/foundation/release/release.js +1 -1
- package/dist/foundation/release/update-transaction.d.ts +1 -0
- package/dist/foundation/release/update-transaction.js +1 -0
- package/dist/foundation/release/update.js +12 -12
- package/dist/foundation/storage/control-store.d.ts +1 -0
- package/dist/foundation/storage/control-store.js +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/backpressure.js +1 -0
- package/dist/foundation/structured-agent-runtime/commands.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/commands.js +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/reconnection.js +1 -0
- package/dist/foundation/structured-agent-runtime/state.d.ts +1 -0
- package/dist/foundation/structured-agent-runtime/state.js +1 -0
- package/dist/foundation/supervision/main.js +1 -1
- package/dist/foundation/supervision/server.d.ts +1 -0
- package/dist/foundation/supervision/server.js +4 -6
- package/dist/integrations/pi/components/conformance.d.ts +1 -0
- package/dist/integrations/pi/components/conformance.js +1 -0
- package/dist/integrations/pi/components/shell-components.d.ts +1 -0
- package/dist/integrations/pi/components/shell-components.js +1 -0
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +10 -0
- package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +19 -13
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +36 -0
- package/dist/integrations/pi/components/shell-presenters-info.js +78 -0
- package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +3 -36
- package/dist/integrations/pi/components/shell-presenters-transcript.js +88 -128
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +11 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +22 -4
- package/dist/integrations/pi/engine/adapter.js +220 -70
- package/dist/integrations/pi/engine/conformance.d.ts +2 -0
- package/dist/integrations/pi/engine/conformance.js +2 -0
- package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
- package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
- package/dist/integrations/pi/engine/index.d.ts +3 -0
- package/dist/integrations/pi/engine/index.js +3 -0
- package/dist/integrations/pi/engine/model-auth-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/model-auth-integration.js +1 -0
- package/dist/integrations/pi/engine/package-integration.js +1 -1
- package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
- package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
- package/dist/integrations/pi/engine/resource-extension-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/resource-extension-integration.js +1 -0
- package/dist/integrations/pi/engine/runtime-integration.d.ts +16 -1
- package/dist/integrations/pi/engine/runtime-integration.js +34 -4
- package/dist/integrations/pi/engine/session-integration.d.ts +1 -0
- package/dist/integrations/pi/engine/session-integration.js +2 -1
- package/dist/integrations/pi/engine/settings-effects.d.ts +66 -0
- package/dist/integrations/pi/engine/settings-effects.js +249 -0
- package/dist/integrations/pi/engine/settings-integration.d.ts +14 -26
- package/dist/integrations/pi/engine/settings-integration.js +102 -108
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +2 -1
- package/dist/integrations/pi/engine/workflow-controllers.js +1 -0
- package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
- package/dist/integrations/pi/session-ui/clipboard-image.js +29 -0
- package/dist/integrations/pi/session-ui/index.d.ts +1 -0
- package/dist/integrations/pi/session-ui/index.js +1 -0
- package/dist/integrations/pi/session-ui/prompt-chips.js +6 -2
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +39 -4
- package/dist/integrations/pi/session-ui/session-shell-root.js +215 -80
- package/dist/integrations/pi/session-ui/session-shell.d.ts +10 -1
- package/dist/integrations/pi/session-ui/session-shell.js +256 -45
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +76 -11
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.d.ts +29 -0
- package/dist/integrations/pi/session-ui/stream-presentation-coalescer.js +79 -0
- package/dist/integrations/pi/session-ui/system-clipboard.d.ts +9 -0
- package/dist/integrations/pi/session-ui/system-clipboard.js +38 -9
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +166 -8
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +25 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +63 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +240 -0
- package/dist/integrations/pi/tui-runtime/index.d.ts +2 -0
- package/dist/integrations/pi/tui-runtime/index.js +2 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
- package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/ui/apps/host.js +5 -9
- package/dist/ui/apps/registry.d.ts +1 -0
- package/dist/ui/apps/registry.js +1 -0
- package/dist/ui/components/dialog-panel.js +5 -3
- package/dist/ui/components/frame.d.ts +1 -0
- package/dist/ui/components/frame.js +1 -0
- package/dist/ui/components/index.d.ts +1 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/line-input.d.ts +1 -6
- package/dist/ui/components/line-input.js +4 -9
- package/dist/ui/components/list-view.d.ts +0 -6
- package/dist/ui/components/list-view.js +14 -7
- package/dist/ui/components/progress-status.d.ts +2 -0
- package/dist/ui/components/progress-status.js +4 -0
- package/dist/ui/components/scrollbar.js +1 -1
- package/dist/ui/components/shortcuts.d.ts +1 -0
- package/dist/ui/components/shortcuts.js +1 -0
- package/dist/ui/components/spans.d.ts +2 -5
- package/dist/ui/components/spans.js +28 -8
- package/dist/ui/components/surface.d.ts +0 -5
- package/dist/ui/components/surface.js +1 -5
- package/dist/ui/components/text-selection.d.ts +10 -1
- package/dist/ui/components/text-selection.js +96 -29
- package/dist/ui/components/text.js +3 -3
- package/dist/ui/components/transcript-viewport.d.ts +42 -0
- package/dist/ui/components/transcript-viewport.js +287 -39
- package/dist/ui/settings/sections.d.ts +6 -19
- package/dist/ui/settings/sections.js +17 -15
- package/dist/ui/settings/session.d.ts +8 -18
- package/dist/ui/settings/session.js +60 -52
- package/dist/ui/settings/store.d.ts +1 -0
- package/dist/ui/settings/store.js +2 -1
- package/docs/architecture/code-documentation.md +77 -0
- package/docs/architecture/project-structure.md +15 -1
- package/docs/architecture/ui-reference-provenance.md +23 -3
- package/docs/ci-release-runbook.md +98 -7
- package/docs/manual-owned-ui-checkpoint.md +28 -1
- package/docs/manual-terminal-colour-check.md +4 -3
- package/docs/repository-governance-live-acceptance.md +77 -0
- package/package.json +11 -3
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
2
3
|
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
4
|
import { tmpdir } from "node:os";
|
|
4
5
|
import { dirname, join, resolve } from "node:path";
|
|
5
6
|
import { promisify } from "node:util";
|
|
6
7
|
import { PRODUCT_IDENTITY } from "../../../product-identity.js";
|
|
7
|
-
import {
|
|
8
|
+
import { configureOwnedHttpDispatcher } from "./http-dispatcher.js";
|
|
9
|
+
import { copyToClipboard, DefaultPackageManager, getAgentDir, ProjectTrustStore, SessionManager, VERSION, } from "@earendil-works/pi-coding-agent";
|
|
8
10
|
import { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, assertOwnedUiCommand, assertOwnedUiExtensionUiPort, assertOwnedUiSnapshot, } from "../../../contracts/owned-ui/index.js";
|
|
9
11
|
import { PINNED_PI_SETTINGS_CALLBACKS, PINNED_PI_WORKFLOW_COMMAND_NAMES, } from "./workflows.js";
|
|
10
12
|
import { createPiRuntimeIntegration } from "./runtime-integration.js";
|
|
@@ -16,7 +18,7 @@ const execFileAsync = promisify(execFile);
|
|
|
16
18
|
* that a streaming burst never holds input, large enough that an ordinary turn is one
|
|
17
19
|
* batch.
|
|
18
20
|
*/
|
|
19
|
-
//
|
|
21
|
+
// Performance: deliver at most one engine event per event-loop turn. Transcript updates can
|
|
20
22
|
// be expensive in long sessions; a larger synchronous batch starves terminal
|
|
21
23
|
// input and makes an in-progress mouse selection appear frozen.
|
|
22
24
|
const EVENT_DELIVERY_BATCH = 1;
|
|
@@ -27,12 +29,14 @@ const DEFAULT_SURFACE = {
|
|
|
27
29
|
focusedRegion: "editor",
|
|
28
30
|
hardwareCursor: false,
|
|
29
31
|
};
|
|
32
|
+
/** Owns the pinned Pi session lifecycle and translates its events into the neutral agent-engine contract. */
|
|
30
33
|
export class PiEngineAdapter {
|
|
31
34
|
#runtimeFactory;
|
|
32
35
|
#checkPackageUpdates;
|
|
33
36
|
#cwd;
|
|
34
37
|
#agentDir;
|
|
35
38
|
#sessionId;
|
|
39
|
+
#sessionPath;
|
|
36
40
|
#workflowHost;
|
|
37
41
|
#workflowInteraction;
|
|
38
42
|
#listeners = new Set();
|
|
@@ -68,6 +72,7 @@ export class PiEngineAdapter {
|
|
|
68
72
|
#messageBlockIds = new WeakMap();
|
|
69
73
|
#messageFallbackIds = new Map();
|
|
70
74
|
#toolBlockIds = new Map();
|
|
75
|
+
#transcriptImageAssets = new Map();
|
|
71
76
|
#pendingToolUpdates = new Map();
|
|
72
77
|
#toolUpdateFlush = null;
|
|
73
78
|
#usageCache;
|
|
@@ -84,12 +89,16 @@ export class PiEngineAdapter {
|
|
|
84
89
|
#extensionShutdown;
|
|
85
90
|
#extensionBound = false;
|
|
86
91
|
#disposed = false;
|
|
87
|
-
|
|
92
|
+
#settingsProductMode;
|
|
93
|
+
#projectTrustPrompt;
|
|
94
|
+
#settingsIntegration;
|
|
95
|
+
#settingsIntegrationManager;
|
|
88
96
|
#availableThemes;
|
|
89
97
|
constructor(options = {}) {
|
|
90
98
|
this.#cwd = options.cwd ?? process.cwd();
|
|
91
99
|
this.#agentDir = options.agentDir ?? getAgentDir();
|
|
92
100
|
this.#sessionId = options.sessionId ?? "owned-session-1";
|
|
101
|
+
this.#sessionPath = options.sessionPath;
|
|
93
102
|
this.#runtimeFactory = options.createRuntime ?? createDefaultPiRuntime;
|
|
94
103
|
this.#checkPackageUpdates = options.checkPackageUpdates
|
|
95
104
|
?? (options.createRuntime
|
|
@@ -97,6 +106,8 @@ export class PiEngineAdapter {
|
|
|
97
106
|
: settingsManager => checkDefaultPiPackageUpdates(this.#cwd, this.#agentDir, settingsManager));
|
|
98
107
|
this.#workflowHost = options.workflowHost ?? defaultWorkflowHost();
|
|
99
108
|
this.#availableThemes = options.availableThemes ?? null;
|
|
109
|
+
this.#settingsProductMode = options.settingsProductMode ?? "bare";
|
|
110
|
+
this.#projectTrustPrompt = options.projectTrustPrompt;
|
|
100
111
|
this.#workflowInteraction = { prompt: async () => null, notify() { } };
|
|
101
112
|
}
|
|
102
113
|
setWorkflowInteractionHost(interaction) {
|
|
@@ -111,6 +122,29 @@ export class PiEngineAdapter {
|
|
|
111
122
|
get agentDir() {
|
|
112
123
|
return this.#agentDir;
|
|
113
124
|
}
|
|
125
|
+
resolveTranscriptImage(assetId) {
|
|
126
|
+
return this.#transcriptImageAssets.get(assetId) ?? null;
|
|
127
|
+
}
|
|
128
|
+
currentSessionFile() {
|
|
129
|
+
const value = this.#session?.sessionManager?.getSessionFile?.();
|
|
130
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
131
|
+
}
|
|
132
|
+
currentSessionResumeMetadata() {
|
|
133
|
+
const manager = this.#session?.sessionManager;
|
|
134
|
+
if (manager === undefined
|
|
135
|
+
|| typeof manager.isPersisted !== "function"
|
|
136
|
+
|| typeof manager.getSessionId !== "function"
|
|
137
|
+
|| typeof manager.getSessionDir !== "function"
|
|
138
|
+
|| typeof manager.usesDefaultSessionDir !== "function"
|
|
139
|
+
|| manager.isPersisted() !== true
|
|
140
|
+
|| this.currentSessionFile() === null)
|
|
141
|
+
return null;
|
|
142
|
+
const sessionId = manager.getSessionId();
|
|
143
|
+
const sessionDir = manager.getSessionDir();
|
|
144
|
+
if (!sessionId || !sessionDir)
|
|
145
|
+
return null;
|
|
146
|
+
return { sessionId, sessionDir, usesDefaultSessionDir: manager.usesDefaultSessionDir() };
|
|
147
|
+
}
|
|
114
148
|
get disposed() {
|
|
115
149
|
return this.#disposed;
|
|
116
150
|
}
|
|
@@ -121,6 +155,8 @@ export class PiEngineAdapter {
|
|
|
121
155
|
cwd: this.#cwd,
|
|
122
156
|
agentDir: this.#agentDir,
|
|
123
157
|
sessionId: this.#sessionId,
|
|
158
|
+
...(this.#sessionPath === undefined ? {} : { sessionPath: this.#sessionPath }),
|
|
159
|
+
...(this.#projectTrustPrompt === undefined ? {} : { projectTrustPrompt: this.#projectTrustPrompt }),
|
|
124
160
|
}).catch(error => {
|
|
125
161
|
this.#lifecycle = "failed";
|
|
126
162
|
this.#addDiagnostic("error", "engine-startup", error instanceof Error ? error.message : String(error), false);
|
|
@@ -140,6 +176,7 @@ export class PiEngineAdapter {
|
|
|
140
176
|
this.#addDiagnostic(diagnostic.type === "error" ? "error" : diagnostic.type === "warning" ? "warning" : "info", "engine-startup", diagnostic.message, diagnostic.type !== "error");
|
|
141
177
|
}
|
|
142
178
|
this.#bindSession(runtime.session);
|
|
179
|
+
await this.#announceChangelog(runtime.services.settingsManager);
|
|
143
180
|
this.#lifecycle = "ready";
|
|
144
181
|
this.#editor = { ...this.#editor, submitEnabled: true };
|
|
145
182
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "ready", reason: null });
|
|
@@ -147,6 +184,19 @@ export class PiEngineAdapter {
|
|
|
147
184
|
void this.#announcePackageUpdates(runtime.services.settingsManager);
|
|
148
185
|
return this.view();
|
|
149
186
|
}
|
|
187
|
+
async #announceChangelog(settingsManager) {
|
|
188
|
+
if (!settingsManager || typeof settingsManager.getLastChangelogVersion !== "function"
|
|
189
|
+
|| typeof settingsManager.setLastChangelogVersion !== "function")
|
|
190
|
+
return;
|
|
191
|
+
if (settingsManager.getLastChangelogVersion() === VERSION)
|
|
192
|
+
return;
|
|
193
|
+
const markdown = await this.#workflowHost.readChangelog().catch(() => "");
|
|
194
|
+
if (markdown.trim().length > 0) {
|
|
195
|
+
this.#addDiagnostic("info", settingsManager.getCollapseChangelog() ? "changelog-collapsed" : "changelog-expanded", markdown, true);
|
|
196
|
+
}
|
|
197
|
+
settingsManager.setLastChangelogVersion(VERSION);
|
|
198
|
+
await settingsManager.flush();
|
|
199
|
+
}
|
|
150
200
|
async #announcePackageUpdates(settingsManager) {
|
|
151
201
|
if (process.env.PI_OFFLINE)
|
|
152
202
|
return;
|
|
@@ -432,16 +482,107 @@ export class PiEngineAdapter {
|
|
|
432
482
|
/** Settings port for the live runtime, or null before the runtime is available. */
|
|
433
483
|
settingsPort() {
|
|
434
484
|
const settings = this.#runtime?.services.settingsManager;
|
|
435
|
-
if (!settings)
|
|
485
|
+
if (!settings || typeof settings.getCompactionEnabled !== "function")
|
|
436
486
|
return null;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
487
|
+
if (this.#settingsIntegration === undefined || this.#settingsIntegrationManager !== settings) {
|
|
488
|
+
this.#settingsIntegrationManager = settings;
|
|
489
|
+
configureOwnedHttpDispatcher(settings.getHttpIdleTimeoutMs());
|
|
490
|
+
this.#settingsIntegration = new PiSettingsIntegration(settings, {
|
|
491
|
+
...(this.#availableThemes === null ? {} : { themes: this.#availableThemes }),
|
|
492
|
+
thinkingLevels: () => {
|
|
493
|
+
const levels = this.#runtime?.session?.getAvailableThinkingLevels?.();
|
|
494
|
+
return Array.isArray(levels) ? levels.map(level => String(level)) : [];
|
|
495
|
+
},
|
|
496
|
+
productMode: this.#settingsProductMode,
|
|
497
|
+
});
|
|
498
|
+
this.#settingsIntegration.bindOwner("shell", {
|
|
499
|
+
enableSkillCommands: { apply: value => {
|
|
500
|
+
if (typeof value !== "boolean")
|
|
501
|
+
throw new TypeError("Skill commands value is invalid");
|
|
502
|
+
settings.setEnableSkillCommands(value);
|
|
503
|
+
} },
|
|
504
|
+
doubleEscapeAction: { apply: value => {
|
|
505
|
+
if (value !== "tree" && value !== "fork" && value !== "none")
|
|
506
|
+
throw new TypeError("Double-Escape action is invalid");
|
|
507
|
+
settings.setDoubleEscapeAction(value);
|
|
508
|
+
} },
|
|
509
|
+
treeFilterMode: { apply: value => {
|
|
510
|
+
if (value !== "default" && value !== "no-tools" && value !== "user-only" && value !== "labeled-only" && value !== "all")
|
|
511
|
+
throw new TypeError("Tree filter mode is invalid");
|
|
512
|
+
settings.setTreeFilterMode(value);
|
|
513
|
+
} },
|
|
514
|
+
showCacheMissNotices: { apply: value => {
|
|
515
|
+
if (typeof value !== "boolean")
|
|
516
|
+
throw new TypeError("Cache-miss notice setting is invalid");
|
|
517
|
+
settings.setShowCacheMissNotices(value);
|
|
518
|
+
} },
|
|
519
|
+
});
|
|
520
|
+
this.#settingsIntegration.bindOwner("startup", {
|
|
521
|
+
// Invariant: deferred application is the owner operation: the next preflight reads
|
|
522
|
+
// the persisted default before constructing project-backed services.
|
|
523
|
+
defaultProjectTrust: { apply() { } },
|
|
524
|
+
collapseChangelog: { apply() { } },
|
|
525
|
+
});
|
|
526
|
+
this.#settingsIntegration.bindOwner("agent", {
|
|
527
|
+
autoCompact: { apply: value => {
|
|
528
|
+
if (typeof value !== "boolean")
|
|
529
|
+
throw new TypeError("Auto compact value is invalid");
|
|
530
|
+
this.#requireWorkflowSession().setAutoCompactionEnabled(value);
|
|
531
|
+
} },
|
|
532
|
+
autoResizeImages: { apply: value => {
|
|
533
|
+
if (typeof value !== "boolean")
|
|
534
|
+
throw new TypeError("Auto-resize images value is invalid");
|
|
535
|
+
settings.setImageAutoResize(value);
|
|
536
|
+
} },
|
|
537
|
+
blockImages: { apply: value => {
|
|
538
|
+
if (typeof value !== "boolean")
|
|
539
|
+
throw new TypeError("Block images value is invalid");
|
|
540
|
+
settings.setBlockImages(value);
|
|
541
|
+
} },
|
|
542
|
+
steeringMode: { apply: value => {
|
|
543
|
+
if (value !== "all" && value !== "one-at-a-time")
|
|
544
|
+
throw new TypeError("Steering mode is invalid");
|
|
545
|
+
this.#requireWorkflowSession().setSteeringMode(value);
|
|
546
|
+
} },
|
|
547
|
+
followUpMode: { apply: value => {
|
|
548
|
+
if (value !== "all" && value !== "one-at-a-time")
|
|
549
|
+
throw new TypeError("Follow-up mode is invalid");
|
|
550
|
+
this.#requireWorkflowSession().setFollowUpMode(value);
|
|
551
|
+
} },
|
|
552
|
+
transport: { apply: value => {
|
|
553
|
+
if (value !== "sse" && value !== "websocket" && value !== "websocket-cached" && value !== "auto")
|
|
554
|
+
throw new TypeError("Transport is invalid");
|
|
555
|
+
this.#requireWorkflowSession().agent.transport = value;
|
|
556
|
+
} },
|
|
557
|
+
httpIdleTimeoutMs: { apply: value => {
|
|
558
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
|
|
559
|
+
throw new TypeError("HTTP idle timeout is invalid");
|
|
560
|
+
// Invariant: provider streaming reads the manager per request; global fetch uses
|
|
561
|
+
// the matching owned dispatcher and zero maps to disabled semantics.
|
|
562
|
+
configureOwnedHttpDispatcher(value);
|
|
563
|
+
settings.setHttpIdleTimeoutMs(value);
|
|
564
|
+
} },
|
|
565
|
+
thinkingLevel: { apply: value => {
|
|
566
|
+
if (!isThinkingLevel(value))
|
|
567
|
+
throw new TypeError("Thinking level is invalid");
|
|
568
|
+
this.#requireWorkflowSession().setThinkingLevel(value);
|
|
569
|
+
this.#thinkingLevel = readThinkingLevel(this.#requireWorkflowSession().thinkingLevel);
|
|
570
|
+
this.#emitView();
|
|
571
|
+
} },
|
|
572
|
+
warnings: { apply: value => {
|
|
573
|
+
if (!isRecord(value) || Object.values(value).some(flag => typeof flag !== "boolean"))
|
|
574
|
+
throw new TypeError("Warnings setting is invalid");
|
|
575
|
+
settings.setWarnings(value);
|
|
576
|
+
} },
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
return this.#settingsIntegration;
|
|
580
|
+
}
|
|
581
|
+
bindSettingsOwner(owner, handlers) {
|
|
582
|
+
const settings = this.settingsPort();
|
|
583
|
+
if (settings === null)
|
|
584
|
+
return () => { };
|
|
585
|
+
return settings.bindOwner(owner, handlers);
|
|
445
586
|
}
|
|
446
587
|
pinnedModelSelectorContext() {
|
|
447
588
|
const session = this.#requireWorkflowSession();
|
|
@@ -718,9 +859,9 @@ export class PiEngineAdapter {
|
|
|
718
859
|
excludeFromContext,
|
|
719
860
|
};
|
|
720
861
|
}
|
|
721
|
-
applyPinnedSettingValue(callback, value) {
|
|
862
|
+
async applyPinnedSettingValue(callback, value) {
|
|
722
863
|
try {
|
|
723
|
-
return this.#applyPinnedSetting(callback, value, true);
|
|
864
|
+
return await this.#applyPinnedSetting(callback, value, true);
|
|
724
865
|
}
|
|
725
866
|
catch (error) {
|
|
726
867
|
return workflowResult("settings", "failed", error instanceof Error ? error.message : String(error));
|
|
@@ -821,6 +962,7 @@ export class PiEngineAdapter {
|
|
|
821
962
|
this.#toolUpdateFlush = null;
|
|
822
963
|
}
|
|
823
964
|
this.#pendingToolUpdates.clear();
|
|
965
|
+
this.#transcriptImageAssets.clear();
|
|
824
966
|
this.#extensionBound = false;
|
|
825
967
|
this.#extensionUi = undefined;
|
|
826
968
|
this.#extensionShutdown = undefined;
|
|
@@ -846,7 +988,7 @@ export class PiEngineAdapter {
|
|
|
846
988
|
case "settings": {
|
|
847
989
|
if (!selection)
|
|
848
990
|
return workflowResult(request.command, "failed", "Settings requires the owned settings controller");
|
|
849
|
-
return this.#applyPinnedSetting(selection);
|
|
991
|
+
return await this.#applyPinnedSetting(selection);
|
|
850
992
|
}
|
|
851
993
|
case "model": {
|
|
852
994
|
const reference = selection ?? argument;
|
|
@@ -1236,7 +1378,7 @@ export class PiEngineAdapter {
|
|
|
1236
1378
|
return [];
|
|
1237
1379
|
return sessionInfoOptions(await SessionManager.list(cwd, typeof sessionDir === "string" ? sessionDir : undefined));
|
|
1238
1380
|
}
|
|
1239
|
-
#applyPinnedSetting(selection, selectedValue, hasSelectedValue = false) {
|
|
1381
|
+
async #applyPinnedSetting(selection, selectedValue, hasSelectedValue = false) {
|
|
1240
1382
|
if (!PINNED_PI_SETTINGS_CALLBACKS.includes(selection)) {
|
|
1241
1383
|
return workflowResult("settings", "failed", `Unknown setting callback: ${selection}`);
|
|
1242
1384
|
}
|
|
@@ -1283,29 +1425,19 @@ export class PiEngineAdapter {
|
|
|
1283
1425
|
selectedValue = currentValues[callback];
|
|
1284
1426
|
hasSelectedValue = true;
|
|
1285
1427
|
}
|
|
1286
|
-
const
|
|
1287
|
-
if (
|
|
1428
|
+
const port = this.settingsPort();
|
|
1429
|
+
if (port === null)
|
|
1288
1430
|
return workflowResult("settings", "failed", "Settings are unavailable");
|
|
1289
|
-
const
|
|
1290
|
-
if (
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
else {
|
|
1296
|
-
const key = settingKeyForCallback(callback);
|
|
1297
|
-
if (key === null)
|
|
1298
|
-
return workflowResult("settings", "failed", `${settingLabel(callback)} is unavailable in this runtime`);
|
|
1299
|
-
const value = agentJsonValue(selectedValue);
|
|
1300
|
-
if (callback === "onAutoCompactChange") {
|
|
1301
|
-
if (typeof value !== "boolean")
|
|
1302
|
-
return workflowResult("settings", "failed", "Auto compact value is invalid");
|
|
1303
|
-
session.setAutoCompactionEnabled?.(value);
|
|
1304
|
-
}
|
|
1305
|
-
new PiSettingsIntegration(settings).writeSettingNow(key, value);
|
|
1431
|
+
const key = settingKeyForCallback(callback);
|
|
1432
|
+
if (key === null)
|
|
1433
|
+
return workflowResult("settings", "failed", `${settingLabel(callback)} is unavailable in this runtime`);
|
|
1434
|
+
const result = await port.writeSetting(key, agentJsonValue(selectedValue));
|
|
1435
|
+
if (result.status === "failed" || result.status === "unavailable") {
|
|
1436
|
+
return workflowResult("settings", "failed", result.failure ?? result.limitationReason ?? `${settingLabel(callback)} is unavailable`);
|
|
1306
1437
|
}
|
|
1307
1438
|
this.#emitView();
|
|
1308
|
-
|
|
1439
|
+
const suffix = result.status === "deferred" ? ` (${result.application})` : "";
|
|
1440
|
+
return workflowResult("settings", "completed", `${settingLabel(callback)}: ${String(selectedValue)}${suffix}`);
|
|
1309
1441
|
}
|
|
1310
1442
|
async #perform(command) {
|
|
1311
1443
|
const runtime = this.#runtime;
|
|
@@ -1384,6 +1516,7 @@ export class PiEngineAdapter {
|
|
|
1384
1516
|
this.#activeModel = readModel(session.model);
|
|
1385
1517
|
this.#reconcileActiveModelAvailability();
|
|
1386
1518
|
this.#thinkingLevel = readThinkingLevel(session.thinkingLevel);
|
|
1519
|
+
this.#transcriptImageAssets.clear();
|
|
1387
1520
|
this.#rebuildTranscript(session.messages, "finalized");
|
|
1388
1521
|
this.#unsubscribe = session.subscribe(event => this.#handlePiEvent(event));
|
|
1389
1522
|
if (this.#extensionUi !== undefined)
|
|
@@ -1433,23 +1566,24 @@ export class PiEngineAdapter {
|
|
|
1433
1566
|
this.#emitView();
|
|
1434
1567
|
}
|
|
1435
1568
|
}
|
|
1436
|
-
|
|
1437
|
-
* Replaces the transcript and the index that finds a block by its identifier. Every
|
|
1438
|
-
* lookup goes through the index, so streaming a chunk costs the same in a long session
|
|
1439
|
-
* as in a new one.
|
|
1440
|
-
*/
|
|
1569
|
+
// Performance: replacing the transcript rebuilds its index so block lookup stays constant-time.
|
|
1441
1570
|
#setTranscript(blocks) {
|
|
1442
1571
|
this.#transcript = blocks;
|
|
1443
1572
|
this.#transcriptIndex.clear();
|
|
1444
1573
|
for (const [index, block] of blocks.entries())
|
|
1445
1574
|
this.#transcriptIndex.set(block.id, index);
|
|
1575
|
+
const retainedAssets = new Set(blocks.flatMap(block => block.imageReferences?.map(reference => reference.assetId) ?? []));
|
|
1576
|
+
for (const assetId of this.#transcriptImageAssets.keys()) {
|
|
1577
|
+
if (!retainedAssets.has(assetId))
|
|
1578
|
+
this.#transcriptImageAssets.delete(assetId);
|
|
1579
|
+
}
|
|
1446
1580
|
this.#transcriptSnapshot = undefined;
|
|
1447
1581
|
}
|
|
1448
1582
|
#transcriptBlock(id) {
|
|
1449
1583
|
const index = this.#transcriptIndex.get(id);
|
|
1450
1584
|
return index === undefined ? undefined : this.#transcript[index];
|
|
1451
1585
|
}
|
|
1452
|
-
|
|
1586
|
+
// Invariant: the named work state is the only state a matching end may clear.
|
|
1453
1587
|
#enterWorkState(kind, message) {
|
|
1454
1588
|
const wasBusy = this.#lifecycle === "busy";
|
|
1455
1589
|
this.#statusKind = kind;
|
|
@@ -1459,21 +1593,16 @@ export class PiEngineAdapter {
|
|
|
1459
1593
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "busy", reason: null });
|
|
1460
1594
|
this.#emitEvent({ type: "status", status: this.#status });
|
|
1461
1595
|
}
|
|
1462
|
-
|
|
1463
|
-
* Ends one named state. A state the shell is not in is left alone, so a finished
|
|
1464
|
-
* compaction or retry cannot clear the working state it never replaced. While the run
|
|
1465
|
-
* continues, ending either of those returns to working rather than to idle.
|
|
1466
|
-
*/
|
|
1596
|
+
// Invariant: ending retry or compaction cannot clear a different active work state.
|
|
1467
1597
|
#endWorkState(kind) {
|
|
1468
1598
|
if (this.#statusKind !== kind)
|
|
1469
1599
|
return;
|
|
1470
1600
|
if (this.#agentRunActive) {
|
|
1471
|
-
this.#enterWorkState("working", "Working
|
|
1601
|
+
this.#enterWorkState("working", "Working");
|
|
1472
1602
|
return;
|
|
1473
1603
|
}
|
|
1474
1604
|
this.#leaveWorkStates();
|
|
1475
1605
|
}
|
|
1476
|
-
/** Leaves every work state and reports the session idle. */
|
|
1477
1606
|
#leaveWorkStates() {
|
|
1478
1607
|
this.#statusKind = null;
|
|
1479
1608
|
this.#lifecycle = "ready";
|
|
@@ -1484,7 +1613,7 @@ export class PiEngineAdapter {
|
|
|
1484
1613
|
#handlePiEvent(event) {
|
|
1485
1614
|
if (!isRecord(event) || typeof event.type !== "string")
|
|
1486
1615
|
return;
|
|
1487
|
-
//
|
|
1616
|
+
// Invariant: usage moves at message and lifecycle boundaries, not with stream chunks, so the
|
|
1488
1617
|
// two streaming event kinds keep the memo and everything else drops it.
|
|
1489
1618
|
if (event.type !== "message_update" && event.type !== "tool_execution_update")
|
|
1490
1619
|
this.#usageCache = undefined;
|
|
@@ -1492,7 +1621,7 @@ export class PiEngineAdapter {
|
|
|
1492
1621
|
case "agent_start":
|
|
1493
1622
|
this.#agentRunActive = true;
|
|
1494
1623
|
this.#emitEvent({ type: "agent-run-started" });
|
|
1495
|
-
this.#enterWorkState("working", "Working
|
|
1624
|
+
this.#enterWorkState("working", "Working");
|
|
1496
1625
|
return;
|
|
1497
1626
|
case "message_start":
|
|
1498
1627
|
this.#upsertMessageBlock(event.message, "live");
|
|
@@ -1501,7 +1630,7 @@ export class PiEngineAdapter {
|
|
|
1501
1630
|
const delta = isRecord(event.assistantMessageEvent) && typeof event.assistantMessageEvent.delta === "string"
|
|
1502
1631
|
? event.assistantMessageEvent.delta
|
|
1503
1632
|
: undefined;
|
|
1504
|
-
//
|
|
1633
|
+
// Invariant: the delta is folded in before the block is stored, so a chunk is one update to
|
|
1505
1634
|
// one block rather than a store without the delta followed by a store with it.
|
|
1506
1635
|
const blocks = this.#messageBlocks(event.message, "live", this.#transcript.length);
|
|
1507
1636
|
for (const [index, block] of blocks.entries()) {
|
|
@@ -1513,7 +1642,7 @@ export class PiEngineAdapter {
|
|
|
1513
1642
|
}
|
|
1514
1643
|
case "message_end":
|
|
1515
1644
|
this.#upsertMessageBlock(event.message, "finalized");
|
|
1516
|
-
//
|
|
1645
|
+
// Compatibility: preserve the same semantic boundary v2 counted. Transcript block
|
|
1517
1646
|
// finalization is intentionally not a substitute: rebuilds, retries,
|
|
1518
1647
|
// thinking parts, and tool rows can all finalize independently.
|
|
1519
1648
|
if (isRecord(event.message) && event.message.role === "assistant") {
|
|
@@ -1529,7 +1658,7 @@ export class PiEngineAdapter {
|
|
|
1529
1658
|
return;
|
|
1530
1659
|
case "tool_execution_start":
|
|
1531
1660
|
case "tool_execution_end": {
|
|
1532
|
-
//
|
|
1661
|
+
// Concurrency: the end supersedes any update still waiting on the coalescing timer.
|
|
1533
1662
|
const toolCallId = stringValue(event.toolCallId);
|
|
1534
1663
|
if (toolCallId !== undefined)
|
|
1535
1664
|
this.#pendingToolUpdates.delete(toolCallId);
|
|
@@ -1550,7 +1679,7 @@ export class PiEngineAdapter {
|
|
|
1550
1679
|
this.#rebuildTranscript(finalMessages, "finalized");
|
|
1551
1680
|
else
|
|
1552
1681
|
this.#setTranscript(this.#transcript.map(block => block.status === "live" ? { ...block, status: "finalized" } : block));
|
|
1553
|
-
//
|
|
1682
|
+
// Compatibility: ending a turn leaves the working state, as the recorded pinned baseline does, but
|
|
1554
1683
|
// it leaves only that state: a compaction or retry being shown outlives the turn
|
|
1555
1684
|
// that ended under it. Settlement ends the run, and with it every state — the
|
|
1556
1685
|
// engine ends a turn for each continuation it makes and settles once.
|
|
@@ -1576,13 +1705,13 @@ export class PiEngineAdapter {
|
|
|
1576
1705
|
return;
|
|
1577
1706
|
}
|
|
1578
1707
|
case "auto_retry_start":
|
|
1579
|
-
this.#enterWorkState("retry", "Retrying
|
|
1708
|
+
this.#enterWorkState("retry", "Retrying");
|
|
1580
1709
|
return;
|
|
1581
1710
|
case "auto_retry_end":
|
|
1582
1711
|
this.#endWorkState("retry");
|
|
1583
1712
|
return;
|
|
1584
1713
|
case "compaction_start":
|
|
1585
|
-
this.#enterWorkState("compaction", "Compacting
|
|
1714
|
+
this.#enterWorkState("compaction", "Compacting");
|
|
1586
1715
|
return;
|
|
1587
1716
|
case "compaction_end":
|
|
1588
1717
|
this.#endWorkState("compaction");
|
|
@@ -1675,7 +1804,7 @@ export class PiEngineAdapter {
|
|
|
1675
1804
|
}
|
|
1676
1805
|
}
|
|
1677
1806
|
}
|
|
1678
|
-
//
|
|
1807
|
+
// Performance: an authoritative rebuild restates most of what is already there. Reusing the block
|
|
1679
1808
|
// that already says it keeps its revision, and with it the rows the shell rendered for
|
|
1680
1809
|
// it — otherwise every turn that ends re-renders the whole session.
|
|
1681
1810
|
this.#setTranscript(blocks.map(block => {
|
|
@@ -1702,6 +1831,7 @@ export class PiEngineAdapter {
|
|
|
1702
1831
|
revision: this.#nextBlockRevision(baseId),
|
|
1703
1832
|
title: "User",
|
|
1704
1833
|
text: textFromContent(message.content),
|
|
1834
|
+
imageReferences: this.#imageReferences(message.content, "user"),
|
|
1705
1835
|
payload: {
|
|
1706
1836
|
role: "user",
|
|
1707
1837
|
imageCount: contentImageCount(message.content),
|
|
@@ -1779,6 +1909,7 @@ export class PiEngineAdapter {
|
|
|
1779
1909
|
revision: this.#nextBlockRevision(blockId),
|
|
1780
1910
|
title: stringValue(message.toolName) ?? existing?.title ?? "Tool result",
|
|
1781
1911
|
text: textFromContent(message.content),
|
|
1912
|
+
imageReferences: this.#imageReferences(message.content, "tool-result"),
|
|
1782
1913
|
payload: {
|
|
1783
1914
|
...(existingPayload ?? {}),
|
|
1784
1915
|
role: "toolResult",
|
|
@@ -1834,12 +1965,25 @@ export class PiEngineAdapter {
|
|
|
1834
1965
|
}
|
|
1835
1966
|
return blocks;
|
|
1836
1967
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1968
|
+
#imageReferences(content, source) {
|
|
1969
|
+
if (!Array.isArray(content))
|
|
1970
|
+
return [];
|
|
1971
|
+
const references = [];
|
|
1972
|
+
for (const item of content) {
|
|
1973
|
+
if (references.length >= 16 || !isRecord(item) || item.type !== "image"
|
|
1974
|
+
|| typeof item.data !== "string" || item.data.length === 0
|
|
1975
|
+
|| typeof item.mimeType !== "string" || !/^image\/[a-z0-9.+-]+$/i.test(item.mimeType))
|
|
1976
|
+
continue;
|
|
1977
|
+
const byteLength = Buffer.from(item.data, "base64").byteLength;
|
|
1978
|
+
if (byteLength < 1 || byteLength > 20 * 1024 * 1024)
|
|
1979
|
+
continue;
|
|
1980
|
+
const assetId = `image-${createHash("sha256").update(item.mimeType).update("\0").update(item.data).digest("hex").slice(0, 24)}`;
|
|
1981
|
+
this.#transcriptImageAssets.set(assetId, { type: "image", data: item.data, mimeType: item.mimeType });
|
|
1982
|
+
references.push({ assetId, mimeType: item.mimeType, byteLength, source });
|
|
1983
|
+
}
|
|
1984
|
+
return references;
|
|
1985
|
+
}
|
|
1986
|
+
// Performance: coalescing each tool to its newest chunk bounds work by frames, not stream events.
|
|
1843
1987
|
#coalesceToolExecutionUpdate(event) {
|
|
1844
1988
|
const toolCallId = stringValue(event.toolCallId);
|
|
1845
1989
|
if (!toolCallId)
|
|
@@ -1882,7 +2026,7 @@ export class PiEngineAdapter {
|
|
|
1882
2026
|
toolCallId,
|
|
1883
2027
|
toolName: stringValue(event.toolName) ?? "unknown",
|
|
1884
2028
|
arguments: jsonSummary(event.args),
|
|
1885
|
-
//
|
|
2029
|
+
// Performance: a partial result repeats the whole accumulated output on every chunk;
|
|
1886
2030
|
// summarizing it each time would cost quadratic work over the stream.
|
|
1887
2031
|
result: ended ? jsonSummary(source) : { summary: "", json: null },
|
|
1888
2032
|
partialResult: event.type === "tool_execution_update",
|
|
@@ -1895,7 +2039,7 @@ export class PiEngineAdapter {
|
|
|
1895
2039
|
const index = this.#transcriptIndex.get(block.id);
|
|
1896
2040
|
if (index !== undefined) {
|
|
1897
2041
|
const existing = this.#transcript[index];
|
|
1898
|
-
//
|
|
2042
|
+
// Performance: nothing is emitted for a block that repeats itself, and keeping the
|
|
1899
2043
|
// revision keeps the rows it already rendered.
|
|
1900
2044
|
if (existing !== undefined && sameBlockContent(existing, block))
|
|
1901
2045
|
return;
|
|
@@ -2012,7 +2156,7 @@ export class PiEngineAdapter {
|
|
|
2012
2156
|
}
|
|
2013
2157
|
}
|
|
2014
2158
|
deliveredSinceYield += 1;
|
|
2015
|
-
//
|
|
2159
|
+
// Concurrency: a microtask chain runs to exhaustion before the loop turns, so a streaming
|
|
2016
2160
|
// burst would hold typed input, pointer reports, and timed indicators until it
|
|
2017
2161
|
// drained. Yielding on a macrotask hands those their turn between batches.
|
|
2018
2162
|
if (deliveredSinceYield >= EVENT_DELIVERY_BATCH && this.#eventQueue.length > 0) {
|
|
@@ -2056,7 +2200,12 @@ export async function createPiEngineAdapter(options = {}) {
|
|
|
2056
2200
|
return adapter;
|
|
2057
2201
|
}
|
|
2058
2202
|
async function createDefaultPiRuntime(input) {
|
|
2059
|
-
return createPiRuntimeIntegration({
|
|
2203
|
+
return createPiRuntimeIntegration({
|
|
2204
|
+
cwd: input.cwd,
|
|
2205
|
+
agentDir: input.agentDir,
|
|
2206
|
+
...(input.sessionPath === undefined ? {} : { sessionPath: input.sessionPath }),
|
|
2207
|
+
...(input.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: input.projectTrustPrompt }),
|
|
2208
|
+
});
|
|
2060
2209
|
}
|
|
2061
2210
|
async function checkDefaultPiPackageUpdates(cwd, agentDir, settingsManager) {
|
|
2062
2211
|
const packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });
|
|
@@ -2282,7 +2431,7 @@ function settingKeyForCallback(callback) {
|
|
|
2282
2431
|
onAutoCompactChange: "autoCompact", onShowImagesChange: "showImages", onImageWidthCellsChange: "imageWidthCells",
|
|
2283
2432
|
onAutoResizeImagesChange: "autoResizeImages", onBlockImagesChange: "blockImages", onEnableSkillCommandsChange: "enableSkillCommands",
|
|
2284
2433
|
onSteeringModeChange: "steeringMode", onFollowUpModeChange: "followUpMode", onTransportChange: "transport",
|
|
2285
|
-
onHttpIdleTimeoutMsChange: "httpIdleTimeoutMs", onThemeChange: "theme", onThemePreview: "theme",
|
|
2434
|
+
onHttpIdleTimeoutMsChange: "httpIdleTimeoutMs", onThinkingLevelChange: "thinkingLevel", onThemeChange: "theme", onThemePreview: "theme",
|
|
2286
2435
|
onHideThinkingBlockChange: "hideThinkingBlock", onMermaidRenderingModeChange: "mermaidRenderingMode",
|
|
2287
2436
|
onShowCacheMissNoticesChange: "showCacheMissNotices", onCollapseChangelogChange: "collapseChangelog",
|
|
2288
2437
|
onEnableInstallTelemetryChange: "enableInstallTelemetry", onQuietStartupChange: "quietStartup",
|
|
@@ -2483,7 +2632,8 @@ function sameBlockContent(left, right) {
|
|
|
2483
2632
|
&& left.status === right.status
|
|
2484
2633
|
&& left.title === right.title
|
|
2485
2634
|
&& left.text === right.text
|
|
2486
|
-
&& sameValue(left.payload, right.payload)
|
|
2635
|
+
&& sameValue(left.payload, right.payload)
|
|
2636
|
+
&& sameValue(left.imageReferences ?? [], right.imageReferences ?? []);
|
|
2487
2637
|
}
|
|
2488
2638
|
function sameValue(left, right) {
|
|
2489
2639
|
if (left === right)
|
|
@@ -13,6 +13,7 @@ export declare const REQUIRED_PI_CAPABILITY_OPERATIONS: Readonly<{
|
|
|
13
13
|
readonly workflows: readonly ["workflow.route", "workflow.validate", "workflow.diagnostics"];
|
|
14
14
|
readonly disposal: readonly ["subscription.dispose", "session.dispose", "services.cleanup"];
|
|
15
15
|
}>;
|
|
16
|
+
/** Identifies one required Pi capability operation that differs from the accepted integration contract. */
|
|
16
17
|
export declare class PiCapabilityCompatibilityError extends Error {
|
|
17
18
|
readonly packageVersion: string;
|
|
18
19
|
readonly capability: string;
|
|
@@ -29,6 +30,7 @@ export interface PiUpgradeConformanceReport {
|
|
|
29
30
|
readonly commandSurface: readonly string[];
|
|
30
31
|
readonly capabilities: readonly PiCapabilityConformanceResult[];
|
|
31
32
|
}
|
|
33
|
+
/** Identifies the public Pi SDK stage that failed during upgrade conformance. */
|
|
32
34
|
export declare class PiUpgradeConformanceError extends Error {
|
|
33
35
|
readonly stage: "exports" | "services" | "session";
|
|
34
36
|
constructor(stage: "exports" | "services" | "session", cause: unknown);
|
|
@@ -14,6 +14,7 @@ export const REQUIRED_PI_CAPABILITY_OPERATIONS = Object.freeze({
|
|
|
14
14
|
workflows: ["workflow.route", "workflow.validate", "workflow.diagnostics"],
|
|
15
15
|
disposal: ["subscription.dispose", "session.dispose", "services.cleanup"],
|
|
16
16
|
});
|
|
17
|
+
/** Identifies one required Pi capability operation that differs from the accepted integration contract. */
|
|
17
18
|
export class PiCapabilityCompatibilityError extends Error {
|
|
18
19
|
packageVersion;
|
|
19
20
|
capability;
|
|
@@ -26,6 +27,7 @@ export class PiCapabilityCompatibilityError extends Error {
|
|
|
26
27
|
this.name = "PiCapabilityCompatibilityError";
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
/** Identifies the public Pi SDK stage that failed during upgrade conformance. */
|
|
29
31
|
export class PiUpgradeConformanceError extends Error {
|
|
30
32
|
stage;
|
|
31
33
|
constructor(stage, cause) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Apply the profile's HTTP timeout to npm undici and its fetch globals. */
|
|
2
|
+
export declare function configureOwnedHttpDispatcher(timeoutMs: number): void;
|
|
3
|
+
/** Test and diagnostics seam; reports configured semantics, not the max-int implementation detail. */
|
|
4
|
+
export declare function configuredOwnedHttpIdleTimeoutMs(): number | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Provenance: mechanically adapted from Pi commit 914cf14
|
|
2
|
+
// packages/coding-agent/src/core/http-dispatcher.ts (MIT).
|
|
3
|
+
// Local modifications: expose only A1's owned timeout seam and retain no private Pi imports.
|
|
4
|
+
import { EnvHttpProxyAgent, install, setGlobalDispatcher } from "undici";
|
|
5
|
+
const MAX_DISABLED_TIMEOUT_MS = 2_147_483_647;
|
|
6
|
+
let configuredTimeoutMs = null;
|
|
7
|
+
/** Apply the profile's HTTP timeout to npm undici and its fetch globals. */
|
|
8
|
+
export function configureOwnedHttpDispatcher(timeoutMs) {
|
|
9
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 0)
|
|
10
|
+
throw new TypeError("HTTP idle timeout is invalid");
|
|
11
|
+
const effectiveTimeoutMs = timeoutMs === 0 ? MAX_DISABLED_TIMEOUT_MS : timeoutMs;
|
|
12
|
+
const dispatcher = new EnvHttpProxyAgent({
|
|
13
|
+
allowH2: false,
|
|
14
|
+
bodyTimeout: effectiveTimeoutMs,
|
|
15
|
+
headersTimeout: effectiveTimeoutMs,
|
|
16
|
+
connect: { autoSelectFamilyAttemptTimeout: 2_000 },
|
|
17
|
+
});
|
|
18
|
+
setGlobalDispatcher(dispatcher);
|
|
19
|
+
install?.();
|
|
20
|
+
configuredTimeoutMs = timeoutMs;
|
|
21
|
+
}
|
|
22
|
+
/** Test and diagnostics seam; reports configured semantics, not the max-int implementation detail. */
|
|
23
|
+
export function configuredOwnedHttpIdleTimeoutMs() {
|
|
24
|
+
return configuredTimeoutMs;
|
|
25
|
+
}
|
|
@@ -4,6 +4,9 @@ export * from "./runtime-integration.js";
|
|
|
4
4
|
export * from "./session-integration.js";
|
|
5
5
|
export * from "./model-auth-integration.js";
|
|
6
6
|
export * from "./settings-integration.js";
|
|
7
|
+
export * from "./settings-effects.js";
|
|
8
|
+
export * from "./project-trust-preflight.js";
|
|
9
|
+
export * from "./http-dispatcher.js";
|
|
7
10
|
export * from "./package-integration.js";
|
|
8
11
|
export * from "./resource-extension-integration.js";
|
|
9
12
|
export * from "./workflow-controllers.js";
|