@mariozechner/pi-coding-agent 0.63.2 → 0.65.0
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 +120 -0
- package/README.md +11 -5
- package/dist/cli/args.d.ts +7 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -15
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +83 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +232 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +116 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +10 -42
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +58 -237
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +2 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -2
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +1 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +20 -28
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +10 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +5 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +70 -8
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +14 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +13 -14
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-registry.d.ts +3 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +7 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +20 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +32 -0
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +21 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +5 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +13 -6
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +15 -4
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +2 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +205 -427
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +20 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +14 -3
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +4 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +48 -15
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +12 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +146 -96
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +6 -11
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +2 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +41 -36
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +95 -64
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts +4 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +234 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/docs/compaction.md +4 -2
- package/docs/extensions.md +133 -40
- package/docs/json.md +5 -2
- package/docs/keybindings.md +2 -0
- package/docs/rpc.md +21 -7
- package/docs/sdk.md +239 -83
- package/docs/settings.md +1 -1
- package/docs/tree.md +6 -3
- package/examples/extensions/README.md +1 -0
- 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/package.json +1 -1
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/hello.ts +18 -17
- package/examples/extensions/hidden-thinking-label.ts +53 -0
- package/examples/extensions/rpc-demo.ts +3 -9
- package/examples/extensions/sandbox/index.ts +4 -0
- package/examples/extensions/status-line.ts +0 -8
- package/examples/extensions/todo.ts +0 -2
- package/examples/extensions/tools.ts +0 -5
- package/examples/extensions/widget-placement.ts +4 -12
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/02-custom-model.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +3 -3
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +7 -4
- package/package.json +4 -4
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { basename, join, resolve } from "node:path";
|
|
3
|
+
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
4
|
+
import { SessionManager } from "./session-manager.js";
|
|
5
|
+
function extractUserMessageText(content) {
|
|
6
|
+
if (typeof content === "string") {
|
|
7
|
+
return content;
|
|
8
|
+
}
|
|
9
|
+
return content
|
|
10
|
+
.filter((part) => part.type === "text" && typeof part.text === "string")
|
|
11
|
+
.map((part) => part.text)
|
|
12
|
+
.join("");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Owns the current AgentSession plus its cwd-bound services.
|
|
16
|
+
*
|
|
17
|
+
* Session replacement methods tear down the current runtime first, then create
|
|
18
|
+
* and apply the next runtime. If creation fails, the error is propagated to the
|
|
19
|
+
* caller. The caller is responsible for user-facing error handling.
|
|
20
|
+
*/
|
|
21
|
+
export class AgentSessionRuntime {
|
|
22
|
+
_session;
|
|
23
|
+
_services;
|
|
24
|
+
createRuntime;
|
|
25
|
+
_diagnostics;
|
|
26
|
+
_modelFallbackMessage;
|
|
27
|
+
constructor(_session, _services, createRuntime, _diagnostics = [], _modelFallbackMessage) {
|
|
28
|
+
this._session = _session;
|
|
29
|
+
this._services = _services;
|
|
30
|
+
this.createRuntime = createRuntime;
|
|
31
|
+
this._diagnostics = _diagnostics;
|
|
32
|
+
this._modelFallbackMessage = _modelFallbackMessage;
|
|
33
|
+
}
|
|
34
|
+
get services() {
|
|
35
|
+
return this._services;
|
|
36
|
+
}
|
|
37
|
+
get session() {
|
|
38
|
+
return this._session;
|
|
39
|
+
}
|
|
40
|
+
get cwd() {
|
|
41
|
+
return this._services.cwd;
|
|
42
|
+
}
|
|
43
|
+
get diagnostics() {
|
|
44
|
+
return this._diagnostics;
|
|
45
|
+
}
|
|
46
|
+
get modelFallbackMessage() {
|
|
47
|
+
return this._modelFallbackMessage;
|
|
48
|
+
}
|
|
49
|
+
async emitBeforeSwitch(reason, targetSessionFile) {
|
|
50
|
+
const runner = this.session.extensionRunner;
|
|
51
|
+
if (!runner?.hasHandlers("session_before_switch")) {
|
|
52
|
+
return { cancelled: false };
|
|
53
|
+
}
|
|
54
|
+
const result = await runner.emit({
|
|
55
|
+
type: "session_before_switch",
|
|
56
|
+
reason,
|
|
57
|
+
targetSessionFile,
|
|
58
|
+
});
|
|
59
|
+
return { cancelled: result?.cancel === true };
|
|
60
|
+
}
|
|
61
|
+
async emitBeforeFork(entryId) {
|
|
62
|
+
const runner = this.session.extensionRunner;
|
|
63
|
+
if (!runner?.hasHandlers("session_before_fork")) {
|
|
64
|
+
return { cancelled: false };
|
|
65
|
+
}
|
|
66
|
+
const result = await runner.emit({
|
|
67
|
+
type: "session_before_fork",
|
|
68
|
+
entryId,
|
|
69
|
+
});
|
|
70
|
+
return { cancelled: result?.cancel === true };
|
|
71
|
+
}
|
|
72
|
+
async teardownCurrent() {
|
|
73
|
+
await emitSessionShutdownEvent(this.session.extensionRunner);
|
|
74
|
+
this.session.dispose();
|
|
75
|
+
}
|
|
76
|
+
apply(result) {
|
|
77
|
+
if (process.cwd() !== result.services.cwd) {
|
|
78
|
+
process.chdir(result.services.cwd);
|
|
79
|
+
}
|
|
80
|
+
this._session = result.session;
|
|
81
|
+
this._services = result.services;
|
|
82
|
+
this._diagnostics = result.diagnostics;
|
|
83
|
+
this._modelFallbackMessage = result.modelFallbackMessage;
|
|
84
|
+
}
|
|
85
|
+
async switchSession(sessionPath) {
|
|
86
|
+
const beforeResult = await this.emitBeforeSwitch("resume", sessionPath);
|
|
87
|
+
if (beforeResult.cancelled) {
|
|
88
|
+
return beforeResult;
|
|
89
|
+
}
|
|
90
|
+
const previousSessionFile = this.session.sessionFile;
|
|
91
|
+
const sessionManager = SessionManager.open(sessionPath);
|
|
92
|
+
await this.teardownCurrent();
|
|
93
|
+
this.apply(await this.createRuntime({
|
|
94
|
+
cwd: sessionManager.getCwd(),
|
|
95
|
+
agentDir: this.services.agentDir,
|
|
96
|
+
sessionManager,
|
|
97
|
+
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
98
|
+
}));
|
|
99
|
+
return { cancelled: false };
|
|
100
|
+
}
|
|
101
|
+
async newSession(options) {
|
|
102
|
+
const beforeResult = await this.emitBeforeSwitch("new");
|
|
103
|
+
if (beforeResult.cancelled) {
|
|
104
|
+
return beforeResult;
|
|
105
|
+
}
|
|
106
|
+
const previousSessionFile = this.session.sessionFile;
|
|
107
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
108
|
+
const sessionManager = SessionManager.create(this.cwd, sessionDir);
|
|
109
|
+
if (options?.parentSession) {
|
|
110
|
+
sessionManager.newSession({ parentSession: options.parentSession });
|
|
111
|
+
}
|
|
112
|
+
await this.teardownCurrent();
|
|
113
|
+
this.apply(await this.createRuntime({
|
|
114
|
+
cwd: this.cwd,
|
|
115
|
+
agentDir: this.services.agentDir,
|
|
116
|
+
sessionManager,
|
|
117
|
+
sessionStartEvent: { type: "session_start", reason: "new", previousSessionFile },
|
|
118
|
+
}));
|
|
119
|
+
if (options?.setup) {
|
|
120
|
+
await options.setup(this.session.sessionManager);
|
|
121
|
+
this.session.agent.state.messages = this.session.sessionManager.buildSessionContext().messages;
|
|
122
|
+
}
|
|
123
|
+
return { cancelled: false };
|
|
124
|
+
}
|
|
125
|
+
async fork(entryId) {
|
|
126
|
+
const beforeResult = await this.emitBeforeFork(entryId);
|
|
127
|
+
if (beforeResult.cancelled) {
|
|
128
|
+
return { cancelled: true };
|
|
129
|
+
}
|
|
130
|
+
const selectedEntry = this.session.sessionManager.getEntry(entryId);
|
|
131
|
+
if (!selectedEntry || selectedEntry.type !== "message" || selectedEntry.message.role !== "user") {
|
|
132
|
+
throw new Error("Invalid entry ID for forking");
|
|
133
|
+
}
|
|
134
|
+
const previousSessionFile = this.session.sessionFile;
|
|
135
|
+
const selectedText = extractUserMessageText(selectedEntry.message.content);
|
|
136
|
+
if (this.session.sessionManager.isPersisted()) {
|
|
137
|
+
const currentSessionFile = this.session.sessionFile;
|
|
138
|
+
if (!currentSessionFile) {
|
|
139
|
+
throw new Error("Persisted session is missing a session file");
|
|
140
|
+
}
|
|
141
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
142
|
+
if (!selectedEntry.parentId) {
|
|
143
|
+
const sessionManager = SessionManager.create(this.cwd, sessionDir);
|
|
144
|
+
sessionManager.newSession({ parentSession: currentSessionFile });
|
|
145
|
+
await this.teardownCurrent();
|
|
146
|
+
this.apply(await this.createRuntime({
|
|
147
|
+
cwd: this.cwd,
|
|
148
|
+
agentDir: this.services.agentDir,
|
|
149
|
+
sessionManager,
|
|
150
|
+
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
151
|
+
}));
|
|
152
|
+
return { cancelled: false, selectedText };
|
|
153
|
+
}
|
|
154
|
+
const sourceManager = SessionManager.open(currentSessionFile, sessionDir);
|
|
155
|
+
const forkedSessionPath = sourceManager.createBranchedSession(selectedEntry.parentId);
|
|
156
|
+
if (!forkedSessionPath) {
|
|
157
|
+
throw new Error("Failed to create forked session");
|
|
158
|
+
}
|
|
159
|
+
const sessionManager = SessionManager.open(forkedSessionPath, sessionDir);
|
|
160
|
+
await this.teardownCurrent();
|
|
161
|
+
this.apply(await this.createRuntime({
|
|
162
|
+
cwd: sessionManager.getCwd(),
|
|
163
|
+
agentDir: this.services.agentDir,
|
|
164
|
+
sessionManager,
|
|
165
|
+
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
166
|
+
}));
|
|
167
|
+
return { cancelled: false, selectedText };
|
|
168
|
+
}
|
|
169
|
+
const sessionManager = this.session.sessionManager;
|
|
170
|
+
if (!selectedEntry.parentId) {
|
|
171
|
+
sessionManager.newSession({ parentSession: this.session.sessionFile });
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
sessionManager.createBranchedSession(selectedEntry.parentId);
|
|
175
|
+
}
|
|
176
|
+
await this.teardownCurrent();
|
|
177
|
+
this.apply(await this.createRuntime({
|
|
178
|
+
cwd: this.cwd,
|
|
179
|
+
agentDir: this.services.agentDir,
|
|
180
|
+
sessionManager,
|
|
181
|
+
sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile },
|
|
182
|
+
}));
|
|
183
|
+
return { cancelled: false, selectedText };
|
|
184
|
+
}
|
|
185
|
+
async importFromJsonl(inputPath) {
|
|
186
|
+
const resolvedPath = resolve(inputPath);
|
|
187
|
+
if (!existsSync(resolvedPath)) {
|
|
188
|
+
throw new Error(`File not found: ${resolvedPath}`);
|
|
189
|
+
}
|
|
190
|
+
const sessionDir = this.session.sessionManager.getSessionDir();
|
|
191
|
+
if (!existsSync(sessionDir)) {
|
|
192
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
193
|
+
}
|
|
194
|
+
const destinationPath = join(sessionDir, basename(resolvedPath));
|
|
195
|
+
const beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
|
|
196
|
+
if (beforeResult.cancelled) {
|
|
197
|
+
return beforeResult;
|
|
198
|
+
}
|
|
199
|
+
const previousSessionFile = this.session.sessionFile;
|
|
200
|
+
if (resolve(destinationPath) !== resolvedPath) {
|
|
201
|
+
copyFileSync(resolvedPath, destinationPath);
|
|
202
|
+
}
|
|
203
|
+
const sessionManager = SessionManager.open(destinationPath, sessionDir);
|
|
204
|
+
await this.teardownCurrent();
|
|
205
|
+
this.apply(await this.createRuntime({
|
|
206
|
+
cwd: sessionManager.getCwd(),
|
|
207
|
+
agentDir: this.services.agentDir,
|
|
208
|
+
sessionManager,
|
|
209
|
+
sessionStartEvent: { type: "session_start", reason: "resume", previousSessionFile },
|
|
210
|
+
}));
|
|
211
|
+
return { cancelled: false };
|
|
212
|
+
}
|
|
213
|
+
async dispose() {
|
|
214
|
+
await emitSessionShutdownEvent(this.session.extensionRunner);
|
|
215
|
+
this.session.dispose();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create the initial runtime from a runtime factory and initial session target.
|
|
220
|
+
*
|
|
221
|
+
* The same factory is stored on the returned AgentSessionRuntime and reused for
|
|
222
|
+
* later /new, /resume, /fork, and import flows.
|
|
223
|
+
*/
|
|
224
|
+
export async function createAgentSessionRuntime(createRuntime, options) {
|
|
225
|
+
const result = await createRuntime(options);
|
|
226
|
+
if (process.cwd() !== result.services.cwd) {
|
|
227
|
+
process.chdir(result.services.cwd);
|
|
228
|
+
}
|
|
229
|
+
return new AgentSessionRuntime(result.session, result.services, createRuntime, result.diagnostics, result.modelFallbackMessage);
|
|
230
|
+
}
|
|
231
|
+
export { createAgentSessionFromServices, createAgentSessionServices, } from "./agent-session-services.js";
|
|
232
|
+
//# sourceMappingURL=agent-session-runtime.js.map
|
|
@@ -0,0 +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 { copyFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { basename, join, resolve } from \"node:path\";\nimport type { AgentSession } from \"./agent-session.js\";\nimport type { AgentSessionRuntimeDiagnostic, AgentSessionServices } from \"./agent-session-services.js\";\nimport type { SessionStartEvent } from \"./extensions/index.js\";\nimport { emitSessionShutdownEvent } from \"./extensions/runner.js\";\nimport type { CreateAgentSessionResult } from \"./sdk.js\";\nimport { SessionManager } from \"./session-manager.js\";\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}) => Promise<CreateAgentSessionRuntimeResult>;\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\tconstructor(\n\t\tprivate _session: AgentSession,\n\t\tprivate _services: AgentSessionServices,\n\t\tprivate readonly createRuntime: CreateAgentSessionRuntimeFactory,\n\t\tprivate _diagnostics: AgentSessionRuntimeDiagnostic[] = [],\n\t\tprivate _modelFallbackMessage?: string,\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\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(entryId: string): 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});\n\t\treturn { cancelled: result?.cancel === true };\n\t}\n\n\tprivate async teardownCurrent(): Promise<void> {\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner);\n\t\tthis.session.dispose();\n\t}\n\n\tprivate apply(result: CreateAgentSessionRuntimeResult): void {\n\t\tif (process.cwd() !== result.services.cwd) {\n\t\t\tprocess.chdir(result.services.cwd);\n\t\t}\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\tasync switchSession(sessionPath: string): 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\tconst sessionManager = SessionManager.open(sessionPath);\n\t\tawait this.teardownCurrent();\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\treturn { cancelled: false };\n\t}\n\n\tasync newSession(options?: {\n\t\tparentSession?: string;\n\t\tsetup?: (sessionManager: SessionManager) => 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 = SessionManager.create(this.cwd, sessionDir);\n\t\tif (options?.parentSession) {\n\t\t\tsessionManager.newSession({ parentSession: options.parentSession });\n\t\t}\n\n\t\tawait this.teardownCurrent();\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.agent.state.messages = this.session.sessionManager.buildSessionContext().messages;\n\t\t}\n\t\treturn { cancelled: false };\n\t}\n\n\tasync fork(entryId: string): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\tconst beforeResult = await this.emitBeforeFork(entryId);\n\t\tif (beforeResult.cancelled) {\n\t\t\treturn { cancelled: true };\n\t\t}\n\n\t\tconst selectedEntry = this.session.sessionManager.getEntry(entryId);\n\t\tif (!selectedEntry || selectedEntry.type !== \"message\" || selectedEntry.message.role !== \"user\") {\n\t\t\tthrow new Error(\"Invalid entry ID for forking\");\n\t\t}\n\n\t\tconst previousSessionFile = this.session.sessionFile;\n\t\tconst selectedText = extractUserMessageText(selectedEntry.message.content);\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 (!selectedEntry.parentId) {\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();\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\treturn { cancelled: false, selectedText };\n\t\t\t}\n\n\t\t\tconst sourceManager = SessionManager.open(currentSessionFile, sessionDir);\n\t\t\tconst forkedSessionPath = sourceManager.createBranchedSession(selectedEntry.parentId);\n\t\t\tif (!forkedSessionPath) {\n\t\t\t\tthrow new Error(\"Failed to create forked session\");\n\t\t\t}\n\t\t\tconst sessionManager = SessionManager.open(forkedSessionPath, sessionDir);\n\t\t\tawait this.teardownCurrent();\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\treturn { cancelled: false, selectedText };\n\t\t}\n\n\t\tconst sessionManager = this.session.sessionManager;\n\t\tif (!selectedEntry.parentId) {\n\t\t\tsessionManager.newSession({ parentSession: this.session.sessionFile });\n\t\t} else {\n\t\t\tsessionManager.createBranchedSession(selectedEntry.parentId);\n\t\t}\n\t\tawait this.teardownCurrent();\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\treturn { cancelled: false, selectedText };\n\t}\n\n\tasync importFromJsonl(inputPath: string): Promise<{ cancelled: boolean }> {\n\t\tconst resolvedPath = resolve(inputPath);\n\t\tif (!existsSync(resolvedPath)) {\n\t\t\tthrow new Error(`File not found: ${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\tconst destinationPath = join(sessionDir, basename(resolvedPath));\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 (resolve(destinationPath) !== resolvedPath) {\n\t\t\tcopyFileSync(resolvedPath, destinationPath);\n\t\t}\n\n\t\tconst sessionManager = SessionManager.open(destinationPath, sessionDir);\n\t\tawait this.teardownCurrent();\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\treturn { cancelled: false };\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tawait emitSessionShutdownEvent(this.session.extensionRunner);\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\tconst result = await createRuntime(options);\n\tif (process.cwd() !== result.services.cwd) {\n\t\tprocess.chdir(result.services.cwd);\n\t}\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.js\";\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
|
|
2
|
+
import type { Model } from "@mariozechner/pi-ai";
|
|
3
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
4
|
+
import type { SessionStartEvent, ToolDefinition } from "./extensions/index.js";
|
|
5
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
6
|
+
import { type DefaultResourceLoaderOptions, type ResourceLoader } from "./resource-loader.js";
|
|
7
|
+
import { type CreateAgentSessionResult } from "./sdk.js";
|
|
8
|
+
import type { SessionManager } from "./session-manager.js";
|
|
9
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
10
|
+
import type { Tool } from "./tools/index.js";
|
|
11
|
+
/**
|
|
12
|
+
* Non-fatal issues collected while creating services or sessions.
|
|
13
|
+
*
|
|
14
|
+
* Runtime creation returns diagnostics to the caller instead of printing or
|
|
15
|
+
* exiting. The app layer decides whether warnings should be shown and whether
|
|
16
|
+
* errors should abort startup.
|
|
17
|
+
*/
|
|
18
|
+
export interface AgentSessionRuntimeDiagnostic {
|
|
19
|
+
type: "info" | "warning" | "error";
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Inputs for creating cwd-bound runtime services.
|
|
24
|
+
*
|
|
25
|
+
* These services are recreated whenever the effective session cwd changes.
|
|
26
|
+
* CLI-provided resource paths should be resolved to absolute paths before they
|
|
27
|
+
* reach this function, so later cwd switches do not reinterpret them.
|
|
28
|
+
*/
|
|
29
|
+
export interface CreateAgentSessionServicesOptions {
|
|
30
|
+
cwd: string;
|
|
31
|
+
agentDir?: string;
|
|
32
|
+
authStorage?: AuthStorage;
|
|
33
|
+
settingsManager?: SettingsManager;
|
|
34
|
+
modelRegistry?: ModelRegistry;
|
|
35
|
+
extensionFlagValues?: Map<string, boolean | string>;
|
|
36
|
+
resourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, "cwd" | "agentDir" | "settingsManager">;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Inputs for creating an AgentSession from already-created services.
|
|
40
|
+
*
|
|
41
|
+
* Use this after services exist and any cwd-bound model/tool/session options
|
|
42
|
+
* have been resolved against those services.
|
|
43
|
+
*/
|
|
44
|
+
export interface CreateAgentSessionFromServicesOptions {
|
|
45
|
+
services: AgentSessionServices;
|
|
46
|
+
sessionManager: SessionManager;
|
|
47
|
+
sessionStartEvent?: SessionStartEvent;
|
|
48
|
+
model?: Model<any>;
|
|
49
|
+
thinkingLevel?: ThinkingLevel;
|
|
50
|
+
scopedModels?: Array<{
|
|
51
|
+
model: Model<any>;
|
|
52
|
+
thinkingLevel?: ThinkingLevel;
|
|
53
|
+
}>;
|
|
54
|
+
tools?: Tool[];
|
|
55
|
+
customTools?: ToolDefinition[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Coherent cwd-bound runtime services for one effective session cwd.
|
|
59
|
+
*
|
|
60
|
+
* This is infrastructure only. The AgentSession itself is created separately so
|
|
61
|
+
* session options can be resolved against these services first.
|
|
62
|
+
*/
|
|
63
|
+
export interface AgentSessionServices {
|
|
64
|
+
cwd: string;
|
|
65
|
+
agentDir: string;
|
|
66
|
+
authStorage: AuthStorage;
|
|
67
|
+
settingsManager: SettingsManager;
|
|
68
|
+
modelRegistry: ModelRegistry;
|
|
69
|
+
resourceLoader: ResourceLoader;
|
|
70
|
+
diagnostics: AgentSessionRuntimeDiagnostic[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create cwd-bound runtime services.
|
|
74
|
+
*
|
|
75
|
+
* Returns services plus diagnostics. It does not create an AgentSession.
|
|
76
|
+
*/
|
|
77
|
+
export declare function createAgentSessionServices(options: CreateAgentSessionServicesOptions): Promise<AgentSessionServices>;
|
|
78
|
+
/**
|
|
79
|
+
* Create an AgentSession from previously created services.
|
|
80
|
+
*
|
|
81
|
+
* This keeps session creation separate from service creation so callers can
|
|
82
|
+
* resolve model, thinking, tools, and other session inputs against the target
|
|
83
|
+
* cwd before constructing the session.
|
|
84
|
+
*/
|
|
85
|
+
export declare function createAgentSessionFromServices(options: CreateAgentSessionFromServicesOptions): Promise<CreateAgentSessionResult>;
|
|
86
|
+
//# sourceMappingURL=agent-session-services.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session-services.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAyB,KAAK,4BAA4B,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACrH,OAAO,EAAE,KAAK,wBAAwB,EAAsB,MAAM,UAAU,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,WAAW,6BAA6B;IAC7C,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iCAAiC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IACpD,qBAAqB,CAAC,EAAE,IAAI,CAAC,4BAA4B,EAAE,KAAK,GAAG,UAAU,GAAG,iBAAiB,CAAC,CAAC;CACnG;AAED;;;;;GAKG;AACH,MAAM,WAAW,qCAAqC;IACrD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,aAAa,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3E,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,6BAA6B,EAAE,CAAC;CAC7C;AAkDD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,iCAAiC,GACxC,OAAO,CAAC,oBAAoB,CAAC,CAuC/B;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CACnD,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,wBAAwB,CAAC,CAgBnC","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport { getAgentDir } from \"../config.js\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { DefaultResourceLoader, type DefaultResourceLoaderOptions, type ResourceLoader } from \"./resource-loader.js\";\nimport { type CreateAgentSessionResult, createAgentSession } from \"./sdk.js\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport { SettingsManager } from \"./settings-manager.js\";\nimport type { Tool } from \"./tools/index.js\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tauthStorage?: AuthStorage;\n\tsettingsManager?: SettingsManager;\n\tmodelRegistry?: ModelRegistry;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: Tool[];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tauthStorage: AuthStorage;\n\tsettingsManager: SettingsManager;\n\tmodelRegistry: ModelRegistry;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = options.cwd;\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst authStorage = options.authStorage ?? AuthStorage.create(join(agentDir, \"auth.json\"));\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, join(agentDir, \"models.json\"));\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload();\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRegistry.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tauthStorage,\n\t\tsettingsManager,\n\t\tmodelRegistry,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tauthStorage: options.services.authStorage,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tmodelRegistry: options.services.modelRegistry,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { getAgentDir } from "../config.js";
|
|
3
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
4
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
5
|
+
import { DefaultResourceLoader } from "./resource-loader.js";
|
|
6
|
+
import { createAgentSession } from "./sdk.js";
|
|
7
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
8
|
+
function applyExtensionFlagValues(resourceLoader, extensionFlagValues) {
|
|
9
|
+
if (!extensionFlagValues) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const diagnostics = [];
|
|
13
|
+
const extensionsResult = resourceLoader.getExtensions();
|
|
14
|
+
const registeredFlags = new Map();
|
|
15
|
+
for (const extension of extensionsResult.extensions) {
|
|
16
|
+
for (const [name, flag] of extension.flags) {
|
|
17
|
+
registeredFlags.set(name, { type: flag.type });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const unknownFlags = [];
|
|
21
|
+
for (const [name, value] of extensionFlagValues) {
|
|
22
|
+
const flag = registeredFlags.get(name);
|
|
23
|
+
if (!flag) {
|
|
24
|
+
unknownFlags.push(name);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (flag.type === "boolean") {
|
|
28
|
+
extensionsResult.runtime.flagValues.set(name, true);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "string") {
|
|
32
|
+
extensionsResult.runtime.flagValues.set(name, value);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
diagnostics.push({
|
|
36
|
+
type: "error",
|
|
37
|
+
message: `Extension flag "--${name}" requires a value`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (unknownFlags.length > 0) {
|
|
41
|
+
diagnostics.push({
|
|
42
|
+
type: "error",
|
|
43
|
+
message: `Unknown option${unknownFlags.length === 1 ? "" : "s"}: ${unknownFlags.map((name) => `--${name}`).join(", ")}`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return diagnostics;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create cwd-bound runtime services.
|
|
50
|
+
*
|
|
51
|
+
* Returns services plus diagnostics. It does not create an AgentSession.
|
|
52
|
+
*/
|
|
53
|
+
export async function createAgentSessionServices(options) {
|
|
54
|
+
const cwd = options.cwd;
|
|
55
|
+
const agentDir = options.agentDir ?? getAgentDir();
|
|
56
|
+
const authStorage = options.authStorage ?? AuthStorage.create(join(agentDir, "auth.json"));
|
|
57
|
+
const settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);
|
|
58
|
+
const modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, join(agentDir, "models.json"));
|
|
59
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
60
|
+
...(options.resourceLoaderOptions ?? {}),
|
|
61
|
+
cwd,
|
|
62
|
+
agentDir,
|
|
63
|
+
settingsManager,
|
|
64
|
+
});
|
|
65
|
+
await resourceLoader.reload();
|
|
66
|
+
const diagnostics = [];
|
|
67
|
+
const extensionsResult = resourceLoader.getExtensions();
|
|
68
|
+
for (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {
|
|
69
|
+
try {
|
|
70
|
+
modelRegistry.registerProvider(name, config);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
74
|
+
diagnostics.push({
|
|
75
|
+
type: "error",
|
|
76
|
+
message: `Extension "${extensionPath}" error: ${message}`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
extensionsResult.runtime.pendingProviderRegistrations = [];
|
|
81
|
+
diagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));
|
|
82
|
+
return {
|
|
83
|
+
cwd,
|
|
84
|
+
agentDir,
|
|
85
|
+
authStorage,
|
|
86
|
+
settingsManager,
|
|
87
|
+
modelRegistry,
|
|
88
|
+
resourceLoader,
|
|
89
|
+
diagnostics,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create an AgentSession from previously created services.
|
|
94
|
+
*
|
|
95
|
+
* This keeps session creation separate from service creation so callers can
|
|
96
|
+
* resolve model, thinking, tools, and other session inputs against the target
|
|
97
|
+
* cwd before constructing the session.
|
|
98
|
+
*/
|
|
99
|
+
export async function createAgentSessionFromServices(options) {
|
|
100
|
+
return createAgentSession({
|
|
101
|
+
cwd: options.services.cwd,
|
|
102
|
+
agentDir: options.services.agentDir,
|
|
103
|
+
authStorage: options.services.authStorage,
|
|
104
|
+
settingsManager: options.services.settingsManager,
|
|
105
|
+
modelRegistry: options.services.modelRegistry,
|
|
106
|
+
resourceLoader: options.services.resourceLoader,
|
|
107
|
+
sessionManager: options.sessionManager,
|
|
108
|
+
model: options.model,
|
|
109
|
+
thinkingLevel: options.thinkingLevel,
|
|
110
|
+
scopedModels: options.scopedModels,
|
|
111
|
+
tools: options.tools,
|
|
112
|
+
customTools: options.customTools,
|
|
113
|
+
sessionStartEvent: options.sessionStartEvent,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=agent-session-services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-session-services.js","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport { getAgentDir } from \"../config.js\";\nimport { AuthStorage } from \"./auth-storage.js\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { DefaultResourceLoader, type DefaultResourceLoaderOptions, type ResourceLoader } from \"./resource-loader.js\";\nimport { type CreateAgentSessionResult, createAgentSession } from \"./sdk.js\";\nimport type { SessionManager } from \"./session-manager.js\";\nimport { SettingsManager } from \"./settings-manager.js\";\nimport type { Tool } from \"./tools/index.js\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tauthStorage?: AuthStorage;\n\tsettingsManager?: SettingsManager;\n\tmodelRegistry?: ModelRegistry;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: Tool[];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tauthStorage: AuthStorage;\n\tsettingsManager: SettingsManager;\n\tmodelRegistry: ModelRegistry;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = options.cwd;\n\tconst agentDir = options.agentDir ?? getAgentDir();\n\tconst authStorage = options.authStorage ?? AuthStorage.create(join(agentDir, \"auth.json\"));\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst modelRegistry = options.modelRegistry ?? ModelRegistry.create(authStorage, join(agentDir, \"models.json\"));\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload();\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRegistry.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tauthStorage,\n\t\tsettingsManager,\n\t\tmodelRegistry,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tauthStorage: options.services.authStorage,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tmodelRegistry: options.services.modelRegistry,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
|
|
@@ -16,14 +16,14 @@ import type { Agent, AgentEvent, AgentMessage, AgentState, AgentTool, ThinkingLe
|
|
|
16
16
|
import type { ImageContent, Model, TextContent } from "@mariozechner/pi-ai";
|
|
17
17
|
import { type BashResult } from "./bash-executor.js";
|
|
18
18
|
import { type CompactionResult } from "./compaction/index.js";
|
|
19
|
-
import { type ContextUsage, type ExtensionCommandContextActions, type ExtensionErrorListener, ExtensionRunner, type ExtensionUIContext, type InputSource, type ShutdownHandler, type ToolDefinition, type ToolInfo } from "./extensions/index.js";
|
|
19
|
+
import { type ContextUsage, type ExtensionCommandContextActions, type ExtensionErrorListener, ExtensionRunner, type ExtensionUIContext, type InputSource, type SessionStartEvent, type ShutdownHandler, type ToolDefinition, type ToolInfo } from "./extensions/index.js";
|
|
20
20
|
import type { CustomMessage } from "./messages.js";
|
|
21
21
|
import type { ModelRegistry } from "./model-registry.js";
|
|
22
22
|
import { type PromptTemplate } from "./prompt-templates.js";
|
|
23
23
|
import type { ResourceLoader } from "./resource-loader.js";
|
|
24
24
|
import type { BranchSummaryEntry, SessionManager } from "./session-manager.js";
|
|
25
25
|
import type { SettingsManager } from "./settings-manager.js";
|
|
26
|
-
import type
|
|
26
|
+
import { type BashOperations } from "./tools/bash.js";
|
|
27
27
|
/** Parsed skill block from a user message */
|
|
28
28
|
export interface ParsedSkillBlock {
|
|
29
29
|
name: string;
|
|
@@ -38,6 +38,10 @@ export interface ParsedSkillBlock {
|
|
|
38
38
|
export declare function parseSkillBlock(text: string): ParsedSkillBlock | null;
|
|
39
39
|
/** Session-specific events that extend the core AgentEvent */
|
|
40
40
|
export type AgentSessionEvent = AgentEvent | {
|
|
41
|
+
type: "queue_update";
|
|
42
|
+
steering: readonly string[];
|
|
43
|
+
followUp: readonly string[];
|
|
44
|
+
} | {
|
|
41
45
|
type: "compaction_start";
|
|
42
46
|
reason: "manual" | "threshold" | "overflow";
|
|
43
47
|
} | {
|
|
@@ -90,6 +94,8 @@ export interface AgentSessionConfig {
|
|
|
90
94
|
extensionRunnerRef?: {
|
|
91
95
|
current?: ExtensionRunner;
|
|
92
96
|
};
|
|
97
|
+
/** Session start event metadata emitted when extensions bind to this runtime. */
|
|
98
|
+
sessionStartEvent?: SessionStartEvent;
|
|
93
99
|
}
|
|
94
100
|
export interface ExtensionBindings {
|
|
95
101
|
uiContext?: ExtensionUIContext;
|
|
@@ -167,6 +173,7 @@ export declare class AgentSession {
|
|
|
167
173
|
private _extensionRunnerRef?;
|
|
168
174
|
private _initialActiveToolNames?;
|
|
169
175
|
private _baseToolsOverride?;
|
|
176
|
+
private _sessionStartEvent;
|
|
170
177
|
private _extensionUIContext?;
|
|
171
178
|
private _extensionCommandContextActions?;
|
|
172
179
|
private _extensionShutdownHandler?;
|
|
@@ -193,6 +200,7 @@ export declare class AgentSession {
|
|
|
193
200
|
private _installAgentToolHooks;
|
|
194
201
|
/** Emit an event to all listeners */
|
|
195
202
|
private _emit;
|
|
203
|
+
private _emitQueueUpdate;
|
|
196
204
|
private _lastAssistantMessage;
|
|
197
205
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
198
206
|
private _handleAgentEvent;
|
|
@@ -372,18 +380,6 @@ export declare class AgentSession {
|
|
|
372
380
|
* Abort current operation and wait for agent to become idle.
|
|
373
381
|
*/
|
|
374
382
|
abort(): Promise<void>;
|
|
375
|
-
/**
|
|
376
|
-
* Start a new session, optionally with initial messages and parent tracking.
|
|
377
|
-
* Clears all messages and starts a new session.
|
|
378
|
-
* Listeners are preserved and will continue receiving events.
|
|
379
|
-
* @param options.parentSession - Optional parent session path for tracking
|
|
380
|
-
* @param options.setup - Optional callback to initialize session (e.g., append messages)
|
|
381
|
-
* @returns true if completed, false if cancelled by extension
|
|
382
|
-
*/
|
|
383
|
-
newSession(options?: {
|
|
384
|
-
parentSession?: string;
|
|
385
|
-
setup?: (sessionManager: SessionManager) => Promise<void>;
|
|
386
|
-
}): Promise<boolean>;
|
|
387
383
|
private _emitModelSelect;
|
|
388
384
|
/**
|
|
389
385
|
* Set model directly.
|
|
@@ -398,7 +394,6 @@ export declare class AgentSession {
|
|
|
398
394
|
* @returns The new model info, or undefined if only one model available
|
|
399
395
|
*/
|
|
400
396
|
cycleModel(direction?: "forward" | "backward"): Promise<ModelCycleResult | undefined>;
|
|
401
|
-
private _getScopedModelsWithAuth;
|
|
402
397
|
private _cycleScopedModel;
|
|
403
398
|
private _cycleAvailableModel;
|
|
404
399
|
/**
|
|
@@ -520,30 +515,10 @@ export declare class AgentSession {
|
|
|
520
515
|
* Called after agent turn completes to maintain proper message ordering.
|
|
521
516
|
*/
|
|
522
517
|
private _flushPendingBashMessages;
|
|
523
|
-
/**
|
|
524
|
-
* Switch to a different session file.
|
|
525
|
-
* Aborts current operation, loads messages, restores model/thinking.
|
|
526
|
-
* Listeners are preserved and will continue receiving events.
|
|
527
|
-
* @returns true if switch completed, false if cancelled by extension
|
|
528
|
-
*/
|
|
529
|
-
switchSession(sessionPath: string): Promise<boolean>;
|
|
530
518
|
/**
|
|
531
519
|
* Set a display name for the current session.
|
|
532
520
|
*/
|
|
533
521
|
setSessionName(name: string): void;
|
|
534
|
-
/**
|
|
535
|
-
* Create a fork from a specific entry.
|
|
536
|
-
* Emits before_fork/fork session events to extensions.
|
|
537
|
-
*
|
|
538
|
-
* @param entryId ID of the entry to fork from
|
|
539
|
-
* @returns Object with:
|
|
540
|
-
* - selectedText: The text of the selected user message (for editor pre-fill)
|
|
541
|
-
* - cancelled: True if an extension cancelled the fork
|
|
542
|
-
*/
|
|
543
|
-
fork(entryId: string): Promise<{
|
|
544
|
-
selectedText: string;
|
|
545
|
-
cancelled: boolean;
|
|
546
|
-
}>;
|
|
547
522
|
/**
|
|
548
523
|
* Navigate to a different node in the session tree.
|
|
549
524
|
* Unlike fork() which creates a new session file, this stays in the same file.
|
|
@@ -592,13 +567,6 @@ export declare class AgentSession {
|
|
|
592
567
|
* @returns The resolved output file path.
|
|
593
568
|
*/
|
|
594
569
|
exportToJsonl(outputPath?: string): string;
|
|
595
|
-
/**
|
|
596
|
-
* Import a JSONL session file.
|
|
597
|
-
* Copies the file into the session directory and switches to it (like /resume).
|
|
598
|
-
* @param inputPath Path to the JSONL file to import.
|
|
599
|
-
* @returns true if the session was switched successfully.
|
|
600
|
-
*/
|
|
601
|
-
importFromJsonl(inputPath: string): Promise<boolean>;
|
|
602
570
|
/**
|
|
603
571
|
* Get text content of last assistant message.
|
|
604
572
|
* Useful for /copy command.
|