@astralyn/pi 0.84.5 → 0.84.7
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 +35 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -0
- package/dist/core/agent-session.js.map +1 -1
- 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/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +6 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +11 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/extensions/background/index.d.ts +95 -20
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +470 -136
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/background/manager.d.ts +14 -0
- package/dist/extensions/background/manager.d.ts.map +1 -1
- package/dist/extensions/background/manager.js +125 -24
- package/dist/extensions/background/manager.js.map +1 -1
- package/dist/extensions/background/registry.d.ts +82 -0
- package/dist/extensions/background/registry.d.ts.map +1 -1
- package/dist/extensions/background/registry.js +237 -6
- package/dist/extensions/background/registry.js.map +1 -1
- package/dist/extensions/background/render.d.ts +35 -11
- package/dist/extensions/background/render.d.ts.map +1 -1
- package/dist/extensions/background/render.js +180 -30
- package/dist/extensions/background/render.js.map +1 -1
- package/dist/extensions/router/dialog-host.d.ts +60 -0
- package/dist/extensions/router/dialog-host.d.ts.map +1 -0
- package/dist/extensions/router/dialog-host.js +196 -0
- package/dist/extensions/router/dialog-host.js.map +1 -0
- package/dist/extensions/router/probe.d.ts.map +1 -1
- package/dist/extensions/router/probe.js +2 -0
- package/dist/extensions/router/probe.js.map +1 -1
- package/dist/extensions/router/ui.d.ts.map +1 -1
- package/dist/extensions/router/ui.js +117 -67
- package/dist/extensions/router/ui.js.map +1 -1
- package/dist/extensions/subagent/activity.d.ts +3 -5
- package/dist/extensions/subagent/activity.d.ts.map +1 -1
- package/dist/extensions/subagent/activity.js +8 -89
- package/dist/extensions/subagent/activity.js.map +1 -1
- package/dist/extensions/subagent/agents-command.d.ts.map +1 -1
- package/dist/extensions/subagent/agents-command.js +391 -161
- package/dist/extensions/subagent/agents-command.js.map +1 -1
- package/dist/extensions/subagent/agents.d.ts +2 -0
- package/dist/extensions/subagent/agents.d.ts.map +1 -1
- package/dist/extensions/subagent/agents.js +7 -1
- package/dist/extensions/subagent/agents.js.map +1 -1
- package/dist/extensions/subagent/budget.d.ts +15 -0
- package/dist/extensions/subagent/budget.d.ts.map +1 -0
- package/dist/extensions/subagent/budget.js +96 -0
- package/dist/extensions/subagent/budget.js.map +1 -0
- package/dist/extensions/subagent/cancellation.d.ts +29 -0
- package/dist/extensions/subagent/cancellation.d.ts.map +1 -0
- package/dist/extensions/subagent/cancellation.js +73 -0
- package/dist/extensions/subagent/cancellation.js.map +1 -0
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +5 -22
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent/model-selection.d.ts +16 -0
- package/dist/extensions/subagent/model-selection.d.ts.map +1 -0
- package/dist/extensions/subagent/model-selection.js +51 -0
- package/dist/extensions/subagent/model-selection.js.map +1 -0
- package/dist/extensions/subagent/render.d.ts +6 -1
- package/dist/extensions/subagent/render.d.ts.map +1 -1
- package/dist/extensions/subagent/render.js +23 -12
- package/dist/extensions/subagent/render.js.map +1 -1
- package/dist/extensions/subagent/resolve.d.ts.map +1 -1
- package/dist/extensions/subagent/resolve.js +2 -21
- package/dist/extensions/subagent/resolve.js.map +1 -1
- package/dist/extensions/subagent/runner.d.ts +4 -5
- package/dist/extensions/subagent/runner.d.ts.map +1 -1
- package/dist/extensions/subagent/runner.js +71 -264
- package/dist/extensions/subagent/runner.js.map +1 -1
- package/dist/extensions/subagent/sdk-runner.d.ts +13 -11
- package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
- package/dist/extensions/subagent/sdk-runner.js +167 -148
- package/dist/extensions/subagent/sdk-runner.js.map +1 -1
- package/dist/extensions/subagent/settings.d.ts.map +1 -1
- package/dist/extensions/subagent/settings.js +11 -4
- package/dist/extensions/subagent/settings.js.map +1 -1
- package/dist/extensions/subagent/state.d.ts +89 -0
- package/dist/extensions/subagent/state.d.ts.map +1 -0
- package/dist/extensions/subagent/state.js +294 -0
- package/dist/extensions/subagent/state.js.map +1 -0
- package/dist/extensions/subagent/text.d.ts +4 -0
- package/dist/extensions/subagent/text.d.ts.map +1 -1
- package/dist/extensions/subagent/text.js +75 -0
- package/dist/extensions/subagent/text.js.map +1 -1
- package/dist/extensions/subagent/types.d.ts +3 -8
- package/dist/extensions/subagent/types.d.ts.map +1 -1
- package/dist/extensions/subagent/types.js.map +1 -1
- package/dist/extensions/subagent/ui/choices.d.ts +36 -0
- package/dist/extensions/subagent/ui/choices.d.ts.map +1 -0
- package/dist/extensions/subagent/ui/choices.js +54 -0
- package/dist/extensions/subagent/ui/choices.js.map +1 -0
- package/dist/extensions/subagent/ui/model-list.d.ts +1 -0
- package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -1
- package/dist/extensions/subagent/ui/model-list.js +15 -18
- package/dist/extensions/subagent/ui/model-list.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/background.md +55 -20
- package/docs/extensions.md +13 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/extensions/subagent/retry.d.ts +0 -17
- package/dist/extensions/subagent/retry.d.ts.map +0 -1
- package/dist/extensions/subagent/retry.js +0 -41
- package/dist/extensions/subagent/retry.js.map +0 -1
|
@@ -2,9 +2,7 @@ import { DefaultResourceLoader } from "../../core/resource-loader.js";
|
|
|
2
2
|
import { createAgentSession } from "../../core/sdk.js";
|
|
3
3
|
import { SessionManager } from "../../core/session-manager.js";
|
|
4
4
|
import { SettingsManager } from "../../core/settings-manager.js";
|
|
5
|
-
import {
|
|
6
|
-
import { ERROR_TEXT_LIMIT, TASK_OUTPUT_LIMIT } from "./constants.js";
|
|
7
|
-
import { beginSubagentRetry, clearSubagentRetry } from "./retry.js";
|
|
5
|
+
import { finalAssistantText } from "./activity.js";
|
|
8
6
|
function workerSystemPrompt(base, task) {
|
|
9
7
|
return [
|
|
10
8
|
base,
|
|
@@ -54,53 +52,63 @@ function createThrottledEmitter(onProgress) {
|
|
|
54
52
|
},
|
|
55
53
|
};
|
|
56
54
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
// Neither resource loading nor session creation takes an abort signal, and
|
|
56
|
+
// both can hang on network work; race both against the scope. The losing
|
|
57
|
+
// chain keeps running, so its eventual result or rejection is always
|
|
58
|
+
// consumed by a no-op handler.
|
|
59
|
+
async function raceInitialization(chain, scope) {
|
|
60
|
+
return new Promise((resolve) => {
|
|
61
|
+
let settled = false;
|
|
62
|
+
const finish = (outcome) => {
|
|
63
|
+
if (settled)
|
|
64
|
+
return;
|
|
65
|
+
settled = true;
|
|
66
|
+
scope.signal.removeEventListener("abort", onAbort);
|
|
67
|
+
resolve(outcome);
|
|
68
|
+
};
|
|
69
|
+
const onAbort = () => {
|
|
70
|
+
finish({ kind: "aborted" });
|
|
71
|
+
};
|
|
72
|
+
if (scope.signal.aborted) {
|
|
73
|
+
onAbort();
|
|
74
|
+
void chain.then(() => undefined, () => undefined);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
scope.signal.addEventListener("abort", onAbort, { once: true });
|
|
78
|
+
void chain.then((outcome) => finish(outcome), (error) => finish({ kind: "error", error }));
|
|
79
|
+
});
|
|
68
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Runs one worker attempt as a pure adapter: it owns the worker session's
|
|
83
|
+
* lifecycle and translates AgentSessionEvents into SubagentRunEvents; every
|
|
84
|
+
* state transition happens in the reducer on the other side of dispatch.
|
|
85
|
+
*/
|
|
69
86
|
export async function runSdkTask(options) {
|
|
70
|
-
const { task,
|
|
87
|
+
const { task, scope, dispatch, modelRuntime, agentDir, projectTrusted, onProgress } = options;
|
|
71
88
|
const throttled = createThrottledEmitter(onProgress);
|
|
72
89
|
let unsubscribe;
|
|
73
90
|
let unregisterAbort;
|
|
74
91
|
let session;
|
|
75
|
-
|
|
92
|
+
// Streaming updates carry no semantic weight; the settled messages are
|
|
93
|
+
// where usage is accounted, and worker sessions can replay them.
|
|
76
94
|
const seenAssistantMessages = new Set();
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
run.status = "aborted";
|
|
81
|
-
run.error ??= "Subagent was aborted.";
|
|
82
|
-
initializationAbortController.abort();
|
|
95
|
+
const emitImmediate = () => onProgress?.();
|
|
96
|
+
const emitThrottled = throttled.emit;
|
|
97
|
+
unregisterAbort = scope.onAbort(async () => {
|
|
83
98
|
if (session)
|
|
84
99
|
await session.abort();
|
|
85
|
-
};
|
|
86
|
-
const isAborted = () => signal?.aborted === true || run.status === "aborted";
|
|
87
|
-
const abortListener = () => {
|
|
88
|
-
void markAbort().catch(() => undefined);
|
|
89
|
-
};
|
|
90
|
-
unregisterAbort = options.registerAbort?.(markAbort);
|
|
91
|
-
if (signal)
|
|
92
|
-
signal.addEventListener("abort", abortListener, { once: true });
|
|
100
|
+
});
|
|
93
101
|
try {
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
if (scope.aborted) {
|
|
103
|
+
dispatch({
|
|
104
|
+
type: "settle",
|
|
105
|
+
verdict: "aborted",
|
|
106
|
+
report: "",
|
|
107
|
+
error: "Subagent was aborted before it started.",
|
|
108
|
+
endedAt: Date.now(),
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
99
111
|
}
|
|
100
|
-
clearSubagentRetry(run);
|
|
101
|
-
run.status = "running";
|
|
102
|
-
run.startedAt = Date.now();
|
|
103
|
-
onProgress?.();
|
|
104
112
|
const settingsManager = SettingsManager.create(task.cwd, agentDir, { projectTrusted });
|
|
105
113
|
const resourceLoader = new DefaultResourceLoader({
|
|
106
114
|
cwd: task.cwd,
|
|
@@ -115,168 +123,179 @@ export async function runSdkTask(options) {
|
|
|
115
123
|
noContextFiles: task.agent.omitContextFiles ?? false,
|
|
116
124
|
systemPromptOverride: (base) => workerSystemPrompt(base, task),
|
|
117
125
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
let creationAbortListener;
|
|
139
|
-
const abortedOutcome = new Promise((resolve) => {
|
|
140
|
-
const resolveAborted = () => resolve({ kind: "aborted" });
|
|
141
|
-
if (initializationSignal.aborted) {
|
|
142
|
-
resolveAborted();
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
creationAbortListener = resolveAborted;
|
|
146
|
-
initializationSignal.addEventListener("abort", resolveAborted, { once: true });
|
|
147
|
-
});
|
|
148
|
-
const outcome = await Promise.race([
|
|
149
|
-
createPromise.then((created) => ({ kind: "created", created })),
|
|
150
|
-
abortedOutcome,
|
|
151
|
-
]).finally(() => {
|
|
152
|
-
if (creationAbortListener)
|
|
153
|
-
initializationSignal.removeEventListener("abort", creationAbortListener);
|
|
154
|
-
});
|
|
126
|
+
const initialization = (async () => {
|
|
127
|
+
await resourceLoader.reload();
|
|
128
|
+
if (scope.signal.aborted)
|
|
129
|
+
return { kind: "aborted" };
|
|
130
|
+
const created = await createAgentSession({
|
|
131
|
+
cwd: task.cwd,
|
|
132
|
+
agentDir,
|
|
133
|
+
modelRuntime,
|
|
134
|
+
model: task.model,
|
|
135
|
+
thinkingLevel: task.thinking,
|
|
136
|
+
tools: task.agent.tools,
|
|
137
|
+
resourceLoader,
|
|
138
|
+
sessionManager: SessionManager.inMemory(task.cwd),
|
|
139
|
+
settingsManager,
|
|
140
|
+
});
|
|
141
|
+
return { kind: "created", session: created.session };
|
|
142
|
+
})();
|
|
143
|
+
const outcome = await raceInitialization(initialization, scope);
|
|
144
|
+
if (outcome.kind === "error")
|
|
145
|
+
throw outcome.error;
|
|
155
146
|
if (outcome.kind === "aborted") {
|
|
156
|
-
// The
|
|
157
|
-
// eventually resolves,
|
|
158
|
-
//
|
|
159
|
-
void
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
147
|
+
// The initialization chain cannot be cancelled. Dispose the
|
|
148
|
+
// session if it eventually resolves, and swallow a late rejection
|
|
149
|
+
// after this run has already settled.
|
|
150
|
+
void initialization.then((late) => {
|
|
151
|
+
if (late.kind === "created") {
|
|
152
|
+
try {
|
|
153
|
+
late.session.dispose();
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// The aborted run has no remaining channel for cleanup errors.
|
|
157
|
+
}
|
|
165
158
|
}
|
|
166
159
|
}, () => { });
|
|
167
|
-
|
|
168
|
-
|
|
160
|
+
dispatch({
|
|
161
|
+
type: "settle",
|
|
162
|
+
verdict: "aborted",
|
|
163
|
+
report: "",
|
|
164
|
+
error: "Subagent was aborted during initialization.",
|
|
165
|
+
endedAt: Date.now(),
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
169
168
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (isAborted()) {
|
|
173
|
-
run.error ??= "Subagent was aborted during initialization.";
|
|
169
|
+
session = outcome.session;
|
|
170
|
+
if (scope.aborted) {
|
|
174
171
|
await session.abort();
|
|
175
|
-
|
|
172
|
+
dispatch({
|
|
173
|
+
type: "settle",
|
|
174
|
+
verdict: "aborted",
|
|
175
|
+
report: "",
|
|
176
|
+
error: "Subagent was aborted during initialization.",
|
|
177
|
+
endedAt: Date.now(),
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
176
180
|
}
|
|
177
|
-
const emitImmediate = () => onProgress?.();
|
|
178
|
-
const emitText = throttled.emit;
|
|
179
181
|
unsubscribe = session.subscribe((event) => {
|
|
180
|
-
if (event.type === "auto_retry_start"
|
|
181
|
-
|
|
182
|
+
if (event.type === "auto_retry_start") {
|
|
183
|
+
dispatch({
|
|
184
|
+
type: "auto_retry_start",
|
|
185
|
+
attempt: event.attempt,
|
|
186
|
+
maxAttempts: event.maxAttempts,
|
|
187
|
+
deadline: Date.now() + event.delayMs,
|
|
188
|
+
error: event.errorMessage,
|
|
189
|
+
});
|
|
190
|
+
emitImmediate();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (event.type === "auto_retry_end") {
|
|
194
|
+
dispatch({ type: "auto_retry_end" });
|
|
182
195
|
emitImmediate();
|
|
183
196
|
return;
|
|
184
197
|
}
|
|
185
198
|
if (event.type === "turn_end") {
|
|
186
|
-
|
|
187
|
-
run.usage.turns++;
|
|
188
|
-
run.currentActivity = undefined;
|
|
199
|
+
dispatch({ type: "turn_end" });
|
|
189
200
|
emitImmediate();
|
|
190
201
|
return;
|
|
191
202
|
}
|
|
192
203
|
if (event.type === "message_end" && event.message.role === "assistant") {
|
|
193
|
-
// Streaming updates carry no semantic weight (message_update is
|
|
194
|
-
// ignored); the settled message is where usage is accounted.
|
|
195
|
-
clearSubagentRetry(run);
|
|
196
204
|
if (!seenAssistantMessages.has(event.message)) {
|
|
197
205
|
seenAssistantMessages.add(event.message);
|
|
198
|
-
|
|
206
|
+
dispatch({ type: "assistant_message_settled", usage: event.message.usage });
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
dispatch({ type: "assistant_message_settled", usage: undefined });
|
|
199
210
|
}
|
|
200
211
|
emitImmediate();
|
|
201
212
|
return;
|
|
202
213
|
}
|
|
203
214
|
if (event.type === "tool_execution_start") {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
id: event.toolCallId,
|
|
215
|
+
dispatch({
|
|
216
|
+
type: "tool_started",
|
|
217
|
+
toolCallId: event.toolCallId,
|
|
208
218
|
toolName: event.toolName,
|
|
209
|
-
|
|
210
|
-
status: "running",
|
|
219
|
+
args: event.args,
|
|
211
220
|
startedAt: Date.now(),
|
|
212
|
-
};
|
|
213
|
-
activeActivities.set(event.toolCallId, activity);
|
|
214
|
-
appendActivity(run.activities, activity);
|
|
215
|
-
run.currentActivity = activity.summary;
|
|
221
|
+
});
|
|
216
222
|
emitImmediate();
|
|
217
223
|
return;
|
|
218
224
|
}
|
|
219
225
|
if (event.type === "tool_execution_update") {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
226
|
+
dispatch({
|
|
227
|
+
type: "tool_updated",
|
|
228
|
+
toolCallId: event.toolCallId,
|
|
229
|
+
toolName: event.toolName,
|
|
230
|
+
args: event.args,
|
|
231
|
+
});
|
|
232
|
+
emitThrottled();
|
|
223
233
|
return;
|
|
224
234
|
}
|
|
225
235
|
if (event.type === "tool_execution_end") {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
activeActivities.delete(event.toolCallId);
|
|
234
|
-
run.currentActivity = undefined;
|
|
236
|
+
dispatch({
|
|
237
|
+
type: "tool_ended",
|
|
238
|
+
toolCallId: event.toolCallId,
|
|
239
|
+
result: event.result,
|
|
240
|
+
isError: event.isError,
|
|
241
|
+
endedAt: Date.now(),
|
|
242
|
+
});
|
|
235
243
|
emitImmediate();
|
|
236
244
|
}
|
|
237
245
|
});
|
|
238
246
|
await session.prompt(task.prompt);
|
|
239
247
|
const finalMessage = lastAssistantMessage(session);
|
|
240
|
-
|
|
248
|
+
const report = finalAssistantText(session.messages);
|
|
241
249
|
const error = assistantError(finalMessage);
|
|
242
|
-
if (signal
|
|
243
|
-
|
|
244
|
-
|
|
250
|
+
if (scope.signal.aborted || finalMessage?.stopReason === "aborted") {
|
|
251
|
+
dispatch({
|
|
252
|
+
type: "settle",
|
|
253
|
+
verdict: "aborted",
|
|
254
|
+
report,
|
|
255
|
+
error: error ?? "Subagent was aborted.",
|
|
256
|
+
endedAt: Date.now(),
|
|
257
|
+
});
|
|
245
258
|
}
|
|
246
259
|
else if (finalMessage?.stopReason === "error" || error) {
|
|
247
|
-
|
|
248
|
-
|
|
260
|
+
dispatch({
|
|
261
|
+
type: "settle",
|
|
262
|
+
verdict: "failed",
|
|
263
|
+
report,
|
|
264
|
+
error: error ?? "Subagent failed.",
|
|
265
|
+
endedAt: Date.now(),
|
|
266
|
+
});
|
|
249
267
|
}
|
|
250
268
|
else {
|
|
251
|
-
|
|
269
|
+
dispatch({ type: "settle", verdict: "completed", report, error: undefined, endedAt: Date.now() });
|
|
252
270
|
}
|
|
253
271
|
}
|
|
254
272
|
catch (error) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
273
|
+
const report = session ? finalAssistantText(session.messages) : "";
|
|
274
|
+
if (scope.signal.aborted) {
|
|
275
|
+
dispatch({
|
|
276
|
+
type: "settle",
|
|
277
|
+
verdict: "aborted",
|
|
278
|
+
report,
|
|
279
|
+
error: "Subagent was aborted.",
|
|
280
|
+
endedAt: Date.now(),
|
|
281
|
+
});
|
|
258
282
|
}
|
|
259
283
|
else {
|
|
260
|
-
|
|
261
|
-
|
|
284
|
+
dispatch({
|
|
285
|
+
type: "settle",
|
|
286
|
+
verdict: "failed",
|
|
287
|
+
report,
|
|
288
|
+
error: error instanceof Error ? error.message : String(error),
|
|
289
|
+
endedAt: Date.now(),
|
|
290
|
+
});
|
|
262
291
|
}
|
|
263
|
-
if (session)
|
|
264
|
-
run.report = finalAssistantText(session.messages);
|
|
265
292
|
}
|
|
266
293
|
finally {
|
|
267
|
-
if (signal)
|
|
268
|
-
signal.removeEventListener("abort", abortListener);
|
|
269
294
|
throttled.cancel();
|
|
270
295
|
unregisterAbort?.();
|
|
271
296
|
unsubscribe?.();
|
|
272
297
|
session?.dispose();
|
|
273
|
-
|
|
274
|
-
if (run.error)
|
|
275
|
-
run.error = boundText(run.error, ERROR_TEXT_LIMIT);
|
|
276
|
-
clearSubagentRetry(run);
|
|
277
|
-
run.endedAt = Date.now();
|
|
278
|
-
onProgress?.();
|
|
298
|
+
emitImmediate();
|
|
279
299
|
}
|
|
280
|
-
return run;
|
|
281
300
|
}
|
|
282
301
|
//# sourceMappingURL=sdk-runner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk-runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/sdk-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAcpE,SAAS,kBAAkB,CAAC,IAAwB,EAAE,IAA0B;IAC/E,OAAO;QACN,IAAI;QACJ,wBAAwB,IAAI,CAAC,KAAK,CAAC,IAAI,iDAAiD;QACxF,wIAAwI;QACxI,6GAA6G;QAC7G,8EAA8E;QAC9E,iEAAiE;QACjE,oGAAoG;QACpG,0EAA0E;QAC1E,6IAA6I;QAC7I,wJAAwJ;QACxJ,uLAAuL;QACvL,IAAI,CAAC,KAAK,CAAC,YAAY;KACvB;SACC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;SACvD,IAAI,CAAC,MAAM,CAAC,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,OAA8C;IAC3E,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACnE,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,OAAO,EAAE,IAAI,KAAK,WAAW;YAAE,OAAO,OAAO,CAAC;IACnD,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,OAAgD;IACvE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,OAAO,CAAC,YAAY,CAAC;AAC7B,CAAC;AAQD,SAAS,sBAAsB,CAAC,UAAoC;IACnE,IAAI,KAAgD,CAAC;IACrD,OAAO;QACN,IAAI,EAAE,GAAG,EAAE;YACV,IAAI,CAAC,UAAU,IAAI,KAAK;gBAAE,OAAO;YACjC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACvB,KAAK,GAAG,SAAS,CAAC;gBAClB,UAAU,EAAE,CAAC;YACd,CAAC,EAAE,EAAE,CAAC,CAAC;QACR,CAAC;QACD,MAAM,EAAE,GAAG,EAAE;YACZ,IAAI,KAAK;gBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;YAC/B,KAAK,GAAG,SAAS,CAAC;QACnB,CAAC;KACD,CAAC;AACH,CAAC;AAID,MAAM,UAAU,2BAA2B,CAAC,GAAuB,EAAE,KAAqB;IACzF,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;QACvC,kBAAkB,CAAC,GAAG,EAAE;YACvB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,YAAY;SACzB,CAAC,CAAC;QACH,OAAO;IACR,CAAC;IACD,kBAAkB,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAyB;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAC1F,MAAM,SAAS,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IACrD,IAAI,WAAqC,CAAC;IAC1C,IAAI,eAAyC,CAAC;IAC9C,IAAI,OAA8E,CAAC;IACnF,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAwB,CAAC;IACzD,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAW,CAAC;IACjD,MAAM,6BAA6B,GAAG,IAAI,eAAe,EAAE,CAAC;IAC5D,MAAM,SAAS,GAAG,KAAK,IAAmB,EAAE;QAC3C,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACxB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,GAAG,CAAC,KAAK,KAAK,uBAAuB,CAAC;QACtC,6BAA6B,CAAC,KAAK,EAAE,CAAC;QACtC,IAAI,OAAO;YAAE,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACpC,CAAC,CAAC;IACF,MAAM,SAAS,GAAG,GAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC;IACtF,MAAM,aAAa,GAAG,GAAG,EAAE;QAC1B,KAAK,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC,CAAC;IACF,eAAe,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC,CAAC;IACrD,IAAI,MAAM;QAAE,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5E,IAAI,CAAC;QACJ,IAAI,SAAS,EAAE,EAAE,CAAC;YACjB,kBAAkB,CAAC,GAAG,CAAC,CAAC;YACxB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;YACvB,GAAG,CAAC,KAAK,GAAG,yCAAyC,CAAC;YACtD,OAAO,GAAG,CAAC;QACZ,CAAC;QAED,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACxB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;QACvB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC3B,UAAU,EAAE,EAAE,CAAC;QACf,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC;QACvF,MAAM,cAAc,GAAG,IAAI,qBAAqB,CAAC;YAChD,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ;YACR,eAAe;YACf,YAAY,EAAE,IAAI;YAClB,QAAQ,EAAE,IAAI;YACd,iBAAiB,EAAE,IAAI;YACvB,QAAQ,EAAE,IAAI;YACd,gEAAgE;YAChE,kEAAkE;YAClE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK;YACpD,oBAAoB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;SAC9D,CAAC,CAAC;QACH,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,IAAI,SAAS,EAAE,EAAE,CAAC;YACjB,GAAG,CAAC,KAAK,KAAK,6CAA6C,CAAC;YAC5D,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,aAAa,GAAG,kBAAkB,CAAC;YACxC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,QAAQ;YACR,YAAY;YACZ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,aAAa,EAAE,IAAI,CAAC,QAAQ;YAC5B,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;YACvB,cAAc;YACd,cAAc,EAAE,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;YACjD,eAAe;SACf,CAAC,CAAC;QACH,wEAAwE;QACxE,sEAAsE;QACtE,kEAAkE;QAClE,MAAM,oBAAoB,GAAG,6BAA6B,CAAC,MAAM,CAAC;QAClE,IAAI,qBAA+C,CAAC;QACpD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAsB,CAAC,OAAO,EAAE,EAAE;YACnE,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YAC1D,IAAI,oBAAoB,CAAC,OAAO,EAAE,CAAC;gBAClC,cAAc,EAAE,CAAC;gBACjB,OAAO;YACR,CAAC;YACD,qBAAqB,GAAG,cAAc,CAAC;YACvC,oBAAoB,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAkB,EAAE,OAAO,EAAE,CAAC,CAAC;YACxE,cAAc;SACd,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACf,IAAI,qBAAqB;gBAAE,oBAAoB,CAAC,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACrG,CAAC,CAAC,CAAC;QACH,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,sEAAsE;YACtE,qEAAqE;YACrE,0DAA0D;YAC1D,KAAK,aAAa,CAAC,IAAI,CACtB,CAAC,WAAW,EAAE,EAAE;gBACf,IAAI,CAAC;oBACJ,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACR,+DAA+D;gBAChE,CAAC;YACF,CAAC,EACD,GAAG,EAAE,GAAE,CAAC,CACR,CAAC;YACF,GAAG,CAAC,KAAK,KAAK,6CAA6C,CAAC;YAC5D,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC1B,IAAI,SAAS,EAAE,EAAE,CAAC;YACjB,GAAG,CAAC,KAAK,KAAK,6CAA6C,CAAC;YAC5D,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,GAAG,CAAC;QACZ,CAAC;QACD,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC;QAChC,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAwB,EAAE,EAAE;YAC5D,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;gBAC1E,2BAA2B,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACxC,aAAa,EAAE,CAAC;gBAChB,OAAO;YACR,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACxB,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBAClB,GAAG,CAAC,eAAe,GAAG,SAAS,CAAC;gBAChC,aAAa,EAAE,CAAC;gBAChB,OAAO;YACR,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACxE,gEAAgE;gBAChE,6DAA6D;gBAC7D,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACxB,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/C,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBACzC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC1C,CAAC;gBACD,aAAa,EAAE,CAAC;gBAChB,OAAO;YACR,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;gBAC3C,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACxB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAiB;oBAC9B,EAAE,EAAE,KAAK,CAAC,UAAU;oBACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC;oBACpD,MAAM,EAAE,SAAS;oBACjB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;iBACrB,CAAC;gBACF,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACjD,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACzC,GAAG,CAAC,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC;gBACvC,aAAa,EAAE,CAAC;gBAChB,OAAO;YACR,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;gBAC5C,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACxB,GAAG,CAAC,eAAe,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAClE,QAAQ,EAAE,CAAC;gBACX,OAAO;YACR,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBACzC,kBAAkB,CAAC,GAAG,CAAC,CAAC;gBACxB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACxD,IAAI,QAAQ,EAAE,CAAC;oBACd,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;oBACzD,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBAC9B,QAAQ,CAAC,aAAa,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACtD,CAAC;gBACD,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC1C,GAAG,CAAC,eAAe,GAAG,SAAS,CAAC;gBAChC,aAAa,EAAE,CAAC;YACjB,CAAC;QACF,CAAC,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACnD,GAAG,CAAC,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QAC3C,IAAI,MAAM,EAAE,OAAO,IAAI,YAAY,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;YAC/D,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;YACvB,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,uBAAuB,EAAE,gBAAgB,CAAC,CAAC;QAC3E,CAAC;aAAM,IAAI,YAAY,EAAE,UAAU,KAAK,OAAO,IAAI,KAAK,EAAE,CAAC;YAC1D,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;YACtB,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,kBAAkB,EAAE,gBAAgB,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,MAAM,GAAG,WAAW,CAAC;QAC1B,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,MAAM,EAAE,OAAO,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjD,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;YACvB,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,uBAAuB,CAAC;QAClD,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC;YACtB,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC;QACjG,CAAC;QACD,IAAI,OAAO;YAAE,GAAG,CAAC,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,CAAC;YAAS,CAAC;QACV,IAAI,MAAM;YAAE,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC/D,SAAS,CAAC,MAAM,EAAE,CAAC;QACnB,eAAe,EAAE,EAAE,CAAC;QACpB,WAAW,EAAE,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,CAAC;QACnB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QACtD,IAAI,GAAG,CAAC,KAAK;YAAE,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAClE,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACxB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,UAAU,EAAE,EAAE,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { DefaultResourceLoader } from \"../../core/resource-loader.ts\";\nimport { createAgentSession } from \"../../core/sdk.ts\";\nimport { SessionManager } from \"../../core/session-manager.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { activitySummary, addUsage, appendActivity, boundText, finalAssistantText, resultSummary } from \"./activity.ts\";\nimport { ERROR_TEXT_LIMIT, TASK_OUTPUT_LIMIT } from \"./constants.ts\";\nimport { beginSubagentRetry, clearSubagentRetry } from \"./retry.ts\";\nimport type { ResolvedSubagentTask, SubagentRunDetails, ToolActivity } from \"./types.ts\";\n\nexport interface SdkRunnerOptions {\n\ttask: ResolvedSubagentTask;\n\trun: SubagentRunDetails;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tsignal?: AbortSignal;\n\tonProgress?: () => void;\n\tregisterAbort?: (abort: () => Promise<void>) => () => void;\n}\n\nfunction workerSystemPrompt(base: string | undefined, task: ResolvedSubagentTask): string {\n\treturn [\n\t\tbase,\n\t\t`You are Pi subagent \"${task.agent.name}\", working independently on one delegated task.`,\n\t\t\"You cannot see the parent conversation; rely entirely on the task briefing and repository context available in your working directory.\",\n\t\t\"Only your final message is returned to the caller; nothing you write in earlier turns is visible to anyone.\",\n\t\t\"Complete the task fully—do not gold-plate it, but do not leave it half-done.\",\n\t\t\"Stay inside the assigned working directory and delegated scope.\",\n\t\t\"Do not ask the end user questions. If blocked, report the exact blocker and what would resolve it.\",\n\t\t\"Do not spawn subagents or invoke tools outside the configured tool list.\",\n\t\t\"When referencing files in the final report, use paths relative to the task's working directory so the caller can locate them unambiguously.\",\n\t\t\"Include code snippets only when the exact text is load-bearing (a bug you found, a signature the caller asked for); do not recap code you merely read.\",\n\t\t\"End with a concise report covering findings or changes, verification performed, blockers, and unresolved risks. The caller will relay it to the user, so include only the essentials.\",\n\t\ttask.agent.systemPrompt,\n\t]\n\t\t.filter((part): part is string => Boolean(part?.trim()))\n\t\t.join(\"\\n\\n\");\n}\n\nfunction lastAssistantMessage(session: { messages: readonly AgentMessage[] }) {\n\tfor (let index = session.messages.length - 1; index >= 0; index--) {\n\t\tconst message = session.messages[index];\n\t\tif (message?.role === \"assistant\") return message;\n\t}\n\treturn undefined;\n}\n\nfunction assistantError(message: ReturnType<typeof lastAssistantMessage>): string | undefined {\n\tif (!message || message.role !== \"assistant\") return undefined;\n\treturn message.errorMessage;\n}\n\ninterface ThrottledEmitter {\n\temit: () => void;\n\t/** Drops any pending timer so nothing fires after the run has settled. */\n\tcancel: () => void;\n}\n\nfunction createThrottledEmitter(onProgress: (() => void) | undefined): ThrottledEmitter {\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\treturn {\n\t\temit: () => {\n\t\t\tif (!onProgress || timer) return;\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimer = undefined;\n\t\t\t\tonProgress();\n\t\t\t}, 80);\n\t\t},\n\t\tcancel: () => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t},\n\t};\n}\n\ntype AutoRetryEvent = Extract<AgentSessionEvent, { type: \"auto_retry_start\" | \"auto_retry_end\" }>;\n\nexport function applySubagentAutoRetryEvent(run: SubagentRunDetails, event: AutoRetryEvent): void {\n\tif (event.type === \"auto_retry_start\") {\n\t\tbeginSubagentRetry(run, {\n\t\t\tattempt: event.attempt,\n\t\t\tmaxAttempts: event.maxAttempts,\n\t\t\tdelayMs: event.delayMs,\n\t\t\terror: event.errorMessage,\n\t\t});\n\t\treturn;\n\t}\n\tclearSubagentRetry(run);\n}\n\nexport async function runSdkTask(options: SdkRunnerOptions): Promise<SubagentRunDetails> {\n\tconst { task, run, modelRuntime, agentDir, projectTrusted, signal, onProgress } = options;\n\tconst throttled = createThrottledEmitter(onProgress);\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unregisterAbort: (() => void) | undefined;\n\tlet session: Awaited<ReturnType<typeof createAgentSession>>[\"session\"] | undefined;\n\tconst activeActivities = new Map<string, ToolActivity>();\n\tconst seenAssistantMessages = new Set<unknown>();\n\tconst initializationAbortController = new AbortController();\n\tconst markAbort = async (): Promise<void> => {\n\t\tclearSubagentRetry(run);\n\t\trun.status = \"aborted\";\n\t\trun.error ??= \"Subagent was aborted.\";\n\t\tinitializationAbortController.abort();\n\t\tif (session) await session.abort();\n\t};\n\tconst isAborted = (): boolean => signal?.aborted === true || run.status === \"aborted\";\n\tconst abortListener = () => {\n\t\tvoid markAbort().catch(() => undefined);\n\t};\n\tunregisterAbort = options.registerAbort?.(markAbort);\n\tif (signal) signal.addEventListener(\"abort\", abortListener, { once: true });\n\n\ttry {\n\t\tif (isAborted()) {\n\t\t\tclearSubagentRetry(run);\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = \"Subagent was aborted before it started.\";\n\t\t\treturn run;\n\t\t}\n\n\t\tclearSubagentRetry(run);\n\t\trun.status = \"running\";\n\t\trun.startedAt = Date.now();\n\t\tonProgress?.();\n\t\tconst settingsManager = SettingsManager.create(task.cwd, agentDir, { projectTrusted });\n\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\tcwd: task.cwd,\n\t\t\tagentDir,\n\t\t\tsettingsManager,\n\t\t\tnoExtensions: true,\n\t\t\tnoSkills: true,\n\t\t\tnoPromptTemplates: true,\n\t\t\tnoThemes: true,\n\t\t\t// Read-only explorers skip AGENTS.md/CLAUDE.md: they don't need\n\t\t\t// commit/PR/style rules, and the parent interprets their results.\n\t\t\tnoContextFiles: task.agent.omitContextFiles ?? false,\n\t\t\tsystemPromptOverride: (base) => workerSystemPrompt(base, task),\n\t\t});\n\t\tawait resourceLoader.reload();\n\t\tif (isAborted()) {\n\t\t\trun.error ??= \"Subagent was aborted during initialization.\";\n\t\t\treturn run;\n\t\t}\n\t\tconst createPromise = createAgentSession({\n\t\t\tcwd: task.cwd,\n\t\t\tagentDir,\n\t\t\tmodelRuntime,\n\t\t\tmodel: task.model,\n\t\t\tthinkingLevel: task.thinking,\n\t\t\ttools: task.agent.tools,\n\t\t\tresourceLoader,\n\t\t\tsessionManager: SessionManager.inMemory(task.cwd),\n\t\t\tsettingsManager,\n\t\t});\n\t\t// createAgentSession takes no signal and can hang on network work. Race\n\t\t// both parent-signal and registered shutdown cancellation against it;\n\t\t// only the winning branch owns disposal of the resulting session.\n\t\tconst initializationSignal = initializationAbortController.signal;\n\t\tlet creationAbortListener: (() => void) | undefined;\n\t\tconst abortedOutcome = new Promise<{ kind: \"aborted\" }>((resolve) => {\n\t\t\tconst resolveAborted = () => resolve({ kind: \"aborted\" });\n\t\t\tif (initializationSignal.aborted) {\n\t\t\t\tresolveAborted();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcreationAbortListener = resolveAborted;\n\t\t\tinitializationSignal.addEventListener(\"abort\", resolveAborted, { once: true });\n\t\t});\n\t\tconst outcome = await Promise.race([\n\t\t\tcreatePromise.then((created) => ({ kind: \"created\" as const, created })),\n\t\t\tabortedOutcome,\n\t\t]).finally(() => {\n\t\t\tif (creationAbortListener) initializationSignal.removeEventListener(\"abort\", creationAbortListener);\n\t\t});\n\t\tif (outcome.kind === \"aborted\") {\n\t\t\t// The creation promise cannot be cancelled. Dispose its session if it\n\t\t\t// eventually resolves, but keep background cleanup from surfacing an\n\t\t\t// unhandled rejection after this run has already settled.\n\t\t\tvoid createPromise.then(\n\t\t\t\t(createdLate) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcreatedLate.session.dispose();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// The aborted run has no remaining channel for cleanup errors.\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {},\n\t\t\t);\n\t\t\trun.error ??= \"Subagent was aborted during initialization.\";\n\t\t\treturn run;\n\t\t}\n\t\tconst created = outcome.created;\n\t\tsession = created.session;\n\t\tif (isAborted()) {\n\t\t\trun.error ??= \"Subagent was aborted during initialization.\";\n\t\t\tawait session.abort();\n\t\t\treturn run;\n\t\t}\n\t\tconst emitImmediate = () => onProgress?.();\n\t\tconst emitText = throttled.emit;\n\t\tunsubscribe = session.subscribe((event: AgentSessionEvent) => {\n\t\t\tif (event.type === \"auto_retry_start\" || event.type === \"auto_retry_end\") {\n\t\t\t\tapplySubagentAutoRetryEvent(run, event);\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"turn_end\") {\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\trun.usage.turns++;\n\t\t\t\trun.currentActivity = undefined;\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"message_end\" && event.message.role === \"assistant\") {\n\t\t\t\t// Streaming updates carry no semantic weight (message_update is\n\t\t\t\t// ignored); the settled message is where usage is accounted.\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\tif (!seenAssistantMessages.has(event.message)) {\n\t\t\t\t\tseenAssistantMessages.add(event.message);\n\t\t\t\t\taddUsage(run.usage, event.message.usage);\n\t\t\t\t}\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\trun.usage.toolUses++;\n\t\t\t\tconst activity: ToolActivity = {\n\t\t\t\t\tid: event.toolCallId,\n\t\t\t\t\ttoolName: event.toolName,\n\t\t\t\t\tsummary: activitySummary(event.toolName, event.args),\n\t\t\t\t\tstatus: \"running\",\n\t\t\t\t\tstartedAt: Date.now(),\n\t\t\t\t};\n\t\t\t\tactiveActivities.set(event.toolCallId, activity);\n\t\t\t\tappendActivity(run.activities, activity);\n\t\t\t\trun.currentActivity = activity.summary;\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_update\") {\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\trun.currentActivity = activitySummary(event.toolName, event.args);\n\t\t\t\temitText();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_end\") {\n\t\t\t\tclearSubagentRetry(run);\n\t\t\t\tconst activity = activeActivities.get(event.toolCallId);\n\t\t\t\tif (activity) {\n\t\t\t\t\tactivity.status = event.isError ? \"failed\" : \"succeeded\";\n\t\t\t\t\tactivity.endedAt = Date.now();\n\t\t\t\t\tactivity.resultSummary = resultSummary(event.result);\n\t\t\t\t}\n\t\t\t\tactiveActivities.delete(event.toolCallId);\n\t\t\t\trun.currentActivity = undefined;\n\t\t\t\temitImmediate();\n\t\t\t}\n\t\t});\n\t\tawait session.prompt(task.prompt);\n\t\tconst finalMessage = lastAssistantMessage(session);\n\t\trun.report = finalAssistantText(session.messages);\n\t\tconst error = assistantError(finalMessage);\n\t\tif (signal?.aborted || finalMessage?.stopReason === \"aborted\") {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = boundText(error ?? \"Subagent was aborted.\", ERROR_TEXT_LIMIT);\n\t\t} else if (finalMessage?.stopReason === \"error\" || error) {\n\t\t\trun.status = \"failed\";\n\t\t\trun.error = boundText(error ?? \"Subagent failed.\", ERROR_TEXT_LIMIT);\n\t\t} else {\n\t\t\trun.status = \"completed\";\n\t\t}\n\t} catch (error) {\n\t\tif (signal?.aborted || run.status === \"aborted\") {\n\t\t\trun.status = \"aborted\";\n\t\t\trun.error = run.error ?? \"Subagent was aborted.\";\n\t\t} else {\n\t\t\trun.status = \"failed\";\n\t\t\trun.error = boundText(error instanceof Error ? error.message : String(error), ERROR_TEXT_LIMIT);\n\t\t}\n\t\tif (session) run.report = finalAssistantText(session.messages);\n\t} finally {\n\t\tif (signal) signal.removeEventListener(\"abort\", abortListener);\n\t\tthrottled.cancel();\n\t\tunregisterAbort?.();\n\t\tunsubscribe?.();\n\t\tsession?.dispose();\n\t\trun.report = boundText(run.report, TASK_OUTPUT_LIMIT);\n\t\tif (run.error) run.error = boundText(run.error, ERROR_TEXT_LIMIT);\n\t\tclearSubagentRetry(run);\n\t\trun.endedAt = Date.now();\n\t\tonProgress?.();\n\t}\n\treturn run;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sdk-runner.js","sourceRoot":"","sources":["../../../src/extensions/subagent/sdk-runner.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.ts\";\nimport type { ModelRuntime } from \"../../core/model-runtime.ts\";\nimport { DefaultResourceLoader } from \"../../core/resource-loader.ts\";\nimport { createAgentSession } from \"../../core/sdk.ts\";\nimport { SessionManager } from \"../../core/session-manager.ts\";\nimport { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { finalAssistantText } from \"./activity.ts\";\nimport type { RunCancellation } from \"./cancellation.ts\";\nimport type { SubagentRunEvent } from \"./state.ts\";\nimport type { ResolvedSubagentTask } from \"./types.ts\";\n\nexport interface SdkRunnerOptions {\n\ttask: ResolvedSubagentTask;\n\t/** Cancellation scope covering this attempt (queued through session end). */\n\tscope: RunCancellation;\n\t/** Reducer input; the adapter never touches run state directly. */\n\tdispatch: (event: SubagentRunEvent) => void;\n\tmodelRuntime: ModelRuntime;\n\tagentDir: string;\n\tprojectTrusted: boolean;\n\tonProgress?: () => void;\n}\n\nfunction workerSystemPrompt(base: string | undefined, task: ResolvedSubagentTask): string {\n\treturn [\n\t\tbase,\n\t\t`You are Pi subagent \"${task.agent.name}\", working independently on one delegated task.`,\n\t\t\"You cannot see the parent conversation; rely entirely on the task briefing and repository context available in your working directory.\",\n\t\t\"Only your final message is returned to the caller; nothing you write in earlier turns is visible to anyone.\",\n\t\t\"Complete the task fully—do not gold-plate it, but do not leave it half-done.\",\n\t\t\"Stay inside the assigned working directory and delegated scope.\",\n\t\t\"Do not ask the end user questions. If blocked, report the exact blocker and what would resolve it.\",\n\t\t\"Do not spawn subagents or invoke tools outside the configured tool list.\",\n\t\t\"When referencing files in the final report, use paths relative to the task's working directory so the caller can locate them unambiguously.\",\n\t\t\"Include code snippets only when the exact text is load-bearing (a bug you found, a signature the caller asked for); do not recap code you merely read.\",\n\t\t\"End with a concise report covering findings or changes, verification performed, blockers, and unresolved risks. The caller will relay it to the user, so include only the essentials.\",\n\t\ttask.agent.systemPrompt,\n\t]\n\t\t.filter((part): part is string => Boolean(part?.trim()))\n\t\t.join(\"\\n\\n\");\n}\n\nfunction lastAssistantMessage(session: { messages: readonly AgentMessage[] }) {\n\tfor (let index = session.messages.length - 1; index >= 0; index--) {\n\t\tconst message = session.messages[index];\n\t\tif (message?.role === \"assistant\") return message;\n\t}\n\treturn undefined;\n}\n\nfunction assistantError(message: ReturnType<typeof lastAssistantMessage>): string | undefined {\n\tif (!message || message.role !== \"assistant\") return undefined;\n\treturn message.errorMessage;\n}\n\ninterface ThrottledEmitter {\n\temit: () => void;\n\t/** Drops any pending timer so nothing fires after the run has settled. */\n\tcancel: () => void;\n}\n\nfunction createThrottledEmitter(onProgress: (() => void) | undefined): ThrottledEmitter {\n\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\treturn {\n\t\temit: () => {\n\t\t\tif (!onProgress || timer) return;\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimer = undefined;\n\t\t\t\tonProgress();\n\t\t\t}, 80);\n\t\t},\n\t\tcancel: () => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t},\n\t};\n}\n\ntype InitializationOutcome =\n\t| { kind: \"created\"; session: Awaited<ReturnType<typeof createAgentSession>>[\"session\"] }\n\t| { kind: \"aborted\" }\n\t| { kind: \"error\"; error: unknown };\n\n// Neither resource loading nor session creation takes an abort signal, and\n// both can hang on network work; race both against the scope. The losing\n// chain keeps running, so its eventual result or rejection is always\n// consumed by a no-op handler.\nasync function raceInitialization(\n\tchain: Promise<InitializationOutcome>,\n\tscope: RunCancellation,\n): Promise<InitializationOutcome> {\n\treturn new Promise<InitializationOutcome>((resolve) => {\n\t\tlet settled = false;\n\t\tconst finish = (outcome: InitializationOutcome): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tscope.signal.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve(outcome);\n\t\t};\n\t\tconst onAbort = (): void => {\n\t\t\tfinish({ kind: \"aborted\" });\n\t\t};\n\t\tif (scope.signal.aborted) {\n\t\t\tonAbort();\n\t\t\tvoid chain.then(\n\t\t\t\t() => undefined,\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tscope.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\tvoid chain.then(\n\t\t\t(outcome) => finish(outcome),\n\t\t\t(error) => finish({ kind: \"error\", error }),\n\t\t);\n\t});\n}\n\n/**\n * Runs one worker attempt as a pure adapter: it owns the worker session's\n * lifecycle and translates AgentSessionEvents into SubagentRunEvents; every\n * state transition happens in the reducer on the other side of dispatch.\n */\nexport async function runSdkTask(options: SdkRunnerOptions): Promise<void> {\n\tconst { task, scope, dispatch, modelRuntime, agentDir, projectTrusted, onProgress } = options;\n\tconst throttled = createThrottledEmitter(onProgress);\n\tlet unsubscribe: (() => void) | undefined;\n\tlet unregisterAbort: (() => void) | undefined;\n\tlet session: Awaited<ReturnType<typeof createAgentSession>>[\"session\"] | undefined;\n\t// Streaming updates carry no semantic weight; the settled messages are\n\t// where usage is accounted, and worker sessions can replay them.\n\tconst seenAssistantMessages = new Set<unknown>();\n\tconst emitImmediate = (): void => onProgress?.();\n\tconst emitThrottled = throttled.emit;\n\n\tunregisterAbort = scope.onAbort(async () => {\n\t\tif (session) await session.abort();\n\t});\n\n\ttry {\n\t\tif (scope.aborted) {\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"aborted\",\n\t\t\t\treport: \"\",\n\t\t\t\terror: \"Subagent was aborted before it started.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst settingsManager = SettingsManager.create(task.cwd, agentDir, { projectTrusted });\n\t\tconst resourceLoader = new DefaultResourceLoader({\n\t\t\tcwd: task.cwd,\n\t\t\tagentDir,\n\t\t\tsettingsManager,\n\t\t\tnoExtensions: true,\n\t\t\tnoSkills: true,\n\t\t\tnoPromptTemplates: true,\n\t\t\tnoThemes: true,\n\t\t\t// Read-only explorers skip AGENTS.md/CLAUDE.md: they don't need\n\t\t\t// commit/PR/style rules, and the parent interprets their results.\n\t\t\tnoContextFiles: task.agent.omitContextFiles ?? false,\n\t\t\tsystemPromptOverride: (base) => workerSystemPrompt(base, task),\n\t\t});\n\t\tconst initialization = (async (): Promise<InitializationOutcome> => {\n\t\t\tawait resourceLoader.reload();\n\t\t\tif (scope.signal.aborted) return { kind: \"aborted\" };\n\t\t\tconst created = await createAgentSession({\n\t\t\t\tcwd: task.cwd,\n\t\t\t\tagentDir,\n\t\t\t\tmodelRuntime,\n\t\t\t\tmodel: task.model,\n\t\t\t\tthinkingLevel: task.thinking,\n\t\t\t\ttools: task.agent.tools,\n\t\t\t\tresourceLoader,\n\t\t\t\tsessionManager: SessionManager.inMemory(task.cwd),\n\t\t\t\tsettingsManager,\n\t\t\t});\n\t\t\treturn { kind: \"created\", session: created.session };\n\t\t})();\n\t\tconst outcome = await raceInitialization(initialization, scope);\n\t\tif (outcome.kind === \"error\") throw outcome.error;\n\t\tif (outcome.kind === \"aborted\") {\n\t\t\t// The initialization chain cannot be cancelled. Dispose the\n\t\t\t// session if it eventually resolves, and swallow a late rejection\n\t\t\t// after this run has already settled.\n\t\t\tvoid initialization.then(\n\t\t\t\t(late) => {\n\t\t\t\t\tif (late.kind === \"created\") {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlate.session.dispose();\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// The aborted run has no remaining channel for cleanup errors.\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {},\n\t\t\t);\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"aborted\",\n\t\t\t\treport: \"\",\n\t\t\t\terror: \"Subagent was aborted during initialization.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tsession = outcome.session;\n\t\tif (scope.aborted) {\n\t\t\tawait session.abort();\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"aborted\",\n\t\t\t\treport: \"\",\n\t\t\t\terror: \"Subagent was aborted during initialization.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tunsubscribe = session.subscribe((event: AgentSessionEvent) => {\n\t\t\tif (event.type === \"auto_retry_start\") {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"auto_retry_start\",\n\t\t\t\t\tattempt: event.attempt,\n\t\t\t\t\tmaxAttempts: event.maxAttempts,\n\t\t\t\t\tdeadline: Date.now() + event.delayMs,\n\t\t\t\t\terror: event.errorMessage,\n\t\t\t\t});\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"auto_retry_end\") {\n\t\t\t\tdispatch({ type: \"auto_retry_end\" });\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"turn_end\") {\n\t\t\t\tdispatch({ type: \"turn_end\" });\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"message_end\" && event.message.role === \"assistant\") {\n\t\t\t\tif (!seenAssistantMessages.has(event.message)) {\n\t\t\t\t\tseenAssistantMessages.add(event.message);\n\t\t\t\t\tdispatch({ type: \"assistant_message_settled\", usage: event.message.usage });\n\t\t\t\t} else {\n\t\t\t\t\tdispatch({ type: \"assistant_message_settled\", usage: undefined });\n\t\t\t\t}\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"tool_started\",\n\t\t\t\t\ttoolCallId: event.toolCallId,\n\t\t\t\t\ttoolName: event.toolName,\n\t\t\t\t\targs: event.args,\n\t\t\t\t\tstartedAt: Date.now(),\n\t\t\t\t});\n\t\t\t\temitImmediate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_update\") {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"tool_updated\",\n\t\t\t\t\ttoolCallId: event.toolCallId,\n\t\t\t\t\ttoolName: event.toolName,\n\t\t\t\t\targs: event.args,\n\t\t\t\t});\n\t\t\t\temitThrottled();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.type === \"tool_execution_end\") {\n\t\t\t\tdispatch({\n\t\t\t\t\ttype: \"tool_ended\",\n\t\t\t\t\ttoolCallId: event.toolCallId,\n\t\t\t\t\tresult: event.result,\n\t\t\t\t\tisError: event.isError,\n\t\t\t\t\tendedAt: Date.now(),\n\t\t\t\t});\n\t\t\t\temitImmediate();\n\t\t\t}\n\t\t});\n\t\tawait session.prompt(task.prompt);\n\t\tconst finalMessage = lastAssistantMessage(session);\n\t\tconst report = finalAssistantText(session.messages);\n\t\tconst error = assistantError(finalMessage);\n\t\tif (scope.signal.aborted || finalMessage?.stopReason === \"aborted\") {\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"aborted\",\n\t\t\t\treport,\n\t\t\t\terror: error ?? \"Subagent was aborted.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t} else if (finalMessage?.stopReason === \"error\" || error) {\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"failed\",\n\t\t\t\treport,\n\t\t\t\terror: error ?? \"Subagent failed.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t} else {\n\t\t\tdispatch({ type: \"settle\", verdict: \"completed\", report, error: undefined, endedAt: Date.now() });\n\t\t}\n\t} catch (error) {\n\t\tconst report = session ? finalAssistantText(session.messages) : \"\";\n\t\tif (scope.signal.aborted) {\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"aborted\",\n\t\t\t\treport,\n\t\t\t\terror: \"Subagent was aborted.\",\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t} else {\n\t\t\tdispatch({\n\t\t\t\ttype: \"settle\",\n\t\t\t\tverdict: \"failed\",\n\t\t\t\treport,\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\tendedAt: Date.now(),\n\t\t\t});\n\t\t}\n\t} finally {\n\t\tthrottled.cancel();\n\t\tunregisterAbort?.();\n\t\tunsubscribe?.();\n\t\tsession?.dispose();\n\t\temitImmediate();\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/settings.ts"],"names":[],"mappings":"AAIA,OAAO,EAIN,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAiC9E,wBAAgB,qBAAqB,CAAC,QAAQ,SAAgB,GAAG,MAAM,CAEtE;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,CAExD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAiCnE;AAeD,wBAAsB,kBAAkB,CAAC,QAAQ,SAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAS9F;AAwBD,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,OAAO,CAAC,uBAAuB,CAAC,EACvC,QAAQ,SAAgB,GACtB,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/extensions/subagent/settings.ts"],"names":[],"mappings":"AAIA,OAAO,EAIN,KAAK,iBAAiB,EAEtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAiC9E,wBAAgB,qBAAqB,CAAC,QAAQ,SAAgB,GAAG,MAAM,CAEtE;AAED,wBAAgB,mBAAmB,IAAI,kBAAkB,CAExD;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAiCnE;AAeD,wBAAsB,kBAAkB,CAAC,QAAQ,SAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAS9F;AAwBD,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,OAAO,CAAC,uBAAuB,CAAC,EACvC,QAAQ,SAAgB,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA4B7B"}
|
|
@@ -125,7 +125,8 @@ export async function updateProfileOverride(profile, patch, agentDir = getAgentD
|
|
|
125
125
|
// different profiles cannot overwrite each other.
|
|
126
126
|
return withFileMutationQueue(filePath, async () => {
|
|
127
127
|
const config = await loadSubagentConfig(agentDir);
|
|
128
|
-
const
|
|
128
|
+
const currentOverride = config.profiles[profile];
|
|
129
|
+
const current = currentOverride ?? {};
|
|
129
130
|
const next = { ...current };
|
|
130
131
|
if ("model" in patch) {
|
|
131
132
|
if (patch.model === undefined)
|
|
@@ -139,10 +140,16 @@ export async function updateProfileOverride(profile, patch, agentDir = getAgentD
|
|
|
139
140
|
else
|
|
140
141
|
next.thinking = patch.thinking;
|
|
141
142
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
const hasNext = Object.keys(next).length > 0;
|
|
144
|
+
const changed = (currentOverride !== undefined) !== hasNext ||
|
|
145
|
+
current.model !== next.model ||
|
|
146
|
+
current.thinking !== next.thinking;
|
|
147
|
+
if (!changed)
|
|
148
|
+
return config;
|
|
149
|
+
if (hasNext)
|
|
145
150
|
config.profiles[profile] = next;
|
|
151
|
+
else
|
|
152
|
+
delete config.profiles[profile];
|
|
146
153
|
await writeSubagentConfigFile(filePath, config);
|
|
147
154
|
return config;
|
|
148
155
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/extensions/subagent/settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { withFileMutationQueue } from \"../../core/tools/file-mutation-queue.ts\";\nimport {\n\tSUBAGENT_AGENT_NAMES,\n\tSUBAGENT_CONFIG_FILE,\n\tSUBAGENT_CONFIG_VERSION,\n\ttype SubagentAgentName,\n\tTHINKING_LEVELS,\n} from \"./constants.ts\";\nimport type { SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\n\nfunction isThinkingLevel(value: unknown): boolean {\n\treturn typeof value === \"string\" && (THINKING_LEVELS as readonly string[]).includes(value);\n}\n\n// Overrides hold concrete values only; absence means \"inherit the parent\n// session\". The file format has no compatibility aliases.\nfunction normalizeOverride(value: unknown, profile: string): SubagentProfileOverride {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Profile override for \"${profile}\" must be an object.`);\n\t}\n\tconst input = value as Record<string, unknown>;\n\tconst output: SubagentProfileOverride = {};\n\tif (input.model !== undefined) {\n\t\tif (typeof input.model !== \"string\" || input.model.trim().length === 0 || input.model === \"inherit\") {\n\t\t\tthrow new Error(`Profile \"${profile}\" model override must be a concrete model id.`);\n\t\t}\n\t\toutput.model = input.model.trim();\n\t}\n\tif (input.thinking !== undefined) {\n\t\tif (!isThinkingLevel(input.thinking)) {\n\t\t\tthrow new Error(`Profile \"${profile}\" thinking override is invalid.`);\n\t\t}\n\t\toutput.thinking = input.thinking as SubagentProfileOverride[\"thinking\"];\n\t}\n\tconst unknownKeys = Object.keys(input).filter((key) => key !== \"model\" && key !== \"thinking\");\n\tif (unknownKeys.length > 0) {\n\t\tthrow new Error(`Profile \"${profile}\" has unsupported setting(s): ${unknownKeys.join(\", \")}.`);\n\t}\n\treturn output;\n}\n\nexport function getSubagentConfigPath(agentDir = getAgentDir()): string {\n\treturn join(agentDir, SUBAGENT_CONFIG_FILE);\n}\n\nexport function emptySubagentConfig(): SubagentConfigFile {\n\treturn { version: SUBAGENT_CONFIG_VERSION, profiles: {} };\n}\n\nexport function parseSubagentConfig(raw: string): SubagentConfigFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} is not valid JSON.`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} must be a JSON object.`);\n\t}\n\tconst root = parsed as Record<string, unknown>;\n\tif (root.version !== SUBAGENT_CONFIG_VERSION) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} has unsupported version ${String(root.version)}.`);\n\t}\n\tif (\n\t\troot.profiles !== undefined &&\n\t\t(!root.profiles || typeof root.profiles !== \"object\" || Array.isArray(root.profiles))\n\t) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} profiles must be an object.`);\n\t}\n\tconst profiles: Record<string, SubagentProfileOverride> = {};\n\tfor (const [name, value] of Object.entries((root.profiles as Record<string, unknown> | undefined) ?? {})) {\n\t\t// The only profiles are the two built-in ones; unknown keys are rejected\n\t\t// outright (no legacy aliases or compatibility mapping).\n\t\tif (!(SUBAGENT_AGENT_NAMES as readonly string[]).includes(name)) {\n\t\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} contains unknown profile \"${name}\".`);\n\t\t}\n\t\tprofiles[name] = normalizeOverride(value, name);\n\t}\n\tconst unknownKeys = Object.keys(root).filter((key) => key !== \"version\" && key !== \"profiles\");\n\tif (unknownKeys.length > 0)\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} has unsupported field(s): ${unknownKeys.join(\", \")}.`);\n\treturn { version: SUBAGENT_CONFIG_VERSION, profiles };\n}\n\n// A stale or invalid config (older formats, unknown profiles, malformed\n// JSON) must not block every subagent call: reset it to an empty, fully\n// inheriting config. The reset is best-effort — when the write fails the\n// caller still gets the empty config and the next load retries the reset.\nasync function resetSubagentConfigFile(filePath: string): Promise<void> {\n\ttry {\n\t\tawait writeSubagentConfigFile(filePath, emptySubagentConfig());\n\t} catch {\n\t\t// Keep the original failure invisible to callers; an unwritable config\n\t\t// file is a setup problem, not a reason to fail the subagent call.\n\t}\n}\n\nexport async function loadSubagentConfig(agentDir = getAgentDir()): Promise<SubagentConfigFile> {\n\tconst filePath = getSubagentConfigPath(agentDir);\n\ttry {\n\t\treturn parseSubagentConfig(await readFile(filePath, \"utf8\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return emptySubagentConfig();\n\t\tawait resetSubagentConfigFile(filePath);\n\t\treturn emptySubagentConfig();\n\t}\n}\n\n// Queue-free write body: read-modify-write callers run their whole\n// transaction inside the queue, so saveSubagentConfig must not queue the\n// same path again — that would deadlock.\nasync function writeSubagentConfigFile(filePath: string, config: SubagentConfigFile): Promise<void> {\n\tconst payload = `${JSON.stringify({ version: SUBAGENT_CONFIG_VERSION, profiles: config.profiles }, null, 2)}\\n`;\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tconst tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n\ttry {\n\t\tawait writeFile(tempPath, payload, { encoding: \"utf8\", mode: 0o600 });\n\t\tawait rename(tempPath, filePath);\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait unlink(tempPath);\n\t\t} catch {\n\t\t\t// Ignore cleanup errors and preserve the original failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n// Only keys present in the patch change; a key set to undefined clears\n// that override (back to inheriting the parent session).\nexport async function updateProfileOverride(\n\tprofile: SubagentAgentName,\n\tpatch: Partial<SubagentProfileOverride>,\n\tagentDir = getAgentDir(),\n): Promise<SubagentConfigFile> {\n\tconst filePath = getSubagentConfigPath(agentDir);\n\t// Load and write run inside one queue slot so concurrent updates to\n\t// different profiles cannot overwrite each other.\n\treturn withFileMutationQueue(filePath, async () => {\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst current = config.profiles[profile] ?? {};\n\t\tconst next: SubagentProfileOverride = { ...current };\n\t\tif (\"model\" in patch) {\n\t\t\tif (patch.model === undefined) delete next.model;\n\t\t\telse next.model = patch.model;\n\t\t}\n\t\tif (\"thinking\" in patch) {\n\t\t\tif (patch.thinking === undefined) delete next.thinking;\n\t\t\telse next.thinking = patch.thinking;\n\t\t}\n\t\tif (Object.keys(next).length === 0) delete config.profiles[profile];\n\t\telse config.profiles[profile] = next;\n\t\tawait writeSubagentConfigFile(filePath, config);\n\t\treturn config;\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/extensions/subagent/settings.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, rename, unlink, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { withFileMutationQueue } from \"../../core/tools/file-mutation-queue.ts\";\nimport {\n\tSUBAGENT_AGENT_NAMES,\n\tSUBAGENT_CONFIG_FILE,\n\tSUBAGENT_CONFIG_VERSION,\n\ttype SubagentAgentName,\n\tTHINKING_LEVELS,\n} from \"./constants.ts\";\nimport type { SubagentConfigFile, SubagentProfileOverride } from \"./types.ts\";\n\nfunction isThinkingLevel(value: unknown): boolean {\n\treturn typeof value === \"string\" && (THINKING_LEVELS as readonly string[]).includes(value);\n}\n\n// Overrides hold concrete values only; absence means \"inherit the parent\n// session\". The file format has no compatibility aliases.\nfunction normalizeOverride(value: unknown, profile: string): SubagentProfileOverride {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Profile override for \"${profile}\" must be an object.`);\n\t}\n\tconst input = value as Record<string, unknown>;\n\tconst output: SubagentProfileOverride = {};\n\tif (input.model !== undefined) {\n\t\tif (typeof input.model !== \"string\" || input.model.trim().length === 0 || input.model === \"inherit\") {\n\t\t\tthrow new Error(`Profile \"${profile}\" model override must be a concrete model id.`);\n\t\t}\n\t\toutput.model = input.model.trim();\n\t}\n\tif (input.thinking !== undefined) {\n\t\tif (!isThinkingLevel(input.thinking)) {\n\t\t\tthrow new Error(`Profile \"${profile}\" thinking override is invalid.`);\n\t\t}\n\t\toutput.thinking = input.thinking as SubagentProfileOverride[\"thinking\"];\n\t}\n\tconst unknownKeys = Object.keys(input).filter((key) => key !== \"model\" && key !== \"thinking\");\n\tif (unknownKeys.length > 0) {\n\t\tthrow new Error(`Profile \"${profile}\" has unsupported setting(s): ${unknownKeys.join(\", \")}.`);\n\t}\n\treturn output;\n}\n\nexport function getSubagentConfigPath(agentDir = getAgentDir()): string {\n\treturn join(agentDir, SUBAGENT_CONFIG_FILE);\n}\n\nexport function emptySubagentConfig(): SubagentConfigFile {\n\treturn { version: SUBAGENT_CONFIG_VERSION, profiles: {} };\n}\n\nexport function parseSubagentConfig(raw: string): SubagentConfigFile {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} is not valid JSON.`);\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} must be a JSON object.`);\n\t}\n\tconst root = parsed as Record<string, unknown>;\n\tif (root.version !== SUBAGENT_CONFIG_VERSION) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} has unsupported version ${String(root.version)}.`);\n\t}\n\tif (\n\t\troot.profiles !== undefined &&\n\t\t(!root.profiles || typeof root.profiles !== \"object\" || Array.isArray(root.profiles))\n\t) {\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} profiles must be an object.`);\n\t}\n\tconst profiles: Record<string, SubagentProfileOverride> = {};\n\tfor (const [name, value] of Object.entries((root.profiles as Record<string, unknown> | undefined) ?? {})) {\n\t\t// The only profiles are the two built-in ones; unknown keys are rejected\n\t\t// outright (no legacy aliases or compatibility mapping).\n\t\tif (!(SUBAGENT_AGENT_NAMES as readonly string[]).includes(name)) {\n\t\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} contains unknown profile \"${name}\".`);\n\t\t}\n\t\tprofiles[name] = normalizeOverride(value, name);\n\t}\n\tconst unknownKeys = Object.keys(root).filter((key) => key !== \"version\" && key !== \"profiles\");\n\tif (unknownKeys.length > 0)\n\t\tthrow new Error(`${SUBAGENT_CONFIG_FILE} has unsupported field(s): ${unknownKeys.join(\", \")}.`);\n\treturn { version: SUBAGENT_CONFIG_VERSION, profiles };\n}\n\n// A stale or invalid config (older formats, unknown profiles, malformed\n// JSON) must not block every subagent call: reset it to an empty, fully\n// inheriting config. The reset is best-effort — when the write fails the\n// caller still gets the empty config and the next load retries the reset.\nasync function resetSubagentConfigFile(filePath: string): Promise<void> {\n\ttry {\n\t\tawait writeSubagentConfigFile(filePath, emptySubagentConfig());\n\t} catch {\n\t\t// Keep the original failure invisible to callers; an unwritable config\n\t\t// file is a setup problem, not a reason to fail the subagent call.\n\t}\n}\n\nexport async function loadSubagentConfig(agentDir = getAgentDir()): Promise<SubagentConfigFile> {\n\tconst filePath = getSubagentConfigPath(agentDir);\n\ttry {\n\t\treturn parseSubagentConfig(await readFile(filePath, \"utf8\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return emptySubagentConfig();\n\t\tawait resetSubagentConfigFile(filePath);\n\t\treturn emptySubagentConfig();\n\t}\n}\n\n// Queue-free write body: read-modify-write callers run their whole\n// transaction inside the queue, so saveSubagentConfig must not queue the\n// same path again — that would deadlock.\nasync function writeSubagentConfigFile(filePath: string, config: SubagentConfigFile): Promise<void> {\n\tconst payload = `${JSON.stringify({ version: SUBAGENT_CONFIG_VERSION, profiles: config.profiles }, null, 2)}\\n`;\n\tawait mkdir(dirname(filePath), { recursive: true });\n\tconst tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n\ttry {\n\t\tawait writeFile(tempPath, payload, { encoding: \"utf8\", mode: 0o600 });\n\t\tawait rename(tempPath, filePath);\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait unlink(tempPath);\n\t\t} catch {\n\t\t\t// Ignore cleanup errors and preserve the original failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n// Only keys present in the patch change; a key set to undefined clears\n// that override (back to inheriting the parent session).\nexport async function updateProfileOverride(\n\tprofile: SubagentAgentName,\n\tpatch: Partial<SubagentProfileOverride>,\n\tagentDir = getAgentDir(),\n): Promise<SubagentConfigFile> {\n\tconst filePath = getSubagentConfigPath(agentDir);\n\t// Load and write run inside one queue slot so concurrent updates to\n\t// different profiles cannot overwrite each other.\n\treturn withFileMutationQueue(filePath, async () => {\n\t\tconst config = await loadSubagentConfig(agentDir);\n\t\tconst currentOverride = config.profiles[profile];\n\t\tconst current = currentOverride ?? {};\n\t\tconst next: SubagentProfileOverride = { ...current };\n\t\tif (\"model\" in patch) {\n\t\t\tif (patch.model === undefined) delete next.model;\n\t\t\telse next.model = patch.model;\n\t\t}\n\t\tif (\"thinking\" in patch) {\n\t\t\tif (patch.thinking === undefined) delete next.thinking;\n\t\t\telse next.thinking = patch.thinking;\n\t\t}\n\t\tconst hasNext = Object.keys(next).length > 0;\n\t\tconst changed =\n\t\t\t(currentOverride !== undefined) !== hasNext ||\n\t\t\tcurrent.model !== next.model ||\n\t\t\tcurrent.thinking !== next.thinking;\n\t\tif (!changed) return config;\n\t\tif (hasNext) config.profiles[profile] = next;\n\t\telse delete config.profiles[profile];\n\t\tawait writeSubagentConfigFile(filePath, config);\n\t\treturn config;\n\t});\n}\n"]}
|