@timurproko/a1 0.2.7-dev.754 → 0.2.7-dev.772
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 +30 -0
- package/bin/cli.js +4 -0
- package/bin/guardian.js +5 -0
- package/bin/tab-launch-context.d.ts +26 -0
- package/bin/tab-launch-context.js +94 -0
- package/bin/ui.js +24 -6
- package/dist/app/session-shell/helper-pool.d.ts +3 -5
- package/dist/app/session-shell/helper-pool.js +3 -5
- package/dist/app/session-shell/session-shell-root.d.ts +28 -1
- package/dist/app/session-shell/session-shell-root.js +4 -3
- package/dist/app/session-shell/session-shell.js +149 -31
- package/dist/app/session-shell/session-viewport-controller.d.ts +1 -1
- package/dist/app/session-shell/session-viewport-controller.js +3 -3
- package/dist/app/session-shell/shell-host.d.ts +2 -0
- package/dist/app/session-shell/shell-host.js +20 -1
- package/dist/cli/dispatch.d.ts +11 -1
- package/dist/cli/dispatch.js +79 -5
- package/dist/cli/tabs-request.d.ts +7 -0
- package/dist/cli/tabs-request.js +1 -0
- package/dist/cli/tabs.d.ts +14 -0
- package/dist/cli/tabs.js +140 -0
- package/dist/composition/owned-ui.d.ts +26 -0
- package/dist/composition/owned-ui.js +176 -6
- package/dist/contracts/owned-ui/session-backend.d.ts +1 -0
- package/dist/features/launch/index.d.ts +1 -1
- package/dist/features/launch/intent.d.ts +3 -1
- package/dist/features/launch/intent.js +7 -4
- package/dist/features/owned-ui/settings-app.js +8 -35
- package/dist/features/resident-tab/auto-name.d.ts +11 -0
- package/dist/features/resident-tab/auto-name.js +42 -0
- package/dist/features/resident-tab/index.d.ts +3 -0
- package/dist/features/resident-tab/index.js +3 -0
- package/dist/features/resident-tab/shortcuts.d.ts +10 -0
- package/dist/features/resident-tab/shortcuts.js +35 -0
- package/dist/features/resident-tab/status-deriver.d.ts +9 -0
- package/dist/features/resident-tab/status-deriver.js +15 -0
- package/dist/foundation/launch-context/index.d.ts +10 -0
- package/dist/foundation/launch-context/index.js +25 -0
- package/dist/foundation/launch-guardian/main.d.ts +5 -0
- package/dist/foundation/launch-guardian/main.js +2 -1
- package/dist/foundation/release/bootstrap.d.ts +6 -0
- package/dist/foundation/release/bootstrap.js +51 -10
- package/dist/foundation/release/cohort-state.d.ts +1 -1
- package/dist/foundation/release/cohort-state.js +1 -1
- package/dist/foundation/release/dependency-certification.js +54 -19
- package/dist/foundation/release/progress-palette.generated.d.ts +2 -2
- package/dist/foundation/release/progress-palette.generated.js +2 -2
- package/dist/foundation/release/release-gc.d.ts +3 -0
- package/dist/foundation/release/release-gc.js +44 -8
- package/dist/foundation/resident-tabs/bounded-host-command.d.ts +16 -0
- package/dist/foundation/resident-tabs/bounded-host-command.js +35 -0
- package/dist/foundation/resident-tabs/bridge-client.d.ts +56 -0
- package/dist/foundation/resident-tabs/bridge-client.js +279 -0
- package/dist/foundation/resident-tabs/doctor.d.ts +29 -0
- package/dist/foundation/resident-tabs/doctor.js +166 -0
- package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
- package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +31 -0
- package/dist/foundation/resident-tabs/ensure-terminal-host.js +147 -0
- package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
- package/dist/foundation/resident-tabs/fault-injection.js +26 -0
- package/dist/foundation/resident-tabs/index.d.ts +12 -0
- package/dist/foundation/resident-tabs/index.js +6 -0
- package/dist/foundation/resident-tabs/maintenance.d.ts +42 -0
- package/dist/foundation/resident-tabs/maintenance.js +78 -0
- package/dist/foundation/resident-tabs/prompt-journal.d.ts +65 -0
- package/dist/foundation/resident-tabs/prompt-journal.js +214 -0
- package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
- package/dist/foundation/resident-tabs/protocol.js +195 -0
- package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
- package/dist/foundation/resident-tabs/recovery.js +205 -0
- package/dist/foundation/resident-tabs/release-holds.d.ts +27 -0
- package/dist/foundation/resident-tabs/release-holds.js +77 -0
- package/dist/foundation/resident-tabs/routing.d.ts +11 -0
- package/dist/foundation/resident-tabs/routing.js +10 -0
- package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
- package/dist/foundation/resident-tabs/session-sync.js +37 -0
- package/dist/foundation/resident-tabs/settings.d.ts +14 -0
- package/dist/foundation/resident-tabs/settings.js +66 -0
- package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +18 -0
- package/dist/foundation/resident-tabs/terminal-host-artifact.js +53 -0
- package/dist/foundation/resident-tabs/zip-archive.d.ts +9 -0
- package/dist/foundation/resident-tabs/zip-archive.js +56 -0
- package/dist/foundation/session-writer-lock/index.d.ts +32 -0
- package/dist/foundation/session-writer-lock/index.js +201 -0
- package/dist/foundation/startup/startup-descriptor.js +2 -2
- package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
- package/dist/foundation/terminal-cleanup/index.js +1 -1
- package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +1 -0
- package/dist/foundation/terminal-cleanup/terminal-reset.js +1 -0
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +1 -1
- package/dist/integrations/pi/components/owned-editor-ux.js +2 -2
- package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
- package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
- package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +4 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +38 -4
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
- package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
- package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/session-footer.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
- package/dist/integrations/pi/components/upstream/components/session-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
- package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
- package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +0 -2
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +41 -20
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
- package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
- package/dist/integrations/pi/components/upstream/history/editor-core.js +5 -5
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
- package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
- package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +3 -0
- package/dist/integrations/pi/components/upstream/theme/theme.js +24 -1
- package/dist/integrations/pi/engine/adapter.d.ts +1 -0
- package/dist/integrations/pi/engine/adapter.js +4 -0
- package/dist/integrations/pi/engine/pi-settings-metadata.json +2 -2
- package/dist/integrations/pi/engine/prompt-suggestions.d.ts +1 -0
- package/dist/integrations/pi/engine/prompt-suggestions.js +40 -0
- package/dist/integrations/pi/engine/resources/changelog.json +4 -4
- package/dist/integrations/pi/engine/runtime-integration.js +102 -29
- package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
- package/dist/integrations/pi/engine/session-runtime.js +8 -3
- package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
- package/dist/integrations/pi/engine/session-selection.js +45 -9
- package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
- package/dist/integrations/pi/startup-public.js +152 -222
- package/dist/integrations/pi/startup-public.manifest.json +266 -177
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +1 -1
- package/dist/native/darwin-arm64/a1_session_lock.node +0 -0
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host +0 -0
- package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +10500 -0
- package/dist/native/darwin-arm64/terminal-host.manifest.json +44 -0
- package/dist/native/darwin-x64/a1_session_lock.node +0 -0
- package/dist/native/darwin-x64/manifest.json +20 -0
- package/dist/native/darwin-x64/process-guardian +0 -0
- package/dist/native/darwin-x64/terminal-host +0 -0
- package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10737 -0
- package/dist/native/darwin-x64/terminal-host.manifest.json +44 -0
- package/dist/native/linux-x64/a1_session_lock.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host +0 -0
- package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +11226 -0
- package/dist/native/linux-x64/terminal-host.manifest.json +44 -0
- package/dist/native/win32-x64/a1_session_lock.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10757 -0
- package/dist/native/win32-x64/terminal-host.exe +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +44 -0
- package/dist/product-identity.d.ts +1 -1
- package/dist/product-identity.js +1 -1
- package/dist/product-identity.json +5 -0
- package/dist/runtime-payload-inventory.json +5349 -6035
- package/dist/ui/components/line-input.d.ts +1 -1
- package/dist/ui/components/prompt-input.d.ts +7 -5
- package/dist/ui/components/prompt-input.js +7 -7
- package/dist/ui/components/transcript-viewport.d.ts +6 -3
- package/dist/ui/components/transcript-viewport.js +13 -15
- package/dist/ui/settings/declarations.d.ts +25 -1
- package/dist/ui/settings/declarations.js +21 -1
- package/dist/ui/settings/index.d.ts +4 -2
- package/dist/ui/settings/index.js +2 -1
- package/dist/ui/settings/manager.d.ts +10 -3
- package/dist/ui/settings/manager.js +90 -30
- package/dist/ui/settings/migrations.d.ts +6 -0
- package/dist/ui/settings/migrations.js +44 -0
- package/dist/ui/settings/profile-document.d.ts +26 -0
- package/dist/ui/settings/profile-document.js +164 -0
- package/docs/architecture/evidence/resident-tabs/linux-x64.md +37 -0
- package/docs/architecture/evidence/resident-tabs/macos-arm64.md +36 -0
- package/docs/architecture/evidence/resident-tabs/macos-x64.md +35 -0
- package/docs/architecture/evidence/resident-tabs/windows-x64.md +36 -0
- package/docs/architecture/internal-naming.md +3 -1
- package/docs/architecture/process-guardian-provenance.md +2 -0
- package/docs/architecture/resident-tabs-requirements.md +18 -0
- package/docs/architecture/resident-tabs.md +594 -0
- package/docs/architecture/terminal-host-proof-gate.md +2 -0
- package/docs/architecture/terminal-host-provenance.md +13 -3
- package/docs/architecture/toolchain.md +1 -1
- package/docs/ci-release-runbook.md +2 -2
- package/docs/features/launch-profiles.md +11 -8
- package/docs/manual-resident-tabs-acceptance.md +51 -0
- package/docs/openspec-archive-automation.md +17 -16
- package/docs/validation.md +9 -1
- package/package.json +10 -4
|
@@ -1,8 +1,63 @@
|
|
|
1
|
+
import { closeSync, mkdirSync, openSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
1
3
|
import { createAgentSessionFromServices, createAgentSessionRuntime, createAgentSessionServices, resolveModelScopeWithDiagnostics, SessionManager, SettingsManager, } from "../startup-public.js";
|
|
2
4
|
import { resolvePiProjectTrustPreflight, } from "./project-trust-preflight.js";
|
|
3
|
-
import { openSelectedPiSession, resolveSessionArgumentPath } from "./session-selection.js";
|
|
5
|
+
import { openSelectedPiSession, resolveSessionArgumentPath, takeSelectedSessionWriter } from "./session-selection.js";
|
|
4
6
|
import { markStartupPhase } from "../../../foundation/startup/startup-runtime.js";
|
|
5
7
|
import { createWindowsNulCleanupExtension } from "./windows-filesystem-hygiene.js";
|
|
8
|
+
import { acquireSessionWriter, } from "../../../foundation/session-writer-lock/index.js";
|
|
9
|
+
class SessionWriterCoordinator {
|
|
10
|
+
#current;
|
|
11
|
+
prepare(manager) {
|
|
12
|
+
const selected = takeSelectedSessionWriter(manager);
|
|
13
|
+
if (selected !== undefined)
|
|
14
|
+
return { handle: selected, alreadyCurrent: false };
|
|
15
|
+
const path = manager.getSessionFile();
|
|
16
|
+
if (path === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (this.#current?.path === path)
|
|
19
|
+
return { handle: this.#current, alreadyCurrent: true };
|
|
20
|
+
const handle = acquireSessionWriter(path);
|
|
21
|
+
try {
|
|
22
|
+
if (!handle.bound) {
|
|
23
|
+
const header = manager.getHeader();
|
|
24
|
+
if (header === null)
|
|
25
|
+
throw new Error("new session is missing its generated header");
|
|
26
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
27
|
+
const descriptor = openSync(path, "wx", 0o600);
|
|
28
|
+
try {
|
|
29
|
+
handle.bind(path);
|
|
30
|
+
writeFileSync(descriptor, `${JSON.stringify(header)}\n`);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
closeSync(descriptor);
|
|
34
|
+
}
|
|
35
|
+
manager.setSessionFile(path);
|
|
36
|
+
}
|
|
37
|
+
return { handle, alreadyCurrent: false };
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
handle.release();
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
activate(pending) {
|
|
45
|
+
if (pending === undefined || pending.alreadyCurrent)
|
|
46
|
+
return;
|
|
47
|
+
const previous = this.#current;
|
|
48
|
+
this.#current = pending.handle;
|
|
49
|
+
previous?.release();
|
|
50
|
+
}
|
|
51
|
+
abandon(pending) {
|
|
52
|
+
if (pending !== undefined && !pending.alreadyCurrent)
|
|
53
|
+
pending.handle.release();
|
|
54
|
+
}
|
|
55
|
+
release() {
|
|
56
|
+
this.#current?.release();
|
|
57
|
+
this.#current = undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const runtimeSessionWriters = new WeakMap();
|
|
6
61
|
/**
|
|
7
62
|
* Mirrors pinned Pi's CLI startup: resolve the `models` patterns from settings
|
|
8
63
|
* into a scoped model list, keep the resolver's warnings (e.g. "No models match
|
|
@@ -69,40 +124,52 @@ export async function createPiRuntimeIntegration(options) {
|
|
|
69
124
|
cwd: options.cwd, selection,
|
|
70
125
|
...(sessionDir === undefined ? {} : { sessionDir }),
|
|
71
126
|
...(options.sessionForkPrompt === undefined ? {} : { forkPrompt: options.sessionForkPrompt }),
|
|
127
|
+
guardWriter: true,
|
|
72
128
|
});
|
|
129
|
+
const sessionWriters = new SessionWriterCoordinator();
|
|
73
130
|
const createRuntime = async ({ cwd, sessionManager: targetSessionManager, sessionStartEvent, }) => {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
...
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
131
|
+
const pendingWriter = sessionWriters.prepare(targetSessionManager);
|
|
132
|
+
try {
|
|
133
|
+
const { services, trust } = await createPiRuntimeServicesAfterTrust({
|
|
134
|
+
cwd,
|
|
135
|
+
agentDir: options.agentDir,
|
|
136
|
+
...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
|
|
137
|
+
...(options.preflightDependencies === undefined ? {} : { preflightDependencies: options.preflightDependencies }),
|
|
138
|
+
...(options.markStartupPhase === undefined ? {} : { markStartupPhase: options.markStartupPhase }),
|
|
139
|
+
});
|
|
140
|
+
const modelScope = await resolveConfiguredModelScope(services, options.signal);
|
|
141
|
+
const hasExistingSession = targetSessionManager.buildSessionContext().messages.length > 0;
|
|
142
|
+
const created = await createAgentSessionFromServices({
|
|
143
|
+
services,
|
|
144
|
+
sessionManager: targetSessionManager,
|
|
145
|
+
...(sessionStartEvent ? { sessionStartEvent } : {}),
|
|
146
|
+
...(modelScope.model && !hasExistingSession ? { model: modelScope.model } : {}),
|
|
147
|
+
...(modelScope.thinkingLevel && !hasExistingSession ? { thinkingLevel: modelScope.thinkingLevel } : {}),
|
|
148
|
+
...(modelScope.scopedModels.length > 0 ? { scopedModels: [...modelScope.scopedModels] } : {}),
|
|
149
|
+
});
|
|
150
|
+
sessionWriters.activate(pendingWriter);
|
|
151
|
+
await (options.markStartupPhase ?? defaultStartupPhaseMarker)("session-created");
|
|
152
|
+
return {
|
|
153
|
+
...created,
|
|
154
|
+
services,
|
|
155
|
+
diagnostics: [
|
|
156
|
+
...(trust.diagnostic === null ? [] : [{ type: "warning", code: "project-trust", message: trust.diagnostic }]),
|
|
157
|
+
...modelScope.diagnostics,
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
sessionWriters.abandon(pendingWriter);
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
100
165
|
};
|
|
101
|
-
|
|
166
|
+
const runtime = await createAgentSessionRuntime(createRuntime, {
|
|
102
167
|
cwd: sessionManager.getCwd(),
|
|
103
168
|
agentDir: options.agentDir,
|
|
104
169
|
sessionManager,
|
|
105
170
|
});
|
|
171
|
+
runtimeSessionWriters.set(runtime, sessionWriters);
|
|
172
|
+
return runtime;
|
|
106
173
|
}
|
|
107
174
|
function defaultStartupPhaseMarker(phase) {
|
|
108
175
|
return markStartupPhase(process.env, phase);
|
|
@@ -119,5 +186,11 @@ export async function replacePiRuntimeSession(runtime, replacement) {
|
|
|
119
186
|
export async function disposePiRuntimeIntegration(runtime) {
|
|
120
187
|
runtime.setRebindSession(undefined);
|
|
121
188
|
runtime.setBeforeSessionInvalidate(undefined);
|
|
122
|
-
|
|
189
|
+
try {
|
|
190
|
+
await runtime.dispose();
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
runtimeSessionWriters.get(runtime)?.release();
|
|
194
|
+
runtimeSessionWriters.delete(runtime);
|
|
195
|
+
}
|
|
123
196
|
}
|
|
@@ -64,12 +64,6 @@ export interface PiEngineRuntimePorts {
|
|
|
64
64
|
diagnostic(severity: OwnedUiDiagnostics["severity"], code: string, message: string, recoverable: boolean): void;
|
|
65
65
|
emitView(): void;
|
|
66
66
|
}
|
|
67
|
-
/**
|
|
68
|
-
* The pinned Pi runtime and the session bound to it: creation through the runtime factory, the
|
|
69
|
-
* session generation that stamps and invalidates events, the subscription that forwards session
|
|
70
|
-
* events, compaction progress observation, the queued-input integration, and disposal order. The
|
|
71
|
-
* adapter derives its view state from the session it is handed and never touches these directly.
|
|
72
|
-
*/
|
|
73
67
|
export declare class PiEngineRuntime {
|
|
74
68
|
#private;
|
|
75
69
|
constructor(options: PiEngineRuntimeOptions, ports: PiEngineRuntimePorts);
|
|
@@ -18,6 +18,9 @@ const GIT_BRANCH_MAX_BUFFER_BYTES = 4 * 1024;
|
|
|
18
18
|
* events, compaction progress observation, the queued-input integration, and disposal order. The
|
|
19
19
|
* adapter derives its view state from the session it is handed and never touches these directly.
|
|
20
20
|
*/
|
|
21
|
+
function hasSessionContent(path, session) {
|
|
22
|
+
return path !== null && existsSync(path) && session.messages.length > 0;
|
|
23
|
+
}
|
|
21
24
|
export class PiEngineRuntime {
|
|
22
25
|
#options;
|
|
23
26
|
#ports;
|
|
@@ -154,14 +157,16 @@ export class PiEngineRuntime {
|
|
|
154
157
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
155
158
|
}
|
|
156
159
|
currentSessionResumeMetadata() {
|
|
157
|
-
const
|
|
158
|
-
|
|
160
|
+
const session = this.#session;
|
|
161
|
+
const manager = session?.sessionManager;
|
|
162
|
+
if (session === undefined
|
|
163
|
+
|| manager === undefined
|
|
159
164
|
|| typeof manager.isPersisted !== "function"
|
|
160
165
|
|| typeof manager.getSessionId !== "function"
|
|
161
166
|
|| typeof manager.getSessionDir !== "function"
|
|
162
167
|
|| typeof manager.usesDefaultSessionDir !== "function"
|
|
163
168
|
|| manager.isPersisted() !== true
|
|
164
|
-
|| !
|
|
169
|
+
|| !hasSessionContent(this.currentSessionFile(), session))
|
|
165
170
|
return null;
|
|
166
171
|
const sessionId = manager.getSessionId();
|
|
167
172
|
const sessionDir = manager.getSessionDir();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SessionManager, type SessionInfo } from "../startup-public.js";
|
|
2
|
+
import { type SessionWriterHandle } from "../../../foundation/session-writer-lock/index.js";
|
|
2
3
|
export interface PiSessionSelection {
|
|
3
4
|
readonly target: string;
|
|
4
5
|
readonly sessionDir?: string;
|
|
@@ -16,11 +17,13 @@ interface SessionSelectionOptions {
|
|
|
16
17
|
readonly selection: PiSessionSelection;
|
|
17
18
|
readonly sessionDir?: string;
|
|
18
19
|
readonly forkPrompt?: PiSessionForkPrompt;
|
|
20
|
+
readonly guardWriter?: boolean;
|
|
19
21
|
/** Public API seam for deterministic lookup/open race and listing-order evidence. */
|
|
20
22
|
readonly sessions?: Pick<typeof SessionManager, "list" | "open" | "forkFrom"> & {
|
|
21
23
|
readonly listAll: (sessionDir?: string) => Promise<SessionInfo[]>;
|
|
22
24
|
};
|
|
23
25
|
}
|
|
26
|
+
export declare function takeSelectedSessionWriter(manager: SessionManager): SessionWriterHandle | undefined;
|
|
24
27
|
/** Pinned Pi 0.84.2 main.ts policy, using SDK APIs rather than importing the CLI. */
|
|
25
28
|
export declare function openSelectedPiSession(options: SessionSelectionOptions): Promise<SessionManager>;
|
|
26
29
|
/** Resolve before switching effective cwd, including quoted home-relative paths. */
|
|
@@ -2,6 +2,7 @@ import { accessSync, constants, existsSync, realpathSync, statSync } from "node:
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { SessionManager } from "../startup-public.js";
|
|
5
|
+
import { acquireExisting, acquireSessionWriter, SessionWriterConflict, } from "../../../foundation/session-writer-lock/index.js";
|
|
5
6
|
/** Expected resume outcomes are concise CLI diagnostics, not engine crashes. */
|
|
6
7
|
export class PiSessionSelectionError extends Error {
|
|
7
8
|
exitCode;
|
|
@@ -11,13 +12,23 @@ export class PiSessionSelectionError extends Error {
|
|
|
11
12
|
this.name = "PiSessionSelectionError";
|
|
12
13
|
}
|
|
13
14
|
}
|
|
15
|
+
const selectedSessionWriters = new WeakMap();
|
|
16
|
+
export function takeSelectedSessionWriter(manager) {
|
|
17
|
+
const writer = selectedSessionWriters.get(manager);
|
|
18
|
+
selectedSessionWriters.delete(manager);
|
|
19
|
+
return writer;
|
|
20
|
+
}
|
|
21
|
+
function holdSelectedWriter(manager, writer) {
|
|
22
|
+
selectedSessionWriters.set(manager, writer);
|
|
23
|
+
return manager;
|
|
24
|
+
}
|
|
14
25
|
/** Pinned Pi 0.84.2 main.ts policy, using SDK APIs rather than importing the CLI. */
|
|
15
26
|
export async function openSelectedPiSession(options) {
|
|
27
|
+
const sessions = options.sessions ?? SessionManager;
|
|
28
|
+
const cwd = resolve(options.cwd);
|
|
29
|
+
const directory = options.selection.sessionDir ?? options.sessionDir ?? process.env.PI_CODING_AGENT_SESSION_DIR;
|
|
30
|
+
const sessionDir = directory === undefined ? undefined : resolveSessionArgumentPath(directory, cwd);
|
|
16
31
|
try {
|
|
17
|
-
const sessions = options.sessions ?? SessionManager;
|
|
18
|
-
const cwd = resolve(options.cwd);
|
|
19
|
-
const directory = options.selection.sessionDir ?? options.sessionDir ?? process.env.PI_CODING_AGENT_SESSION_DIR;
|
|
20
|
-
const sessionDir = directory === undefined ? undefined : resolveSessionArgumentPath(directory, cwd);
|
|
21
32
|
const target = options.selection.target;
|
|
22
33
|
let path;
|
|
23
34
|
let global;
|
|
@@ -43,18 +54,43 @@ export async function openSelectedPiSession(options) {
|
|
|
43
54
|
}
|
|
44
55
|
assertResumeFile(path);
|
|
45
56
|
assertCwd(cwd);
|
|
46
|
-
|
|
57
|
+
const manager = sessions.forkFrom(path, cwd, sessionDir);
|
|
58
|
+
if (!options.guardWriter)
|
|
59
|
+
return manager;
|
|
60
|
+
const target = manager.getSessionFile();
|
|
61
|
+
if (target === undefined)
|
|
62
|
+
throw new PiSessionSelectionError("Fork did not create a session file");
|
|
63
|
+
return holdSelectedWriter(manager, acquireSessionWriter(target));
|
|
47
64
|
}
|
|
48
65
|
// Invariant: no await between the final guard and SDK open. A disappeared target
|
|
49
66
|
// can otherwise produce a new in-memory header instead of an existing session.
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
const writer = options.guardWriter ? acquireExisting(path) : undefined;
|
|
68
|
+
try {
|
|
69
|
+
const manager = sessions.open(path, sessionDir);
|
|
70
|
+
assertResumeFile(path);
|
|
71
|
+
assertCwd(manager.getCwd());
|
|
72
|
+
return writer === undefined ? manager : holdSelectedWriter(manager, writer);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
writer?.release();
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
54
78
|
}
|
|
55
79
|
catch (error) {
|
|
56
80
|
if (error instanceof PiSessionSelectionError)
|
|
57
81
|
throw error;
|
|
82
|
+
if (error instanceof SessionWriterConflict) {
|
|
83
|
+
if (options.forkPrompt && await options.forkPrompt({ sourceCwd: cwd })) {
|
|
84
|
+
const manager = sessions.forkFrom(error.path, cwd, sessionDir);
|
|
85
|
+
if (!options.guardWriter)
|
|
86
|
+
return manager;
|
|
87
|
+
const target = manager.getSessionFile();
|
|
88
|
+
if (target === undefined)
|
|
89
|
+
throw new PiSessionSelectionError("Fork did not create a session file");
|
|
90
|
+
return holdSelectedWriter(manager, acquireSessionWriter(target));
|
|
91
|
+
}
|
|
92
|
+
throw new PiSessionSelectionError("session is open in another A1 process");
|
|
93
|
+
}
|
|
58
94
|
throw new PiSessionSelectionError(`Could not resume session: ${error instanceof Error ? error.message : String(error)}`);
|
|
59
95
|
}
|
|
60
96
|
}
|
|
@@ -3,6 +3,7 @@ import { dirname, resolve } from "node:path";
|
|
|
3
3
|
import { dynamicObject, isRecord, requireCapability, stringProperty } from "./message-values.js";
|
|
4
4
|
import { ProjectTrustStore, SessionManager } from "../startup-public.js";
|
|
5
5
|
import { resolveConfiguredModelIds, scopedModelRecords, scopedModelReference, workflowOptions } from "./workflow-support.js";
|
|
6
|
+
import { acquireExisting } from "../../../foundation/session-writer-lock/index.js";
|
|
6
7
|
/**
|
|
7
8
|
* The selector contexts and option lists the owned UI's workflow dialogs read from pinned Pi:
|
|
8
9
|
* model, scoped-model, session, tree, fork, project-trust, and provider-authentication state,
|
|
@@ -102,7 +103,15 @@ export class PiWorkflowContexts {
|
|
|
102
103
|
const next = (nextName ?? "").trim();
|
|
103
104
|
if (!next)
|
|
104
105
|
return;
|
|
105
|
-
|
|
106
|
+
const isCurrent = typeof currentSessionFilePath === "string"
|
|
107
|
+
&& resolve(currentSessionFilePath) === resolve(sessionFilePath);
|
|
108
|
+
const writer = isCurrent ? undefined : acquireExisting(sessionFilePath);
|
|
109
|
+
try {
|
|
110
|
+
SessionManager.open(sessionFilePath).appendSessionInfo(next);
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
writer?.release();
|
|
114
|
+
}
|
|
106
115
|
},
|
|
107
116
|
};
|
|
108
117
|
}
|