@ferris1225/pi-subagents 0.24.0 → 0.25.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/README.md +574 -476
- package/package.json +53 -53
- package/src/background.ts +112 -106
- package/src/fixloop.ts +84 -76
- package/src/index.ts +494 -11
- package/src/monitor.ts +6 -1
- package/src/spawn.ts +40 -0
package/src/spawn.ts
CHANGED
|
@@ -74,6 +74,11 @@ export interface SingleResult {
|
|
|
74
74
|
* exit (a concurrent pi startup race) before it produced a result. Set only when
|
|
75
75
|
* the run actually recovered after retrying, so callers can surface it. */
|
|
76
76
|
startupRetries?: number;
|
|
77
|
+
/** Tool calls that failed inside the run (from tool_execution_end events). A
|
|
78
|
+
* clean process exit can still hide a failed build/test/tool — the completion
|
|
79
|
+
* message must surface these so the main agent is never misled by a rosy final
|
|
80
|
+
* text (e.g. a worker that ended with "keep waiting" while its build failed). */
|
|
81
|
+
failedTools?: Array<{ toolName: string; error: string }>;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
export interface SubagentDetails {
|
|
@@ -123,6 +128,29 @@ export function reviewVerdict(output: string): "pass" | "fail" | undefined {
|
|
|
123
128
|
return undefined;
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
/** Tool errors are usually the trailing lines of a long output (build logs);
|
|
132
|
+
* keep the last non-empty lines, clipped to RESULT_LINE_MAX each. */
|
|
133
|
+
export function extractToolErrorText(content: unknown): string {
|
|
134
|
+
const parts = Array.isArray(content) ? content : [];
|
|
135
|
+
const text = parts
|
|
136
|
+
.filter(
|
|
137
|
+
(part): part is { type: "text"; text: string } =>
|
|
138
|
+
typeof part === "object" &&
|
|
139
|
+
part !== null &&
|
|
140
|
+
(part as { type?: unknown }).type === "text" &&
|
|
141
|
+
typeof (part as { text?: unknown }).text === "string",
|
|
142
|
+
)
|
|
143
|
+
.map((part) => part.text)
|
|
144
|
+
.join("\n");
|
|
145
|
+
return text
|
|
146
|
+
.split("\n")
|
|
147
|
+
.map((line) => line.trim())
|
|
148
|
+
.filter(Boolean)
|
|
149
|
+
.slice(-3)
|
|
150
|
+
.map((line) => (line.length > RESULT_LINE_MAX ? `${line.slice(0, RESULT_LINE_MAX)}…` : line))
|
|
151
|
+
.join("\n");
|
|
152
|
+
}
|
|
153
|
+
|
|
126
154
|
/** Hard cap for a single line inside a truncated result (minified blobs must not blow up). */
|
|
127
155
|
export const RESULT_LINE_MAX = 200;
|
|
128
156
|
|
|
@@ -493,6 +521,12 @@ export async function runSingleAgent(options: RunSingleOptions): Promise<SingleR
|
|
|
493
521
|
onLive({ kind: "tool_end", toolName: event.toolName ?? "unknown", isError: Boolean(event.isError) });
|
|
494
522
|
} catch { /* never throw from event handling */ }
|
|
495
523
|
}
|
|
524
|
+
if (event.isError) {
|
|
525
|
+
(currentResult.failedTools ??= []).push({
|
|
526
|
+
toolName: event.toolName ?? "unknown",
|
|
527
|
+
error: extractToolErrorText(event.result?.content),
|
|
528
|
+
});
|
|
529
|
+
}
|
|
496
530
|
}
|
|
497
531
|
|
|
498
532
|
if (event.type === "message_end" && event.message) {
|
|
@@ -695,5 +729,11 @@ export async function runSingleAgentWithModelFallback(
|
|
|
695
729
|
if (!agent || !launchedRef || !fallbackModelRef || launchedRef === fallbackModelRef) return result;
|
|
696
730
|
if (!isModelLevelFailure(result)) return result;
|
|
697
731
|
const retried = await runWithStartupRetry({ ...options, agent: { ...agent, model: fallbackModelRef } });
|
|
732
|
+
// The fallback replaces the result wholesale: `retried.failedTools` reflect
|
|
733
|
+
// ONLY the fallback (final) attempt. The original attempt's failedTools are
|
|
734
|
+
// intentionally not merged — a fallback relaunch redoes the work, so attaching
|
|
735
|
+
// the first attempt's stale build errors to a clean final attempt would
|
|
736
|
+
// misattribute failures the worker already fixed. This makes the README's
|
|
737
|
+
// "failed tool calls from the run's final attempt" claim accurate.
|
|
698
738
|
return { ...retried, modelFallbackFrom: launchedRef };
|
|
699
739
|
}
|