@bastani/atomic 0.9.15 → 0.9.16-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/builtin/intercom/CHANGELOG.md +10 -0
- package/dist/builtin/intercom/README.md +8 -8
- package/dist/builtin/intercom/contact-supervisor-tool.ts +68 -32
- package/dist/builtin/intercom/index-heavy.ts +1 -0
- package/dist/builtin/intercom/index.ts +21 -15
- package/dist/builtin/intercom/intercom-tool.ts +66 -10
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/parent-ask-handoff.ts +72 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +26 -0
- package/dist/builtin/subagents/README.md +37 -114
- package/dist/builtin/subagents/agents/worker.md +2 -2
- package/dist/builtin/subagents/package.json +1 -5
- package/dist/builtin/subagents/skills/subagent/SKILL.md +26 -103
- package/dist/builtin/subagents/src/extension/index.ts +5 -30
- package/dist/builtin/subagents/src/extension/notification-content.ts +1 -1
- package/dist/builtin/subagents/src/extension/schemas.ts +2 -14
- package/dist/builtin/subagents/src/extension/tool-description.ts +1 -4
- package/dist/builtin/subagents/src/extension/tool-rendering.ts +53 -0
- package/dist/builtin/subagents/src/intercom/intercom-bridge.ts +1 -54
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/execution-parent-ask-handoff.ts +78 -0
- package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +7 -5
- package/dist/builtin/subagents/src/runs/foreground/notify.ts +5 -6
- package/dist/builtin/subagents/src/runs/foreground/parent-ask-output.ts +48 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-burst-display.ts +46 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-burst.ts +403 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +48 -9
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-input.ts +3 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-live-update.ts +11 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +164 -93
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +36 -29
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parent-ask-projection.ts +11 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +42 -17
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +3 -121
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +7 -2
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +30 -257
- package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +0 -34
- package/dist/builtin/subagents/src/runs/inprocess/index.ts +0 -12
- package/dist/builtin/subagents/src/runs/inprocess/prompt-behavior.ts +1 -1
- package/dist/builtin/subagents/src/runs/inprocess/runner.ts +2 -141
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +8 -0
- package/dist/builtin/subagents/src/shared/status-format.ts +3 -3
- package/dist/builtin/subagents/src/shared/types-config.ts +41 -0
- package/dist/builtin/subagents/src/shared/types-foreground-state.ts +7 -15
- package/dist/builtin/subagents/src/shared/types-results.ts +3 -1
- package/dist/builtin/subagents/src/shared/types-runtime.ts +1 -11
- package/dist/builtin/subagents/src/slash/slash-commands.ts +4 -468
- package/dist/builtin/subagents/src/tui/render-progress.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-result-compact.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-result.ts +38 -14
- package/dist/builtin/subagents/src/tui/render-status-progress.ts +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +16 -0
- package/dist/builtin/workflows/README.md +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/bro/LICENSE.txt +21 -0
- package/dist/builtin/workflows/skills/bro/SKILL.md +14 -0
- package/dist/builtin/workflows/skills/how/LICENSE.txt +21 -0
- package/dist/builtin/workflows/skills/how/SKILL.md +162 -0
- package/dist/builtin/workflows/skills/how/references/critic-prompt.md +59 -0
- package/dist/builtin/workflows/skills/how/references/critique-rubric.md +58 -0
- package/dist/builtin/workflows/skills/how/references/explainer-prompt.md +55 -0
- package/dist/builtin/workflows/skills/how/references/explorer-prompt.md +52 -0
- package/dist/builtin/workflows/skills/teach/LICENSE.txt +21 -0
- package/dist/builtin/workflows/skills/teach/SKILL.md +28 -0
- package/dist/builtin/workflows/skills/unslop/LICENSE.txt +21 -0
- package/dist/builtin/workflows/skills/unslop/SKILL.md +87 -0
- package/dist/builtin/workflows/skills/why/LICENSE.txt +21 -0
- package/dist/builtin/workflows/skills/why/SKILL.md +267 -0
- package/dist/builtin/workflows/skills/why/references/epistemics.md +144 -0
- package/dist/builtin/workflows/skills/why/references/investigator-prompt.md +103 -0
- package/dist/builtin/workflows/skills/why/references/source-playbook.md +17 -0
- package/dist/builtin/workflows/skills/why/references/sources/code-archaeology.md +88 -0
- package/dist/builtin/workflows/skills/why/references/sources/databricks.md +70 -0
- package/dist/builtin/workflows/skills/why/references/sources/datadog.md +99 -0
- package/dist/builtin/workflows/skills/why/references/sources/incident-postmortem.md +15 -0
- package/dist/builtin/workflows/skills/why/references/sources/linear.md +48 -0
- package/dist/builtin/workflows/skills/why/references/sources/notion.md +55 -0
- package/dist/builtin/workflows/skills/why/references/sources/sentry.md +100 -0
- package/dist/builtin/workflows/skills/why/references/sources/slack.md +54 -0
- package/dist/builtin/workflows/skills/why/references/synthesizer-prompt.md +135 -0
- package/dist/builtin/workflows/src/durable/dbos-embedded-postgres-root.ts +548 -39
- package/dist/builtin/workflows/src/durable/dbos-embedded-postgres.ts +529 -65
- package/dist/builtin/workflows/src/durable/dbos-lifecycle.ts +30 -8
- package/dist/builtin/workflows/src/durable/dbos-local-postgres.ts +36 -3
- package/dist/builtin/workflows/src/durable/local-command.ts +68 -10
- package/dist/builtin/workflows/src/extension/companions.ts +1 -1
- package/dist/builtin/workflows/src/extension/dispatcher.ts +7 -1
- package/dist/builtin/workflows/src/extension/extension-factory.ts +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +1094 -298
- package/dist/builtin/workflows/src/extension/public-types.ts +2 -2
- package/dist/builtin/workflows/src/extension/render-result.ts +16 -2
- package/dist/builtin/workflows/src/extension/runtime.ts +8 -1
- package/dist/builtin/workflows/src/extension/workflow-request-abort.ts +15 -0
- package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +4 -3
- package/dist/builtin/workflows/src/extension/workflow-tool-registration.ts +107 -13
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +22 -12
- package/dist/builtin/workflows/src/tui/widget.ts +25 -6
- package/dist/core/agent-session-auto-compaction.js +10 -10
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +11 -13
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +1 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js +5 -7
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-prompt.js +4 -4
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +4 -4
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +8 -34
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +4 -4
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +3 -10
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/dist/core/event-bus.d.ts.map +1 -1
- package/dist/core/event-bus.js +19 -3
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -12
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/modes/interactive-engine/remote-command-catalog.d.ts +1 -1
- package/dist/modes/interactive-engine/remote-command-catalog.js +1 -1
- package/dist/modes/interactive-engine/remote-command-catalog.js.map +1 -1
- package/docs/intercom.md +29 -27
- package/docs/settings.md +2 -2
- package/docs/subagents.md +18 -15
- package/docs/usage.md +0 -9
- package/docs/workflows.md +27 -10
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/dist/builtin/subagents/prompts/gather-context-and-clarify.md +0 -27
- package/dist/builtin/subagents/prompts/parallel-cleanup.md +0 -61
- package/dist/builtin/subagents/prompts/parallel-context-build.md +0 -43
- package/dist/builtin/subagents/prompts/parallel-handoff-plan.md +0 -47
- package/dist/builtin/subagents/prompts/parallel-research.md +0 -34
- package/dist/builtin/subagents/prompts/parallel-review.md +0 -47
- package/dist/builtin/subagents/prompts/review-loop.md +0 -39
- package/dist/builtin/subagents/src/extension/doctor.ts +0 -188
- package/dist/builtin/subagents/src/runs/inprocess/attempt-handles.ts +0 -104
- /package/dist/builtin/subagents/src/runs/foreground/{subagent-executor-resume.ts → subagent-executor-cwd.ts} +0 -0
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
type SubagentState,
|
|
18
18
|
type SubagentToolResult,
|
|
19
19
|
} from "../../shared/types.js";
|
|
20
|
-
import { compactForegroundDetails,
|
|
20
|
+
import { compactForegroundDetails, getSingleResultOutput } from "../../shared/utils.js";
|
|
21
21
|
import {
|
|
22
22
|
formatControlIntercomMessage,
|
|
23
23
|
formatControlNoticeMessage,
|
|
@@ -77,128 +77,10 @@ export function foregroundStatusResult(control: ForegroundControl): SubagentTool
|
|
|
77
77
|
return { content: [{ type: "text", text: lines.join("\n") }], details: { mode: "management", results: [] } };
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
export function retainedForegroundStatusResult(state: SubagentState, runId: string): SubagentToolResult | undefined {
|
|
81
|
-
const run = state.foregroundRuns?.get(runId);
|
|
82
|
-
if (!run) return undefined;
|
|
83
|
-
const statuses = run.children.map((child) => child.status);
|
|
84
|
-
const stateLabel = statuses.includes("detached")
|
|
85
|
-
? "detached"
|
|
86
|
-
: statuses.includes("failed")
|
|
87
|
-
? "failed"
|
|
88
|
-
: statuses.includes("paused")
|
|
89
|
-
? "paused"
|
|
90
|
-
: statuses.every((status) => status === "completed")
|
|
91
|
-
? "completed"
|
|
92
|
-
: (statuses[0] ?? "unknown");
|
|
93
|
-
const lines = [`Run: ${run.runId}`, `State: ${stateLabel}`, `Mode: ${run.mode}`];
|
|
94
|
-
for (const child of run.children) {
|
|
95
|
-
lines.push(`Child ${child.index + 1}: ${child.agent} (${child.status})`);
|
|
96
|
-
const output = child.result ? getSingleResultOutput(child.result) : "";
|
|
97
|
-
if (output) lines.push(output);
|
|
98
|
-
else if (child.result?.error) lines.push(child.result.error);
|
|
99
|
-
}
|
|
100
|
-
return { content: [{ type: "text", text: lines.join("\n") }], details: { mode: "management", results: [] } };
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const earlyDetachedResults = new WeakMap<SubagentState, Map<string, Map<number, SingleResult>>>();
|
|
104
|
-
const MAX_EARLY_DETACHED_RUNS = 50;
|
|
105
|
-
const MAX_EARLY_DETACHED_CHILDREN_PER_RUN = 50;
|
|
106
|
-
|
|
107
|
-
function takeEarlyDetachedResult(state: SubagentState, runId: string, index: number): SingleResult | undefined {
|
|
108
|
-
const byRun = earlyDetachedResults.get(state);
|
|
109
|
-
const byIndex = byRun?.get(runId);
|
|
110
|
-
const result = byIndex?.get(index);
|
|
111
|
-
byIndex?.delete(index);
|
|
112
|
-
if (byIndex?.size === 0) byRun?.delete(runId);
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function rememberForegroundRun(
|
|
117
|
-
state: SubagentState,
|
|
118
|
-
input: {
|
|
119
|
-
runId: string;
|
|
120
|
-
mode: "single" | "parallel";
|
|
121
|
-
cwd: string;
|
|
122
|
-
results: SingleResult[];
|
|
123
|
-
},
|
|
124
|
-
): void {
|
|
125
|
-
state.foregroundRuns ??= new Map();
|
|
126
|
-
state.foregroundRuns.set(input.runId, {
|
|
127
|
-
runId: input.runId,
|
|
128
|
-
mode: input.mode,
|
|
129
|
-
cwd: input.cwd,
|
|
130
|
-
updatedAt: Date.now(),
|
|
131
|
-
children: input.results.map((originalResult, index) => {
|
|
132
|
-
const result = takeEarlyDetachedResult(state, input.runId, index) ?? originalResult;
|
|
133
|
-
return {
|
|
134
|
-
agent: result.agent,
|
|
135
|
-
index,
|
|
136
|
-
status: resolveSubagentResultStatus({
|
|
137
|
-
status: result.status,
|
|
138
|
-
interrupted: result.interrupted,
|
|
139
|
-
detached: result.detached,
|
|
140
|
-
}),
|
|
141
|
-
...(result.sessionFile ? { sessionFile: result.sessionFile } : {}),
|
|
142
|
-
result,
|
|
143
|
-
};
|
|
144
|
-
}),
|
|
145
|
-
});
|
|
146
|
-
while (state.foregroundRuns.size > 50) {
|
|
147
|
-
const oldest = [...state.foregroundRuns.values()].sort((left, right) => left.updatedAt - right.updatedAt)[0];
|
|
148
|
-
if (!oldest) break;
|
|
149
|
-
state.foregroundRuns.delete(oldest.runId);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export function replaceForegroundRunChild(
|
|
154
|
-
state: SubagentState,
|
|
155
|
-
runId: string,
|
|
156
|
-
index: number,
|
|
157
|
-
result: SingleResult,
|
|
158
|
-
options: { onlyWhenDetached?: boolean } = {},
|
|
159
|
-
): void {
|
|
160
|
-
const retainedResult = compactForegroundResult(result);
|
|
161
|
-
const run = state.foregroundRuns?.get(runId);
|
|
162
|
-
if (!run) {
|
|
163
|
-
let byRun = earlyDetachedResults.get(state);
|
|
164
|
-
if (!byRun) {
|
|
165
|
-
byRun = new Map();
|
|
166
|
-
earlyDetachedResults.set(state, byRun);
|
|
167
|
-
}
|
|
168
|
-
let byIndex = byRun.get(runId);
|
|
169
|
-
if (!byIndex) {
|
|
170
|
-
byIndex = new Map();
|
|
171
|
-
byRun.set(runId, byIndex);
|
|
172
|
-
}
|
|
173
|
-
byIndex.set(index, retainedResult);
|
|
174
|
-
while (byIndex.size > MAX_EARLY_DETACHED_CHILDREN_PER_RUN) {
|
|
175
|
-
const oldestIndex = byIndex.keys().next().value;
|
|
176
|
-
if (oldestIndex === undefined) break;
|
|
177
|
-
byIndex.delete(oldestIndex);
|
|
178
|
-
}
|
|
179
|
-
while (byRun.size > MAX_EARLY_DETACHED_RUNS) {
|
|
180
|
-
const oldestRun = byRun.keys().next().value;
|
|
181
|
-
if (oldestRun === undefined) break;
|
|
182
|
-
byRun.delete(oldestRun);
|
|
183
|
-
}
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const child = run.children.find((entry) => entry.index === index);
|
|
187
|
-
if (!child || (options.onlyWhenDetached !== false && child.status !== "detached")) return;
|
|
188
|
-
child.status = resolveSubagentResultStatus({
|
|
189
|
-
status: retainedResult.status,
|
|
190
|
-
interrupted: retainedResult.interrupted,
|
|
191
|
-
detached: retainedResult.detached,
|
|
192
|
-
});
|
|
193
|
-
child.result = retainedResult;
|
|
194
|
-
if (retainedResult.sessionFile) child.sessionFile = retainedResult.sessionFile;
|
|
195
|
-
run.updatedAt = Date.now();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
80
|
export function emitControlNotification(input: {
|
|
199
81
|
pi: ExtensionAPI;
|
|
200
82
|
controlConfig: ExecutionContextData["controlConfig"];
|
|
201
|
-
intercomBridge: IntercomBridgeState
|
|
83
|
+
intercomBridge: Pick<IntercomBridgeState, "active" | "orchestratorTarget">;
|
|
202
84
|
event: ControlEvent;
|
|
203
85
|
}): void {
|
|
204
86
|
if (!shouldNotifyControlEvent(input.controlConfig, input.event)) return;
|
|
@@ -284,7 +166,7 @@ export function notifyDetachedForegroundChildExit(input: {
|
|
|
284
166
|
agent: result.agent,
|
|
285
167
|
status: result.status,
|
|
286
168
|
summary: resultSummaryForIntercom(result),
|
|
287
|
-
...(result.interrupted ? { state: "
|
|
169
|
+
...(result.interrupted ? { state: "interrupted" } : {}),
|
|
288
170
|
timestamp: Date.now(),
|
|
289
171
|
...(result.progressSummary?.durationMs !== undefined ? { durationMs: result.progressSummary.durationMs } : {}),
|
|
290
172
|
...(result.sessionFile ? { sessionFile: result.sessionFile } : {}),
|
|
@@ -14,6 +14,8 @@ import type {
|
|
|
14
14
|
import type { ChildModePolicy } from "../inprocess/child-policy.js";
|
|
15
15
|
import type { runSync } from "./execution.js";
|
|
16
16
|
|
|
17
|
+
export const BURST_TASK_DISCOVERY_CWD = Symbol("burstTaskDiscoveryCwd");
|
|
18
|
+
|
|
17
19
|
export interface TaskParam {
|
|
18
20
|
agent: string;
|
|
19
21
|
task: string;
|
|
@@ -28,14 +30,16 @@ export interface TaskParam {
|
|
|
28
30
|
group?: string | true;
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
export type BurstTaskParam = TaskParam & {
|
|
34
|
+
[BURST_TASK_DISCOVERY_CWD]?: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
31
37
|
export interface SubagentParamsLike {
|
|
32
38
|
action?: (typeof SUBAGENT_ACTIONS)[number];
|
|
33
39
|
id?: string;
|
|
34
40
|
runId?: string;
|
|
35
|
-
index?: number;
|
|
36
41
|
agent?: string;
|
|
37
42
|
task?: string;
|
|
38
|
-
message?: string;
|
|
39
43
|
config?: unknown;
|
|
40
44
|
tasks?: TaskParam[];
|
|
41
45
|
concurrency?: number;
|
|
@@ -94,6 +98,7 @@ export interface ExecutionContextData {
|
|
|
94
98
|
signal: AbortSignal;
|
|
95
99
|
onUpdate?: (r: SubagentToolResult) => void;
|
|
96
100
|
agents: AgentConfig[];
|
|
101
|
+
parallelAgentConfigs?: AgentConfig[];
|
|
97
102
|
runId: string;
|
|
98
103
|
shareEnabled: boolean;
|
|
99
104
|
sessionRoot: string;
|
|
@@ -1,55 +1,16 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
1
|
import type { ExtensionContext } from "@bastani/atomic";
|
|
4
2
|
import { handleManagementAction } from "../../agents/agent-management.js";
|
|
5
|
-
import { resolveExecutionAgentScope } from "../../agents/agent-scope.js";
|
|
6
3
|
import { clearPendingForegroundControlNotices } from "../../extension/control-notices.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
resolveIntercomBridge,
|
|
11
|
-
resolveIntercomSessionTarget,
|
|
12
|
-
resolveSubagentIntercomTarget,
|
|
13
|
-
} from "../../intercom/intercom-bridge.js";
|
|
14
|
-
import { requestSupervisorAuthorization } from "../../intercom/supervisor-authorization.js";
|
|
15
|
-
import { getArtifactsDir } from "../../shared/artifacts.js";
|
|
16
|
-
import { collectKnownModelProviders, toModelInfo } from "../../shared/model-info.js";
|
|
17
|
-
import { createCandidateModelResolver } from "../../shared/model-resolution.js";
|
|
18
|
-
import {
|
|
19
|
-
injectSingleProgressInstruction,
|
|
20
|
-
resolveSingleProgress,
|
|
21
|
-
writeInitialProgressFile,
|
|
22
|
-
} from "../../shared/settings.js";
|
|
23
|
-
import {
|
|
24
|
-
DEFAULT_ARTIFACT_CONFIG,
|
|
25
|
-
getCurrentSubagentDepth,
|
|
26
|
-
isWorkflowStageOrchestrationContext,
|
|
27
|
-
type SingleResult,
|
|
28
|
-
SUBAGENT_ACTIONS,
|
|
29
|
-
type SubagentToolResult,
|
|
30
|
-
workflowSessionMetadataFromContext,
|
|
31
|
-
} from "../../shared/types.js";
|
|
32
|
-
import {
|
|
33
|
-
inspectInProcessChildStatus,
|
|
34
|
-
interruptInProcessChild,
|
|
35
|
-
resumeInProcessChild,
|
|
36
|
-
} from "../inprocess/control-status.js";
|
|
37
|
-
import { inheritedIntercomGroup } from "../shared/intercom-group.js";
|
|
38
|
-
import { currentModelFullId } from "../shared/model-fallback.js";
|
|
39
|
-
import { resolveControlConfig } from "../shared/subagent-control.js";
|
|
4
|
+
import { SUBAGENT_ACTIONS, type SubagentToolResult } from "../../shared/types.js";
|
|
5
|
+
import { inspectInProcessChildStatus, interruptInProcessChild } from "../inprocess/control-status.js";
|
|
6
|
+
import { createExecutionBurstDispatcher } from "./subagent-executor-burst.js";
|
|
40
7
|
import { prepareExecutionContext, refuseSubagentChildDelegation } from "./subagent-executor-context.js";
|
|
8
|
+
import { resolveRequestedCwd } from "./subagent-executor-cwd.js";
|
|
41
9
|
import { toExecutionErrorResult, withForkContext } from "./subagent-executor-input.js";
|
|
42
10
|
import { runParallelPath } from "./subagent-executor-parallel.js";
|
|
43
|
-
import { resolveRequestedCwd } from "./subagent-executor-resume.js";
|
|
44
11
|
import { resolveSubagentExecutorRuntimeDeps } from "./subagent-executor-runtime.js";
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
foregroundStatusResult,
|
|
48
|
-
getForegroundControl,
|
|
49
|
-
notifyDetachedForegroundChildExit,
|
|
50
|
-
replaceForegroundRunChild,
|
|
51
|
-
retainedForegroundStatusResult,
|
|
52
|
-
} from "./subagent-executor-status.js";
|
|
12
|
+
import { runSinglePath } from "./subagent-executor-single.js";
|
|
13
|
+
import { foregroundStatusResult, getForegroundControl } from "./subagent-executor-status.js";
|
|
53
14
|
import {
|
|
54
15
|
type ExecutorDeps,
|
|
55
16
|
isManagementActionsRestricted,
|
|
@@ -57,130 +18,9 @@ import {
|
|
|
57
18
|
type SubagentParamsLike,
|
|
58
19
|
} from "./subagent-executor-types.js";
|
|
59
20
|
|
|
60
|
-
async function resumeRetainedForegroundChild(
|
|
61
|
-
params: SubagentParamsLike,
|
|
62
|
-
message: string,
|
|
63
|
-
ctx: ExtensionContext,
|
|
64
|
-
deps: ResolvedExecutorDeps,
|
|
65
|
-
onUpdate: ((r: SubagentToolResult) => void) | undefined,
|
|
66
|
-
): Promise<SubagentToolResult | undefined> {
|
|
67
|
-
const requested = params.id ?? params.runId;
|
|
68
|
-
if (!requested) return undefined;
|
|
69
|
-
const run = deps.state.foregroundRuns?.get(requested);
|
|
70
|
-
if (!run) return undefined;
|
|
71
|
-
const child = run.children[params.index ?? 0];
|
|
72
|
-
if (!child) return undefined;
|
|
73
|
-
const agents = deps.discoverAgents(run.cwd, resolveExecutionAgentScope(params.agentScope)).agents;
|
|
74
|
-
const agentConfig = agents.find((agent) => agent.name === child.agent);
|
|
75
|
-
if (!agentConfig) {
|
|
76
|
-
return {
|
|
77
|
-
content: [{ type: "text", text: `Unknown agent for resume: ${child.agent}` }],
|
|
78
|
-
isError: true,
|
|
79
|
-
details: { mode: "single", results: [] },
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
const parentSessionFile = ctx.sessionManager.getSessionFile() ?? null;
|
|
83
|
-
const sessionName = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
|
|
84
|
-
const intercomBridge = resolveIntercomBridge({
|
|
85
|
-
config: deps.config.intercomBridge,
|
|
86
|
-
context: params.context,
|
|
87
|
-
orchestratorTarget: sessionName,
|
|
88
|
-
cwd: run.cwd,
|
|
89
|
-
});
|
|
90
|
-
const supervisedTarget = intercomBridge.active
|
|
91
|
-
? resolveSubagentIntercomTarget(run.runId, child.agent, child.index)
|
|
92
|
-
: undefined;
|
|
93
|
-
const supervisorAuthorization = await requestSupervisorAuthorization(deps.pi.events, supervisedTarget);
|
|
94
|
-
const artifactConfig = { ...DEFAULT_ARTIFACT_CONFIG, enabled: params.artifacts !== false };
|
|
95
|
-
const artifactsDir = getArtifactsDir(parentSessionFile);
|
|
96
|
-
const progressDir = resolveSingleProgress(agentConfig, params.progress, message)
|
|
97
|
-
? path.join(artifactsDir, "progress", run.runId)
|
|
98
|
-
: undefined;
|
|
99
|
-
if (progressDir) {
|
|
100
|
-
writeInitialProgressFile(progressDir);
|
|
101
|
-
message = injectSingleProgressInstruction(message, progressDir);
|
|
102
|
-
}
|
|
103
|
-
const cleanupProgress = (): void => {
|
|
104
|
-
if (!progressDir || artifactConfig.enabled) return;
|
|
105
|
-
try {
|
|
106
|
-
fs.rmSync(progressDir, { recursive: true, force: true });
|
|
107
|
-
} catch {
|
|
108
|
-
// Scratch cleanup must never replace the child run's result or original error.
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const forwardSingleUpdate = createForwardSingleUpdate(
|
|
112
|
-
onUpdate,
|
|
113
|
-
getForegroundControl(deps.state, run.runId),
|
|
114
|
-
child.agent,
|
|
115
|
-
child.index,
|
|
116
|
-
);
|
|
117
|
-
let result: SingleResult;
|
|
118
|
-
try {
|
|
119
|
-
result = await deps.runtime.runSync(run.cwd, agents, child.agent, message, {
|
|
120
|
-
cwd: run.cwd,
|
|
121
|
-
signal: ctx.signal,
|
|
122
|
-
interruptSignal: ctx.signal,
|
|
123
|
-
allowIntercomDetach: agentConfig.systemPrompt?.includes(INTERCOM_BRIDGE_MARKER) === true,
|
|
124
|
-
intercomEvents: deps.pi.events,
|
|
125
|
-
runId: run.runId,
|
|
126
|
-
index: child.index,
|
|
127
|
-
sessionDir: child.sessionFile ? path.dirname(child.sessionFile) : undefined,
|
|
128
|
-
sessionFile: child.sessionFile,
|
|
129
|
-
share: params.share === true,
|
|
130
|
-
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
131
|
-
artifactConfig,
|
|
132
|
-
maxOutput: params.maxOutput,
|
|
133
|
-
parentDepth: getCurrentSubagentDepth(ctx),
|
|
134
|
-
workflowStageSubagentGuard: isWorkflowStageOrchestrationContext(ctx),
|
|
135
|
-
workflowSessionMetadata: workflowSessionMetadataFromContext(ctx),
|
|
136
|
-
controlConfig: resolveControlConfig(deps.config.control, params.control),
|
|
137
|
-
intercomSessionName: intercomBridge.active
|
|
138
|
-
? resolveSubagentIntercomTarget(run.runId, child.agent, child.index)
|
|
139
|
-
: undefined,
|
|
140
|
-
orchestratorIntercomTarget: intercomBridge.active ? intercomBridge.orchestratorTarget : undefined,
|
|
141
|
-
intercomGroup: inheritedIntercomGroup(ctx),
|
|
142
|
-
supervisorAuthorization,
|
|
143
|
-
modelOverride: params.model,
|
|
144
|
-
availableModels: ctx.modelRegistry.getAvailable().map(toModelInfo),
|
|
145
|
-
knownModelProviders: collectKnownModelProviders(ctx.modelRegistry),
|
|
146
|
-
resolveCandidateModel: createCandidateModelResolver(ctx.modelRegistry, ctx.model?.provider),
|
|
147
|
-
preferredModelProvider: ctx.model?.provider,
|
|
148
|
-
currentModel: currentModelFullId(ctx.model),
|
|
149
|
-
currentThinkingLevel: ctx.thinkingLevel,
|
|
150
|
-
onUpdate: forwardSingleUpdate,
|
|
151
|
-
onDetachedExit: (detachedResult) => {
|
|
152
|
-
cleanupProgress();
|
|
153
|
-
if (detachedResult) {
|
|
154
|
-
replaceForegroundRunChild(deps.state, run.runId, child.index, detachedResult);
|
|
155
|
-
notifyDetachedForegroundChildExit({
|
|
156
|
-
pi: deps.pi,
|
|
157
|
-
runId: run.runId,
|
|
158
|
-
mode: "single",
|
|
159
|
-
index: child.index,
|
|
160
|
-
result: detachedResult,
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
} catch (error) {
|
|
166
|
-
cleanupProgress();
|
|
167
|
-
throw error;
|
|
168
|
-
}
|
|
169
|
-
if (!result.detached) cleanupProgress();
|
|
170
|
-
replaceForegroundRunChild(deps.state, run.runId, child.index, result, { onlyWhenDetached: false });
|
|
171
|
-
return {
|
|
172
|
-
content: [{ type: "text", text: result.finalOutput ?? result.envelope ?? result.error ?? "" }],
|
|
173
|
-
details: { mode: "single", runId: run.runId, results: [result] },
|
|
174
|
-
...(result.status === "error" ? { isError: true } : {}),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
21
|
const MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete"]);
|
|
178
|
-
/**
|
|
179
|
-
|
|
180
|
-
* definitions or starts/continues agent execution, so a child without fanout
|
|
181
|
-
* authorization is refused all of them.
|
|
182
|
-
*/
|
|
183
|
-
const READ_ONLY_MANAGEMENT_ACTIONS = new Set(["list", "get", "status", "doctor"]);
|
|
22
|
+
/** Observing management actions do not start or mutate child execution. */
|
|
23
|
+
const READ_ONLY_MANAGEMENT_ACTIONS = new Set(["list", "get", "status"]);
|
|
184
24
|
const FANOUT_REFUSAL_MESSAGE = "Subagent fanout is not authorized for this child.";
|
|
185
25
|
|
|
186
26
|
export type { SubagentExecutorRuntimeDeps, SubagentParamsLike } from "./subagent-executor-types.js";
|
|
@@ -191,9 +31,8 @@ async function handleManagementRequest(input: {
|
|
|
191
31
|
requestCwd: string;
|
|
192
32
|
ctx: ExtensionContext;
|
|
193
33
|
deps: ResolvedExecutorDeps;
|
|
194
|
-
onUpdate?: (r: SubagentToolResult) => void;
|
|
195
34
|
}): Promise<SubagentToolResult> {
|
|
196
|
-
const { params, paramsWithResolvedCwd, requestCwd, ctx, deps
|
|
35
|
+
const { params, paramsWithResolvedCwd, requestCwd, ctx, deps } = input;
|
|
197
36
|
const action = params.action;
|
|
198
37
|
if (!action) {
|
|
199
38
|
return {
|
|
@@ -216,9 +55,8 @@ async function handleManagementRequest(input: {
|
|
|
216
55
|
details: { mode: "management" as const, results: [] },
|
|
217
56
|
};
|
|
218
57
|
}
|
|
219
|
-
// `
|
|
220
|
-
//
|
|
221
|
-
// reach their handlers for a child without fanout authorization.
|
|
58
|
+
// `interrupt` is privileged control over a running child, so only the
|
|
59
|
+
// observing actions reach handlers for a child without fanout authorization.
|
|
222
60
|
if (deps.childPolicy && !deps.childPolicy.fanoutAuthorized && !READ_ONLY_MANAGEMENT_ACTIONS.has(action)) {
|
|
223
61
|
return {
|
|
224
62
|
content: [{ type: "text", text: FANOUT_REFUSAL_MESSAGE }],
|
|
@@ -226,57 +64,17 @@ async function handleManagementRequest(input: {
|
|
|
226
64
|
details: { mode: "management" as const, results: [] },
|
|
227
65
|
};
|
|
228
66
|
}
|
|
229
|
-
// Delegation is one level deep: a
|
|
230
|
-
// never start or continue another agent, whatever else it is authorized for.
|
|
67
|
+
// Delegation is one level deep: a child may never control another child.
|
|
231
68
|
if (!READ_ONLY_MANAGEMENT_ACTIONS.has(action)) {
|
|
232
69
|
const childRefusal = refuseSubagentChildDelegation(ctx, "management");
|
|
233
70
|
if (childRefusal) return childRefusal;
|
|
234
71
|
}
|
|
235
|
-
if (action === "doctor") {
|
|
236
|
-
let currentSessionFile: string | null = null;
|
|
237
|
-
let currentSessionId = deps.state.currentSessionId;
|
|
238
|
-
let sessionError: string | undefined;
|
|
239
|
-
try {
|
|
240
|
-
currentSessionFile = ctx.sessionManager.getSessionFile() ?? null;
|
|
241
|
-
currentSessionId = ctx.sessionManager.getSessionId();
|
|
242
|
-
} catch (error) {
|
|
243
|
-
sessionError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
244
|
-
}
|
|
245
|
-
let orchestratorTarget: string | undefined;
|
|
246
|
-
try {
|
|
247
|
-
orchestratorTarget = resolveIntercomSessionTarget(deps.pi.getSessionName(), ctx.sessionManager.getSessionId());
|
|
248
|
-
} catch {}
|
|
249
|
-
return {
|
|
250
|
-
content: [
|
|
251
|
-
{
|
|
252
|
-
type: "text",
|
|
253
|
-
text: buildDoctorReport({
|
|
254
|
-
cwd: requestCwd,
|
|
255
|
-
config: deps.config,
|
|
256
|
-
state: deps.state,
|
|
257
|
-
context: paramsWithResolvedCwd.context,
|
|
258
|
-
requestedSessionDir: paramsWithResolvedCwd.sessionDir,
|
|
259
|
-
currentSessionFile,
|
|
260
|
-
currentSessionId,
|
|
261
|
-
orchestratorTarget,
|
|
262
|
-
sessionError,
|
|
263
|
-
expandTilde: deps.expandTilde,
|
|
264
|
-
}),
|
|
265
|
-
},
|
|
266
|
-
],
|
|
267
|
-
details: { mode: "management", results: [] },
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
72
|
if (action === "status") {
|
|
271
73
|
const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
272
74
|
const inProcess = inspectInProcessChildStatus(targetRunId);
|
|
273
75
|
if (inProcess) return inProcess;
|
|
274
76
|
const foreground = getForegroundControl(deps.state, targetRunId);
|
|
275
77
|
if (foreground) return foregroundStatusResult(foreground);
|
|
276
|
-
if (targetRunId) {
|
|
277
|
-
const retained = retainedForegroundStatusResult(deps.state, targetRunId);
|
|
278
|
-
if (retained) return retained;
|
|
279
|
-
}
|
|
280
78
|
return {
|
|
281
79
|
content: [
|
|
282
80
|
{
|
|
@@ -288,26 +86,6 @@ async function handleManagementRequest(input: {
|
|
|
288
86
|
details: { mode: "management", results: [] },
|
|
289
87
|
};
|
|
290
88
|
}
|
|
291
|
-
if (action === "resume") {
|
|
292
|
-
const targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;
|
|
293
|
-
const message = paramsWithResolvedCwd.message ?? paramsWithResolvedCwd.task;
|
|
294
|
-
if (!targetRunId || !message) {
|
|
295
|
-
return {
|
|
296
|
-
content: [{ type: "text", text: "action='resume' requires id/runId and message." }],
|
|
297
|
-
isError: true,
|
|
298
|
-
details: { mode: "management", results: [] },
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
const inProcess = await resumeInProcessChild(targetRunId, message, { model: ctx.model });
|
|
302
|
-
if (inProcess) return inProcess;
|
|
303
|
-
const retained = await resumeRetainedForegroundChild(paramsWithResolvedCwd, message, ctx, deps, onUpdate);
|
|
304
|
-
if (retained) return retained;
|
|
305
|
-
return {
|
|
306
|
-
content: [{ type: "text", text: `No in-process child found for '${targetRunId}'.` }],
|
|
307
|
-
isError: true,
|
|
308
|
-
details: { mode: "management", results: [] },
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
89
|
if (action === "interrupt") {
|
|
312
90
|
const targetRunId = paramsWithResolvedCwd.runId ?? paramsWithResolvedCwd.id;
|
|
313
91
|
if (targetRunId) {
|
|
@@ -366,18 +144,16 @@ export function createSubagentExecutor(rawDeps: ExecutorDeps): {
|
|
|
366
144
|
ctx: ExtensionContext,
|
|
367
145
|
): Promise<SubagentToolResult> => {
|
|
368
146
|
deps.state.baseCwd = ctx.cwd;
|
|
369
|
-
deps.state.foregroundRuns ??= new Map();
|
|
370
147
|
deps.state.foregroundControls ??= new Map();
|
|
371
148
|
deps.state.lastForegroundControlId ??= null;
|
|
372
149
|
const requestCwd = resolveRequestedCwd(ctx.cwd, params.cwd);
|
|
373
150
|
const paramsWithResolvedCwd = params.cwd === undefined ? params : { ...params, cwd: requestCwd };
|
|
374
151
|
if (params.action) {
|
|
375
|
-
return handleManagementRequest({ params, paramsWithResolvedCwd, requestCwd, ctx, deps
|
|
152
|
+
return handleManagementRequest({ params, paramsWithResolvedCwd, requestCwd, ctx, deps });
|
|
376
153
|
}
|
|
377
|
-
// Fanout authorization gates delegation and
|
|
378
|
-
//
|
|
379
|
-
//
|
|
380
|
-
// and mutating management are refused inside handleManagementRequest.
|
|
154
|
+
// Fanout authorization gates delegation and privileged control. Only `list`,
|
|
155
|
+
// `get`, and `status` stay available to an unauthorized child; `interrupt`
|
|
156
|
+
// and mutating management are refused by handleManagementRequest.
|
|
381
157
|
if (deps.childPolicy && !deps.childPolicy.fanoutAuthorized) {
|
|
382
158
|
return {
|
|
383
159
|
content: [{ type: "text", text: FANOUT_REFUSAL_MESSAGE }],
|
|
@@ -423,22 +199,19 @@ export function createSubagentExecutor(rawDeps: ExecutorDeps): {
|
|
|
423
199
|
);
|
|
424
200
|
};
|
|
425
201
|
|
|
426
|
-
const
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (deps.state.subagentInProgress === true) return duplicateSubagentCallResult(params);
|
|
435
|
-
deps.state.subagentInProgress = true;
|
|
436
|
-
try {
|
|
437
|
-
return await execute(id, params, signal, onUpdate, ctx);
|
|
438
|
-
} finally {
|
|
439
|
-
deps.state.subagentInProgress = false;
|
|
440
|
-
}
|
|
441
|
-
};
|
|
202
|
+
const executeWithBurstCollection = createExecutionBurstDispatcher({
|
|
203
|
+
execute,
|
|
204
|
+
isActive: () => deps.state.subagentInProgress === true,
|
|
205
|
+
setActive: (active) => {
|
|
206
|
+
deps.state.subagentInProgress = active;
|
|
207
|
+
},
|
|
208
|
+
duplicateResult: duplicateSubagentCallResult,
|
|
209
|
+
});
|
|
442
210
|
|
|
443
|
-
return {
|
|
211
|
+
return {
|
|
212
|
+
execute: (id, params, signal, onUpdate, ctx) =>
|
|
213
|
+
params.action
|
|
214
|
+
? execute(id, params, signal, onUpdate, ctx)
|
|
215
|
+
: executeWithBurstCollection(id, params, signal, onUpdate, ctx),
|
|
216
|
+
};
|
|
444
217
|
}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import type { SubagentToolResult } from "../../shared/types.js";
|
|
2
2
|
import { findSubagentControl, listSubagentControls } from "./control-registry.js";
|
|
3
|
-
import type { ModelCandidate } from "./runner.js";
|
|
4
3
|
|
|
5
4
|
function canonicalChildren(control: NonNullable<ReturnType<typeof findSubagentControl>>) {
|
|
6
5
|
return [...control.listChildren()].sort((left, right) => left.path.localeCompare(right.path));
|
|
7
6
|
}
|
|
8
7
|
|
|
9
|
-
function resumeTarget(control: NonNullable<ReturnType<typeof findSubagentControl>>, id: string) {
|
|
10
|
-
if (id !== control.parent.path) return control.findChild(id);
|
|
11
|
-
const children = canonicalChildren(control);
|
|
12
|
-
return children.find((child) => child.status === "interrupted") ?? children[0];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
8
|
function childLines(control: ReturnType<typeof findSubagentControl>, id?: string): string[] {
|
|
16
9
|
if (!control) return [];
|
|
17
10
|
if (id) {
|
|
@@ -77,30 +70,3 @@ export async function interruptInProcessChild(id: string): Promise<SubagentToolR
|
|
|
77
70
|
details: { mode: "management", results: [] },
|
|
78
71
|
};
|
|
79
72
|
}
|
|
80
|
-
|
|
81
|
-
export async function resumeInProcessChild(
|
|
82
|
-
id: string,
|
|
83
|
-
message: string,
|
|
84
|
-
candidate: ModelCandidate,
|
|
85
|
-
): Promise<SubagentToolResult | undefined> {
|
|
86
|
-
const control = findSubagentControl(id);
|
|
87
|
-
if (!control) return undefined;
|
|
88
|
-
const target = resumeTarget(control, id);
|
|
89
|
-
if (!target) {
|
|
90
|
-
return {
|
|
91
|
-
content: [{ type: "text", text: `No in-process child found for '${id}'.` }],
|
|
92
|
-
isError: true,
|
|
93
|
-
details: { mode: "management", results: [] },
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
const outcome = await control.resumeChild(target.path, message, candidate);
|
|
97
|
-
const selection =
|
|
98
|
-
id === control.parent.path && control.listChildren().length > 1
|
|
99
|
-
? `Bare run id resolved to ${target.path}; interrupted children are preferred, then canonical path order.\n\n`
|
|
100
|
-
: "";
|
|
101
|
-
return {
|
|
102
|
-
content: [{ type: "text", text: `${selection}${outcome.envelope}` }],
|
|
103
|
-
isError: outcome.status === "error" || outcome.status === "interrupted" ? true : undefined,
|
|
104
|
-
details: { mode: "management", results: [] },
|
|
105
|
-
};
|
|
106
|
-
}
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
InProcessAttemptControlResult,
|
|
3
|
-
InProcessAttemptHandle,
|
|
4
|
-
InProcessAttemptResumeOutcome,
|
|
5
|
-
} from "./attempt-handles.js";
|
|
6
|
-
export {
|
|
7
|
-
clearInProcessAttemptHandles,
|
|
8
|
-
interruptInProcessAttempt,
|
|
9
|
-
registerInProcessAttempt,
|
|
10
|
-
resumeInProcessAttempt,
|
|
11
|
-
} from "./attempt-handles.js";
|
|
12
1
|
export type {
|
|
13
2
|
AdmissionRefusal,
|
|
14
3
|
AdmittedResult,
|
|
@@ -32,7 +21,6 @@ export {
|
|
|
32
21
|
continue_detached,
|
|
33
22
|
createSubagentControl,
|
|
34
23
|
deliver_child_result,
|
|
35
|
-
reload_cold_child,
|
|
36
24
|
run_child_attempt,
|
|
37
25
|
SubagentControlRuntime,
|
|
38
26
|
terminate_child_attempt,
|
|
@@ -11,7 +11,7 @@ export const CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS = [
|
|
|
11
11
|
export const CHILD_FANOUT_BOUNDARY_INSTRUCTIONS = [
|
|
12
12
|
"You are a child subagent with explicit fanout responsibility for this assigned task.",
|
|
13
13
|
"The parent session owns final orchestration, completion decisions, and follow-up implementation launches.",
|
|
14
|
-
"Delegation is one level deep: the `subagent` tool refuses every launch
|
|
14
|
+
"Delegation is one level deep: the `subagent` tool refuses every launch and interrupt from inside a subagent.",
|
|
15
15
|
"Do the assigned fanout work yourself and report what you found; do not plan around delegating it.",
|
|
16
16
|
"If you need to edit files, call the actual edit/write tools. Do not print tool-call syntax, patches, or pseudo-tool calls as text.",
|
|
17
17
|
].join("\n");
|