@timurproko/a1 0.1.8-dev.182 → 0.1.8-dev.218
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/bin/cli.js +2 -2
- package/bin/sync-pi-tui-proxy.js +1 -1
- package/bin/ui.js +1 -1
- 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.js +1 -1
- package/dist/composition/settings-route-host.js +6 -4
- 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/project-trust-prompt.d.ts +11 -6
- package/dist/features/owned-ui/project-trust-prompt.js +134 -17
- package/dist/features/owned-ui/settings-app.js +47 -50
- 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-footer-status.d.ts +1 -1
- package/dist/integrations/pi/components/shell-footer-status.js +8 -7
- package/dist/integrations/pi/components/shell-shared-facade.js +1 -1
- package/dist/integrations/pi/engine/adapter.d.ts +7 -0
- package/dist/integrations/pi/engine/adapter.js +37 -35
- 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.js +1 -1
- 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.js +1 -1
- 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/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 +13 -2
- package/dist/integrations/pi/engine/settings-effects.js +62 -42
- package/dist/integrations/pi/engine/settings-integration.js +4 -4
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +1 -0
- package/dist/integrations/pi/engine/workflow-controllers.js +1 -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 +1 -1
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +30 -2
- package/dist/integrations/pi/session-ui/session-shell-root.js +133 -72
- package/dist/integrations/pi/session-ui/session-shell.d.ts +9 -2
- package/dist/integrations/pi/session-ui/session-shell.js +112 -37
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +44 -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.js +6 -6
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +2 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +138 -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 +3 -3
- package/dist/native/darwin-arm64/process-guardian +0 -0
- 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 +0 -5
- package/dist/ui/components/spans.js +3 -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 +0 -2
- package/dist/ui/settings/sections.js +10 -16
- package/dist/ui/settings/session.js +5 -4
- 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 +1 -1
- package/docs/architecture/ui-reference-provenance.md +23 -3
- package/docs/ci-release-runbook.md +48 -4
- package/docs/manual-owned-ui-checkpoint.md +28 -1
- package/docs/manual-terminal-colour-check.md +4 -3
- package/package.json +7 -2
|
@@ -96,18 +96,18 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
96
96
|
await removeEndpointArtifacts(owner.paths.endpointMetadataPath, owner.paths.endpoint);
|
|
97
97
|
return { priorActiveVersion };
|
|
98
98
|
}
|
|
99
|
-
//
|
|
99
|
+
// Rationale: leaving sessions alone is the expected outcome, and saying so mid-update tears
|
|
100
100
|
// the progress bar; only ending a session (below) is worth interrupting it for.
|
|
101
101
|
if (plan === "leave-running")
|
|
102
102
|
return { priorActiveVersion };
|
|
103
|
-
//
|
|
103
|
+
// Rationale: say whose work is ending before it ends.
|
|
104
104
|
const live = endpoint.ownership.liveInstanceIds.length;
|
|
105
105
|
if (live > 0) {
|
|
106
106
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`ending ${live === 1 ? "one session" : `${live} sessions`} that run from the installation being replaced; a session started by an installed release would have been left alone.`)}\n`);
|
|
107
107
|
}
|
|
108
108
|
const identity = await requestUpdateShutdown(endpoint, targetVersion, 2_000);
|
|
109
109
|
if (!identity.accepted && processIsAlive(endpoint.pid)) {
|
|
110
|
-
//
|
|
110
|
+
// Security: explicit update consent permits bounded cleanup of an authenticated
|
|
111
111
|
// older owner that predates the update-shutdown message.
|
|
112
112
|
const cleanup = await cleanupVerifiedOwner(endpoint, { allowLiveInstances: true, reason: "legacy-mutable-install" });
|
|
113
113
|
if (!cleanup.terminated)
|
|
@@ -133,7 +133,7 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
133
133
|
await rename(probe, packageRoot);
|
|
134
134
|
}
|
|
135
135
|
catch (error) {
|
|
136
|
-
//
|
|
136
|
+
// Invariant: best-effort rollback runs if the first rename succeeded and the second did not.
|
|
137
137
|
await rename(probe, packageRoot).catch(() => { });
|
|
138
138
|
throw new Error(PRODUCT_TEXT.diagnostic(`package remains locked after verified shutdown: ${errorMessage(error)}`));
|
|
139
139
|
}
|
|
@@ -214,7 +214,7 @@ function createUpdateProgress(output, enabled) {
|
|
|
214
214
|
draw();
|
|
215
215
|
if (creepTo <= current)
|
|
216
216
|
return;
|
|
217
|
-
//
|
|
217
|
+
// Rationale: creep asymptotically toward (but never reach) the next milestone so
|
|
218
218
|
// long opaque phases such as npm install still show visible motion. The
|
|
219
219
|
// ceiling stays a whole point below the milestone: settling on `creepTo`
|
|
220
220
|
// itself would render as that milestone and make arriving at it invisible,
|
|
@@ -225,7 +225,7 @@ function createUpdateProgress(output, enabled) {
|
|
|
225
225
|
}, PROGRESS_TICK_MS);
|
|
226
226
|
timer.unref?.();
|
|
227
227
|
},
|
|
228
|
-
//
|
|
228
|
+
// Rationale: the bar exists to say the update is still moving. Once it has finished
|
|
229
229
|
// there is a better line to occupy that row — the one naming what is now
|
|
230
230
|
// installed — so the bar gives the row back rather than leaving a full
|
|
231
231
|
// meter above a message that already implies it.
|
|
@@ -283,7 +283,7 @@ async function resolveRequestedPreview(runner, requested, output) {
|
|
|
283
283
|
const versions = (Array.isArray(published) ? published : [published]).filter((value) => typeof value === "string");
|
|
284
284
|
const exact = versions.find(version => version === requested);
|
|
285
285
|
if (exact !== undefined) {
|
|
286
|
-
//
|
|
286
|
+
// Rationale: naming a release here would install it through the preview path, which is a
|
|
287
287
|
// different command with a different meaning.
|
|
288
288
|
if (!exact.includes("-dev.")) {
|
|
289
289
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`${exact} is a release, not a preview; run ${PRODUCT_TEXT.commandName} update to move to the current release.`)}\n`);
|
|
@@ -336,7 +336,7 @@ export async function runSelfUpdate(options) {
|
|
|
336
336
|
if (resolved.version === null)
|
|
337
337
|
return resolved.exitCode;
|
|
338
338
|
const targetVersion = resolved.version;
|
|
339
|
-
//
|
|
339
|
+
// Rationale: no full stop after a version: it already ends in a dot-separated identifier,
|
|
340
340
|
// and a trailing one reads as part of the version rather than as punctuation.
|
|
341
341
|
output.stdout(`${PRODUCT_TEXT.commandName} update: ${runningVersion} → ${targetVersion}\n`);
|
|
342
342
|
const progress = createUpdateProgress(output, options.progress ?? (options.output === undefined && process.stdout.isTTY === true));
|
|
@@ -375,7 +375,7 @@ export async function runSelfUpdate(options) {
|
|
|
375
375
|
output.stdout(`${PRODUCT_TEXT.commandName} is up to date — no update needed.\n`);
|
|
376
376
|
return 0;
|
|
377
377
|
}
|
|
378
|
-
//
|
|
378
|
+
// Rationale: the bar first appears here so a no-change run never flashes it.
|
|
379
379
|
progress.set(3, 15);
|
|
380
380
|
const cohortState = await new CohortStateStore(paths.dataDir).read();
|
|
381
381
|
transaction = await transactionStore.begin({
|
|
@@ -403,7 +403,7 @@ export async function runSelfUpdate(options) {
|
|
|
403
403
|
}
|
|
404
404
|
transaction = await transactionStore.advance("package-installed");
|
|
405
405
|
}
|
|
406
|
-
// npm 12 blocks install scripts unless allowScripts covers the package, so
|
|
406
|
+
// Compatibility: npm 12 blocks install scripts unless allowScripts covers the package, so
|
|
407
407
|
// the postinstall that points the #pi-tui proxy at the tree npm just built
|
|
408
408
|
// may never have run. Run the shipped script directly: the proxy must be
|
|
409
409
|
// correct before the release store copies this tree. A failure is reported
|
|
@@ -417,7 +417,7 @@ export async function runSelfUpdate(options) {
|
|
|
417
417
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not point the #pi-tui proxy at the installed tree: ${errorMessage(error)}`)}\n`);
|
|
418
418
|
}
|
|
419
419
|
progress.set(70, 75);
|
|
420
|
-
//
|
|
420
|
+
// Concurrency: ownership can be reacquired after an interrupted installation (for
|
|
421
421
|
// example, if bare A1 is launched before the update is resumed). Recheck
|
|
422
422
|
// immediately before activation so recovery cannot start a second cohort.
|
|
423
423
|
await measure("ownership-release", async () => { await lifecycle.shutdownVerifiedOwners(targetVersion); });
|
|
@@ -530,7 +530,7 @@ async function rollbackPriorCohort(dataDir, environment, priorReleaseId) {
|
|
|
530
530
|
}
|
|
531
531
|
const release = await readMaterializedRelease(prior.releaseRoot);
|
|
532
532
|
const paths = resolveProductPaths(environment);
|
|
533
|
-
//
|
|
533
|
+
// Invariant: rollback re-points the active reference and starts the prior cohort on its own endpoint;
|
|
534
534
|
// a cohort that survived the update keeps serving the work it already had.
|
|
535
535
|
await startSupervisor(release, environment);
|
|
536
536
|
await waitForVerifiedEndpoint(resolveCohortEndpoint(paths, release.releaseId, environment).endpointMetadataPath, release, 8_000);
|
|
@@ -14,6 +14,7 @@ export interface StoredWorkspaceAgent {
|
|
|
14
14
|
readonly agent: ManagedAgentDescriptor;
|
|
15
15
|
readonly presentation: WorkspaceAgentPresentation;
|
|
16
16
|
}
|
|
17
|
+
/** Owns WAL-backed control persistence and reconciles prior-boot records before current use. */
|
|
17
18
|
export declare class ControlStore {
|
|
18
19
|
#private;
|
|
19
20
|
readonly bootNonce: string | null;
|
|
@@ -6,6 +6,7 @@ import { assertManagedAgentDescriptor, assertRecoveryAuthority, assertTerminalSe
|
|
|
6
6
|
import { assertLaunchInstance, assertLaunchInstanceOutcome, assertNativeProcessIdentity, assertProcessContainmentIdentity, } from "../lifecycle/index.js";
|
|
7
7
|
export const DEFAULT_WORKSPACE_ID = "workspace-default";
|
|
8
8
|
const INITIAL_WORKSPACE_ID = DEFAULT_WORKSPACE_ID;
|
|
9
|
+
/** Owns WAL-backed control persistence and reconciles prior-boot records before current use. */
|
|
9
10
|
export class ControlStore {
|
|
10
11
|
bootNonce;
|
|
11
12
|
database;
|
|
@@ -33,6 +33,7 @@ export type StructuredBackpressureReleaseResult = {
|
|
|
33
33
|
readonly code: "unknown-lease" | "invalid-request";
|
|
34
34
|
readonly diagnostic: string;
|
|
35
35
|
};
|
|
36
|
+
/** Issues bounded resource leases and selects the negotiated backpressure action on exhaustion. */
|
|
36
37
|
export declare class StructuredBackpressureController {
|
|
37
38
|
#private;
|
|
38
39
|
readonly adapterId: string;
|
|
@@ -38,6 +38,7 @@ export type StructuredCommandOutcomeResult = {
|
|
|
38
38
|
readonly code: string;
|
|
39
39
|
readonly diagnostic: string;
|
|
40
40
|
};
|
|
41
|
+
/** Tracks structured commands by correlation identity through one idempotent terminal outcome. */
|
|
41
42
|
export declare class StructuredCommandTracker {
|
|
42
43
|
#private;
|
|
43
44
|
readonly agentId: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assertStructuredCapability, assertWorkspaceCommand, } from "../../contracts/workspace/index.js";
|
|
2
|
+
/** Tracks structured commands by correlation identity through one idempotent terminal outcome. */
|
|
2
3
|
export class StructuredCommandTracker {
|
|
3
4
|
agentId;
|
|
4
5
|
#capability;
|
|
@@ -30,6 +30,7 @@ export type StructuredReconnectionResult = {
|
|
|
30
30
|
readonly code: string;
|
|
31
31
|
readonly diagnostic: string;
|
|
32
32
|
};
|
|
33
|
+
/** Accepts a recovery boundary once after validating negotiated identity, proof, and protocol continuity. */
|
|
33
34
|
export declare class StructuredReconnectionManager {
|
|
34
35
|
#private;
|
|
35
36
|
constructor(capability: StructuredCapabilityContract);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { WORKSPACE_CONTRACT_VERSION, assertRecoveryAuthority, assertStructuredAgentSnapshot, assertStructuredCapability, } from "../../contracts/workspace/index.js";
|
|
2
2
|
import { StructuredEventReducer } from "./state.js";
|
|
3
|
+
/** Accepts a recovery boundary once after validating negotiated identity, proof, and protocol continuity. */
|
|
3
4
|
export class StructuredReconnectionManager {
|
|
4
5
|
#capability;
|
|
5
6
|
#acceptedBoundaries = new Set();
|
|
@@ -44,6 +44,7 @@ export type StructuredSnapshotApplyResult = {
|
|
|
44
44
|
readonly code: string;
|
|
45
45
|
readonly diagnostic: string;
|
|
46
46
|
};
|
|
47
|
+
/** Applies ordered structured events and snapshots while exposing gaps as explicit resynchronization. */
|
|
47
48
|
export declare class StructuredEventReducer {
|
|
48
49
|
#private;
|
|
49
50
|
readonly agentId: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assertStructuredAgentSnapshot, assertStructuredCapability, assertWorkspaceEvent, } from "../../contracts/workspace/index.js";
|
|
2
|
+
/** Applies ordered structured events and snapshots while exposing gaps as explicit resynchronization. */
|
|
2
3
|
export class StructuredEventReducer {
|
|
3
4
|
agentId;
|
|
4
5
|
#capability;
|
|
@@ -19,7 +19,7 @@ export async function runSupervisor() {
|
|
|
19
19
|
throw new Error(PRODUCT_TEXT.diagnostic("supervisor must be launched from a verified immutable release"));
|
|
20
20
|
const release = await readCertifiedReleaseManifest({ releaseRoot, releaseId, contentDigest }, resolve(paths.dataDir, "releases"));
|
|
21
21
|
await assertImmutableExecutionRoot(release, paths.dataDir);
|
|
22
|
-
//
|
|
22
|
+
// Protocol: one endpoint per cohort: a superseded cohort keeps serving what it already has while the
|
|
23
23
|
// installed release listens on its own address.
|
|
24
24
|
paths = { ...productPaths, ...resolveCohortEndpoint(productPaths, release.releaseId) };
|
|
25
25
|
const bootNonce = randomUUID();
|
|
@@ -2,6 +2,7 @@ import { type SupervisorSnapshot } from "../lifecycle/index.js";
|
|
|
2
2
|
import { type MaterializedRelease } from "../release/index.js";
|
|
3
3
|
import { ControlStore } from "../storage/index.js";
|
|
4
4
|
import { type ProductPaths } from "./paths.js";
|
|
5
|
+
/** Owns one release-cohort endpoint and the authenticated launch instances registered through it. */
|
|
5
6
|
export declare class SupervisorServer {
|
|
6
7
|
#private;
|
|
7
8
|
readonly store: ControlStore;
|
|
@@ -8,6 +8,7 @@ import { processIsAlive } from "../release/index.js";
|
|
|
8
8
|
import { ControlStore } from "../storage/index.js";
|
|
9
9
|
import { resolveProductPaths } from "./paths.js";
|
|
10
10
|
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
11
|
+
/** Owns one release-cohort endpoint and the authenticated launch instances registered through it. */
|
|
11
12
|
export class SupervisorServer {
|
|
12
13
|
store;
|
|
13
14
|
release;
|
|
@@ -90,10 +91,7 @@ export class SupervisorServer {
|
|
|
90
91
|
this.#supersededPoll = poll;
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
-
* Notices that another release has become the one new sessions start on. Nothing is
|
|
95
|
-
* interrupted by that: this cohort finishes what it is holding and then leaves.
|
|
96
|
-
*/
|
|
94
|
+
// Invariant: superseding a cohort never interrupts its held instances; it retires only when empty.
|
|
97
95
|
async #refreshCohortRole() {
|
|
98
96
|
if (this.#closing || !this.readActiveReleaseId)
|
|
99
97
|
return;
|
|
@@ -327,7 +325,7 @@ export class SupervisorServer {
|
|
|
327
325
|
this.#uncertainInstances.delete(stored.id);
|
|
328
326
|
this.#unbindOwner(stored.id, socket);
|
|
329
327
|
this.#mutated();
|
|
330
|
-
//
|
|
328
|
+
// Invariant: the last session on a superseded cohort has left; there is nothing here to keep.
|
|
331
329
|
if (this.#superseded && this.#instances.size === 0)
|
|
332
330
|
void this.retire();
|
|
333
331
|
}
|
|
@@ -421,7 +419,7 @@ export class SupervisorServer {
|
|
|
421
419
|
const deadline = Date.now() + timeoutMs;
|
|
422
420
|
while (Date.now() < deadline) {
|
|
423
421
|
if (this.#instances.size === 0) {
|
|
424
|
-
//
|
|
422
|
+
// Concurrency: allow the terminal command result to flush before closing owner sockets.
|
|
425
423
|
await new Promise(resolvePromise => setTimeout(resolvePromise, 25));
|
|
426
424
|
return this.#instances.size === 0;
|
|
427
425
|
}
|
|
@@ -10,6 +10,7 @@ export interface PiComponentConformanceReport {
|
|
|
10
10
|
readonly componentResults: readonly PiComponentConformanceResult[];
|
|
11
11
|
readonly componentFamilies: readonly string[];
|
|
12
12
|
}
|
|
13
|
+
/** Identifies the Pi presentation-conformance stage that failed against the pinned component surface. */
|
|
13
14
|
export declare class PiComponentConformanceError extends Error {
|
|
14
15
|
readonly stage: "theme" | "components";
|
|
15
16
|
constructor(stage: "theme" | "components", cause: unknown);
|
|
@@ -5,6 +5,7 @@ import { AssistantMessageComponent, ExtensionSelectorComponent, initTheme, Login
|
|
|
5
5
|
import { OWNED_UI_CONTRACT_VERSION } from "../../../contracts/owned-ui/index.js";
|
|
6
6
|
import { createTuiFacade, validatedAssistantMessage } from "./shell-components.js";
|
|
7
7
|
import { PRODUCT_IDENTITY } from "../../../product-identity.js";
|
|
8
|
+
/** Identifies the Pi presentation-conformance stage that failed against the pinned component surface. */
|
|
8
9
|
export class PiComponentConformanceError extends Error {
|
|
9
10
|
stage;
|
|
10
11
|
constructor(stage, cause) {
|
|
@@ -2,6 +2,6 @@ import type { OwnedUiSessionViewModel } from "../../../contracts/owned-ui/index.
|
|
|
2
2
|
import { type PiShellViewComponentPort, type PiShellStatusPort, type PiShellQueuedInputPort, type PiShellHeaderPort, type PiShellResourceEntry, type PiShellLoadedResourcesPort, type PiShellHeaderOptions, type PiShellEditorOptions } from "./shell-shared-facade.js";
|
|
3
3
|
export declare function createPiShellHeader(options?: PiShellHeaderOptions): PiShellHeaderPort;
|
|
4
4
|
export declare function createPiShellLoadedResources(resources: readonly PiShellResourceEntry[], initialExpanded?: boolean): PiShellLoadedResourcesPort;
|
|
5
|
-
export declare function createPiShellStatus(view: OwnedUiSessionViewModel, runtime?: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">): PiShellStatusPort;
|
|
5
|
+
export declare function createPiShellStatus(view: OwnedUiSessionViewModel, formatProgressStatus: (message: string) => string, runtime?: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">): PiShellStatusPort;
|
|
6
6
|
export declare function createPiShellFooter(view: OwnedUiSessionViewModel, cwd: string): PiShellViewComponentPort;
|
|
7
7
|
export declare function createPiQueuedInputStatus(submissions: readonly string[], presentation?: "pinned" | "custom-viewport"): PiShellQueuedInputPort;
|
|
@@ -67,12 +67,12 @@ export function createPiShellLoadedResources(resources, initialExpanded = false)
|
|
|
67
67
|
invalidate() { },
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
|
-
export function createPiShellStatus(view, runtime) {
|
|
70
|
+
export function createPiShellStatus(view, formatProgressStatus, runtime) {
|
|
71
71
|
ensureTheme();
|
|
72
72
|
const statusUi = createTuiFacade(runtime ?? { getColumns: () => 80, getRows: () => 24, requestRender() { } });
|
|
73
73
|
let workingOverride;
|
|
74
74
|
let outputPad = PINNED_PI_LAYOUT.outputPad;
|
|
75
|
-
let component = statusComponent(view, statusUi, workingOverride, outputPad);
|
|
75
|
+
let component = statusComponent(view, statusUi, workingOverride, outputPad, formatProgressStatus);
|
|
76
76
|
let signature = statusSignature(view, workingOverride, outputPad);
|
|
77
77
|
const rebuild = () => {
|
|
78
78
|
const nextSignature = statusSignature(view, workingOverride, outputPad);
|
|
@@ -81,7 +81,7 @@ export function createPiShellStatus(view, runtime) {
|
|
|
81
81
|
if (component !== undefined && "dispose" in component && typeof component.dispose === "function")
|
|
82
82
|
component.dispose();
|
|
83
83
|
signature = nextSignature;
|
|
84
|
-
component = statusComponent(view, statusUi, workingOverride, outputPad);
|
|
84
|
+
component = statusComponent(view, statusUi, workingOverride, outputPad, formatProgressStatus);
|
|
85
85
|
};
|
|
86
86
|
return {
|
|
87
87
|
render: width => component?.render(width) ?? [],
|
|
@@ -126,9 +126,10 @@ export function createPiQueuedInputStatus(submissions, presentation = "pinned")
|
|
|
126
126
|
},
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
|
-
function statusComponent(view, ui, workingOverride, outputPad) {
|
|
130
|
-
if (view.lifecycle === "busy")
|
|
131
|
-
return new WorkingStatusIndicator(ui, workingOverride ?? view.status.workingMessage ?? "Working
|
|
129
|
+
function statusComponent(view, ui, workingOverride, outputPad, formatProgressStatus) {
|
|
130
|
+
if (view.lifecycle === "busy") {
|
|
131
|
+
return new WorkingStatusIndicator(ui, formatProgressStatus(workingOverride ?? view.status.workingMessage ?? "Working"));
|
|
132
|
+
}
|
|
132
133
|
if (view.lifecycle === "failed") {
|
|
133
134
|
return new Text(piTheme().fg("error", view.status.diagnostics.at(-1) ?? "Session failed"), outputPad, 0);
|
|
134
135
|
}
|
|
@@ -149,7 +150,7 @@ function queuedInputText(submissions, presentation) {
|
|
|
149
150
|
}
|
|
150
151
|
const messages = submissions.map(submission => theme.fg("dim", `Steering: ${submission.replaceAll("\n", " ⏎ ")}`));
|
|
151
152
|
const dequeueHint = theme.fg("dim", "↳ Alt+Up to edit all queued messages");
|
|
152
|
-
//
|
|
153
|
+
// Compatibility: the custom viewport matches Pi's interactive queue presentation while the
|
|
153
154
|
// comparison shell remains byte-for-byte compatible with its pinned fixture.
|
|
154
155
|
return ["", ...messages, dequeueHint].join("\n");
|
|
155
156
|
}
|
|
@@ -3,7 +3,7 @@ import { KeybindingsManager, } from "./upstream/adjacent/core/keybindings.js";
|
|
|
3
3
|
import { ensurePiTheme, } from "./theme.js";
|
|
4
4
|
/** Terminal-cell width authority used by Pi-rendered component rows. */
|
|
5
5
|
export const piShellVisibleWidth = visibleWidth;
|
|
6
|
-
//
|
|
6
|
+
// Provenance: pinned from packages/coding-agent/src/core/slash-commands.ts at 914cf14.
|
|
7
7
|
export function createTuiFacade(options) {
|
|
8
8
|
const children = [];
|
|
9
9
|
const terminal = {
|
|
@@ -46,6 +46,11 @@ export interface PiTreeSelectorContext {
|
|
|
46
46
|
readonly skipSummaryPrompt: boolean;
|
|
47
47
|
readonly appendLabelChange: (entryId: string, label: string | undefined) => void;
|
|
48
48
|
}
|
|
49
|
+
export interface PiSessionResumeMetadata {
|
|
50
|
+
readonly sessionId: string;
|
|
51
|
+
readonly sessionDir: string;
|
|
52
|
+
readonly usesDefaultSessionDir: boolean;
|
|
53
|
+
}
|
|
49
54
|
export interface PiSessionSelectorContext {
|
|
50
55
|
readonly currentSessionFilePath: string | undefined;
|
|
51
56
|
readonly loadCurrentSessions: (onProgress?: (loaded: number, total: number) => void) => Promise<SessionInfo[]>;
|
|
@@ -116,6 +121,7 @@ export interface AdapterCommandResult {
|
|
|
116
121
|
readonly outcome: OwnedUiCommandOutcome;
|
|
117
122
|
readonly diagnostic: string | null;
|
|
118
123
|
}
|
|
124
|
+
/** Owns the pinned Pi session lifecycle and translates its events into the neutral agent-engine contract. */
|
|
119
125
|
export declare class PiEngineAdapter {
|
|
120
126
|
#private;
|
|
121
127
|
constructor(options?: PiEngineAdapterOptions);
|
|
@@ -125,6 +131,7 @@ export declare class PiEngineAdapter {
|
|
|
125
131
|
get agentDir(): string;
|
|
126
132
|
resolveTranscriptImage(assetId: string): OwnedUiImageAttachment | null;
|
|
127
133
|
currentSessionFile(): string | null;
|
|
134
|
+
currentSessionResumeMetadata(): PiSessionResumeMetadata | null;
|
|
128
135
|
get disposed(): boolean;
|
|
129
136
|
start(): Promise<OwnedUiSessionViewModel>;
|
|
130
137
|
onEvent(listener: (event: OwnedUiEvent) => void): () => void;
|
|
@@ -18,7 +18,7 @@ const execFileAsync = promisify(execFile);
|
|
|
18
18
|
* that a streaming burst never holds input, large enough that an ordinary turn is one
|
|
19
19
|
* batch.
|
|
20
20
|
*/
|
|
21
|
-
//
|
|
21
|
+
// Performance: deliver at most one engine event per event-loop turn. Transcript updates can
|
|
22
22
|
// be expensive in long sessions; a larger synchronous batch starves terminal
|
|
23
23
|
// input and makes an in-progress mouse selection appear frozen.
|
|
24
24
|
const EVENT_DELIVERY_BATCH = 1;
|
|
@@ -29,6 +29,7 @@ const DEFAULT_SURFACE = {
|
|
|
29
29
|
focusedRegion: "editor",
|
|
30
30
|
hardwareCursor: false,
|
|
31
31
|
};
|
|
32
|
+
/** Owns the pinned Pi session lifecycle and translates its events into the neutral agent-engine contract. */
|
|
32
33
|
export class PiEngineAdapter {
|
|
33
34
|
#runtimeFactory;
|
|
34
35
|
#checkPackageUpdates;
|
|
@@ -92,7 +93,6 @@ export class PiEngineAdapter {
|
|
|
92
93
|
#projectTrustPrompt;
|
|
93
94
|
#settingsIntegration;
|
|
94
95
|
#settingsIntegrationManager;
|
|
95
|
-
/** Lists the themes installed on this machine, when the caller supplies one. */
|
|
96
96
|
#availableThemes;
|
|
97
97
|
constructor(options = {}) {
|
|
98
98
|
this.#cwd = options.cwd ?? process.cwd();
|
|
@@ -129,6 +129,22 @@ export class PiEngineAdapter {
|
|
|
129
129
|
const value = this.#session?.sessionManager?.getSessionFile?.();
|
|
130
130
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
131
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
|
+
}
|
|
132
148
|
get disposed() {
|
|
133
149
|
return this.#disposed;
|
|
134
150
|
}
|
|
@@ -502,7 +518,7 @@ export class PiEngineAdapter {
|
|
|
502
518
|
} },
|
|
503
519
|
});
|
|
504
520
|
this.#settingsIntegration.bindOwner("startup", {
|
|
505
|
-
//
|
|
521
|
+
// Invariant: deferred application is the owner operation: the next preflight reads
|
|
506
522
|
// the persisted default before constructing project-backed services.
|
|
507
523
|
defaultProjectTrust: { apply() { } },
|
|
508
524
|
collapseChangelog: { apply() { } },
|
|
@@ -541,7 +557,7 @@ export class PiEngineAdapter {
|
|
|
541
557
|
httpIdleTimeoutMs: { apply: value => {
|
|
542
558
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
|
|
543
559
|
throw new TypeError("HTTP idle timeout is invalid");
|
|
544
|
-
//
|
|
560
|
+
// Invariant: provider streaming reads the manager per request; global fetch uses
|
|
545
561
|
// the matching owned dispatcher and zero maps to disabled semantics.
|
|
546
562
|
configureOwnedHttpDispatcher(value);
|
|
547
563
|
settings.setHttpIdleTimeoutMs(value);
|
|
@@ -1550,11 +1566,7 @@ export class PiEngineAdapter {
|
|
|
1550
1566
|
this.#emitView();
|
|
1551
1567
|
}
|
|
1552
1568
|
}
|
|
1553
|
-
|
|
1554
|
-
* Replaces the transcript and the index that finds a block by its identifier. Every
|
|
1555
|
-
* lookup goes through the index, so streaming a chunk costs the same in a long session
|
|
1556
|
-
* as in a new one.
|
|
1557
|
-
*/
|
|
1569
|
+
// Performance: replacing the transcript rebuilds its index so block lookup stays constant-time.
|
|
1558
1570
|
#setTranscript(blocks) {
|
|
1559
1571
|
this.#transcript = blocks;
|
|
1560
1572
|
this.#transcriptIndex.clear();
|
|
@@ -1571,7 +1583,7 @@ export class PiEngineAdapter {
|
|
|
1571
1583
|
const index = this.#transcriptIndex.get(id);
|
|
1572
1584
|
return index === undefined ? undefined : this.#transcript[index];
|
|
1573
1585
|
}
|
|
1574
|
-
|
|
1586
|
+
// Invariant: the named work state is the only state a matching end may clear.
|
|
1575
1587
|
#enterWorkState(kind, message) {
|
|
1576
1588
|
const wasBusy = this.#lifecycle === "busy";
|
|
1577
1589
|
this.#statusKind = kind;
|
|
@@ -1581,21 +1593,16 @@ export class PiEngineAdapter {
|
|
|
1581
1593
|
this.#emitEvent({ type: "session-lifecycle", lifecycle: "busy", reason: null });
|
|
1582
1594
|
this.#emitEvent({ type: "status", status: this.#status });
|
|
1583
1595
|
}
|
|
1584
|
-
|
|
1585
|
-
* Ends one named state. A state the shell is not in is left alone, so a finished
|
|
1586
|
-
* compaction or retry cannot clear the working state it never replaced. While the run
|
|
1587
|
-
* continues, ending either of those returns to working rather than to idle.
|
|
1588
|
-
*/
|
|
1596
|
+
// Invariant: ending retry or compaction cannot clear a different active work state.
|
|
1589
1597
|
#endWorkState(kind) {
|
|
1590
1598
|
if (this.#statusKind !== kind)
|
|
1591
1599
|
return;
|
|
1592
1600
|
if (this.#agentRunActive) {
|
|
1593
|
-
this.#enterWorkState("working", "Working
|
|
1601
|
+
this.#enterWorkState("working", "Working");
|
|
1594
1602
|
return;
|
|
1595
1603
|
}
|
|
1596
1604
|
this.#leaveWorkStates();
|
|
1597
1605
|
}
|
|
1598
|
-
/** Leaves every work state and reports the session idle. */
|
|
1599
1606
|
#leaveWorkStates() {
|
|
1600
1607
|
this.#statusKind = null;
|
|
1601
1608
|
this.#lifecycle = "ready";
|
|
@@ -1606,7 +1613,7 @@ export class PiEngineAdapter {
|
|
|
1606
1613
|
#handlePiEvent(event) {
|
|
1607
1614
|
if (!isRecord(event) || typeof event.type !== "string")
|
|
1608
1615
|
return;
|
|
1609
|
-
//
|
|
1616
|
+
// Invariant: usage moves at message and lifecycle boundaries, not with stream chunks, so the
|
|
1610
1617
|
// two streaming event kinds keep the memo and everything else drops it.
|
|
1611
1618
|
if (event.type !== "message_update" && event.type !== "tool_execution_update")
|
|
1612
1619
|
this.#usageCache = undefined;
|
|
@@ -1614,7 +1621,7 @@ export class PiEngineAdapter {
|
|
|
1614
1621
|
case "agent_start":
|
|
1615
1622
|
this.#agentRunActive = true;
|
|
1616
1623
|
this.#emitEvent({ type: "agent-run-started" });
|
|
1617
|
-
this.#enterWorkState("working", "Working
|
|
1624
|
+
this.#enterWorkState("working", "Working");
|
|
1618
1625
|
return;
|
|
1619
1626
|
case "message_start":
|
|
1620
1627
|
this.#upsertMessageBlock(event.message, "live");
|
|
@@ -1623,7 +1630,7 @@ export class PiEngineAdapter {
|
|
|
1623
1630
|
const delta = isRecord(event.assistantMessageEvent) && typeof event.assistantMessageEvent.delta === "string"
|
|
1624
1631
|
? event.assistantMessageEvent.delta
|
|
1625
1632
|
: undefined;
|
|
1626
|
-
//
|
|
1633
|
+
// Invariant: the delta is folded in before the block is stored, so a chunk is one update to
|
|
1627
1634
|
// one block rather than a store without the delta followed by a store with it.
|
|
1628
1635
|
const blocks = this.#messageBlocks(event.message, "live", this.#transcript.length);
|
|
1629
1636
|
for (const [index, block] of blocks.entries()) {
|
|
@@ -1635,7 +1642,7 @@ export class PiEngineAdapter {
|
|
|
1635
1642
|
}
|
|
1636
1643
|
case "message_end":
|
|
1637
1644
|
this.#upsertMessageBlock(event.message, "finalized");
|
|
1638
|
-
//
|
|
1645
|
+
// Compatibility: preserve the same semantic boundary v2 counted. Transcript block
|
|
1639
1646
|
// finalization is intentionally not a substitute: rebuilds, retries,
|
|
1640
1647
|
// thinking parts, and tool rows can all finalize independently.
|
|
1641
1648
|
if (isRecord(event.message) && event.message.role === "assistant") {
|
|
@@ -1651,7 +1658,7 @@ export class PiEngineAdapter {
|
|
|
1651
1658
|
return;
|
|
1652
1659
|
case "tool_execution_start":
|
|
1653
1660
|
case "tool_execution_end": {
|
|
1654
|
-
//
|
|
1661
|
+
// Concurrency: the end supersedes any update still waiting on the coalescing timer.
|
|
1655
1662
|
const toolCallId = stringValue(event.toolCallId);
|
|
1656
1663
|
if (toolCallId !== undefined)
|
|
1657
1664
|
this.#pendingToolUpdates.delete(toolCallId);
|
|
@@ -1672,7 +1679,7 @@ export class PiEngineAdapter {
|
|
|
1672
1679
|
this.#rebuildTranscript(finalMessages, "finalized");
|
|
1673
1680
|
else
|
|
1674
1681
|
this.#setTranscript(this.#transcript.map(block => block.status === "live" ? { ...block, status: "finalized" } : block));
|
|
1675
|
-
//
|
|
1682
|
+
// Compatibility: ending a turn leaves the working state, as the recorded pinned baseline does, but
|
|
1676
1683
|
// it leaves only that state: a compaction or retry being shown outlives the turn
|
|
1677
1684
|
// that ended under it. Settlement ends the run, and with it every state — the
|
|
1678
1685
|
// engine ends a turn for each continuation it makes and settles once.
|
|
@@ -1698,13 +1705,13 @@ export class PiEngineAdapter {
|
|
|
1698
1705
|
return;
|
|
1699
1706
|
}
|
|
1700
1707
|
case "auto_retry_start":
|
|
1701
|
-
this.#enterWorkState("retry", "Retrying
|
|
1708
|
+
this.#enterWorkState("retry", "Retrying");
|
|
1702
1709
|
return;
|
|
1703
1710
|
case "auto_retry_end":
|
|
1704
1711
|
this.#endWorkState("retry");
|
|
1705
1712
|
return;
|
|
1706
1713
|
case "compaction_start":
|
|
1707
|
-
this.#enterWorkState("compaction", "Compacting
|
|
1714
|
+
this.#enterWorkState("compaction", "Compacting");
|
|
1708
1715
|
return;
|
|
1709
1716
|
case "compaction_end":
|
|
1710
1717
|
this.#endWorkState("compaction");
|
|
@@ -1797,7 +1804,7 @@ export class PiEngineAdapter {
|
|
|
1797
1804
|
}
|
|
1798
1805
|
}
|
|
1799
1806
|
}
|
|
1800
|
-
//
|
|
1807
|
+
// Performance: an authoritative rebuild restates most of what is already there. Reusing the block
|
|
1801
1808
|
// that already says it keeps its revision, and with it the rows the shell rendered for
|
|
1802
1809
|
// it — otherwise every turn that ends re-renders the whole session.
|
|
1803
1810
|
this.#setTranscript(blocks.map(block => {
|
|
@@ -1976,12 +1983,7 @@ export class PiEngineAdapter {
|
|
|
1976
1983
|
}
|
|
1977
1984
|
return references;
|
|
1978
1985
|
}
|
|
1979
|
-
|
|
1980
|
-
* A busy tool streams far more output chunks than a terminal frame can show, and every
|
|
1981
|
-
* chunk restates the whole accumulated output. Keeping only the newest chunk per tool
|
|
1982
|
-
* and applying it on a short timer bounds the per-command work by frames rather than
|
|
1983
|
-
* by chunks, which is what keeps typed input and the spinner alive under the stream.
|
|
1984
|
-
*/
|
|
1986
|
+
// Performance: coalescing each tool to its newest chunk bounds work by frames, not stream events.
|
|
1985
1987
|
#coalesceToolExecutionUpdate(event) {
|
|
1986
1988
|
const toolCallId = stringValue(event.toolCallId);
|
|
1987
1989
|
if (!toolCallId)
|
|
@@ -2024,7 +2026,7 @@ export class PiEngineAdapter {
|
|
|
2024
2026
|
toolCallId,
|
|
2025
2027
|
toolName: stringValue(event.toolName) ?? "unknown",
|
|
2026
2028
|
arguments: jsonSummary(event.args),
|
|
2027
|
-
//
|
|
2029
|
+
// Performance: a partial result repeats the whole accumulated output on every chunk;
|
|
2028
2030
|
// summarizing it each time would cost quadratic work over the stream.
|
|
2029
2031
|
result: ended ? jsonSummary(source) : { summary: "", json: null },
|
|
2030
2032
|
partialResult: event.type === "tool_execution_update",
|
|
@@ -2037,7 +2039,7 @@ export class PiEngineAdapter {
|
|
|
2037
2039
|
const index = this.#transcriptIndex.get(block.id);
|
|
2038
2040
|
if (index !== undefined) {
|
|
2039
2041
|
const existing = this.#transcript[index];
|
|
2040
|
-
//
|
|
2042
|
+
// Performance: nothing is emitted for a block that repeats itself, and keeping the
|
|
2041
2043
|
// revision keeps the rows it already rendered.
|
|
2042
2044
|
if (existing !== undefined && sameBlockContent(existing, block))
|
|
2043
2045
|
return;
|
|
@@ -2154,7 +2156,7 @@ export class PiEngineAdapter {
|
|
|
2154
2156
|
}
|
|
2155
2157
|
}
|
|
2156
2158
|
deliveredSinceYield += 1;
|
|
2157
|
-
//
|
|
2159
|
+
// Concurrency: a microtask chain runs to exhaustion before the loop turns, so a streaming
|
|
2158
2160
|
// burst would hold typed input, pointer reports, and timed indicators until it
|
|
2159
2161
|
// drained. Yielding on a macrotask hands those their turn between batches.
|
|
2160
2162
|
if (deliveredSinceYield >= EVENT_DELIVERY_BATCH && this.#eventQueue.length > 0) {
|
|
@@ -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) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Provenance: mechanically adapted from Pi commit 914cf14
|
|
2
2
|
// packages/coding-agent/src/core/http-dispatcher.ts (MIT).
|
|
3
3
|
// Local modifications: expose only A1's owned timeout seam and retain no private Pi imports.
|
|
4
4
|
import { EnvHttpProxyAgent, install, setGlobalDispatcher } from "undici";
|
|
@@ -9,6 +9,7 @@ export interface PiModelAuthenticationOptions {
|
|
|
9
9
|
readonly timeoutMs?: number;
|
|
10
10
|
readonly scopedModelIds?: () => readonly string[] | undefined;
|
|
11
11
|
}
|
|
12
|
+
/** Adapts the pinned model runtime to neutral model selection and authentication operations. */
|
|
12
13
|
export declare class PiModelAuthenticationIntegration implements AgentModelPort, AgentAuthenticationPort {
|
|
13
14
|
#private;
|
|
14
15
|
private readonly options;
|