@pi-archimedes/subagent 0.7.0 → 0.9.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/package.json +2 -2
- package/src/agent-manager.ts +1654 -0
- package/src/agents.ts +58 -15
- package/src/compact.ts +60 -87
- package/src/execute.ts +8 -8
- package/src/frontmatter-io.ts +103 -0
- package/src/handlers.ts +25 -15
- package/src/index.ts +39 -5
- package/src/spawn.ts +19 -3
- package/src/stream.ts +28 -5
package/src/stream.ts
CHANGED
|
@@ -25,10 +25,29 @@ export function streamEvents(
|
|
|
25
25
|
): Promise<SubagentResult> {
|
|
26
26
|
return new Promise((resolve, reject) => {
|
|
27
27
|
const startTime = Date.now();
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
// Startup safeguard: if the child produces no JSON event within
|
|
30
|
+
// STARTUP_TIMEOUT_MS, kill it. This guards against hangs during pi
|
|
31
|
+
// initialization (model never loads, auth fails, etc.) and is the only
|
|
32
|
+
// automatic timeout. Once any event arrives the model is considered
|
|
33
|
+
// active and runtime is controlled entirely by the user's abort
|
|
34
|
+
// signal — a model that is REALLY thinking is left alone until the
|
|
35
|
+
// user explicitly cancels.
|
|
36
|
+
const STARTUP_TIMEOUT_MS = 2 * 60 * 1000;
|
|
37
|
+
|
|
38
|
+
let startupTimer: NodeJS.Timeout | undefined = setTimeout(() => {
|
|
29
39
|
child.kill("SIGKILL");
|
|
30
|
-
reject(new Error(
|
|
31
|
-
|
|
40
|
+
reject(new Error(
|
|
41
|
+
`subagent timed out: no model output within ${STARTUP_TIMEOUT_MS / 60_000} minutes of startup`,
|
|
42
|
+
));
|
|
43
|
+
}, STARTUP_TIMEOUT_MS);
|
|
44
|
+
|
|
45
|
+
const clearStartupTimer = (): void => {
|
|
46
|
+
if (startupTimer) {
|
|
47
|
+
clearTimeout(startupTimer);
|
|
48
|
+
startupTimer = undefined;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
32
51
|
|
|
33
52
|
const state: StreamState = {
|
|
34
53
|
toolCount: 0,
|
|
@@ -97,6 +116,10 @@ export function streamEvents(
|
|
|
97
116
|
return; // Skip non-JSON lines
|
|
98
117
|
}
|
|
99
118
|
|
|
119
|
+
// First event received from the child means the model has engaged —
|
|
120
|
+
// from here on, the user controls lifetime via the abort signal.
|
|
121
|
+
clearStartupTimer();
|
|
122
|
+
|
|
100
123
|
switch (event.type) {
|
|
101
124
|
case "tool_execution_start": {
|
|
102
125
|
handleToolStart(state, event);
|
|
@@ -131,7 +154,7 @@ export function streamEvents(
|
|
|
131
154
|
|
|
132
155
|
// Handle process exit
|
|
133
156
|
child.on("close", (code) => {
|
|
134
|
-
|
|
157
|
+
clearStartupTimer();
|
|
135
158
|
clearInterval(heartbeat);
|
|
136
159
|
const durationMs = Date.now() - startTime;
|
|
137
160
|
const exitCode = code ?? 1;
|
|
@@ -174,7 +197,7 @@ export function streamEvents(
|
|
|
174
197
|
});
|
|
175
198
|
|
|
176
199
|
child.on("error", (err) => {
|
|
177
|
-
|
|
200
|
+
clearStartupTimer();
|
|
178
201
|
clearInterval(heartbeat);
|
|
179
202
|
reject(err);
|
|
180
203
|
});
|