@humain/terminal 0.2.1 → 0.2.3
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 +8 -0
- package/dist/bundle/chunks/{chunk-I47ZWR55.js → chunk-LYOOYM65.js} +11 -11
- package/dist/bundle/chunks/{chunk-EY4DWHQU.js → chunk-U75GS4NL.js} +1 -1
- package/dist/bundle/chunks/{compat-QCV26HNS.js → compat-22OQ5DBK.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/model-runtime.d.ts +21 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +34 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/tools/subagent-env.d.ts +2 -0
- package/dist/core/tools/subagent-env.d.ts.map +1 -1
- package/dist/core/tools/subagent-env.js +4 -0
- package/dist/core/tools/subagent-env.js.map +1 -1
- package/dist/core/tools/subagent-scheduler.d.ts +6 -1
- package/dist/core/tools/subagent-scheduler.d.ts.map +1 -1
- package/dist/core/tools/subagent-scheduler.js +12 -2
- package/dist/core/tools/subagent-scheduler.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +2 -0
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +49 -18
- package/dist/core/tools/subagent.js.map +1 -1
- package/docs/environment-variables.md +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -66,7 +66,9 @@ export async function runDag(tasks, concurrency, run, isFailed, skip, onEvent, s
|
|
|
66
66
|
const graphError = validateTaskGraph(tasks);
|
|
67
67
|
if (graphError)
|
|
68
68
|
return Promise.reject(new Error(graphError));
|
|
69
|
-
const
|
|
69
|
+
const opts = typeof concurrency === "number" ? { concurrency } : concurrency;
|
|
70
|
+
const limit = Math.max(1, Math.min(opts.concurrency, tasks.length));
|
|
71
|
+
const worktreeLimit = Math.max(1, opts.worktrees ?? limit);
|
|
70
72
|
const results = new Array(tasks.length);
|
|
71
73
|
const serialAfter = implicitSerializationEdges(tasks);
|
|
72
74
|
const done = new Set();
|
|
@@ -75,6 +77,7 @@ export async function runDag(tasks, concurrency, run, isFailed, skip, onEvent, s
|
|
|
75
77
|
const waitedOnCap = new Set();
|
|
76
78
|
const serializedAnnounced = new Set();
|
|
77
79
|
let running = 0;
|
|
80
|
+
let runningIsolated = 0;
|
|
78
81
|
const failedExplicitDep = (t) => (t.dependsOn ?? []).find((d) => failed.has(d));
|
|
79
82
|
const blockedBy = (t) => [...(t.dependsOn ?? []), ...(serialAfter.get(t.id) ?? [])].filter((d) => !done.has(d));
|
|
80
83
|
return new Promise((resolve, reject) => {
|
|
@@ -159,7 +162,8 @@ export async function runDag(tasks, concurrency, run, isFailed, skip, onEvent, s
|
|
|
159
162
|
}
|
|
160
163
|
continue;
|
|
161
164
|
}
|
|
162
|
-
|
|
165
|
+
const isIsolated = t.isolation === "worktree";
|
|
166
|
+
if (running >= limit || (isIsolated && runningIsolated >= worktreeLimit)) {
|
|
163
167
|
if (!waitedOnCap.has(t.id)) {
|
|
164
168
|
waitedOnCap.add(t.id);
|
|
165
169
|
safeEvent({ type: "wait", id: t.id, reason: "concurrency" });
|
|
@@ -168,15 +172,21 @@ export async function runDag(tasks, concurrency, run, isFailed, skip, onEvent, s
|
|
|
168
172
|
}
|
|
169
173
|
started.add(t.id);
|
|
170
174
|
running++;
|
|
175
|
+
if (isIsolated)
|
|
176
|
+
runningIsolated++;
|
|
171
177
|
startedOrSettledThisPass = true;
|
|
172
178
|
progress = true;
|
|
173
179
|
safeEvent({ type: "start", id: t.id });
|
|
174
180
|
run(t, i).then((r) => {
|
|
175
181
|
running--;
|
|
182
|
+
if (isIsolated)
|
|
183
|
+
runningIsolated--;
|
|
176
184
|
settle(i, r);
|
|
177
185
|
pump();
|
|
178
186
|
}, (err) => {
|
|
179
187
|
running--;
|
|
188
|
+
if (isIsolated)
|
|
189
|
+
runningIsolated--;
|
|
180
190
|
if (!safeSettleWith(i, () => skip(t, i, err instanceof Error ? err.message : String(err))))
|
|
181
191
|
return;
|
|
182
192
|
pump();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent-scheduler.js","sourceRoot":"","sources":["../../../src/core/tools/subagent-scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure scheduling for the subagent tool's parallel mode. No I/O, no spawn.\n * Explicit `dependsOn` edges gate start and propagate failure as a skip.\n * Implicit owner-path edges only order siblings; they never skip.\n */\nexport interface SchedulableTask {\n\tid: string;\n\tdependsOn?: string[];\n\townerPaths?: string[];\n}\n\nexport type DagEvent =\n\t| { type: \"wait\"; id: string; reason: \"concurrency\" }\n\t| { type: \"serialize\"; id: string; after: string[] }\n\t| { type: \"start\"; id: string }\n\t| { type: \"skip\"; id: string; failedDependency: string };\n\nexport function validateTaskGraph(tasks: SchedulableTask[]): string | null {\n\tconst ids = new Set<string>();\n\tfor (const t of tasks) {\n\t\tif (ids.has(t.id)) return `duplicate task id \"${t.id}\"`;\n\t\tids.add(t.id);\n\t}\n\tfor (const t of tasks) {\n\t\tfor (const dep of t.dependsOn ?? []) {\n\t\t\tif (dep === t.id) return `task \"${t.id}\" depends on itself`;\n\t\t\tif (!ids.has(dep)) return `task \"${t.id}\" has unknown dependency \"${dep}\"`;\n\t\t}\n\t}\n\t// Kahn's algorithm; anything left with in-degree > 0 is on a cycle.\n\tconst indegree = new Map<string, number>(tasks.map((t) => [t.id, t.dependsOn?.length ?? 0]));\n\tconst dependents = new Map<string, string[]>();\n\tfor (const t of tasks)\n\t\tfor (const dep of t.dependsOn ?? []) dependents.set(dep, [...(dependents.get(dep) ?? []), t.id]);\n\tconst queue = tasks.filter((t) => (indegree.get(t.id) ?? 0) === 0).map((t) => t.id);\n\tlet visited = 0;\n\twhile (queue.length) {\n\t\tconst id = queue.shift() as string;\n\t\tvisited++;\n\t\tfor (const next of dependents.get(id) ?? []) {\n\t\t\tconst d = (indegree.get(next) ?? 0) - 1;\n\t\t\tindegree.set(next, d);\n\t\t\tif (d === 0) queue.push(next);\n\t\t}\n\t}\n\tif (visited !== tasks.length) return \"task graph contains a dependency cycle\";\n\treturn null;\n}\n\nfunction normalizePath(p: string): string {\n\treturn p.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction pathCovers(a: string, b: string): boolean {\n\treturn a === b || b.startsWith(`${a}/`) || a.startsWith(`${b}/`);\n}\n\nexport function ownerPathsOverlap(a: string[] | undefined, b: string[] | undefined): boolean {\n\tif (!a?.length || !b?.length) return false;\n\tconst na = a.map(normalizePath);\n\tconst nb = b.map(normalizePath);\n\treturn na.some((x) => nb.some((y) => pathCovers(x, y)));\n}\n\nexport function implicitSerializationEdges(tasks: SchedulableTask[]): Map<string, string[]> {\n\tconst edges = new Map<string, string[]>();\n\tfor (let i = 0; i < tasks.length; i++) {\n\t\tconst after: string[] = [];\n\t\tfor (let j = 0; j < i; j++) {\n\t\t\tif (ownerPathsOverlap(tasks[i].ownerPaths, tasks[j].ownerPaths)) after.push(tasks[j].id);\n\t\t}\n\t\tedges.set(tasks[i].id, after);\n\t}\n\treturn edges;\n}\n\nexport async function runDag<TIn extends SchedulableTask, TOut>(\n\ttasks: TIn[],\n\tconcurrency: number,\n\trun: (task: TIn, index: number) => Promise<TOut>,\n\tisFailed: (result: TOut) => boolean,\n\tskip: (task: TIn, index: number, failedDependency: string) => TOut,\n\tonEvent?: (event: DagEvent) => void,\n\tsignal?: AbortSignal,\n\tonAbort?: (task: TIn, index: number) => TOut,\n): Promise<TOut[]> {\n\tif (tasks.length === 0) return [];\n\tconst graphError = validateTaskGraph(tasks);\n\tif (graphError) return Promise.reject(new Error(graphError));\n\tconst limit = Math.max(1, Math.min(concurrency, tasks.length));\n\tconst results: TOut[] = new Array(tasks.length);\n\tconst serialAfter = implicitSerializationEdges(tasks);\n\tconst done = new Set<string>();\n\tconst failed = new Set<string>();\n\tconst started = new Set<string>();\n\tconst waitedOnCap = new Set<string>();\n\tconst serializedAnnounced = new Set<string>();\n\tlet running = 0;\n\n\tconst failedExplicitDep = (t: TIn): string | undefined => (t.dependsOn ?? []).find((d) => failed.has(d));\n\tconst blockedBy = (t: TIn): string[] =>\n\t\t[...(t.dependsOn ?? []), ...(serialAfter.get(t.id) ?? [])].filter((d) => !done.has(d));\n\n\treturn new Promise<TOut[]>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst settle = (index: number, result: TOut) => {\n\t\t\tresults[index] = result;\n\t\t\tconst id = tasks[index].id;\n\t\t\tdone.add(id);\n\t\t\tif (isFailed(result)) failed.add(id);\n\t\t};\n\t\tconst safeEvent = (event: DagEvent) => {\n\t\t\ttry {\n\t\t\t\tonEvent?.(event);\n\t\t\t} catch {\n\t\t\t\t/* observer errors never affect scheduling */\n\t\t\t}\n\t\t};\n\t\t/** Returns false when the promise was rejected and pumping must stop. */\n\t\tconst safeSettleWith = (index: number, produce: () => TOut): boolean => {\n\t\t\ttry {\n\t\t\t\tsettle(index, produce());\n\t\t\t\treturn true;\n\t\t\t} catch (err) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tconst pump = () => {\n\t\t\tlet startedOrSettledThisPass = false;\n\t\t\tlet progress = true;\n\t\t\twhile (progress) {\n\t\t\t\tprogress = false;\n\t\t\t\t// 0. Abort short-circuits everything not yet started.\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\t\tif (!safeSettleWith(i, () => (onAbort ? onAbort(t, i) : skip(t, i, \"aborted\")))) return;\n\t\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 1. Skip dependents of failed tasks, to a fixed point.\n\t\t\t\tlet skipped = true;\n\t\t\t\twhile (skipped) {\n\t\t\t\t\tskipped = false;\n\t\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\t\tconst dep = failedExplicitDep(t);\n\t\t\t\t\t\tif (dep) {\n\t\t\t\t\t\t\tsafeEvent({ type: \"skip\", id: t.id, failedDependency: dep });\n\t\t\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\t\t\tif (!safeSettleWith(i, () => skip(t, i, dep))) return;\n\t\t\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\t\t\tprogress = true;\n\t\t\t\t\t\t\tskipped = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 2. Start ready tasks up to the cap.\n\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\tconst blockers = blockedBy(t);\n\t\t\t\t\tif (blockers.length) {\n\t\t\t\t\t\tconst serial = (serialAfter.get(t.id) ?? []).filter((d) => !done.has(d));\n\t\t\t\t\t\tif (serial.length && !serializedAnnounced.has(t.id)) {\n\t\t\t\t\t\t\tserializedAnnounced.add(t.id);\n\t\t\t\t\t\t\tsafeEvent({ type: \"serialize\", id: t.id, after: serial });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (running >= limit) {\n\t\t\t\t\t\tif (!waitedOnCap.has(t.id)) {\n\t\t\t\t\t\t\twaitedOnCap.add(t.id);\n\t\t\t\t\t\t\tsafeEvent({ type: \"wait\", id: t.id, reason: \"concurrency\" });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\trunning++;\n\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\tprogress = true;\n\t\t\t\t\tsafeEvent({ type: \"start\", id: t.id });\n\t\t\t\t\trun(t, i).then(\n\t\t\t\t\t\t(r) => {\n\t\t\t\t\t\t\trunning--;\n\t\t\t\t\t\t\tsettle(i, r);\n\t\t\t\t\t\t\tpump();\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(err) => {\n\t\t\t\t\t\t\trunning--;\n\t\t\t\t\t\t\tif (!safeSettleWith(i, () => skip(t, i, err instanceof Error ? err.message : String(err)))) return;\n\t\t\t\t\t\t\tpump();\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (done.size === tasks.length) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tresolve(results);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (running === 0 && !startedOrSettledThisPass) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new Error(\"task graph stalled: no runnable task remains\"));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tpump();\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"subagent-scheduler.js","sourceRoot":"","sources":["../../../src/core/tools/subagent-scheduler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure scheduling for the subagent tool's parallel mode. No I/O, no spawn.\n * Explicit `dependsOn` edges gate start and propagate failure as a skip.\n * Implicit owner-path edges only order siblings; they never skip.\n */\nexport interface SchedulableTask {\n\tid: string;\n\tdependsOn?: string[];\n\townerPaths?: string[];\n\t/** Only the literal \"worktree\" consumes a worktree slot. */\n\tisolation?: string;\n}\n\nexport type DagEvent =\n\t| { type: \"wait\"; id: string; reason: \"concurrency\" }\n\t| { type: \"serialize\"; id: string; after: string[] }\n\t| { type: \"start\"; id: string }\n\t| { type: \"skip\"; id: string; failedDependency: string };\n\nexport function validateTaskGraph(tasks: SchedulableTask[]): string | null {\n\tconst ids = new Set<string>();\n\tfor (const t of tasks) {\n\t\tif (ids.has(t.id)) return `duplicate task id \"${t.id}\"`;\n\t\tids.add(t.id);\n\t}\n\tfor (const t of tasks) {\n\t\tfor (const dep of t.dependsOn ?? []) {\n\t\t\tif (dep === t.id) return `task \"${t.id}\" depends on itself`;\n\t\t\tif (!ids.has(dep)) return `task \"${t.id}\" has unknown dependency \"${dep}\"`;\n\t\t}\n\t}\n\t// Kahn's algorithm; anything left with in-degree > 0 is on a cycle.\n\tconst indegree = new Map<string, number>(tasks.map((t) => [t.id, t.dependsOn?.length ?? 0]));\n\tconst dependents = new Map<string, string[]>();\n\tfor (const t of tasks)\n\t\tfor (const dep of t.dependsOn ?? []) dependents.set(dep, [...(dependents.get(dep) ?? []), t.id]);\n\tconst queue = tasks.filter((t) => (indegree.get(t.id) ?? 0) === 0).map((t) => t.id);\n\tlet visited = 0;\n\twhile (queue.length) {\n\t\tconst id = queue.shift() as string;\n\t\tvisited++;\n\t\tfor (const next of dependents.get(id) ?? []) {\n\t\t\tconst d = (indegree.get(next) ?? 0) - 1;\n\t\t\tindegree.set(next, d);\n\t\t\tif (d === 0) queue.push(next);\n\t\t}\n\t}\n\tif (visited !== tasks.length) return \"task graph contains a dependency cycle\";\n\treturn null;\n}\n\nfunction normalizePath(p: string): string {\n\treturn p.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/+$/, \"\");\n}\n\nfunction pathCovers(a: string, b: string): boolean {\n\treturn a === b || b.startsWith(`${a}/`) || a.startsWith(`${b}/`);\n}\n\nexport function ownerPathsOverlap(a: string[] | undefined, b: string[] | undefined): boolean {\n\tif (!a?.length || !b?.length) return false;\n\tconst na = a.map(normalizePath);\n\tconst nb = b.map(normalizePath);\n\treturn na.some((x) => nb.some((y) => pathCovers(x, y)));\n}\n\nexport function implicitSerializationEdges(tasks: SchedulableTask[]): Map<string, string[]> {\n\tconst edges = new Map<string, string[]>();\n\tfor (let i = 0; i < tasks.length; i++) {\n\t\tconst after: string[] = [];\n\t\tfor (let j = 0; j < i; j++) {\n\t\t\tif (ownerPathsOverlap(tasks[i].ownerPaths, tasks[j].ownerPaths)) after.push(tasks[j].id);\n\t\t}\n\t\tedges.set(tasks[i].id, after);\n\t}\n\treturn edges;\n}\n\nexport async function runDag<TIn extends SchedulableTask, TOut>(\n\ttasks: TIn[],\n\tconcurrency: number | { concurrency: number; worktrees?: number },\n\trun: (task: TIn, index: number) => Promise<TOut>,\n\tisFailed: (result: TOut) => boolean,\n\tskip: (task: TIn, index: number, failedDependency: string) => TOut,\n\tonEvent?: (event: DagEvent) => void,\n\tsignal?: AbortSignal,\n\tonAbort?: (task: TIn, index: number) => TOut,\n): Promise<TOut[]> {\n\tif (tasks.length === 0) return [];\n\tconst graphError = validateTaskGraph(tasks);\n\tif (graphError) return Promise.reject(new Error(graphError));\n\tconst opts = typeof concurrency === \"number\" ? { concurrency } : concurrency;\n\tconst limit = Math.max(1, Math.min(opts.concurrency, tasks.length));\n\tconst worktreeLimit = Math.max(1, opts.worktrees ?? limit);\n\tconst results: TOut[] = new Array(tasks.length);\n\tconst serialAfter = implicitSerializationEdges(tasks);\n\tconst done = new Set<string>();\n\tconst failed = new Set<string>();\n\tconst started = new Set<string>();\n\tconst waitedOnCap = new Set<string>();\n\tconst serializedAnnounced = new Set<string>();\n\tlet running = 0;\n\tlet runningIsolated = 0;\n\n\tconst failedExplicitDep = (t: TIn): string | undefined => (t.dependsOn ?? []).find((d) => failed.has(d));\n\tconst blockedBy = (t: TIn): string[] =>\n\t\t[...(t.dependsOn ?? []), ...(serialAfter.get(t.id) ?? [])].filter((d) => !done.has(d));\n\n\treturn new Promise<TOut[]>((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst settle = (index: number, result: TOut) => {\n\t\t\tresults[index] = result;\n\t\t\tconst id = tasks[index].id;\n\t\t\tdone.add(id);\n\t\t\tif (isFailed(result)) failed.add(id);\n\t\t};\n\t\tconst safeEvent = (event: DagEvent) => {\n\t\t\ttry {\n\t\t\t\tonEvent?.(event);\n\t\t\t} catch {\n\t\t\t\t/* observer errors never affect scheduling */\n\t\t\t}\n\t\t};\n\t\t/** Returns false when the promise was rejected and pumping must stop. */\n\t\tconst safeSettleWith = (index: number, produce: () => TOut): boolean => {\n\t\t\ttry {\n\t\t\t\tsettle(index, produce());\n\t\t\t\treturn true;\n\t\t\t} catch (err) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(err instanceof Error ? err : new Error(String(err)));\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t};\n\n\t\tconst pump = () => {\n\t\t\tlet startedOrSettledThisPass = false;\n\t\t\tlet progress = true;\n\t\t\twhile (progress) {\n\t\t\t\tprogress = false;\n\t\t\t\t// 0. Abort short-circuits everything not yet started.\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\t\tif (!safeSettleWith(i, () => (onAbort ? onAbort(t, i) : skip(t, i, \"aborted\")))) return;\n\t\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 1. Skip dependents of failed tasks, to a fixed point.\n\t\t\t\tlet skipped = true;\n\t\t\t\twhile (skipped) {\n\t\t\t\t\tskipped = false;\n\t\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\t\tconst dep = failedExplicitDep(t);\n\t\t\t\t\t\tif (dep) {\n\t\t\t\t\t\t\tsafeEvent({ type: \"skip\", id: t.id, failedDependency: dep });\n\t\t\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\t\t\tif (!safeSettleWith(i, () => skip(t, i, dep))) return;\n\t\t\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\t\t\tprogress = true;\n\t\t\t\t\t\t\tskipped = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// 2. Start ready tasks up to the cap.\n\t\t\t\tfor (let i = 0; i < tasks.length; i++) {\n\t\t\t\t\tconst t = tasks[i];\n\t\t\t\t\tif (started.has(t.id) || done.has(t.id)) continue;\n\t\t\t\t\tconst blockers = blockedBy(t);\n\t\t\t\t\tif (blockers.length) {\n\t\t\t\t\t\tconst serial = (serialAfter.get(t.id) ?? []).filter((d) => !done.has(d));\n\t\t\t\t\t\tif (serial.length && !serializedAnnounced.has(t.id)) {\n\t\t\t\t\t\t\tserializedAnnounced.add(t.id);\n\t\t\t\t\t\t\tsafeEvent({ type: \"serialize\", id: t.id, after: serial });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst isIsolated = t.isolation === \"worktree\";\n\t\t\t\t\tif (running >= limit || (isIsolated && runningIsolated >= worktreeLimit)) {\n\t\t\t\t\t\tif (!waitedOnCap.has(t.id)) {\n\t\t\t\t\t\t\twaitedOnCap.add(t.id);\n\t\t\t\t\t\t\tsafeEvent({ type: \"wait\", id: t.id, reason: \"concurrency\" });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tstarted.add(t.id);\n\t\t\t\t\trunning++;\n\t\t\t\t\tif (isIsolated) runningIsolated++;\n\t\t\t\t\tstartedOrSettledThisPass = true;\n\t\t\t\t\tprogress = true;\n\t\t\t\t\tsafeEvent({ type: \"start\", id: t.id });\n\t\t\t\t\trun(t, i).then(\n\t\t\t\t\t\t(r) => {\n\t\t\t\t\t\t\trunning--;\n\t\t\t\t\t\t\tif (isIsolated) runningIsolated--;\n\t\t\t\t\t\t\tsettle(i, r);\n\t\t\t\t\t\t\tpump();\n\t\t\t\t\t\t},\n\t\t\t\t\t\t(err) => {\n\t\t\t\t\t\t\trunning--;\n\t\t\t\t\t\t\tif (isIsolated) runningIsolated--;\n\t\t\t\t\t\t\tif (!safeSettleWith(i, () => skip(t, i, err instanceof Error ? err.message : String(err)))) return;\n\t\t\t\t\t\t\tpump();\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (done.size === tasks.length) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tresolve(results);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (running === 0 && !startedOrSettledThisPass) {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\treject(new Error(\"task graph stalled: no runnable task remains\"));\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tpump();\n\t});\n}\n"]}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import type { Message } from "@earendil-works/pi-ai";
|
|
15
15
|
import { Type } from "typebox";
|
|
16
|
+
import type { ResourceDiagnostic } from "../diagnostics.ts";
|
|
16
17
|
import type { ToolDefinition } from "../extensions/types.ts";
|
|
17
18
|
export { SUBAGENT_DEPTH_ENV } from "./subagent-env.ts";
|
|
18
19
|
import { type SubagentIsolation, type SubagentMergeOutcome } from "./subagent-worktree.ts";
|
|
@@ -29,6 +30,7 @@ export interface AgentConfig {
|
|
|
29
30
|
export interface AgentDiscoveryResult {
|
|
30
31
|
agents: AgentConfig[];
|
|
31
32
|
projectAgentsDir: string | null;
|
|
33
|
+
diagnostics: ResourceDiagnostic[];
|
|
32
34
|
}
|
|
33
35
|
export declare function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult;
|
|
34
36
|
export interface SubagentUsageStats {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAO,OAAO,EAAS,MAAM,uBAAuB,CAAC;AAGjE,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAI/B,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../../src/core/tools/subagent.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,7 +23,7 @@ import { getMarkdownTheme } from "../../modes/interactive/theme/theme.js";
|
|
|
23
23
|
import { parseFrontmatter } from "../../utils/frontmatter.js";
|
|
24
24
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
25
25
|
import { shortenPath } from "./render-utils.js";
|
|
26
|
-
import { currentSubagentDepth, currentTaskId, maxParallelTasks, maxSubagentConcurrency, maxSubagentDepth, PARENT_TASK_ID_ENV, SUBAGENT_DEPTH_ENV, TASK_BASE_REVISION_ENV, TASK_ID_ENV, } from "./subagent-env.js";
|
|
26
|
+
import { currentSubagentDepth, currentTaskId, maxParallelTasks, maxSubagentConcurrency, maxSubagentDepth, maxSubagentWorktrees, PARENT_TASK_ID_ENV, SUBAGENT_DEPTH_ENV, TASK_BASE_REVISION_ENV, TASK_ID_ENV, } from "./subagent-env.js";
|
|
27
27
|
import { runDag, validateTaskGraph } from "./subagent-scheduler.js";
|
|
28
28
|
export { SUBAGENT_DEPTH_ENV } from "./subagent-env.js";
|
|
29
29
|
import { createSubagentWorktree, isGitWorkTree, } from "./subagent-worktree.js";
|
|
@@ -32,15 +32,16 @@ const COLLAPSED_ITEM_COUNT = 10;
|
|
|
32
32
|
const PER_TASK_OUTPUT_CAP = 50 * 1024;
|
|
33
33
|
function loadAgentsFromDir(dir, source) {
|
|
34
34
|
const agents = [];
|
|
35
|
+
const diagnostics = [];
|
|
35
36
|
if (!fs.existsSync(dir)) {
|
|
36
|
-
return agents;
|
|
37
|
+
return { agents, diagnostics };
|
|
37
38
|
}
|
|
38
39
|
let entries;
|
|
39
40
|
try {
|
|
40
41
|
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
41
42
|
}
|
|
42
43
|
catch {
|
|
43
|
-
return agents;
|
|
44
|
+
return { agents, diagnostics };
|
|
44
45
|
}
|
|
45
46
|
for (const entry of entries) {
|
|
46
47
|
if (!entry.name.endsWith(".md"))
|
|
@@ -55,8 +56,27 @@ function loadAgentsFromDir(dir, source) {
|
|
|
55
56
|
catch {
|
|
56
57
|
continue;
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
+
let frontmatter;
|
|
60
|
+
let body;
|
|
61
|
+
try {
|
|
62
|
+
({ frontmatter, body } = parseFrontmatter(content));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// Malformed frontmatter (e.g. invalid YAML) must not take down the whole
|
|
66
|
+
// directory — skip this one file and surface a diagnostic instead.
|
|
67
|
+
const message = error instanceof Error ? error.message : "failed to parse agent file";
|
|
68
|
+
diagnostics.push({ type: "warning", message, path: filePath });
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
59
71
|
if (!frontmatter.name || !frontmatter.description) {
|
|
72
|
+
const missing = [!frontmatter.name && "name", !frontmatter.description && "description"]
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
.join(" and ");
|
|
75
|
+
diagnostics.push({
|
|
76
|
+
type: "warning",
|
|
77
|
+
message: `missing required frontmatter field(s): ${missing}`,
|
|
78
|
+
path: filePath,
|
|
79
|
+
});
|
|
60
80
|
continue;
|
|
61
81
|
}
|
|
62
82
|
const tools = frontmatter.tools
|
|
@@ -73,7 +93,7 @@ function loadAgentsFromDir(dir, source) {
|
|
|
73
93
|
filePath,
|
|
74
94
|
});
|
|
75
95
|
}
|
|
76
|
-
return agents;
|
|
96
|
+
return { agents, diagnostics };
|
|
77
97
|
}
|
|
78
98
|
function isDirectory(p) {
|
|
79
99
|
try {
|
|
@@ -98,24 +118,29 @@ function findNearestProjectAgentsDir(cwd) {
|
|
|
98
118
|
export function discoverAgents(cwd, scope) {
|
|
99
119
|
const userDir = path.join(getAgentDir(), "agents");
|
|
100
120
|
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
101
|
-
const
|
|
102
|
-
const
|
|
121
|
+
const emptyResult = { agents: [], diagnostics: [] };
|
|
122
|
+
const userResult = scope === "project" ? emptyResult : loadAgentsFromDir(userDir, "user");
|
|
123
|
+
const projectResult = scope === "user" || !projectAgentsDir ? emptyResult : loadAgentsFromDir(projectAgentsDir, "project");
|
|
103
124
|
const agentMap = new Map();
|
|
104
125
|
if (scope === "both") {
|
|
105
|
-
for (const agent of
|
|
126
|
+
for (const agent of userResult.agents)
|
|
106
127
|
agentMap.set(agent.name, agent);
|
|
107
|
-
for (const agent of
|
|
128
|
+
for (const agent of projectResult.agents)
|
|
108
129
|
agentMap.set(agent.name, agent);
|
|
109
130
|
}
|
|
110
131
|
else if (scope === "user") {
|
|
111
|
-
for (const agent of
|
|
132
|
+
for (const agent of userResult.agents)
|
|
112
133
|
agentMap.set(agent.name, agent);
|
|
113
134
|
}
|
|
114
135
|
else {
|
|
115
|
-
for (const agent of
|
|
136
|
+
for (const agent of projectResult.agents)
|
|
116
137
|
agentMap.set(agent.name, agent);
|
|
117
138
|
}
|
|
118
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
agents: Array.from(agentMap.values()),
|
|
141
|
+
projectAgentsDir,
|
|
142
|
+
diagnostics: [...userResult.diagnostics, ...projectResult.diagnostics],
|
|
143
|
+
};
|
|
119
144
|
}
|
|
120
145
|
// --- Formatting helpers ---
|
|
121
146
|
function formatTokens(count) {
|
|
@@ -285,12 +310,17 @@ function getCliInvocation(args) {
|
|
|
285
310
|
}
|
|
286
311
|
return { command: "humain-terminal", args };
|
|
287
312
|
}
|
|
288
|
-
async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, isolation, step, model, parentModel, signal, onUpdate, makeDetails, toolCallId, childIndex, options) {
|
|
313
|
+
async function runSingleAgent(defaultCwd, agents, agentDiagnostics, agentName, task, cwd, isolation, step, model, parentModel, signal, onUpdate, makeDetails, toolCallId, childIndex, options) {
|
|
289
314
|
const childDepth = currentSubagentDepth() + 1;
|
|
290
315
|
const parentTaskId = currentTaskId() ?? toolCallId;
|
|
291
316
|
const agent = agents.find((a) => a.name === agentName);
|
|
292
317
|
if (!agent) {
|
|
293
318
|
const available = agents.map((a) => `"${a.name}"`).join(", ") || "none";
|
|
319
|
+
const skippedNote = agentDiagnostics.length > 0
|
|
320
|
+
? ` ${agentDiagnostics.length} agent file(s) failed to load and were skipped: ${agentDiagnostics
|
|
321
|
+
.map((d) => `${d.path ?? "(unknown path)"} (${d.message})`)
|
|
322
|
+
.join("; ")}.`
|
|
323
|
+
: "";
|
|
294
324
|
return {
|
|
295
325
|
agent: agentName,
|
|
296
326
|
agentSource: "unknown",
|
|
@@ -300,7 +330,7 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, isolatio
|
|
|
300
330
|
depth: childDepth,
|
|
301
331
|
exitCode: 1,
|
|
302
332
|
messages: [],
|
|
303
|
-
stderr: `Unknown agent: "${agentName}". Available agents: ${available}
|
|
333
|
+
stderr: `Unknown agent: "${agentName}". Available agents: ${available}.${skippedNote}`,
|
|
304
334
|
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, contextTokens: 0, turns: 0 },
|
|
305
335
|
step,
|
|
306
336
|
isolation: "shared",
|
|
@@ -773,7 +803,7 @@ export function createSubagentToolDefinition(cwd) {
|
|
|
773
803
|
}
|
|
774
804
|
}
|
|
775
805
|
: undefined;
|
|
776
|
-
const result = await runSingleAgent(defaultCwd, agents, step.agent, taskWithContext, step.cwd, undefined, i + 1, step.model, parentModel, signal, chainUpdate, makeDetails("chain"), toolCallId, i, { taskId: `${toolCallId}-${i}`, thinking: step.thinking });
|
|
806
|
+
const result = await runSingleAgent(defaultCwd, agents, discovery.diagnostics, step.agent, taskWithContext, step.cwd, undefined, i + 1, step.model, parentModel, signal, chainUpdate, makeDetails("chain"), toolCallId, i, { taskId: `${toolCallId}-${i}`, thinking: step.thinking });
|
|
777
807
|
results.push(result);
|
|
778
808
|
const isError = isFailedResult(result);
|
|
779
809
|
if (isError) {
|
|
@@ -810,6 +840,7 @@ export function createSubagentToolDefinition(cwd) {
|
|
|
810
840
|
id: t.id ?? `${toolCallId}-${i}`,
|
|
811
841
|
dependsOn: t.dependsOn ?? [],
|
|
812
842
|
ownerPaths: t.ownerPaths ?? [],
|
|
843
|
+
isolation: t.isolation,
|
|
813
844
|
}));
|
|
814
845
|
const graphError = validateTaskGraph(graph);
|
|
815
846
|
if (graphError) {
|
|
@@ -864,7 +895,7 @@ export function createSubagentToolDefinition(cwd) {
|
|
|
864
895
|
};
|
|
865
896
|
let results;
|
|
866
897
|
try {
|
|
867
|
-
results = await runDag(graph, maxSubagentConcurrency(), async (g, index) => {
|
|
898
|
+
results = await runDag(graph, { concurrency: maxSubagentConcurrency(), worktrees: maxSubagentWorktrees() }, async (g, index) => {
|
|
868
899
|
const maxAttempts = Math.min(3, Math.max(1, g.onFailure?.maxAttempts ?? 1));
|
|
869
900
|
let attempt = 1;
|
|
870
901
|
let model = g.model;
|
|
@@ -872,7 +903,7 @@ export function createSubagentToolDefinition(cwd) {
|
|
|
872
903
|
let result;
|
|
873
904
|
for (;;) {
|
|
874
905
|
emitTaskEvent({ type: "start", taskId: g.id, attempt, at: now() });
|
|
875
|
-
result = await runSingleAgent(defaultCwd, agents, g.agent, g.task, g.cwd, g.isolation, undefined, model, parentModel, signal, (partial) => {
|
|
906
|
+
result = await runSingleAgent(defaultCwd, agents, discovery.diagnostics, g.agent, g.task, g.cwd, g.isolation, undefined, model, parentModel, signal, (partial) => {
|
|
876
907
|
if (partial.details?.results[0]) {
|
|
877
908
|
allResults[index] = partial.details.results[0];
|
|
878
909
|
emitParallelUpdate();
|
|
@@ -956,7 +987,7 @@ export function createSubagentToolDefinition(cwd) {
|
|
|
956
987
|
};
|
|
957
988
|
}
|
|
958
989
|
if (params.agent && params.task) {
|
|
959
|
-
const result = await runSingleAgent(defaultCwd, agents, params.agent, params.task, params.cwd, params.isolation, undefined, params.model, parentModel, signal, onUpdate, makeDetails("single"), toolCallId, 0, { taskId: `${toolCallId}-0`, thinking: params.thinking });
|
|
990
|
+
const result = await runSingleAgent(defaultCwd, agents, discovery.diagnostics, params.agent, params.task, params.cwd, params.isolation, undefined, params.model, parentModel, signal, onUpdate, makeDetails("single"), toolCallId, 0, { taskId: `${toolCallId}-0`, thinking: params.thinking });
|
|
960
991
|
const isError = isFailedResult(result);
|
|
961
992
|
if (isError) {
|
|
962
993
|
const errorMsg = getResultOutput(result);
|