maestro-agent-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +24 -0
- package/README.md +133 -0
- package/dist/agents/contracts.d.ts +49 -0
- package/dist/agents/contracts.d.ts.map +1 -0
- package/dist/agents/contracts.js +2 -0
- package/dist/agents/contracts.js.map +1 -0
- package/dist/agents/rollout/shared.d.ts +24 -0
- package/dist/agents/rollout/shared.d.ts.map +1 -0
- package/dist/agents/rollout/shared.js +105 -0
- package/dist/agents/rollout/shared.js.map +1 -0
- package/dist/core/agent.d.ts +71 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +22 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/loop.d.ts +26 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +317 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +79 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +176 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/pool-cache.d.ts +103 -0
- package/dist/mcp/pool-cache.d.ts.map +1 -0
- package/dist/mcp/pool-cache.js +249 -0
- package/dist/mcp/pool-cache.js.map +1 -0
- package/dist/mcp/pool.d.ts +65 -0
- package/dist/mcp/pool.d.ts.map +1 -0
- package/dist/mcp/pool.js +86 -0
- package/dist/mcp/pool.js.map +1 -0
- package/dist/media/file-events.d.ts +8 -0
- package/dist/media/file-events.d.ts.map +1 -0
- package/dist/media/file-events.js +15 -0
- package/dist/media/file-events.js.map +1 -0
- package/dist/memory/active-task-template.d.ts +34 -0
- package/dist/memory/active-task-template.d.ts.map +1 -0
- package/dist/memory/active-task-template.js +63 -0
- package/dist/memory/active-task-template.js.map +1 -0
- package/dist/memory/compressor.d.ts +87 -0
- package/dist/memory/compressor.d.ts.map +1 -0
- package/dist/memory/compressor.js +164 -0
- package/dist/memory/compressor.js.map +1 -0
- package/dist/memory/hash.d.ts +17 -0
- package/dist/memory/hash.d.ts.map +1 -0
- package/dist/memory/hash.js +20 -0
- package/dist/memory/hash.js.map +1 -0
- package/dist/memory/prune.d.ts +117 -0
- package/dist/memory/prune.d.ts.map +1 -0
- package/dist/memory/prune.js +416 -0
- package/dist/memory/prune.js.map +1 -0
- package/dist/memory/reminder.d.ts +57 -0
- package/dist/memory/reminder.d.ts.map +1 -0
- package/dist/memory/reminder.js +57 -0
- package/dist/memory/reminder.js.map +1 -0
- package/dist/memory/scrubber.d.ts +28 -0
- package/dist/memory/scrubber.d.ts.map +1 -0
- package/dist/memory/scrubber.js +147 -0
- package/dist/memory/scrubber.js.map +1 -0
- package/dist/memory/token-estimate.d.ts +10 -0
- package/dist/memory/token-estimate.d.ts.map +1 -0
- package/dist/memory/token-estimate.js +69 -0
- package/dist/memory/token-estimate.js.map +1 -0
- package/dist/platform/config.d.ts +12 -0
- package/dist/platform/config.d.ts.map +1 -0
- package/dist/platform/config.js +54 -0
- package/dist/platform/config.js.map +1 -0
- package/dist/platform/jsonl.d.ts +15 -0
- package/dist/platform/jsonl.d.ts.map +1 -0
- package/dist/platform/jsonl.js +80 -0
- package/dist/platform/jsonl.js.map +1 -0
- package/dist/platform/lifecycle.d.ts +22 -0
- package/dist/platform/lifecycle.d.ts.map +1 -0
- package/dist/platform/lifecycle.js +60 -0
- package/dist/platform/lifecycle.js.map +1 -0
- package/dist/platform/logger.d.ts +26 -0
- package/dist/platform/logger.d.ts.map +1 -0
- package/dist/platform/logger.js +41 -0
- package/dist/platform/logger.js.map +1 -0
- package/dist/platform/mcp-config.d.ts +15 -0
- package/dist/platform/mcp-config.d.ts.map +1 -0
- package/dist/platform/mcp-config.js +8 -0
- package/dist/platform/mcp-config.js.map +1 -0
- package/dist/provider.d.ts +81 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +444 -0
- package/dist/provider.js.map +1 -0
- package/dist/providers/anthropic.d.ts +132 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +518 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/base.d.ts +140 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +2 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/deepseek.d.ts +118 -0
- package/dist/providers/deepseek.d.ts.map +1 -0
- package/dist/providers/deepseek.js +467 -0
- package/dist/providers/deepseek.js.map +1 -0
- package/dist/registry.d.ts +3 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +94 -0
- package/dist/registry.js.map +1 -0
- package/dist/session-store.d.ts +133 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +277 -0
- package/dist/session-store.js.map +1 -0
- package/dist/skills/curator.d.ts +104 -0
- package/dist/skills/curator.d.ts.map +1 -0
- package/dist/skills/curator.js +162 -0
- package/dist/skills/curator.js.map +1 -0
- package/dist/skills/index-builder.d.ts +42 -0
- package/dist/skills/index-builder.d.ts.map +1 -0
- package/dist/skills/index-builder.js +94 -0
- package/dist/skills/index-builder.js.map +1 -0
- package/dist/skills/loader.d.ts +107 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +286 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/preprocess.d.ts +45 -0
- package/dist/skills/preprocess.d.ts.map +1 -0
- package/dist/skills/preprocess.js +126 -0
- package/dist/skills/preprocess.js.map +1 -0
- package/dist/skills/usage.d.ts +75 -0
- package/dist/skills/usage.d.ts.map +1 -0
- package/dist/skills/usage.js +147 -0
- package/dist/skills/usage.js.map +1 -0
- package/dist/state/todos.d.ts +95 -0
- package/dist/state/todos.d.ts.map +1 -0
- package/dist/state/todos.js +198 -0
- package/dist/state/todos.js.map +1 -0
- package/dist/storage/conversations.d.ts +28 -0
- package/dist/storage/conversations.d.ts.map +1 -0
- package/dist/storage/conversations.js +8 -0
- package/dist/storage/conversations.js.map +1 -0
- package/dist/sub-agent/runner.d.ts +78 -0
- package/dist/sub-agent/runner.d.ts.map +1 -0
- package/dist/sub-agent/runner.js +215 -0
- package/dist/sub-agent/runner.js.map +1 -0
- package/dist/tools/builtin/agent.d.ts +33 -0
- package/dist/tools/builtin/agent.d.ts.map +1 -0
- package/dist/tools/builtin/agent.js +76 -0
- package/dist/tools/builtin/agent.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +11 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +91 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +21 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +238 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +17 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +139 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/sandbox.d.ts +16 -0
- package/dist/tools/builtin/sandbox.d.ts.map +1 -0
- package/dist/tools/builtin/sandbox.js +58 -0
- package/dist/tools/builtin/sandbox.js.map +1 -0
- package/dist/tools/builtin/skill_view.d.ts +37 -0
- package/dist/tools/builtin/skill_view.d.ts.map +1 -0
- package/dist/tools/builtin/skill_view.js +82 -0
- package/dist/tools/builtin/skill_view.js.map +1 -0
- package/dist/tools/builtin/todo_write.d.ts +29 -0
- package/dist/tools/builtin/todo_write.d.ts.map +1 -0
- package/dist/tools/builtin/todo_write.js +96 -0
- package/dist/tools/builtin/todo_write.js.map +1 -0
- package/dist/tools/builtin/web_fetch.d.ts +10 -0
- package/dist/tools/builtin/web_fetch.d.ts.map +1 -0
- package/dist/tools/builtin/web_fetch.js +150 -0
- package/dist/tools/builtin/web_fetch.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +35 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +70 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/file-state.d.ts +99 -0
- package/dist/tools/file-state.d.ts.map +1 -0
- package/dist/tools/file-state.js +133 -0
- package/dist/tools/file-state.js.map +1 -0
- package/dist/tools/hooks/sandbox-fs.d.ts +25 -0
- package/dist/tools/hooks/sandbox-fs.d.ts.map +1 -0
- package/dist/tools/hooks/sandbox-fs.js +48 -0
- package/dist/tools/hooks/sandbox-fs.js.map +1 -0
- package/dist/tools/registry.d.ts +102 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +93 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/types.d.ts +109 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { AIAgent } from "../core/agent.js";
|
|
6
|
+
import { runConversation } from "../core/loop.js";
|
|
7
|
+
import { buildSystemReminder } from "../memory/reminder.js";
|
|
8
|
+
import { effortToThinkingBudget } from "../providers/anthropic.js";
|
|
9
|
+
import { providerForModel } from "../provider.js";
|
|
10
|
+
import { deleteMaestroSession } from "../session-store.js";
|
|
11
|
+
import { loadSkillsCached } from "../skills/loader.js";
|
|
12
|
+
import { bashTool } from "../tools/builtin/bash.js";
|
|
13
|
+
import { createEditTool } from "../tools/builtin/edit.js";
|
|
14
|
+
import { createReadTool } from "../tools/builtin/read.js";
|
|
15
|
+
import { createSkillViewTool } from "../tools/builtin/skill_view.js";
|
|
16
|
+
import { webFetchTool } from "../tools/builtin/web_fetch.js";
|
|
17
|
+
import { createWriteTool } from "../tools/builtin/write.js";
|
|
18
|
+
import { getFileStateTracker } from "../tools/file-state.js";
|
|
19
|
+
import { createSandboxFsHook } from "../tools/hooks/sandbox-fs.js";
|
|
20
|
+
import { ToolRegistry } from "../tools/registry.js";
|
|
21
|
+
import { logger } from "../platform/logger.js";
|
|
22
|
+
/** Hard cap on the sub-agent's per-API-call max output tokens. Defaults
|
|
23
|
+
* to 4096 (same as parent's default in AIAgent.config). Env-override for
|
|
24
|
+
* large delegated reports. */
|
|
25
|
+
function resolveMaxTokens() {
|
|
26
|
+
const env = process.env.MAESTRO_SUBAGENT_MAX_TOKENS;
|
|
27
|
+
if (env) {
|
|
28
|
+
const n = Number.parseInt(env, 10);
|
|
29
|
+
if (Number.isFinite(n) && n > 0)
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
return 4096;
|
|
33
|
+
}
|
|
34
|
+
/** Where the sub-agent overlay prompts live on disk. Co-located with the
|
|
35
|
+
* other prompt resources under `src/prompts/`. Resolved via `fileURLToPath`
|
|
36
|
+
* for Node compatibility (clawgram's Bun build used `import.meta.dir`). */
|
|
37
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
38
|
+
const OVERLAY_DIR = join(__dirname, "..", "prompts", "sub-agents");
|
|
39
|
+
function loadOverlay(kind) {
|
|
40
|
+
const path = join(OVERLAY_DIR, `${kind}.md`);
|
|
41
|
+
try {
|
|
42
|
+
return readFileSync(path, "utf8");
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
// Fall back to a tiny inline reminder so a missing prompt file doesn't
|
|
46
|
+
// crash the whole call. The sub-agent will still know it's scoped.
|
|
47
|
+
logger.warn({ err: e, path }, "runSubAgent: overlay file missing, using fallback");
|
|
48
|
+
return "You are a focused sub-agent. Return one final text answer to the parent.";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the per-subagent-type tool registry.
|
|
53
|
+
*
|
|
54
|
+
* `general` — bash + Read + Write + Edit + WebFetch + skill_view.
|
|
55
|
+
* `explore` — Read + WebFetch + skill_view only. NO bash, write, edit —
|
|
56
|
+
* the role is read-only by construction.
|
|
57
|
+
*
|
|
58
|
+
* Both types share the same sandbox-fs hook. Neither registers `Agent`
|
|
59
|
+
* (recursion cap) or `todo_write` (sub-agents don't plan iteratively).
|
|
60
|
+
*/
|
|
61
|
+
function buildToolRegistry(kind, subSessionId, skills, abortSignal) {
|
|
62
|
+
void abortSignal; // reserved for future bash abort wiring
|
|
63
|
+
const tools = new ToolRegistry();
|
|
64
|
+
tools.use(createSandboxFsHook());
|
|
65
|
+
// Sub-agent's OWN file-state tracker — keyed off subSessionId, NOT the
|
|
66
|
+
// parent's. Sharing would mean the parent's Read could let the sub-agent
|
|
67
|
+
// skip Read-before-Edit (or vice-versa), defeating the invariant.
|
|
68
|
+
const fileTracker = getFileStateTracker(subSessionId);
|
|
69
|
+
tools.register(createReadTool({ tracker: fileTracker }));
|
|
70
|
+
tools.register(webFetchTool);
|
|
71
|
+
if (skills.length > 0) {
|
|
72
|
+
tools.register(createSkillViewTool({ skills, sessionId: subSessionId }));
|
|
73
|
+
}
|
|
74
|
+
if (kind === "general") {
|
|
75
|
+
tools.register(bashTool);
|
|
76
|
+
tools.register(createWriteTool({ tracker: fileTracker }));
|
|
77
|
+
tools.register(createEditTool({ tracker: fileTracker }));
|
|
78
|
+
}
|
|
79
|
+
// `explore` stops here — read-only.
|
|
80
|
+
return tools;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Run a sub-agent to completion. Returns its final text + accumulated
|
|
84
|
+
* usage; the caller (Agent tool) decides how to surface that to the
|
|
85
|
+
* parent model.
|
|
86
|
+
*
|
|
87
|
+
* Cleanup contract (load-bearing):
|
|
88
|
+
* - Clean drain or thrown error → `deleteMaestroSession(subSessionId)`
|
|
89
|
+
* in the finally block. Frees the JSONL + file-state tracker + (any)
|
|
90
|
+
* todo store for this sub-session.
|
|
91
|
+
* - Abort → leave JSONL on disk. The 30-day TTL sweep will eventually
|
|
92
|
+
* clear it; meanwhile it's available for postmortem.
|
|
93
|
+
*/
|
|
94
|
+
export async function runSubAgent(opts) {
|
|
95
|
+
const subSessionId = randomUUID();
|
|
96
|
+
let provider;
|
|
97
|
+
try {
|
|
98
|
+
provider = providerForModel(opts.parentModel);
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
return {
|
|
102
|
+
text: `[sub-agent failed to start: ${e instanceof Error ? e.message : String(e)}]`,
|
|
103
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
104
|
+
subSessionId,
|
|
105
|
+
aborted: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const tools = buildToolRegistry(opts.subagentType, subSessionId, opts.skills, opts.parentAbortSignal);
|
|
109
|
+
const overlay = loadOverlay(opts.subagentType);
|
|
110
|
+
const systemPrompt = `${opts.parentSystemPrompt}\n\n${overlay}`;
|
|
111
|
+
const maxTokens = resolveMaxTokens();
|
|
112
|
+
const thinkingBudget = opts.parentEffort ? effortToThinkingBudget(opts.parentEffort) : undefined;
|
|
113
|
+
// Sub-agent's user message follows the parent contract: prompt + own
|
|
114
|
+
// system reminder. The reminder reflects the SUB-SESSION's state
|
|
115
|
+
// (its own session id), not the parent's.
|
|
116
|
+
const reminderText = buildSystemReminder({ sessionId: subSessionId });
|
|
117
|
+
const userBlocks = [
|
|
118
|
+
{ type: "text", text: opts.prompt },
|
|
119
|
+
{ type: "text", text: reminderText },
|
|
120
|
+
];
|
|
121
|
+
const messages = [{ role: "user", content: userBlocks }];
|
|
122
|
+
const agent = new AIAgent(provider, tools, {
|
|
123
|
+
model: opts.parentModel,
|
|
124
|
+
systemPrompt,
|
|
125
|
+
maxTokens,
|
|
126
|
+
...(thinkingBudget ? { thinkingBudget } : {}),
|
|
127
|
+
...(opts.parentEffort ? { effort: opts.parentEffort } : {}),
|
|
128
|
+
...(opts.parentAbortSignal ? { abortSignal: opts.parentAbortSignal } : {}),
|
|
129
|
+
});
|
|
130
|
+
logger.info({
|
|
131
|
+
parentSessionId: opts.parentSessionId,
|
|
132
|
+
subSessionId,
|
|
133
|
+
subagentType: opts.subagentType,
|
|
134
|
+
model: opts.parentModel,
|
|
135
|
+
}, "runSubAgent: starting");
|
|
136
|
+
let finalText = "";
|
|
137
|
+
let usage = { inputTokens: 0, outputTokens: 0 };
|
|
138
|
+
let aborted = false;
|
|
139
|
+
let crashed = false;
|
|
140
|
+
try {
|
|
141
|
+
for await (const event of runConversation(agent, messages)) {
|
|
142
|
+
// Silent-by-default: we only consume terminal events. text_deltas,
|
|
143
|
+
// tool_uses, tool_results all stay inside the sub-agent's loop.
|
|
144
|
+
if (event.type === "result") {
|
|
145
|
+
finalText = event.content;
|
|
146
|
+
if (event.usage)
|
|
147
|
+
usage = event.usage;
|
|
148
|
+
}
|
|
149
|
+
else if (event.type === "error") {
|
|
150
|
+
// Surface as part of the final text so the parent sees the failure
|
|
151
|
+
// reason. The sub-agent's error event is its terminal state when
|
|
152
|
+
// it can't return a normal result.
|
|
153
|
+
finalText = finalText
|
|
154
|
+
? `${finalText}\n\n[sub-agent error: ${event.content}]`
|
|
155
|
+
: `[sub-agent error: ${event.content}]`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
if (isAbortError(e) || opts.parentAbortSignal?.aborted) {
|
|
161
|
+
aborted = true;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
crashed = true;
|
|
165
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
166
|
+
finalText = finalText
|
|
167
|
+
? `${finalText}\n\n[sub-agent crashed: ${msg}]`
|
|
168
|
+
: `[sub-agent crashed: ${msg}]`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
if (!aborted) {
|
|
173
|
+
// Clean drain OR provider-crashed: nuke the sub-session JSONL +
|
|
174
|
+
// in-memory caches. Aborts intentionally skip this so a parent
|
|
175
|
+
// interrupt leaves the JSONL for postmortem; the 30-day TTL sweep
|
|
176
|
+
// (cleanupStaleMaestroSessions) eventually clears it.
|
|
177
|
+
try {
|
|
178
|
+
deleteMaestroSession(subSessionId);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
logger.warn({ err: e, subSessionId }, "runSubAgent: cleanup failed");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
logger.info({
|
|
185
|
+
parentSessionId: opts.parentSessionId,
|
|
186
|
+
subSessionId,
|
|
187
|
+
subagentType: opts.subagentType,
|
|
188
|
+
aborted,
|
|
189
|
+
crashed,
|
|
190
|
+
textLen: finalText.length,
|
|
191
|
+
usage,
|
|
192
|
+
}, "runSubAgent: finished");
|
|
193
|
+
}
|
|
194
|
+
return { text: finalText, usage, subSessionId, aborted };
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Mirror of `maestroProvider`'s `isAbortError`. Inlined to avoid an extra
|
|
198
|
+
* import path and keep this module self-contained for the sub-agent
|
|
199
|
+
* boundary — the abort-shape detection is small and the runner is the
|
|
200
|
+
* only sub-agent caller in v1.
|
|
201
|
+
*/
|
|
202
|
+
function isAbortError(err) {
|
|
203
|
+
if (!err || typeof err !== "object")
|
|
204
|
+
return false;
|
|
205
|
+
const e = err;
|
|
206
|
+
if (e.name === "AbortError")
|
|
207
|
+
return true;
|
|
208
|
+
if (e.code === 20 || e.code === "ABORT_ERR")
|
|
209
|
+
return true;
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
/** Convenience re-export for test setup — lets tests prime the loaded
|
|
213
|
+
* catalog without re-fetching from disk. */
|
|
214
|
+
export { loadSkillsCached };
|
|
215
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/sub-agent/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type RunSubAgentOptions } from "../../sub-agent/runner.js";
|
|
2
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
3
|
+
/**
|
|
4
|
+
* `Agent` builtin — spawn a focused sub-agent for one delegated task.
|
|
5
|
+
*
|
|
6
|
+
* Returns only the sub-agent's final text to the parent model — tool calls,
|
|
7
|
+
* intermediate text, and the sub-agent's own session id are not surfaced
|
|
8
|
+
* mid-stream. This is the same contract Claude Code's Task tool exposes.
|
|
9
|
+
*
|
|
10
|
+
* Two scoped types in v1:
|
|
11
|
+
* - `general` — full builtin toolkit (bash + Read + Write + Edit +
|
|
12
|
+
* WebFetch + skill_view). Use for self-contained units of work.
|
|
13
|
+
* - `explore` — read-only (Read + WebFetch + skill_view). Use for
|
|
14
|
+
* finding / surveying / reporting tasks where you don't want the
|
|
15
|
+
* sub-agent mutating files by accident.
|
|
16
|
+
*
|
|
17
|
+
* `parallelSafe: false` — sub-agent invocation spawns a child loop with
|
|
18
|
+
* side effects (file writes for `general`, MCP-less Anthropic API calls
|
|
19
|
+
* for both). Running two in parallel would race the API rate limits + the
|
|
20
|
+
* shared file-state tracker registry.
|
|
21
|
+
*
|
|
22
|
+
* No `description` field on the schema (advisor): the model would either
|
|
23
|
+
* skip it or duplicate the prompt into it. We derive a log label from the
|
|
24
|
+
* prompt's first line internally.
|
|
25
|
+
*/
|
|
26
|
+
export interface AgentToolFactoryOptions {
|
|
27
|
+
/** Parent context the sub-agent inherits from. The runner uses these to
|
|
28
|
+
* build the sub-agent's system prompt, model, abort signal, and skill
|
|
29
|
+
* catalog — none of which the model needs to (or should) pass. */
|
|
30
|
+
parent: Pick<RunSubAgentOptions, "parentSessionId" | "parentSystemPrompt" | "parentModel" | "parentEffort" | "parentAbortSignal" | "skills">;
|
|
31
|
+
}
|
|
32
|
+
export declare function createAgentTool(opts: AgentToolFactoryOptions): ToolHandler;
|
|
33
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAGxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,uBAAuB;IACtC;;uEAEmE;IACnE,MAAM,EAAE,IAAI,CACV,kBAAkB,EAChB,iBAAiB,GACjB,oBAAoB,GACpB,aAAa,GACb,cAAc,GACd,mBAAmB,GACnB,QAAQ,CACX,CAAC;CACH;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,uBAAuB,GAAG,WAAW,CAiF1E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { runSubAgent, } from "../../sub-agent/runner.js";
|
|
2
|
+
const VALID_TYPES = new Set(["general", "explore"]);
|
|
3
|
+
export function createAgentTool(opts) {
|
|
4
|
+
return {
|
|
5
|
+
parallelSafe: false,
|
|
6
|
+
schema: {
|
|
7
|
+
name: "Agent",
|
|
8
|
+
description: "Spawn a focused sub-agent to do ONE delegated task and return its final text. " +
|
|
9
|
+
"The sub-agent has its own context — your tool calls, files-Read state, and todo list " +
|
|
10
|
+
"are NOT shared with it. Use `general` for self-contained work that may need bash/Write/Edit, " +
|
|
11
|
+
"and `explore` for read-only surveys (Read/WebFetch/skill_view only). " +
|
|
12
|
+
"The sub-agent cannot spawn its own sub-agents (no recursion). Pass a self-contained " +
|
|
13
|
+
"prompt — the sub-agent sees ONLY that prompt and the inherited system context.",
|
|
14
|
+
input_schema: {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: {
|
|
17
|
+
subagent_type: {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Sub-agent role. 'general' = full builtin toolkit. 'explore' = read-only " +
|
|
20
|
+
"(Read/WebFetch/skill_view only — no bash, no write, no edit).",
|
|
21
|
+
},
|
|
22
|
+
prompt: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Self-contained task brief. The sub-agent sees ONLY this text as its initial " +
|
|
25
|
+
"user message. State the goal, any constraints, and what 'done' looks like.",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: ["subagent_type", "prompt"],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
async execute(input) {
|
|
32
|
+
const subagentTypeRaw = input.subagent_type;
|
|
33
|
+
const prompt = input.prompt;
|
|
34
|
+
if (typeof subagentTypeRaw !== "string" ||
|
|
35
|
+
!VALID_TYPES.has(subagentTypeRaw)) {
|
|
36
|
+
return JSON.stringify({
|
|
37
|
+
error: `Agent: subagent_type must be one of ${Array.from(VALID_TYPES).join(", ")}, got '${subagentTypeRaw}'`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (typeof prompt !== "string" || prompt.trim().length === 0) {
|
|
41
|
+
return JSON.stringify({
|
|
42
|
+
error: "Agent: prompt must be a non-empty string",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const subagentType = subagentTypeRaw;
|
|
46
|
+
const result = await runSubAgent({
|
|
47
|
+
subagentType,
|
|
48
|
+
prompt,
|
|
49
|
+
parentSessionId: opts.parent.parentSessionId,
|
|
50
|
+
parentSystemPrompt: opts.parent.parentSystemPrompt,
|
|
51
|
+
parentModel: opts.parent.parentModel,
|
|
52
|
+
...(opts.parent.parentEffort ? { parentEffort: opts.parent.parentEffort } : {}),
|
|
53
|
+
...(opts.parent.parentAbortSignal
|
|
54
|
+
? { parentAbortSignal: opts.parent.parentAbortSignal }
|
|
55
|
+
: {}),
|
|
56
|
+
skills: opts.parent.skills,
|
|
57
|
+
});
|
|
58
|
+
if (result.aborted) {
|
|
59
|
+
// Aborted sub-agent: don't pretend a normal result. The parent
|
|
60
|
+
// model's next turn (if any) sees this and can decide.
|
|
61
|
+
return JSON.stringify({
|
|
62
|
+
error: "Agent: sub-agent was aborted (parent abort signal fired)",
|
|
63
|
+
subSessionId: result.subSessionId,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Final text + a one-line provenance footer the model can use to
|
|
67
|
+
// attribute facts ("from the explore sub-agent: ...") and so the
|
|
68
|
+
// unified conversation log carries traceability without needing a
|
|
69
|
+
// separate event type. Usage is included for cost transparency.
|
|
70
|
+
const footer = `\n\n— end of ${subagentType} sub-agent (${result.subSessionId.slice(0, 8)}) — ` +
|
|
71
|
+
`${result.usage.inputTokens} in / ${result.usage.outputTokens} out`;
|
|
72
|
+
return `${result.text}${footer}`;
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/tools/builtin/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Bash tool — PoC for Phase 1.
|
|
4
|
+
*
|
|
5
|
+
* Minimal: shell out, capture stdout/stderr, enforce a 30s timeout and a
|
|
6
|
+
* 16KB output cap. NOT a long-term solution — Phase 5 will replace this with
|
|
7
|
+
* an adapter to Clawgram's MCP terminal tool so the Maestro loop inherits
|
|
8
|
+
* Clawgram's permission system instead of having an unguarded subprocess.
|
|
9
|
+
*/
|
|
10
|
+
export declare const bashTool: ToolHandler;
|
|
11
|
+
//# sourceMappingURL=bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAKpD;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,WAmFtB,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
const BASH_TIMEOUT_MS = 30_000;
|
|
3
|
+
const BASH_MAX_OUTPUT = 16_000;
|
|
4
|
+
/**
|
|
5
|
+
* Bash tool — PoC for Phase 1.
|
|
6
|
+
*
|
|
7
|
+
* Minimal: shell out, capture stdout/stderr, enforce a 30s timeout and a
|
|
8
|
+
* 16KB output cap. NOT a long-term solution — Phase 5 will replace this with
|
|
9
|
+
* an adapter to Clawgram's MCP terminal tool so the Maestro loop inherits
|
|
10
|
+
* Clawgram's permission system instead of having an unguarded subprocess.
|
|
11
|
+
*/
|
|
12
|
+
export const bashTool = {
|
|
13
|
+
schema: {
|
|
14
|
+
name: "bash",
|
|
15
|
+
description: "Execute a bash command and return stdout/stderr. 30s timeout, 16KB output cap.",
|
|
16
|
+
input_schema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
command: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Bash command to execute",
|
|
22
|
+
},
|
|
23
|
+
cwd: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "Working directory (optional)",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
required: ["command"],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
async execute(input) {
|
|
32
|
+
const command = String(input.command ?? "");
|
|
33
|
+
if (!command.trim()) {
|
|
34
|
+
return JSON.stringify({ error: "empty command" });
|
|
35
|
+
}
|
|
36
|
+
const cwd = typeof input.cwd === "string" ? input.cwd : undefined;
|
|
37
|
+
return new Promise((resolve) => {
|
|
38
|
+
const child = spawn("bash", ["-c", command], {
|
|
39
|
+
...(cwd ? { cwd } : {}),
|
|
40
|
+
env: process.env,
|
|
41
|
+
});
|
|
42
|
+
let stdout = "";
|
|
43
|
+
let stderr = "";
|
|
44
|
+
let truncated = false;
|
|
45
|
+
const timer = setTimeout(() => {
|
|
46
|
+
child.kill("SIGKILL");
|
|
47
|
+
resolve(JSON.stringify({
|
|
48
|
+
error: `timeout after ${BASH_TIMEOUT_MS}ms`,
|
|
49
|
+
stdout,
|
|
50
|
+
stderr,
|
|
51
|
+
}));
|
|
52
|
+
}, BASH_TIMEOUT_MS);
|
|
53
|
+
child.stdout?.on("data", (chunk) => {
|
|
54
|
+
const text = chunk.toString("utf-8");
|
|
55
|
+
if (stdout.length + text.length > BASH_MAX_OUTPUT) {
|
|
56
|
+
stdout += text.slice(0, BASH_MAX_OUTPUT - stdout.length);
|
|
57
|
+
truncated = true;
|
|
58
|
+
child.stdout?.destroy();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
stdout += text;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
child.stderr?.on("data", (chunk) => {
|
|
65
|
+
const text = chunk.toString("utf-8");
|
|
66
|
+
if (stderr.length + text.length > BASH_MAX_OUTPUT) {
|
|
67
|
+
stderr += text.slice(0, BASH_MAX_OUTPUT - stderr.length);
|
|
68
|
+
truncated = true;
|
|
69
|
+
child.stderr?.destroy();
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
stderr += text;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
child.on("close", (code) => {
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
resolve(JSON.stringify({
|
|
78
|
+
exitCode: code,
|
|
79
|
+
stdout,
|
|
80
|
+
stderr,
|
|
81
|
+
...(truncated ? { truncated: true } : {}),
|
|
82
|
+
}));
|
|
83
|
+
});
|
|
84
|
+
child.on("error", (err) => {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
resolve(JSON.stringify({ error: err.message }));
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
//# sourceMappingURL=bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/tools/builtin/bash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FileStateTracker } from "../../tools/file-state.js";
|
|
2
|
+
import type { ToolHandler } from "../../tools/registry.js";
|
|
3
|
+
export interface EditToolOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Per-session file-state tracker. When provided, Edit enforces the
|
|
6
|
+
* Read-before-Edit invariant: the path must have been Read in this session
|
|
7
|
+
* AND its mtime/size must still match the recorded values.
|
|
8
|
+
*/
|
|
9
|
+
tracker?: FileStateTracker;
|
|
10
|
+
}
|
|
11
|
+
export declare function createEditTool(opts?: EditToolOptions): ToolHandler;
|
|
12
|
+
/** Backwards-compatible singleton (no tracker — Read-before-Edit gate off). */
|
|
13
|
+
export declare const editTool: ToolHandler;
|
|
14
|
+
/**
|
|
15
|
+
* Count non-overlapping occurrences of `needle` in `haystack`. We use this
|
|
16
|
+
* to drive the unique-match check; `indexOf` in a loop is fast enough for
|
|
17
|
+
* the 10MB cap and avoids the regex escaping the model would have to do.
|
|
18
|
+
*/
|
|
19
|
+
export declare function countOccurrences(haystack: string, needle: string): number;
|
|
20
|
+
export declare const __MAX_FILE_BYTES: number;
|
|
21
|
+
//# sourceMappingURL=edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/tools/builtin/edit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAqCpD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,IAAI,GAAE,eAAoB,GAAG,WAAW,CA4JtE;AAED,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,EAAE,WAA8B,CAAC;AAEtD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAUzE;AAqCD,eAAO,MAAM,gBAAgB,QAAiB,CAAC"}
|