@gonzih/cc-agent 0.15.16 → 0.15.18

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.
@@ -0,0 +1,81 @@
1
+ /**
2
+ * swarm.ts — swarm execution for cc-agent
3
+ *
4
+ * Decomposes a high-level goal into N sub-tasks via Anthropic Messages API
5
+ * (native fetch, zero new npm deps), fans out parallel agents, waits for
6
+ * all to complete, then spawns a synthesis agent that writes one deliverable.
7
+ */
8
+ import type { Redis } from "ioredis";
9
+ import type { JobManager } from "./agent.js";
10
+ export declare const SWARM_MAX_AGENTS_HARD_CAP = 50;
11
+ export type SwarmStatus = "running_subs" | "synthesizing" | "done" | "failed";
12
+ export interface SwarmRecord {
13
+ swarm_id: string;
14
+ goal: string;
15
+ repo_url: string;
16
+ sub_job_ids: string[];
17
+ decomposed_tasks: Array<{
18
+ id: string;
19
+ task: string;
20
+ }>;
21
+ synthesis_job_id?: string;
22
+ synthesis_output: string;
23
+ status: SwarmStatus;
24
+ created_at: string;
25
+ completed_at?: string;
26
+ error?: string;
27
+ }
28
+ export interface RunSwarmParams {
29
+ repoUrl: string;
30
+ goal: string;
31
+ maxAgents?: number;
32
+ synthesisOutput?: string;
33
+ synthesisPrompt?: string;
34
+ maxBudgetPerAgent?: number;
35
+ agentModel?: string;
36
+ agentDriver?: string;
37
+ manager: JobManager;
38
+ redis: Redis | null;
39
+ getJobOutput: (id: string, offset: number) => Promise<string[]>;
40
+ }
41
+ /**
42
+ * Parse the text content from an Anthropic Messages API response and extract
43
+ * the JSON array of subtask objects. Exported for unit testing.
44
+ */
45
+ export declare function parseDecomposeResponse(text: string): Array<{
46
+ id: string;
47
+ task: string;
48
+ }>;
49
+ /**
50
+ * Build the synthesis agent task string. Exported for unit testing.
51
+ *
52
+ * The synthesis agent receives: goal, all N sub-job outputs labelled by
53
+ * sub-task description, and an instruction to write the result to
54
+ * synthesisOutput and open a PR. No MCP tools needed — all data is inline.
55
+ */
56
+ export declare function buildSynthesisTask(goal: string, tasks: Array<{
57
+ id: string;
58
+ task: string;
59
+ }>, outputs: Array<{
60
+ taskId: string;
61
+ task: string;
62
+ status: string;
63
+ lines: string[];
64
+ }>, synthesisOutput: string, synthesisPrompt?: string): string;
65
+ /**
66
+ * Entry point called from index.ts.
67
+ * Returns immediately (< 5s) with swarm_id + sub_job_ids.
68
+ * Background async handles fan-in + synthesis.
69
+ */
70
+ export declare function runSwarm(params: RunSwarmParams): Promise<{
71
+ swarm_id: string;
72
+ sub_job_ids: string[];
73
+ decomposed_tasks: Array<{
74
+ id: string;
75
+ task: string;
76
+ }>;
77
+ status: "running";
78
+ }>;
79
+ /** Status polling — called by get_swarm_status MCP tool. */
80
+ export declare function getSwarmStatus(swarmId: string, redis: Redis | null): Promise<SwarmRecord | null>;
81
+ //# sourceMappingURL=swarm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm.d.ts","sourceRoot":"","sources":["../src/swarm.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAY7C,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAW5C,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,cAAc,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACjE;AAiCD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BxF;AAuGD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAC1C,OAAO,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EACjF,eAAe,EAAE,MAAM,EACvB,eAAe,CAAC,EAAE,MAAM,GACvB,MAAM,CA8BR;AAyJD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC,CA2GD;AAED,4DAA4D;AAC5D,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,GAAG,IAAI,GAClB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAE7B"}
package/dist/swarm.js ADDED
@@ -0,0 +1,409 @@
1
+ /**
2
+ * swarm.ts — swarm execution for cc-agent
3
+ *
4
+ * Decomposes a high-level goal into N sub-tasks via Anthropic Messages API
5
+ * (native fetch, zero new npm deps), fans out parallel agents, waits for
6
+ * all to complete, then spawns a synthesis agent that writes one deliverable.
7
+ */
8
+ import { v4 as uuidv4 } from "uuid";
9
+ import { logger } from "./logger.js";
10
+ // ─── Constants ────────────────────────────────────────────────────────────────
11
+ const SWARM_TTL_SECONDS = 7 * 24 * 60 * 60;
12
+ const DECOMPOSE_MODEL = "claude-haiku-4-5-20251001";
13
+ const ANTHROPIC_API_URL = "https://api.anthropic.com/v1/messages";
14
+ const ANTHROPIC_API_VERSION = "2023-06-01";
15
+ const TERMINAL_STATUSES = new Set(["done", "failed", "cancelled", "rejected", "interrupted"]);
16
+ // Hard cap on agents per swarm
17
+ export const SWARM_MAX_AGENTS_HARD_CAP = 50;
18
+ // Polling interval for waitForAllSubJobs background loop
19
+ const POLL_INTERVAL_MS = 5000;
20
+ // Per-sub-job output limits for synthesis prompt
21
+ const MAX_OUTPUT_LINES = 500;
22
+ const MAX_OUTPUT_CHARS = 20_000;
23
+ // ─── Redis helpers ────────────────────────────────────────────────────────────
24
+ /** In-memory fallback map when Redis is unavailable. */
25
+ const memSwarms = new Map();
26
+ async function saveSwarm(redis, record) {
27
+ if (redis) {
28
+ try {
29
+ await redis.set(`cca:swarm:${record.swarm_id}`, JSON.stringify(record), "EX", SWARM_TTL_SECONDS);
30
+ return;
31
+ }
32
+ catch (err) {
33
+ logger.error("swarm:save-failed", { swarm_id: record.swarm_id, err: String(err) });
34
+ }
35
+ }
36
+ memSwarms.set(record.swarm_id, record);
37
+ }
38
+ async function loadSwarm(redis, swarmId) {
39
+ if (redis) {
40
+ try {
41
+ const raw = await redis.get(`cca:swarm:${swarmId}`);
42
+ return raw ? JSON.parse(raw) : null;
43
+ }
44
+ catch (err) {
45
+ logger.error("swarm:load-failed", { swarm_id: swarmId, err: String(err) });
46
+ }
47
+ }
48
+ return memSwarms.get(swarmId) ?? null;
49
+ }
50
+ // ─── Decomposition ────────────────────────────────────────────────────────────
51
+ /**
52
+ * Parse the text content from an Anthropic Messages API response and extract
53
+ * the JSON array of subtask objects. Exported for unit testing.
54
+ */
55
+ export function parseDecomposeResponse(text) {
56
+ // Try to extract a JSON array from the text (may be surrounded by markdown fences or prose)
57
+ const cleaned = text.trim();
58
+ // Strategy 1: entire text is valid JSON
59
+ try {
60
+ const parsed = JSON.parse(cleaned);
61
+ if (Array.isArray(parsed))
62
+ return validateTasks(parsed);
63
+ }
64
+ catch { /* fall through */ }
65
+ // Strategy 2: find first [...] block (handles markdown fences + prose)
66
+ const arrayMatch = cleaned.match(/\[[\s\S]*\]/);
67
+ if (arrayMatch) {
68
+ try {
69
+ const parsed = JSON.parse(arrayMatch[0]);
70
+ if (Array.isArray(parsed))
71
+ return validateTasks(parsed);
72
+ }
73
+ catch { /* fall through */ }
74
+ }
75
+ // Strategy 3: find a JSON code fence block
76
+ const fenceMatch = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
77
+ if (fenceMatch) {
78
+ try {
79
+ const parsed = JSON.parse(fenceMatch[1].trim());
80
+ if (Array.isArray(parsed))
81
+ return validateTasks(parsed);
82
+ }
83
+ catch { /* fall through */ }
84
+ }
85
+ throw new Error(`Cannot extract JSON array from decompose response: ${cleaned.slice(0, 500)}`);
86
+ }
87
+ /** Ensure every element has { id: string, task: string }. Missing id is auto-generated. */
88
+ function validateTasks(arr) {
89
+ return arr
90
+ .filter((item) => typeof item === "object" && item !== null && "task" in item)
91
+ .map((item, i) => ({
92
+ id: String(item.id || `task-${i + 1}`),
93
+ task: String(item.task || ""),
94
+ }))
95
+ .filter((item) => item.task.trim().length > 0);
96
+ }
97
+ /** Call Anthropic Messages API to decompose a goal into N subtasks. */
98
+ async function decomposeGoal(goal, maxAgents) {
99
+ const apiKey = process.env.ANTHROPIC_API_KEY;
100
+ const oauthToken = process.env.CLAUDE_CODE_OAUTH_TOKEN ?? process.env.CLAUDE_CODE_TOKEN;
101
+ if (!apiKey && !oauthToken) {
102
+ throw new Error("Decomposition requires ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN to be set");
103
+ }
104
+ const headers = {
105
+ "content-type": "application/json",
106
+ "anthropic-version": ANTHROPIC_API_VERSION,
107
+ };
108
+ if (apiKey) {
109
+ headers["x-api-key"] = apiKey;
110
+ }
111
+ else {
112
+ headers["authorization"] = `Bearer ${oauthToken}`;
113
+ headers["anthropic-beta"] = "oauth-2025-04-20";
114
+ }
115
+ const prompt = buildDecomposePrompt(goal, maxAgents);
116
+ const body = JSON.stringify({
117
+ model: DECOMPOSE_MODEL,
118
+ max_tokens: 2048,
119
+ messages: [{ role: "user", content: prompt }],
120
+ });
121
+ logger.info("swarm:decompose-request", { model: DECOMPOSE_MODEL, goal: goal.slice(0, 120) });
122
+ const response = await fetch(ANTHROPIC_API_URL, {
123
+ method: "POST",
124
+ headers,
125
+ body,
126
+ });
127
+ if (!response.ok) {
128
+ const errText = await response.text().catch(() => "(no body)");
129
+ throw new Error(`Anthropic API error ${response.status}: ${errText.slice(0, 500)}`);
130
+ }
131
+ const data = (await response.json());
132
+ const textBlock = data.content?.find((b) => b.type === "text");
133
+ if (!textBlock?.text) {
134
+ throw new Error("Anthropic API returned no text content in decompose response");
135
+ }
136
+ const tasks = parseDecomposeResponse(textBlock.text);
137
+ if (tasks.length === 0) {
138
+ throw new Error("Decomposition returned 0 tasks — cannot proceed");
139
+ }
140
+ logger.info("swarm:decomposed", { task_count: tasks.length });
141
+ return tasks;
142
+ }
143
+ function buildDecomposePrompt(goal, maxAgents) {
144
+ return `You are a task decomposition assistant. Break the following goal into at most ${maxAgents} parallel, independent sub-tasks that can be executed simultaneously by separate coding agents. Each sub-task should be a self-contained unit of work.
145
+
146
+ GOAL:
147
+ ${goal}
148
+
149
+ Return ONLY a JSON array (no prose, no markdown fences) where each element has:
150
+ - "id": a short slug (e.g. "task-1", "task-2")
151
+ - "task": a clear, actionable description for that sub-task
152
+
153
+ Example output:
154
+ [
155
+ {"id": "task-1", "task": "..."},
156
+ {"id": "task-2", "task": "..."}
157
+ ]
158
+
159
+ Return no more than ${maxAgents} tasks. Return at least 1 task.`;
160
+ }
161
+ // ─── Synthesis ────────────────────────────────────────────────────────────────
162
+ /**
163
+ * Build the synthesis agent task string. Exported for unit testing.
164
+ *
165
+ * The synthesis agent receives: goal, all N sub-job outputs labelled by
166
+ * sub-task description, and an instruction to write the result to
167
+ * synthesisOutput and open a PR. No MCP tools needed — all data is inline.
168
+ */
169
+ export function buildSynthesisTask(goal, tasks, outputs, synthesisOutput, synthesisPrompt) {
170
+ const outputSections = outputs
171
+ .map((o) => {
172
+ const truncated = truncateOutput(o.lines);
173
+ return `### Sub-task: ${o.task}
174
+ Status: ${o.status}
175
+ Output (${o.lines.length} total lines${truncated.length < o.lines.length ? `, showing last ${truncated.length}` : ""}):
176
+ \`\`\`
177
+ ${truncated.join("\n")}
178
+ \`\`\``;
179
+ })
180
+ .join("\n\n");
181
+ const instruction = synthesisPrompt ??
182
+ `Review all sub-task outputs above, synthesize the findings, and produce a unified deliverable. Write the final synthesis report to \`${synthesisOutput}\` in the repository and open a Pull Request with your result.`;
183
+ return `# Swarm Synthesis Task
184
+
185
+ ## Original Goal
186
+ ${goal}
187
+
188
+ ## Sub-task Outputs (${outputs.length} sub-tasks)
189
+
190
+ ${outputSections}
191
+
192
+ ## Instructions
193
+ ${instruction}
194
+
195
+ Write the synthesized result to \`${synthesisOutput}\` in this repository and open a Pull Request titled "swarm synthesis: ${goal.slice(0, 60)}".`;
196
+ }
197
+ function truncateOutput(lines) {
198
+ const tail = lines.slice(-MAX_OUTPUT_LINES);
199
+ const joined = tail.join("\n");
200
+ if (joined.length <= MAX_OUTPUT_CHARS)
201
+ return tail;
202
+ // Char-limit: take last MAX_OUTPUT_CHARS characters, split by newline
203
+ const chars = joined.slice(-MAX_OUTPUT_CHARS);
204
+ const newlineIdx = chars.indexOf("\n");
205
+ return (newlineIdx > 0 ? chars.slice(newlineIdx + 1) : chars).split("\n");
206
+ }
207
+ // ─── Background fan-in + synthesis ────────────────────────────────────────────
208
+ async function waitForAllSubJobs(swarmId, record, tasks, synthesisPrompt, manager, redis, getJobOutput, maxBudgetPerAgent, agentModel, agentDriver) {
209
+ const { sub_job_ids: subJobIds, goal, repo_url: repoUrl, synthesis_output: synthesisOutput } = record;
210
+ logger.info("swarm:waiting", { swarm_id: swarmId, sub_count: subJobIds.length });
211
+ // Wait for all sub-jobs to reach terminal state
212
+ const TIMEOUT_MS = 6 * 60 * 60 * 1000; // 6-hour hard cap
213
+ const deadline = Date.now() + TIMEOUT_MS;
214
+ while (Date.now() < deadline) {
215
+ let allDone = true;
216
+ for (const jobId of subJobIds) {
217
+ const rec = await fetchJobRecord(jobId, redis);
218
+ if (!rec || !TERMINAL_STATUSES.has(rec.status)) {
219
+ allDone = false;
220
+ break;
221
+ }
222
+ }
223
+ if (allDone)
224
+ break;
225
+ await sleep(POLL_INTERVAL_MS);
226
+ }
227
+ // Collect outputs for all sub-jobs
228
+ const outputs = [];
229
+ let totalCost = 0;
230
+ for (let i = 0; i < subJobIds.length; i++) {
231
+ const jobId = subJobIds[i];
232
+ const taskEntry = tasks[i] ?? { id: `task-${i + 1}`, task: "(unknown)" };
233
+ const rec = await fetchJobRecord(jobId, redis);
234
+ const status = rec?.status ?? "unknown";
235
+ if (rec?.costUsd)
236
+ totalCost += rec.costUsd;
237
+ let lines = [];
238
+ try {
239
+ lines = await getJobOutput(jobId, 0);
240
+ }
241
+ catch (err) {
242
+ logger.warn("swarm:get-output-failed", { swarm_id: swarmId, job_id: jobId, err: String(err) });
243
+ lines = [`[error reading output: ${String(err)}]`];
244
+ }
245
+ outputs.push({ taskId: taskEntry.id, task: taskEntry.task, status, lines });
246
+ }
247
+ logger.info("swarm:all-subs-done", {
248
+ swarm_id: swarmId,
249
+ total_cost_usd: totalCost,
250
+ done: outputs.filter((o) => o.status === "done").length,
251
+ failed: outputs.filter((o) => o.status !== "done").length,
252
+ });
253
+ // Build synthesis task
254
+ const synthesisTask = buildSynthesisTask(goal, tasks, outputs, synthesisOutput, synthesisPrompt);
255
+ // Update swarm to synthesizing
256
+ record.status = "synthesizing";
257
+ await saveSwarm(redis, record);
258
+ // Spawn synthesis agent
259
+ let synthesisJobId;
260
+ try {
261
+ synthesisJobId = await manager.spawn({
262
+ repoUrl,
263
+ task: synthesisTask,
264
+ maxBudgetUsd: maxBudgetPerAgent,
265
+ agentModel,
266
+ agentDriver,
267
+ noPreamble: false,
268
+ });
269
+ logger.info("swarm:synthesis-spawned", { swarm_id: swarmId, synthesis_job_id: synthesisJobId });
270
+ }
271
+ catch (err) {
272
+ logger.error("swarm:synthesis-spawn-failed", { swarm_id: swarmId, err: String(err) });
273
+ record.status = "failed";
274
+ record.error = `Synthesis spawn failed: ${String(err)}`;
275
+ record.completed_at = new Date().toISOString();
276
+ await saveSwarm(redis, record);
277
+ return;
278
+ }
279
+ record.synthesis_job_id = synthesisJobId;
280
+ await saveSwarm(redis, record);
281
+ // Wait for synthesis job to complete
282
+ const synthDeadline = Date.now() + TIMEOUT_MS;
283
+ while (Date.now() < synthDeadline) {
284
+ const rec = await fetchJobRecord(synthesisJobId, redis);
285
+ if (rec && TERMINAL_STATUSES.has(rec.status)) {
286
+ record.status = rec.status === "done" ? "done" : "failed";
287
+ if (rec.status !== "done") {
288
+ record.error = `Synthesis job ${synthesisJobId} ended with status: ${rec.status}`;
289
+ }
290
+ record.completed_at = new Date().toISOString();
291
+ await saveSwarm(redis, record);
292
+ logger.info("swarm:synthesis-done", { swarm_id: swarmId, synthesis_status: rec.status });
293
+ return;
294
+ }
295
+ await sleep(POLL_INTERVAL_MS);
296
+ }
297
+ // Synthesis timed out
298
+ record.status = "failed";
299
+ record.error = "Synthesis job timed out (6h)";
300
+ record.completed_at = new Date().toISOString();
301
+ await saveSwarm(redis, record);
302
+ logger.warn("swarm:synthesis-timeout", { swarm_id: swarmId });
303
+ }
304
+ /** Fetch a job record from Redis or return null. */
305
+ async function fetchJobRecord(jobId, redis) {
306
+ if (!redis)
307
+ return null;
308
+ try {
309
+ const raw = await redis.get(`cca:job:${jobId}`);
310
+ if (!raw)
311
+ return null;
312
+ return JSON.parse(raw);
313
+ }
314
+ catch {
315
+ return null;
316
+ }
317
+ }
318
+ function sleep(ms) {
319
+ return new Promise((resolve) => setTimeout(resolve, ms));
320
+ }
321
+ // ─── Public API ───────────────────────────────────────────────────────────────
322
+ /**
323
+ * Entry point called from index.ts.
324
+ * Returns immediately (< 5s) with swarm_id + sub_job_ids.
325
+ * Background async handles fan-in + synthesis.
326
+ */
327
+ export async function runSwarm(params) {
328
+ const { repoUrl, goal, maxAgents = 10, synthesisOutput = "swarm-synthesis.md", synthesisPrompt, maxBudgetPerAgent = 5, agentModel, agentDriver, manager, redis, getJobOutput, } = params;
329
+ // Validate hard cap
330
+ const effectiveMax = Math.min(maxAgents, SWARM_MAX_AGENTS_HARD_CAP);
331
+ // Decompose goal (fast — uses haiku model)
332
+ let tasks;
333
+ try {
334
+ tasks = await decomposeGoal(goal, effectiveMax);
335
+ }
336
+ catch (err) {
337
+ throw new Error(`Swarm decomposition failed: ${String(err)}`);
338
+ }
339
+ const swarmId = uuidv4();
340
+ // Spawn all sub-agents in parallel
341
+ const subJobIds = [];
342
+ for (const taskEntry of tasks) {
343
+ try {
344
+ const jobId = await manager.spawn({
345
+ repoUrl,
346
+ task: taskEntry.task,
347
+ maxBudgetUsd: maxBudgetPerAgent,
348
+ agentModel,
349
+ agentDriver,
350
+ noPreamble: false,
351
+ });
352
+ subJobIds.push(jobId);
353
+ }
354
+ catch (err) {
355
+ logger.error("swarm:sub-spawn-failed", {
356
+ swarm_id: swarmId,
357
+ task_id: taskEntry.id,
358
+ err: String(err),
359
+ });
360
+ // Continue spawning other agents even if one fails
361
+ }
362
+ }
363
+ if (subJobIds.length === 0) {
364
+ throw new Error("All sub-agent spawns failed — cannot proceed with swarm");
365
+ }
366
+ // Build and persist swarm record
367
+ const record = {
368
+ swarm_id: swarmId,
369
+ goal,
370
+ repo_url: repoUrl,
371
+ sub_job_ids: subJobIds,
372
+ decomposed_tasks: tasks,
373
+ synthesis_output: synthesisOutput,
374
+ status: "running_subs",
375
+ created_at: new Date().toISOString(),
376
+ };
377
+ await saveSwarm(redis, record);
378
+ logger.info("swarm:started", {
379
+ swarm_id: swarmId,
380
+ sub_count: subJobIds.length,
381
+ goal: goal.slice(0, 120),
382
+ });
383
+ // Fire-and-forget background fan-in + synthesis
384
+ waitForAllSubJobs(swarmId, record, tasks, synthesisPrompt, manager, redis, getJobOutput, maxBudgetPerAgent, agentModel, agentDriver).catch((err) => {
385
+ logger.error("swarm:background-failed", { swarm_id: swarmId, err: String(err) });
386
+ // Best-effort: try to mark swarm as failed
387
+ loadSwarm(redis, swarmId)
388
+ .then((r) => {
389
+ if (r && r.status !== "done") {
390
+ r.status = "failed";
391
+ r.error = `Background error: ${String(err)}`;
392
+ r.completed_at = new Date().toISOString();
393
+ return saveSwarm(redis, r);
394
+ }
395
+ })
396
+ .catch(() => { });
397
+ });
398
+ return {
399
+ swarm_id: swarmId,
400
+ sub_job_ids: subJobIds,
401
+ decomposed_tasks: tasks,
402
+ status: "running",
403
+ };
404
+ }
405
+ /** Status polling — called by get_swarm_status MCP tool. */
406
+ export async function getSwarmStatus(swarmId, redis) {
407
+ return loadSwarm(redis, swarmId);
408
+ }
409
+ //# sourceMappingURL=swarm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm.js","sourceRoot":"","sources":["../src/swarm.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,iFAAiF;AAEjF,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAC3C,MAAM,eAAe,GAAG,2BAA2B,CAAC;AACpD,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAClE,MAAM,qBAAqB,GAAG,YAAY,CAAC;AAC3C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;AAE9F,+BAA+B;AAC/B,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,yDAAyD;AACzD,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,iDAAiD;AACjD,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAkChC,iFAAiF;AAEjF,wDAAwD;AACxD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAuB,CAAC;AAEjD,KAAK,UAAU,SAAS,CAAC,KAAmB,EAAE,MAAmB;IAC/D,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACjG,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,KAAmB,EAAE,OAAe;IAC3D,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;YACpD,OAAO,GAAG,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;AACxC,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,4FAA4F;IAC5F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE5B,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAE9B,uEAAuE;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC;IAED,2CAA2C;IAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjE,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAChD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,sDAAsD,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AACjG,CAAC;AAED,2FAA2F;AAC3F,SAAS,aAAa,CAAC,GAAc;IACnC,OAAO,GAAG;SACP,MAAM,CAAC,CAAC,IAAI,EAAmC,EAAE,CAChD,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,CAC5D;SACA,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACjB,EAAE,EAAE,MAAM,CAAE,IAAI,CAAC,EAAc,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,IAAI,EAAE,MAAM,CAAE,IAAI,CAAC,IAAgB,IAAI,EAAE,CAAC;KAC3C,CAAC,CAAC;SACF,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,uEAAuE;AACvE,KAAK,UAAU,aAAa,CAC1B,IAAY,EACZ,SAAiB;IAEjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC7C,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAEvE,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,mBAAmB,EAAE,qBAAqB;KAC3C,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,UAAW,EAAE,CAAC;QACnD,OAAO,CAAC,gBAAgB,CAAC,GAAG,kBAAkB,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAErD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,KAAK,EAAE,eAAe;QACtB,UAAU,EAAE,IAAI;QAChB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;KAC9C,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAE7F,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI;KACL,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;QAC/D,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC/D,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IAED,MAAM,KAAK,GAAG,sBAAsB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY,EAAE,SAAiB;IAC3D,OAAO,iFAAiF,SAAS;;;EAGjG,IAAI;;;;;;;;;;;;sBAYgB,SAAS,iCAAiC,CAAC;AACjE,CAAC;AAED,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,KAA0C,EAC1C,OAAiF,EACjF,eAAuB,EACvB,eAAwB;IAExB,MAAM,cAAc,GAAG,OAAO;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,iBAAiB,CAAC,CAAC,IAAI;UAC1B,CAAC,CAAC,MAAM;UACR,CAAC,CAAC,KAAK,CAAC,MAAM,eAAe,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;;EAElH,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;OACf,CAAC;IACJ,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,WAAW,GACf,eAAe;QACf,wIAAwI,eAAe,gEAAgE,CAAC;IAE1N,OAAO;;;EAGP,IAAI;;uBAEiB,OAAO,CAAC,MAAM;;EAEnC,cAAc;;;EAGd,WAAW;;oCAEuB,eAAe,0EAA0E,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;AACnJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAe;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,MAAM,IAAI,gBAAgB;QAAE,OAAO,IAAI,CAAC;IACnD,sEAAsE;IACtE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC5E,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,iBAAiB,CAC9B,OAAe,EACf,MAAmB,EACnB,KAA0C,EAC1C,eAAmC,EACnC,OAAmB,EACnB,KAAmB,EACnB,YAA+D,EAC/D,iBAAyB,EACzB,UAA8B,EAC9B,WAA+B;IAE/B,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAEtG,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAEjF,gDAAgD;IAChD,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,kBAAkB;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAEzC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/C,OAAO,GAAG,KAAK,CAAC;gBAChB,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,OAAO;YAAE,MAAM;QACnB,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAChC,CAAC;IAED,mCAAmC;IACnC,MAAM,OAAO,GAA6E,EAAE,CAAC;IAC7F,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,SAAS,CAAC;QACxC,IAAI,GAAG,EAAE,OAAO;YAAE,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC;QAE3C,IAAI,KAAK,GAAa,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/F,KAAK,GAAG,CAAC,0BAA0B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,qBAAqB,EAAE;QACjC,QAAQ,EAAE,OAAO;QACjB,cAAc,EAAE,SAAS;QACzB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;QACvD,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;KAC1D,CAAC,CAAC;IAEH,uBAAuB;IACvB,MAAM,aAAa,GAAG,kBAAkB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;IAEjG,+BAA+B;IAC/B,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC;IAC/B,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAE/B,wBAAwB;IACxB,IAAI,cAAkC,CAAC;IACvC,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;YACnC,OAAO;YACP,IAAI,EAAE,aAAa;YACnB,YAAY,EAAE,iBAAiB;YAC/B,UAAU;YACV,WAAW;YACX,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC,CAAC;IAClG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtF,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC;QACzB,MAAM,CAAC,KAAK,GAAG,2BAA2B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,MAAM,CAAC,gBAAgB,GAAG,cAAc,CAAC;IACzC,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAE/B,qCAAqC;IACrC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;IAC9C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACxD,IAAI,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;YAC1D,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,CAAC,KAAK,GAAG,iBAAiB,cAAc,uBAAuB,GAAG,CAAC,MAAM,EAAE,CAAC;YACpF,CAAC;YACD,MAAM,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC/C,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACzF,OAAO;QACT,CAAC;QACD,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAChC,CAAC;IAED,sBAAsB;IACtB,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC;IACzB,MAAM,CAAC,KAAK,GAAG,8BAA8B,CAAC;IAC9C,MAAM,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,oDAAoD;AACpD,KAAK,UAAU,cAAc,CAC3B,KAAa,EACb,KAAmB;IAEnB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAsB;IAMnD,MAAM,EACJ,OAAO,EACP,IAAI,EACJ,SAAS,GAAG,EAAE,EACd,eAAe,GAAG,oBAAoB,EACtC,eAAe,EACf,iBAAiB,GAAG,CAAC,EACrB,UAAU,EACV,WAAW,EACX,OAAO,EACP,KAAK,EACL,YAAY,GACb,GAAG,MAAM,CAAC;IAEX,oBAAoB;IACpB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,yBAAyB,CAAC,CAAC;IAEpE,2CAA2C;IAC3C,IAAI,KAA0C,CAAC;IAC/C,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;IAEzB,mCAAmC;IACnC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;gBAChC,OAAO;gBACP,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,YAAY,EAAE,iBAAiB;gBAC/B,UAAU;gBACV,WAAW;gBACX,UAAU,EAAE,KAAK;aAClB,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE;gBACrC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,SAAS,CAAC,EAAE;gBACrB,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC;aACjB,CAAC,CAAC;YACH,mDAAmD;QACrD,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,iCAAiC;IACjC,MAAM,MAAM,GAAgB;QAC1B,QAAQ,EAAE,OAAO;QACjB,IAAI;QACJ,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,SAAS;QACtB,gBAAgB,EAAE,KAAK;QACvB,gBAAgB,EAAE,eAAe;QACjC,MAAM,EAAE,cAAc;QACtB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACrC,CAAC;IACF,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAE/B,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;QAC3B,QAAQ,EAAE,OAAO;QACjB,SAAS,EAAE,SAAS,CAAC,MAAM;QAC3B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;KACzB,CAAC,CAAC;IAEH,gDAAgD;IAChD,iBAAiB,CACf,OAAO,EACP,MAAM,EACN,KAAK,EACL,eAAe,EACf,OAAO,EACP,KAAK,EACL,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,WAAW,CACZ,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACjF,2CAA2C;QAC3C,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC;aACtB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC7B,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACpB,CAAC,CAAC,KAAK,GAAG,qBAAqB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7C,CAAC,CAAC,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC1C,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,SAAS;QACtB,gBAAgB,EAAE,KAAK;QACvB,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,KAAmB;IAEnB,OAAO,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACnC,CAAC"}
package/dist/types.d.ts CHANGED
@@ -14,7 +14,7 @@ export interface JobEvent {
14
14
  repoUrl: string;
15
15
  lastLines: string[];
16
16
  score?: number;
17
- timestamp: number;
17
+ timestamp: string;
18
18
  coordinatorPlan?: CoordinatorPlan;
19
19
  }
20
20
  export interface OnComplete {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gonzih/cc-agent",
3
- "version": "0.15.16",
3
+ "version": "0.15.18",
4
4
  "description": "MCP server for spawning Claude Code agents in cloned repos — branch your agents",
5
5
  "type": "module",
6
6
  "bin": {