@astralyn/pi 0.87.1 → 0.87.2
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/CHANGELOG.md +14 -0
- package/dist/bundle/chunks/{chunk-CDMUKIXY.js → chunk-NBIUJDV6.js} +1 -1
- package/dist/bundle/chunks/{chunk-772GXEFD.js → chunk-RFLBIA5Z.js} +69 -69
- package/dist/bundle/chunks/{virtual-modules-LQO2MG3T.js → virtual-modules-GOHLE5JL.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +9 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +158 -157
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +14 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +437 -434
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background/types.d.ts +2 -0
- package/dist/core/background/types.d.ts.map +1 -1
- package/dist/core/background/types.js.map +1 -1
- package/dist/core/extensions/distribution-api.d.ts +41 -0
- package/dist/core/extensions/distribution-api.d.ts.map +1 -0
- package/dist/core/extensions/distribution-api.js +12 -0
- package/dist/core/extensions/distribution-api.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +1 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +0 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +15 -45
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +1 -11
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/virtual-modules.js +2 -1
- package/dist/core/extensions/virtual-modules.js.map +1 -1
- package/dist/core/keybinding-registry.d.ts +11 -0
- package/dist/core/keybinding-registry.d.ts.map +1 -0
- package/dist/core/keybinding-registry.js +24 -0
- package/dist/core/keybinding-registry.js.map +1 -0
- package/dist/core/keybindings.d.ts +4 -64
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -41
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +70 -2
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +2 -26
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +5 -11
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts +1 -0
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +21 -0
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +11 -48
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/extensions/background/index.d.ts +2 -0
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +17 -0
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/keybindings.d.ts +10 -0
- package/dist/extensions/background/keybindings.d.ts.map +1 -0
- package/dist/extensions/background/keybindings.js +14 -0
- package/dist/extensions/background/keybindings.js.map +1 -0
- package/dist/extensions/background/manager.d.ts +2 -0
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +1 -0
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/btw/controller.d.ts +1 -0
- package/dist/extensions/btw/controller.d.ts.map +1 -1
- package/dist/extensions/btw/controller.js +5 -5
- package/dist/extensions/btw/controller.js.map +1 -1
- package/dist/extensions/btw/index.js +1 -2
- package/dist/extensions/btw/index.js.map +1 -1
- package/dist/extensions/btw/keybindings.d.ts +10 -0
- package/dist/extensions/btw/keybindings.d.ts.map +1 -0
- package/dist/extensions/btw/keybindings.js +8 -0
- package/dist/extensions/btw/keybindings.js.map +1 -0
- package/dist/extensions/btw/panel.d.ts +1 -0
- package/dist/extensions/btw/panel.d.ts.map +1 -1
- package/dist/extensions/btw/panel.js +1 -0
- package/dist/extensions/btw/panel.js.map +1 -1
- package/dist/extensions/list-keybindings.d.ts +8 -0
- package/dist/extensions/list-keybindings.d.ts.map +1 -0
- package/dist/extensions/list-keybindings.js +8 -0
- package/dist/extensions/list-keybindings.js.map +1 -0
- package/dist/extensions/provider/compat-fields.d.ts.map +1 -1
- package/dist/extensions/provider/compat-fields.js +23 -3
- package/dist/extensions/provider/compat-fields.js.map +1 -1
- package/dist/extensions/provider/connection.d.ts.map +1 -1
- package/dist/extensions/provider/connection.js +1 -1
- package/dist/extensions/provider/connection.js.map +1 -1
- package/dist/extensions/provider/constants.d.ts +2 -0
- package/dist/extensions/provider/constants.d.ts.map +1 -1
- package/dist/extensions/provider/constants.js +2 -0
- package/dist/extensions/provider/constants.js.map +1 -1
- package/dist/extensions/provider/keybindings.d.ts +9 -0
- package/dist/extensions/provider/keybindings.d.ts.map +1 -0
- package/dist/extensions/provider/keybindings.js +12 -0
- package/dist/extensions/provider/keybindings.js.map +1 -0
- package/dist/extensions/provider/probe.d.ts +8 -4
- package/dist/extensions/provider/probe.d.ts.map +1 -1
- package/dist/extensions/provider/probe.js +169 -11
- package/dist/extensions/provider/probe.js.map +1 -1
- package/dist/extensions/provider/ui/builtin-data.d.ts +1 -0
- package/dist/extensions/provider/ui/builtin-data.d.ts.map +1 -1
- package/dist/extensions/provider/ui/builtin-data.js +1 -0
- package/dist/extensions/provider/ui/builtin-data.js.map +1 -1
- package/dist/extensions/provider/ui/compat.d.ts +1 -0
- package/dist/extensions/provider/ui/compat.d.ts.map +1 -1
- package/dist/extensions/provider/ui/compat.js +1 -0
- package/dist/extensions/provider/ui/compat.js.map +1 -1
- package/dist/extensions/provider/ui/dictionary.d.ts +1 -0
- package/dist/extensions/provider/ui/dictionary.d.ts.map +1 -1
- package/dist/extensions/provider/ui/dictionary.js +1 -0
- package/dist/extensions/provider/ui/dictionary.js.map +1 -1
- package/dist/extensions/provider/ui/editor.d.ts +1 -0
- package/dist/extensions/provider/ui/editor.d.ts.map +1 -1
- package/dist/extensions/provider/ui/editor.js +1 -0
- package/dist/extensions/provider/ui/editor.js.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.d.ts +5 -3
- package/dist/extensions/provider/ui/fetch-models.d.ts.map +1 -1
- package/dist/extensions/provider/ui/fetch-models.js +28 -3
- package/dist/extensions/provider/ui/fetch-models.js.map +1 -1
- package/dist/extensions/provider/ui/model-fields.d.ts +1 -0
- package/dist/extensions/provider/ui/model-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-fields.js +1 -0
- package/dist/extensions/provider/ui/model-fields.js.map +1 -1
- package/dist/extensions/provider/ui/model-options.d.ts +1 -0
- package/dist/extensions/provider/ui/model-options.d.ts.map +1 -1
- package/dist/extensions/provider/ui/model-options.js +1 -0
- package/dist/extensions/provider/ui/model-options.js.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.d.ts +1 -0
- package/dist/extensions/provider/ui/provider-fields.d.ts.map +1 -1
- package/dist/extensions/provider/ui/provider-fields.js +1 -0
- package/dist/extensions/provider/ui/provider-fields.js.map +1 -1
- package/dist/extensions/question/dialog.d.ts +1 -0
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +1 -0
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/keybindings.d.ts +2 -0
- package/dist/extensions/question/keybindings.d.ts.map +1 -0
- package/dist/extensions/question/keybindings.js +3 -0
- package/dist/extensions/question/keybindings.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/editor-host.d.ts +43 -0
- package/dist/modes/interactive/editor-host.d.ts.map +1 -0
- package/dist/modes/interactive/editor-host.js +83 -0
- package/dist/modes/interactive/editor-host.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -11
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +300 -360
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tool-chat.d.ts +21 -0
- package/dist/modes/interactive/tool-chat.d.ts.map +1 -0
- package/dist/modes/interactive/tool-chat.js +58 -0
- package/dist/modes/interactive/tool-chat.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +0 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/path-identity.d.ts +12 -0
- package/dist/utils/path-identity.d.ts.map +1 -0
- package/dist/utils/path-identity.js +63 -0
- package/dist/utils/path-identity.js.map +1 -0
- package/dist/utils/shell.d.ts +0 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +0 -21
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +2 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +2 -0
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/docs/bundled/extensions/provider.md +7 -3
- package/docs/extensions.md +15 -5
- package/examples/extensions/README.md +34 -14
- package/examples/extensions/auto-commit-on-exit.ts +1 -1
- package/examples/extensions/bash-spawn-hook.ts +2 -2
- package/examples/extensions/bookmark.ts +1 -1
- package/examples/extensions/border-status-editor.ts +6 -1
- package/examples/extensions/built-in-tool-renderer.ts +2 -2
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/confirm-destructive.ts +1 -1
- package/examples/extensions/custom-compaction.ts +2 -2
- package/examples/extensions/custom-footer.ts +1 -1
- package/examples/extensions/custom-header.ts +2 -2
- package/examples/extensions/custom-provider-anthropic/index.ts +6 -6
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/dirty-repo-guard.ts +1 -1
- package/examples/extensions/doom-overlay/index.ts +1 -1
- package/examples/extensions/dynamic-resources/dynamic.json +3 -1
- package/examples/extensions/dynamic-resources/index.ts +1 -1
- package/examples/extensions/dynamic-tools.ts +1 -1
- package/examples/extensions/entry-renderer.ts +1 -1
- package/examples/extensions/event-bus.ts +1 -1
- package/examples/extensions/file-trigger.ts +1 -1
- package/examples/extensions/git-checkpoint.ts +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +1 -1
- package/examples/extensions/github-issue-autocomplete.ts +1 -1
- package/examples/extensions/gondolin/index.ts +9 -7
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +2 -2
- package/examples/extensions/hello.ts +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +1 -1
- package/examples/extensions/input-transform-streaming.ts +1 -1
- package/examples/extensions/input-transform.ts +1 -1
- package/examples/extensions/interactive-shell.ts +1 -1
- package/examples/extensions/mac-system-theme.ts +1 -1
- package/examples/extensions/message-renderer.ts +1 -1
- package/examples/extensions/minimal-mode.ts +2 -2
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/notify.ts +1 -1
- package/examples/extensions/overlay-qa-tests.ts +3 -3
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/permission-gate.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/plan-mode/index.ts +1 -1
- package/examples/extensions/preset.ts +2 -2
- package/examples/extensions/project-trust.ts +3 -3
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/protected-paths.ts +1 -1
- package/examples/extensions/provider-payload.ts +1 -1
- package/examples/extensions/qna.ts +2 -2
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/reload-runtime.ts +1 -1
- package/examples/extensions/rpc-demo.ts +1 -1
- package/examples/extensions/sandbox/index.ts +2 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/send-user-message.ts +1 -1
- package/examples/extensions/session-name.ts +1 -1
- package/examples/extensions/shutdown-command.ts +1 -1
- package/examples/extensions/snake.ts +1 -1
- package/examples/extensions/space-invaders.ts +1 -1
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/status-line.ts +1 -1
- package/examples/extensions/structured-output.ts +1 -1
- package/examples/extensions/summarize.ts +2 -3
- package/examples/extensions/system-prompt-header.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/timed-confirm.ts +1 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +2 -2
- package/examples/extensions/trigger-compact.ts +1 -1
- package/examples/extensions/truncated-tool.ts +4 -4
- package/examples/extensions/widget-placement.ts +1 -1
- package/examples/extensions/with-deps/index.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/working-indicator.ts +1 -1
- package/examples/extensions/working-message-test.ts +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -118,128 +118,111 @@ export class AgentSessionRuntime {
|
|
|
118
118
|
await withSession(this.session.createReplacedSessionContext());
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Hold the outgoing session's background delivery across a replacement. The
|
|
123
|
+
* pause belongs to the session current at entry, not the replacement.
|
|
124
|
+
*/
|
|
125
|
+
async withBackgroundPaused(operation) {
|
|
122
126
|
const resumeBackground = this.session.pauseBackgroundNotifications();
|
|
123
127
|
try {
|
|
124
|
-
|
|
125
|
-
if (beforeResult.cancelled) {
|
|
126
|
-
return beforeResult;
|
|
127
|
-
}
|
|
128
|
-
const previousSessionFile = this.session.sessionFile;
|
|
129
|
-
let sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);
|
|
130
|
-
assertSessionCwdExists(sessionManager, this.cwd);
|
|
131
|
-
await this.teardownCurrent("resume", sessionManager.getSessionFile());
|
|
132
|
-
// Resuming the current file must include usage persisted during teardown.
|
|
133
|
-
sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);
|
|
134
|
-
this.apply(await this.createRuntime({
|
|
135
|
-
cwd: sessionManager.getCwd(),
|
|
136
|
-
agentDir: this.services.agentDir,
|
|
137
|
-
sessionManager,
|
|
138
|
-
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
139
|
-
projectTrustContext: options?.projectTrustContextFactory?.(sessionManager.getCwd()),
|
|
140
|
-
}));
|
|
141
|
-
await this.finishSessionReplacement(options?.withSession);
|
|
142
|
-
return { cancelled: false };
|
|
128
|
+
return await operation();
|
|
143
129
|
}
|
|
144
130
|
finally {
|
|
145
131
|
resumeBackground();
|
|
146
132
|
}
|
|
147
133
|
}
|
|
134
|
+
async switchSession(sessionPath, options) {
|
|
135
|
+
return this.withBackgroundPaused(() => this.switchSessionBody(sessionPath, options));
|
|
136
|
+
}
|
|
137
|
+
async switchSessionBody(sessionPath, options) {
|
|
138
|
+
const beforeResult = await this.emitBeforeSwitch("resume", sessionPath);
|
|
139
|
+
if (beforeResult.cancelled) {
|
|
140
|
+
return beforeResult;
|
|
141
|
+
}
|
|
142
|
+
const previousSessionFile = this.session.sessionFile;
|
|
143
|
+
let sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);
|
|
144
|
+
assertSessionCwdExists(sessionManager, this.cwd);
|
|
145
|
+
await this.teardownCurrent("resume", sessionManager.getSessionFile());
|
|
146
|
+
// Resuming the current file must include usage persisted during teardown.
|
|
147
|
+
sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);
|
|
148
|
+
this.apply(await this.createRuntime({
|
|
149
|
+
cwd: sessionManager.getCwd(),
|
|
150
|
+
agentDir: this.services.agentDir,
|
|
151
|
+
sessionManager,
|
|
152
|
+
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
153
|
+
projectTrustContext: options?.projectTrustContextFactory?.(sessionManager.getCwd()),
|
|
154
|
+
}));
|
|
155
|
+
await this.finishSessionReplacement(options?.withSession);
|
|
156
|
+
return { cancelled: false };
|
|
157
|
+
}
|
|
148
158
|
async newSession(options) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const previousSessionFile = this.session.sessionFile;
|
|
156
|
-
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
157
|
-
const sessionManager = this.session.sessionManager.isPersisted()
|
|
158
|
-
? SessionManager.create(this.cwd, sessionDir)
|
|
159
|
-
: SessionManager.inMemory(this.cwd);
|
|
160
|
-
if (options?.parentSession) {
|
|
161
|
-
sessionManager.newSession({ parentSession: options.parentSession });
|
|
162
|
-
}
|
|
163
|
-
await this.teardownCurrent("new", sessionManager.getSessionFile());
|
|
164
|
-
this.apply(await this.createRuntime({
|
|
165
|
-
cwd: this.cwd,
|
|
166
|
-
agentDir: this.services.agentDir,
|
|
167
|
-
sessionManager,
|
|
168
|
-
sessionStartEvent: { type: "session_start", reason: "new", previousSessionFile },
|
|
169
|
-
}));
|
|
170
|
-
if (options?.setup) {
|
|
171
|
-
await options.setup(this.session.sessionManager);
|
|
172
|
-
this.session.refreshContext();
|
|
173
|
-
}
|
|
174
|
-
await this.finishSessionReplacement(options?.withSession);
|
|
175
|
-
return { cancelled: false };
|
|
159
|
+
return this.withBackgroundPaused(() => this.newSessionBody(options));
|
|
160
|
+
}
|
|
161
|
+
async newSessionBody(options) {
|
|
162
|
+
const beforeResult = await this.emitBeforeSwitch("new");
|
|
163
|
+
if (beforeResult.cancelled) {
|
|
164
|
+
return beforeResult;
|
|
176
165
|
}
|
|
177
|
-
|
|
178
|
-
|
|
166
|
+
const previousSessionFile = this.session.sessionFile;
|
|
167
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
168
|
+
const sessionManager = this.session.sessionManager.isPersisted()
|
|
169
|
+
? SessionManager.create(this.cwd, sessionDir)
|
|
170
|
+
: SessionManager.inMemory(this.cwd);
|
|
171
|
+
if (options?.parentSession) {
|
|
172
|
+
sessionManager.newSession({ parentSession: options.parentSession });
|
|
173
|
+
}
|
|
174
|
+
await this.teardownCurrent("new", sessionManager.getSessionFile());
|
|
175
|
+
this.apply(await this.createRuntime({
|
|
176
|
+
cwd: this.cwd,
|
|
177
|
+
agentDir: this.services.agentDir,
|
|
178
|
+
sessionManager,
|
|
179
|
+
sessionStartEvent: { type: "session_start", reason: "new", previousSessionFile },
|
|
180
|
+
}));
|
|
181
|
+
if (options?.setup) {
|
|
182
|
+
await options.setup(this.session.sessionManager);
|
|
183
|
+
this.session.refreshContext();
|
|
179
184
|
}
|
|
185
|
+
await this.finishSessionReplacement(options?.withSession);
|
|
186
|
+
return { cancelled: false };
|
|
180
187
|
}
|
|
181
188
|
async fork(entryId, options) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
189
|
+
return this.withBackgroundPaused(() => this.forkBody(entryId, options));
|
|
190
|
+
}
|
|
191
|
+
async forkBody(entryId, options) {
|
|
192
|
+
const position = options?.position ?? "before";
|
|
193
|
+
const beforeResult = await this.emitBeforeFork(entryId, { position });
|
|
194
|
+
if (beforeResult.cancelled) {
|
|
195
|
+
return { cancelled: true };
|
|
196
|
+
}
|
|
197
|
+
let targetLeafId;
|
|
198
|
+
let selectedText;
|
|
199
|
+
const selectedEntry = this.session.sessionManager.getEntry(entryId);
|
|
200
|
+
if (!selectedEntry) {
|
|
201
|
+
throw new Error("Invalid entry ID for forking");
|
|
202
|
+
}
|
|
203
|
+
if (position === "at") {
|
|
204
|
+
targetLeafId = selectedEntry.id;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
if (selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
|
|
193
208
|
throw new Error("Invalid entry ID for forking");
|
|
194
209
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
selectedText = extractUserMessageText(selectedEntry.message.content);
|
|
210
|
+
targetLeafId = selectedEntry.parentId;
|
|
211
|
+
selectedText = extractUserMessageText(selectedEntry.message.content);
|
|
212
|
+
}
|
|
213
|
+
const previousSessionFile = this.session.sessionFile;
|
|
214
|
+
if (this.session.sessionManager.isPersisted()) {
|
|
215
|
+
const currentSessionFile = this.session.sessionFile;
|
|
216
|
+
if (!currentSessionFile) {
|
|
217
|
+
throw new Error("Persisted session is missing a session file");
|
|
204
218
|
}
|
|
205
|
-
const
|
|
206
|
-
if (
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
throw new Error("Persisted session is missing a session file");
|
|
210
|
-
}
|
|
211
|
-
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
212
|
-
if (!targetLeafId) {
|
|
213
|
-
const sessionManager = SessionManager.create(this.cwd, sessionDir);
|
|
214
|
-
sessionManager.newSession({ parentSession: currentSessionFile });
|
|
215
|
-
await this.teardownCurrent("fork", sessionManager.getSessionFile());
|
|
216
|
-
this.apply(await this.createRuntime({
|
|
217
|
-
cwd: this.cwd,
|
|
218
|
-
agentDir: this.services.agentDir,
|
|
219
|
-
sessionManager,
|
|
220
|
-
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
221
|
-
}));
|
|
222
|
-
await this.finishSessionReplacement(options?.withSession);
|
|
223
|
-
return { cancelled: false, selectedText };
|
|
224
|
-
}
|
|
225
|
-
if (!existsSync(currentSessionFile)) {
|
|
226
|
-
throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");
|
|
227
|
-
}
|
|
228
|
-
// Validate and honor vetoes before closing admission, but settle owned
|
|
229
|
-
// usage before reading the source file for the fork.
|
|
230
|
-
const forkingCurrentLeaf = targetLeafId === this.session.sessionManager.getLeafId();
|
|
231
|
-
this.session.background.close();
|
|
232
|
-
await Promise.all([this.session.background.shutdown(), this.session.abort()]);
|
|
233
|
-
if (forkingCurrentLeaf)
|
|
234
|
-
targetLeafId = this.session.sessionManager.getLeafId();
|
|
235
|
-
const sessionManager = SessionManager.open(currentSessionFile, sessionDir);
|
|
236
|
-
const forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);
|
|
237
|
-
if (!forkedSessionPath) {
|
|
238
|
-
throw new Error("Failed to create forked session");
|
|
239
|
-
}
|
|
219
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
220
|
+
if (!targetLeafId) {
|
|
221
|
+
const sessionManager = SessionManager.create(this.cwd, sessionDir);
|
|
222
|
+
sessionManager.newSession({ parentSession: currentSessionFile });
|
|
240
223
|
await this.teardownCurrent("fork", sessionManager.getSessionFile());
|
|
241
224
|
this.apply(await this.createRuntime({
|
|
242
|
-
cwd:
|
|
225
|
+
cwd: this.cwd,
|
|
243
226
|
agentDir: this.services.agentDir,
|
|
244
227
|
sessionManager,
|
|
245
228
|
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
@@ -247,19 +230,24 @@ export class AgentSessionRuntime {
|
|
|
247
230
|
await this.finishSessionReplacement(options?.withSession);
|
|
248
231
|
return { cancelled: false, selectedText };
|
|
249
232
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
await this.teardownCurrent("fork", sessionManager.getSessionFile());
|
|
253
|
-
if (forkingCurrentLeaf)
|
|
254
|
-
targetLeafId = sessionManager.getLeafId();
|
|
255
|
-
if (!targetLeafId) {
|
|
256
|
-
sessionManager.newSession({ parentSession: previousSessionFile });
|
|
233
|
+
if (!existsSync(currentSessionFile)) {
|
|
234
|
+
throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");
|
|
257
235
|
}
|
|
258
|
-
|
|
259
|
-
|
|
236
|
+
// Validate and honor vetoes before closing admission, but settle owned
|
|
237
|
+
// usage before reading the source file for the fork.
|
|
238
|
+
const forkingCurrentLeaf = targetLeafId === this.session.sessionManager.getLeafId();
|
|
239
|
+
this.session.background.close();
|
|
240
|
+
await Promise.all([this.session.background.shutdown(), this.session.abort()]);
|
|
241
|
+
if (forkingCurrentLeaf)
|
|
242
|
+
targetLeafId = this.session.sessionManager.getLeafId();
|
|
243
|
+
const sessionManager = SessionManager.open(currentSessionFile, sessionDir);
|
|
244
|
+
const forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);
|
|
245
|
+
if (!forkedSessionPath) {
|
|
246
|
+
throw new Error("Failed to create forked session");
|
|
260
247
|
}
|
|
248
|
+
await this.teardownCurrent("fork", sessionManager.getSessionFile());
|
|
261
249
|
this.apply(await this.createRuntime({
|
|
262
|
-
cwd:
|
|
250
|
+
cwd: sessionManager.getCwd(),
|
|
263
251
|
agentDir: this.services.agentDir,
|
|
264
252
|
sessionManager,
|
|
265
253
|
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
@@ -267,9 +255,25 @@ export class AgentSessionRuntime {
|
|
|
267
255
|
await this.finishSessionReplacement(options?.withSession);
|
|
268
256
|
return { cancelled: false, selectedText };
|
|
269
257
|
}
|
|
270
|
-
|
|
271
|
-
|
|
258
|
+
const sessionManager = this.session.sessionManager;
|
|
259
|
+
const forkingCurrentLeaf = targetLeafId !== null && targetLeafId === sessionManager.getLeafId();
|
|
260
|
+
await this.teardownCurrent("fork", sessionManager.getSessionFile());
|
|
261
|
+
if (forkingCurrentLeaf)
|
|
262
|
+
targetLeafId = sessionManager.getLeafId();
|
|
263
|
+
if (!targetLeafId) {
|
|
264
|
+
sessionManager.newSession({ parentSession: previousSessionFile });
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
sessionManager.createBranchedSession(targetLeafId);
|
|
272
268
|
}
|
|
269
|
+
this.apply(await this.createRuntime({
|
|
270
|
+
cwd: this.cwd,
|
|
271
|
+
agentDir: this.services.agentDir,
|
|
272
|
+
sessionManager,
|
|
273
|
+
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
274
|
+
}));
|
|
275
|
+
await this.finishSessionReplacement(options?.withSession);
|
|
276
|
+
return { cancelled: false, selectedText };
|
|
273
277
|
}
|
|
274
278
|
/**
|
|
275
279
|
* Import a session JSONL file and switch runtime state to the imported session.
|
|
@@ -279,49 +283,46 @@ export class AgentSessionRuntime {
|
|
|
279
283
|
* @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.
|
|
280
284
|
*/
|
|
281
285
|
async importFromJsonl(inputPath, cwdOverride) {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
const beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
|
|
302
|
-
if (beforeResult.cancelled) {
|
|
303
|
-
return beforeResult;
|
|
304
|
-
}
|
|
305
|
-
const previousSessionFile = this.session.sessionFile;
|
|
306
|
-
if (!sourceAlreadyStored) {
|
|
307
|
-
copyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);
|
|
286
|
+
return this.withBackgroundPaused(() => this.importFromJsonlBody(inputPath, cwdOverride));
|
|
287
|
+
}
|
|
288
|
+
async importFromJsonlBody(inputPath, cwdOverride) {
|
|
289
|
+
const resolvedPath = resolvePath(inputPath);
|
|
290
|
+
if (!existsSync(resolvedPath)) {
|
|
291
|
+
throw new SessionImportFileNotFoundError(resolvedPath);
|
|
292
|
+
}
|
|
293
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
294
|
+
if (!existsSync(sessionDir)) {
|
|
295
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
296
|
+
}
|
|
297
|
+
let destinationPath = join(sessionDir, basename(resolvedPath));
|
|
298
|
+
const sourceAlreadyStored = resolve(destinationPath) === resolvedPath;
|
|
299
|
+
if (!sourceAlreadyStored) {
|
|
300
|
+
const { name, ext } = parse(destinationPath);
|
|
301
|
+
let suffix = 1;
|
|
302
|
+
while (existsSync(destinationPath)) {
|
|
303
|
+
destinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);
|
|
308
304
|
}
|
|
309
|
-
let sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
|
|
310
|
-
assertSessionCwdExists(sessionManager, this.cwd);
|
|
311
|
-
await this.teardownCurrent("resume", sessionManager.getSessionFile());
|
|
312
|
-
sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
|
|
313
|
-
this.apply(await this.createRuntime({
|
|
314
|
-
cwd: sessionManager.getCwd(),
|
|
315
|
-
agentDir: this.services.agentDir,
|
|
316
|
-
sessionManager,
|
|
317
|
-
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
318
|
-
}));
|
|
319
|
-
await this.finishSessionReplacement();
|
|
320
|
-
return { cancelled: false };
|
|
321
305
|
}
|
|
322
|
-
|
|
323
|
-
|
|
306
|
+
const beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
|
|
307
|
+
if (beforeResult.cancelled) {
|
|
308
|
+
return beforeResult;
|
|
309
|
+
}
|
|
310
|
+
const previousSessionFile = this.session.sessionFile;
|
|
311
|
+
if (!sourceAlreadyStored) {
|
|
312
|
+
copyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);
|
|
324
313
|
}
|
|
314
|
+
let sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
|
|
315
|
+
assertSessionCwdExists(sessionManager, this.cwd);
|
|
316
|
+
await this.teardownCurrent("resume", sessionManager.getSessionFile());
|
|
317
|
+
sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
|
|
318
|
+
this.apply(await this.createRuntime({
|
|
319
|
+
cwd: sessionManager.getCwd(),
|
|
320
|
+
agentDir: this.services.agentDir,
|
|
321
|
+
sessionManager,
|
|
322
|
+
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
323
|
+
}));
|
|
324
|
+
await this.finishSessionReplacement();
|
|
325
|
+
return { cancelled: false };
|
|
325
326
|
}
|
|
326
327
|
async dispose() {
|
|
327
328
|
this.session.background.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-session-runtime.js","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type {\n\tProjectTrustContext,\n\tReplacedSessionContext,\n\tSessionShutdownEvent,\n\tSessionStartEvent,\n} from \"./extensions/index.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { CreateAgentSessionResult } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tprojectTrustContext?: ProjectTrustContext;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(`File not found: ${filePath}`);\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _modelFallbackMessage?: string;\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn this._diagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async emitBeforeSwitch(\n\t\treason: \"new\" | \"resume\",\n\t\ttargetSessionFile?: string,\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst runner = this.session.extensionRunner;\n\t\tif (!runner.hasHandlers(\"session_before_switch\")) {\n\t\t\treturn { cancelled: false };\n\t\t}\n\n\t\tconst result = await runner.emit({\n\t\t\ttype: \"session_before_switch\",\n\t\t\treason,\n\t\t\ttargetSessionFile,\n\t\t});\n\t\treturn { cancelled: result?.cancel === true };\n\t}\n\n\tprivate async emitBeforeFork(\n\t\tentryId: string,\n\t\toptions: { position: \"before\" | \"at\" },\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst runner = this.session.extensionRunner;\n\t\tif (!runner.hasHandlers(\"session_before_fork\")) {\n\t\t\treturn { cancelled: false };\n\t\t}\n\n\t\tconst result = await runner.emit({\n\t\t\ttype: \"session_before_fork\",\n\t\t\tentryId,\n\t\t\t...options,\n\t\t});\n\t\treturn { cancelled: result?.cancel === true };\n\t}\n\n\tprivate async teardownCurrent(reason: SessionShutdownEvent[\"reason\"], targetSessionFile?: string): Promise<void> {\n\t\tthis.session.background.close();\n\t\t// Stop the main loop immediately too, while bounded worker cleanup runs.\n\t\t// Both must finish before extension shutdown and runtime invalidation.\n\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner, {\n\t\t\ttype: \"session_shutdown\",\n\t\t\treason,\n\t\t\ttargetSessionFile,\n\t\t});\n\t\tthis.beforeSessionInvalidate?.();\n\t\tthis.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t\tprojectTrustContextFactory?: (cwd: string) => ProjectTrustContext;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst resumeBackground = this.session.pauseBackgroundNotifications();\n\t\ttry {\n\t\t\tconst beforeResult = await this.emitBeforeSwitch(\"resume\", sessionPath);\n\t\t\tif (beforeResult.cancelled) {\n\t\t\t\treturn beforeResult;\n\t\t\t}\n\n\t\t\tconst previousSessionFile = this.session.sessionFile;\n\t\t\tlet sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\t\t// Resuming the current file must include usage persisted during teardown.\n\t\t\tsessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"resume\", previousSessionFile },\n\t\t\t\t\tprojectTrustContext: options?.projectTrustContextFactory?.(sessionManager.getCwd()),\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false };\n\t\t} finally {\n\t\t\tresumeBackground();\n\t\t}\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst resumeBackground = this.session.pauseBackgroundNotifications();\n\t\ttry {\n\t\t\tconst beforeResult = await this.emitBeforeSwitch(\"new\");\n\t\t\tif (beforeResult.cancelled) {\n\t\t\t\treturn beforeResult;\n\t\t\t}\n\n\t\t\tconst previousSessionFile = this.session.sessionFile;\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t\t: SessionManager.inMemory(this.cwd);\n\t\t\tif (options?.parentSession) {\n\t\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t\t}\n\n\t\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"new\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (options?.setup) {\n\t\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\t\tthis.session.refreshContext();\n\t\t\t}\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false };\n\t\t} finally {\n\t\t\tresumeBackground();\n\t\t}\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst resumeBackground = this.session.pauseBackgroundNotifications();\n\t\ttry {\n\t\t\tconst position = options?.position ?? \"before\";\n\t\t\tconst beforeResult = await this.emitBeforeFork(entryId, { position });\n\t\t\tif (beforeResult.cancelled) {\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tlet targetLeafId: string | null;\n\t\t\tlet selectedText: string | undefined;\n\n\t\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\t\tif (!selectedEntry) {\n\t\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t\t}\n\n\t\t\tif (position === \"at\") {\n\t\t\t\ttargetLeafId = selectedEntry.id;\n\t\t\t} else {\n\t\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t\t\t}\n\t\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t\t}\n\n\t\t\tconst previousSessionFile = this.session.sessionFile;\n\t\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\t\tif (!currentSessionFile) {\n\t\t\t\t\tthrow new Error(\"Persisted session is missing a session file\");\n\t\t\t\t}\n\t\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\t\tif (!targetLeafId) {\n\t\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\t\tthis.apply(\n\t\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t\t}\n\n\t\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"This session has not been saved yet. Wait for the first assistant response before cloning or forking it.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// Validate and honor vetoes before closing admission, but settle owned\n\t\t\t\t// usage before reading the source file for the fork.\n\t\t\t\tconst forkingCurrentLeaf = targetLeafId === this.session.sessionManager.getLeafId();\n\t\t\t\tthis.session.background.close();\n\t\t\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\t\t\tif (forkingCurrentLeaf) targetLeafId = this.session.sessionManager.getLeafId()!;\n\t\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\t\tif (!forkedSessionPath) {\n\t\t\t\t\tthrow new Error(\"Failed to create forked session\");\n\t\t\t\t}\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tconst sessionManager = this.session.sessionManager;\n\t\t\tconst forkingCurrentLeaf = targetLeafId !== null && targetLeafId === sessionManager.getLeafId();\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tif (forkingCurrentLeaf) targetLeafId = sessionManager.getLeafId();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t\t} else {\n\t\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t\t}\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t} finally {\n\t\t\tresumeBackground();\n\t\t}\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @returns `{ cancelled: true }` when cancelled by `session_before_switch`, otherwise `{ cancelled: false }`.\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resumeBackground = this.session.pauseBackgroundNotifications();\n\t\ttry {\n\t\t\tconst resolvedPath = resolvePath(inputPath);\n\t\t\tif (!existsSync(resolvedPath)) {\n\t\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t\t}\n\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!existsSync(sessionDir)) {\n\t\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t\t}\n\n\t\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\t\tif (!sourceAlreadyStored) {\n\t\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\t\tlet suffix = 1;\n\t\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst beforeResult = await this.emitBeforeSwitch(\"resume\", destinationPath);\n\t\t\tif (beforeResult.cancelled) {\n\t\t\t\treturn beforeResult;\n\t\t\t}\n\n\t\t\tconst previousSessionFile = this.session.sessionFile;\n\t\t\tif (!sourceAlreadyStored) {\n\t\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t\t}\n\n\t\t\tlet sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\t\tsessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"resume\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement();\n\t\t\treturn { cancelled: false };\n\t\t} finally {\n\t\t\tresumeBackground();\n\t\t}\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.session.background.close();\n\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner, {\n\t\t\ttype: \"session_shutdown\",\n\t\t\treason: \"quit\",\n\t\t});\n\t\tthis.beforeSessionInvalidate?.();\n\t\tthis.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartEvent;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
|
|
1
|
+
{"version":3,"file":"agent-session-runtime.js","sourceRoot":"","sources":["../../src/core/agent-session-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { constants, copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, parse, resolve } from \"node:path\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { AgentSession } from \"./agent-session.ts\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.ts\";\nimport type {\n\tProjectTrustContext,\n\tReplacedSessionContext,\n\tSessionShutdownEvent,\n\tSessionStartEvent,\n} from \"./extensions/index.ts\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.ts\";\nimport type { CreateAgentSessionResult } from \"./sdk.ts\";\nimport { assertSessionCwdExists } from \"./session-cwd.ts\";\nimport { SessionManager } from \"./session-manager.ts\";\n\n/**\n * Result returned by runtime creation.\n *\n * The caller gets the created session, its cwd-bound services, and all\n * diagnostics collected during setup.\n */\nexport interface CreateAgentSessionRuntimeResult extends CreateAgentSessionResult {\n\tservices: AgentSessionServices;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\n/**\n * Creates a full runtime for a target cwd and session manager.\n *\n * The factory closes over process-global fixed inputs, recreates cwd-bound\n * services for the effective cwd, resolves session options against those\n * services, and finally creates the AgentSession.\n */\nexport type CreateAgentSessionRuntimeFactory = (options: {\n\tcwd: string;\n\tagentDir: string;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tprojectTrustContext?: ProjectTrustContext;\n}) => Promise<CreateAgentSessionRuntimeResult>;\n\n/**\n * Thrown when /import references a JSONL file path that does not exist.\n */\nexport class SessionImportFileNotFoundError extends Error {\n\treadonly filePath: string;\n\n\tconstructor(filePath: string) {\n\t\tsuper(`File not found: ${filePath}`);\n\t\tthis.name = \"SessionImportFileNotFoundError\";\n\t\tthis.filePath = filePath;\n\t}\n}\n\nfunction extractUserMessageText(content: string | Array<{ type: string; text?: string }>): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is { type: \"text\"; text: string } => part.type === \"text\" && typeof part.text === \"string\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\");\n}\n\n/**\n * Owns the current AgentSession plus its cwd-bound services.\n *\n * Session replacement methods tear down the current runtime first, then create\n * and apply the next runtime. If creation fails, the error is propagated to the\n * caller. The caller is responsible for user-facing error handling.\n */\nexport class AgentSessionRuntime {\n\tprivate rebindSession?: (session: AgentSession) => Promise<void>;\n\tprivate beforeSessionInvalidate?: () => void;\n\tprivate _session: AgentSession;\n\tprivate _services: AgentSessionServices;\n\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory;\n\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[];\n\tprivate _modelFallbackMessage?: string;\n\n\tconstructor(\n\t\t_session: AgentSession,\n\t\t_services: AgentSessionServices,\n\t\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\t\t_diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\t_modelFallbackMessage?: string,\n\t) {\n\t\tthis._session = _session;\n\t\tthis._services = _services;\n\t\tthis.createRuntime = createRuntime;\n\t\tthis._diagnostics = _diagnostics;\n\t\tthis._modelFallbackMessage = _modelFallbackMessage;\n\t}\n\n\tget services(): AgentSessionServices {\n\t\treturn this._services;\n\t}\n\n\tget session(): AgentSession {\n\t\treturn this._session;\n\t}\n\n\tget cwd(): string {\n\t\treturn this._services.cwd;\n\t}\n\n\tget diagnostics(): readonly AgentSessionRuntimeDiagnostic[] {\n\t\treturn this._diagnostics;\n\t}\n\n\tget modelFallbackMessage(): string | undefined {\n\t\treturn this._modelFallbackMessage;\n\t}\n\n\tsetRebindSession(rebindSession?: (session: AgentSession) => Promise<void>): void {\n\t\tthis.rebindSession = rebindSession;\n\t}\n\n\t/**\n\t * Set a synchronous callback that runs after `session_shutdown` handlers finish\n\t * but before the current session is invalidated.\n\t *\n\t * This is for host-owned UI teardown that must not yield to the event loop,\n\t * such as detaching extension-provided TUI components before the old extension\n\t * context becomes stale.\n\t */\n\tsetBeforeSessionInvalidate(beforeSessionInvalidate?: () => void): void {\n\t\tthis.beforeSessionInvalidate = beforeSessionInvalidate;\n\t}\n\n\tprivate async emitBeforeSwitch(\n\t\treason: \"new\" | \"resume\",\n\t\ttargetSessionFile?: string,\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst runner = this.session.extensionRunner;\n\t\tif (!runner.hasHandlers(\"session_before_switch\")) {\n\t\t\treturn { cancelled: false };\n\t\t}\n\n\t\tconst result = await runner.emit({\n\t\t\ttype: \"session_before_switch\",\n\t\t\treason,\n\t\t\ttargetSessionFile,\n\t\t});\n\t\treturn { cancelled: result?.cancel === true };\n\t}\n\n\tprivate async emitBeforeFork(\n\t\tentryId: string,\n\t\toptions: { position: \"before\" | \"at\" },\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst runner = this.session.extensionRunner;\n\t\tif (!runner.hasHandlers(\"session_before_fork\")) {\n\t\t\treturn { cancelled: false };\n\t\t}\n\n\t\tconst result = await runner.emit({\n\t\t\ttype: \"session_before_fork\",\n\t\t\tentryId,\n\t\t\t...options,\n\t\t});\n\t\treturn { cancelled: result?.cancel === true };\n\t}\n\n\tprivate async teardownCurrent(reason: SessionShutdownEvent[\"reason\"], targetSessionFile?: string): Promise<void> {\n\t\tthis.session.background.close();\n\t\t// Stop the main loop immediately too, while bounded worker cleanup runs.\n\t\t// Both must finish before extension shutdown and runtime invalidation.\n\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner, {\n\t\t\ttype: \"session_shutdown\",\n\t\t\treason,\n\t\t\ttargetSessionFile,\n\t\t});\n\t\tthis.beforeSessionInvalidate?.();\n\t\tthis.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tthis._session = result.session;\n\t\tthis._services = result.services;\n\t\tthis._diagnostics = result.diagnostics;\n\t\tthis._modelFallbackMessage = result.modelFallbackMessage;\n\t}\n\n\tprivate async finishSessionReplacement(withSession?: (ctx: ReplacedSessionContext) => Promise<void>): Promise<void> {\n\t\tif (this.rebindSession) {\n\t\t\tawait this.rebindSession(this.session);\n\t\t}\n\t\tif (withSession) {\n\t\t\tawait withSession(this.session.createReplacedSessionContext());\n\t\t}\n\t}\n\n\t/**\n\t * Hold the outgoing session's background delivery across a replacement. The\n\t * pause belongs to the session current at entry, not the replacement.\n\t */\n\tprivate async withBackgroundPaused<T>(operation: () => Promise<T>): Promise<T> {\n\t\tconst resumeBackground = this.session.pauseBackgroundNotifications();\n\t\ttry {\n\t\t\treturn await operation();\n\t\t} finally {\n\t\t\tresumeBackground();\n\t\t}\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t\tprojectTrustContextFactory?: (cwd: string) => ProjectTrustContext;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\treturn this.withBackgroundPaused(() => this.switchSessionBody(sessionPath, options));\n\t}\n\n\tprivate async switchSessionBody(\n\t\tsessionPath: string,\n\t\toptions?: {\n\t\t\tcwdOverride?: string;\n\t\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t\t\tprojectTrustContextFactory?: (cwd: string) => ProjectTrustContext;\n\t\t},\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst beforeResult = await this.emitBeforeSwitch(\"resume\", sessionPath);\n\t\tif (beforeResult.cancelled) {\n\t\t\treturn beforeResult;\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tlet sessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\t// Resuming the current file must include usage persisted during teardown.\n\t\tsessionManager = SessionManager.open(sessionPath, undefined, options?.cwdOverride);\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"resume\", previousSessionFile },\n\t\t\t\tprojectTrustContext: options?.projectTrustContextFactory?.(sessionManager.getCwd()),\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\treturn this.withBackgroundPaused(() => this.newSessionBody(options));\n\t}\n\n\tprivate async newSessionBody(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => Promise<void>;\n\t\twithSession?: (ctx: ReplacedSessionContext) => Promise<void>;\n\t}): Promise<{ cancelled: boolean }> {\n\t\tconst beforeResult = await this.emitBeforeSwitch(\"new\");\n\t\tif (beforeResult.cancelled) {\n\t\t\treturn beforeResult;\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tconst sessionManager = this.session.sessionManager.isPersisted()\n\t\t\t? SessionManager.create(this.cwd, sessionDir)\n\t\t\t: SessionManager.inMemory(this.cwd);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent(\"new\", sessionManager.getSessionFile());\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"new\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tif (options?.setup) {\n\t\t\tawait options.setup(this.session.sessionManager);\n\t\t\tthis.session.refreshContext();\n\t\t}\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\treturn this.withBackgroundPaused(() => this.forkBody(entryId, options));\n\t}\n\n\tprivate async forkBody(\n\t\tentryId: string,\n\t\toptions?: { position?: \"before\" | \"at\"; withSession?: (ctx: ReplacedSessionContext) => Promise<void> },\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst position = options?.position ?? \"before\";\n\t\tconst beforeResult = await this.emitBeforeFork(entryId, { position });\n\t\tif (beforeResult.cancelled) {\n\t\t\treturn { cancelled: true };\n\t\t}\n\t\tlet targetLeafId: string | null;\n\t\tlet selectedText: string | undefined;\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry) {\n\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t}\n\n\t\tif (position === \"at\") {\n\t\t\ttargetLeafId = selectedEntry.id;\n\t\t} else {\n\t\t\tif (selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t\t}\n\t\t\ttargetLeafId = selectedEntry.parentId;\n\t\t\tselectedText = extractUserMessageText(selectedEntry.message.content);\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (this.session.sessionManager.isPersisted()) {\n\t\t\tconst currentSessionFile = this.session.sessionFile;\n\t\t\tif (!currentSessionFile) {\n\t\t\t\tthrow new Error(\"Persisted session is missing a session file\");\n\t\t\t}\n\t\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\t\tif (!targetLeafId) {\n\t\t\t\tconst sessionManager = SessionManager.create(this.cwd, sessionDir);\n\t\t\t\tsessionManager.newSession({ parentSession: currentSessionFile });\n\t\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\t\tthis.apply(\n\t\t\t\t\tawait this.createRuntime({\n\t\t\t\t\t\tcwd: this.cwd,\n\t\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\t\tsessionManager,\n\t\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\t\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tif (!existsSync(currentSessionFile)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"This session has not been saved yet. Wait for the first assistant response before cloning or forking it.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Validate and honor vetoes before closing admission, but settle owned\n\t\t\t// usage before reading the source file for the fork.\n\t\t\tconst forkingCurrentLeaf = targetLeafId === this.session.sessionManager.getLeafId();\n\t\t\tthis.session.background.close();\n\t\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\t\tif (forkingCurrentLeaf) targetLeafId = this.session.sessionManager.getLeafId()!;\n\t\t\tconst sessionManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sessionManager.createBranchedSession(targetLeafId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(\"Failed to create forked session\");\n\t\t\t}\n\t\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\t\tthis.apply(\n\t\t\t\tawait this.createRuntime({\n\t\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\t\tsessionManager,\n\t\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t\t}),\n\t\t\t);\n\t\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\t\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tconst forkingCurrentLeaf = targetLeafId !== null && targetLeafId === sessionManager.getLeafId();\n\t\tawait this.teardownCurrent(\"fork\", sessionManager.getSessionFile());\n\t\tif (forkingCurrentLeaf) targetLeafId = sessionManager.getLeafId();\n\t\tif (!targetLeafId) {\n\t\t\tsessionManager.newSession({ parentSession: previousSessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(targetLeafId);\n\t\t}\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: this.cwd,\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"fork\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement(options?.withSession);\n\t\treturn { cancelled: false, selectedText };\n\t}\n\n\t/**\n\t * Import a session JSONL file and switch runtime state to the imported session.\n\t *\n\t * @returns `{ cancelled: true }` when cancelled by `session_before_switch`, otherwise `{ cancelled: false }`.\n\t * @throws {SessionImportFileNotFoundError} When the input path does not exist.\n\t * @throws {MissingSessionCwdError} When the imported session cwd cannot be resolved and no override is provided.\n\t */\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\treturn this.withBackgroundPaused(() => this.importFromJsonlBody(inputPath, cwdOverride));\n\t}\n\n\tprivate async importFromJsonlBody(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolvePath(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new SessionImportFileNotFoundError(resolvedPath);\n\t\t}\n\n\t\tconst sessionDir = this.session.sessionManager.getSessionDir();\n\t\tif (!existsSync(sessionDir)) {\n\t\t\tmkdirSync(sessionDir, { recursive: true });\n\t\t}\n\n\t\tlet destinationPath = join(sessionDir, basename(resolvedPath));\n\t\tconst sourceAlreadyStored = resolve(destinationPath) === resolvedPath;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tconst { name, ext } = parse(destinationPath);\n\t\t\tlet suffix = 1;\n\t\t\twhile (existsSync(destinationPath)) {\n\t\t\t\tdestinationPath = join(sessionDir, `${name}-${suffix++}${ext}`);\n\t\t\t}\n\t\t}\n\t\tconst beforeResult = await this.emitBeforeSwitch(\"resume\", destinationPath);\n\t\tif (beforeResult.cancelled) {\n\t\t\treturn beforeResult;\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tif (!sourceAlreadyStored) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath, constants.COPYFILE_EXCL);\n\t\t}\n\n\t\tlet sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tassertSessionCwdExists(sessionManager, this.cwd);\n\t\tawait this.teardownCurrent(\"resume\", sessionManager.getSessionFile());\n\t\tsessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);\n\t\tthis.apply(\n\t\t\tawait this.createRuntime({\n\t\t\t\tcwd: sessionManager.getCwd(),\n\t\t\t\tagentDir: this.services.agentDir,\n\t\t\t\tsessionManager,\n\t\t\t\tsessionStartEvent: { type: \"session_start\", reason: \"resume\", previousSessionFile },\n\t\t\t}),\n\t\t);\n\t\tawait this.finishSessionReplacement();\n\t\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.session.background.close();\n\t\tawait Promise.all([this.session.background.shutdown(), this.session.abort()]);\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner, {\n\t\t\ttype: \"session_shutdown\",\n\t\t\treason: \"quit\",\n\t\t});\n\t\tthis.beforeSessionInvalidate?.();\n\t\tthis.session.dispose();\n\t}\n}\n\n/**\n * Create the initial runtime from a runtime factory and initial session target.\n *\n * The same factory is stored on the returned AgentSessionRuntime and reused for\n * later /new, /resume, /fork, and import flows.\n */\nexport async function createAgentSessionRuntime(\n\tcreateRuntime: CreateAgentSessionRuntimeFactory,\n\toptions: {\n\t\tcwd: string;\n\t\tagentDir: string;\n\t\tsessionManager: SessionManager;\n\t\tsessionStartEvent?: SessionStartEvent;\n\t},\n): Promise<AgentSessionRuntime> {\n\tassertSessionCwdExists(options.sessionManager, options.cwd);\n\tconst result = await createRuntime(options);\n\treturn new AgentSessionRuntime(\n\t\tresult.session,\n\t\tresult.services,\n\t\tcreateRuntime,\n\t\tresult.diagnostics,\n\t\tresult.modelFallbackMessage,\n\t);\n}\n\nexport {\n\ttype AgentSessionRuntimeDiagnostic,\n\ttype AgentSessionServices,\n\ttype CreateAgentSessionFromServicesOptions,\n\ttype CreateAgentSessionServicesOptions,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./agent-session-services.ts\";\n"]}
|
|
@@ -275,6 +275,11 @@ export declare class AgentSession {
|
|
|
275
275
|
pauseBackgroundNotifications(): () => void;
|
|
276
276
|
/** Explicit retry after a host delivery failure; never spins on a timer by itself. */
|
|
277
277
|
retryBackgroundNotifications(): void;
|
|
278
|
+
/**
|
|
279
|
+
* Run a lifecycle operation with delivery paused across its asynchronous gaps.
|
|
280
|
+
* Lifecycle methods are thin shells over upstream bodies so those keep upstream's shape.
|
|
281
|
+
*/
|
|
282
|
+
private _withBackgroundPaused;
|
|
278
283
|
get modelRuntime(): ModelRuntime;
|
|
279
284
|
/** Capture stable state before any asynchronous context preparation. Never includes a partial stream. */
|
|
280
285
|
getContextSnapshot(): Promise<ContextSnapshot>;
|
|
@@ -307,7 +312,12 @@ export declare class AgentSession {
|
|
|
307
312
|
private _emitSessionCompactFailed;
|
|
308
313
|
private _getIdleWaitPromise;
|
|
309
314
|
private _resolveIdleWaitIfIdle;
|
|
315
|
+
/**
|
|
316
|
+
* Background completions stay paused until runs requested by settled handlers have started,
|
|
317
|
+
* so a deferred prompt never races a delivery for the same idle gap.
|
|
318
|
+
*/
|
|
310
319
|
private _emitAgentSettled;
|
|
320
|
+
private _emitAgentSettledBody;
|
|
311
321
|
/**
|
|
312
322
|
* Persist model/custom messages and consume queued context only after the append succeeds.
|
|
313
323
|
* Returns the persisted entry ID, which boundary events and recovery omissions resolve later.
|
|
@@ -628,6 +638,7 @@ export declare class AgentSession {
|
|
|
628
638
|
* @param customInstructions Optional instructions for the compaction summary
|
|
629
639
|
*/
|
|
630
640
|
compact(customInstructions?: string): Promise<CompactionResult>;
|
|
641
|
+
private _compactBody;
|
|
631
642
|
/**
|
|
632
643
|
* Cancel in-progress compaction (manual or auto).
|
|
633
644
|
*/
|
|
@@ -669,6 +680,7 @@ export declare class AgentSession {
|
|
|
669
680
|
* @returns Whether the post-run loop should call `agent.continue()`
|
|
670
681
|
*/
|
|
671
682
|
private _runAutoCompaction;
|
|
683
|
+
private _runAutoCompactionBody;
|
|
672
684
|
/**
|
|
673
685
|
* Toggle auto-compaction setting.
|
|
674
686
|
*/
|
|
@@ -676,6 +688,7 @@ export declare class AgentSession {
|
|
|
676
688
|
/** Whether auto-compaction is enabled */
|
|
677
689
|
get autoCompactionEnabled(): boolean;
|
|
678
690
|
bindExtensions(bindings: ExtensionBindings): Promise<void>;
|
|
691
|
+
private _bindExtensionsBody;
|
|
679
692
|
private extendResourcesFromExtensions;
|
|
680
693
|
private buildExtensionResourcePaths;
|
|
681
694
|
private getExtensionSourceLabel;
|
|
@@ -687,6 +700,7 @@ export declare class AgentSession {
|
|
|
687
700
|
reload(options?: {
|
|
688
701
|
beforeSessionStart?: () => void | Promise<void>;
|
|
689
702
|
}): Promise<void>;
|
|
703
|
+
private _reloadBody;
|
|
690
704
|
/**
|
|
691
705
|
* Check if an error is retryable (overloaded, rate limit, server errors).
|
|
692
706
|
* Context overflow errors are NOT retryable (handled by compaction instead).
|