@pi-unipi/subagents 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.
Files changed (49) hide show
  1. package/dist/agent-manager.d.ts +69 -0
  2. package/dist/agent-manager.d.ts.map +1 -0
  3. package/dist/agent-manager.js +240 -0
  4. package/dist/agent-manager.js.map +1 -0
  5. package/dist/agent-runner.d.ts +50 -0
  6. package/dist/agent-runner.d.ts.map +1 -0
  7. package/dist/agent-runner.js +238 -0
  8. package/dist/agent-runner.js.map +1 -0
  9. package/dist/config.d.ts +24 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +115 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/custom-agents.d.ts +14 -0
  14. package/dist/custom-agents.d.ts.map +1 -0
  15. package/dist/custom-agents.js +94 -0
  16. package/dist/custom-agents.js.map +1 -0
  17. package/dist/file-lock.d.ts +42 -0
  18. package/dist/file-lock.d.ts.map +1 -0
  19. package/dist/file-lock.js +91 -0
  20. package/dist/file-lock.js.map +1 -0
  21. package/dist/index.d.ts +9 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +270 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/prompts.d.ts +13 -0
  26. package/dist/prompts.d.ts.map +1 -0
  27. package/dist/prompts.js +31 -0
  28. package/dist/prompts.js.map +1 -0
  29. package/dist/types.d.ts +79 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +6 -0
  32. package/dist/types.js.map +1 -0
  33. package/dist/widget.d.ts +22 -0
  34. package/dist/widget.d.ts.map +1 -0
  35. package/dist/widget.js +108 -0
  36. package/dist/widget.js.map +1 -0
  37. package/package.json +30 -0
  38. package/src/agent-manager.ts +302 -0
  39. package/src/agent-runner.ts +306 -0
  40. package/src/config.ts +128 -0
  41. package/src/custom-agents.ts +106 -0
  42. package/src/file-lock.ts +102 -0
  43. package/src/index.ts +323 -0
  44. package/src/prompts.ts +39 -0
  45. package/src/skills/explore/SKILL.md +32 -0
  46. package/src/skills/work/SKILL.md +40 -0
  47. package/src/types.ts +86 -0
  48. package/src/widget.ts +123 -0
  49. package/tsconfig.json +19 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @pi-unipi/subagents — System prompt builder
3
+ */
4
+ import type { AgentConfig } from "./types.js";
5
+ /**
6
+ * Build system prompt for an agent.
7
+ */
8
+ export declare function buildAgentPrompt(config: AgentConfig, cwd: string, env: {
9
+ isGitRepo: boolean;
10
+ branch: string;
11
+ platform: string;
12
+ }, parentSystemPrompt: string): string;
13
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC7D,kBAAkB,EAAE,MAAM,GACzB,MAAM,CAwBR"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @pi-unipi/subagents — System prompt builder
3
+ */
4
+ /**
5
+ * Build system prompt for an agent.
6
+ */
7
+ export function buildAgentPrompt(config, cwd, env, parentSystemPrompt) {
8
+ if (config.promptMode === "append") {
9
+ // Append mode: parent prompt + agent additions
10
+ return [
11
+ parentSystemPrompt,
12
+ "",
13
+ "---",
14
+ "",
15
+ `## Agent Role: ${config.displayName ?? config.name}`,
16
+ config.systemPrompt,
17
+ ].join("\n");
18
+ }
19
+ // Replace mode: standalone prompt
20
+ return [
21
+ `# ${config.displayName ?? config.name}`,
22
+ "",
23
+ config.systemPrompt,
24
+ "",
25
+ "---",
26
+ "",
27
+ `Working directory: ${cwd}`,
28
+ `Git: ${env.isGitRepo ? `${env.branch} on ${env.platform}` : "not a git repo"}`,
29
+ ].join("\n");
30
+ }
31
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,GAAW,EACX,GAA6D,EAC7D,kBAA0B;IAE1B,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,+CAA+C;QAC/C,OAAO;YACL,kBAAkB;YAClB,EAAE;YACF,KAAK;YACL,EAAE;YACF,kBAAkB,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;YACrD,MAAM,CAAC,YAAY;SACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;IAED,kCAAkC;IAClC,OAAO;QACL,KAAK,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,EAAE;QACxC,EAAE;QACF,MAAM,CAAC,YAAY;QACnB,EAAE;QACF,KAAK;QACL,EAAE;QACF,sBAAsB,GAAG,EAAE;QAC3B,QAAQ,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,gBAAgB,EAAE;KAChF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @pi-unipi/subagents — Type definitions
3
+ */
4
+ import type { ThinkingLevel } from "@mariozechner/pi-agent-core";
5
+ import type { AgentSession } from "@mariozechner/pi-coding-agent";
6
+ export type { ThinkingLevel };
7
+ /** Agent type name: built-in or user-defined. */
8
+ export type AgentType = string;
9
+ /** Built-in agent type names. */
10
+ export declare const BUILTIN_TYPES: readonly ["explore", "work"];
11
+ /** Memory scope for persistent agent memory. */
12
+ export type MemoryScope = "user" | "project" | "local";
13
+ /** Unified agent configuration. */
14
+ export interface AgentConfig {
15
+ name: string;
16
+ displayName?: string;
17
+ description: string;
18
+ builtinToolNames?: string[];
19
+ disallowedTools?: string[];
20
+ extensions: true | string[] | false;
21
+ skills: true | string[] | false;
22
+ model?: string;
23
+ thinking?: ThinkingLevel;
24
+ maxTurns?: number;
25
+ systemPrompt: string;
26
+ promptMode: "replace" | "append";
27
+ inheritContext?: boolean;
28
+ runInBackground?: boolean;
29
+ isolated?: boolean;
30
+ memory?: MemoryScope;
31
+ isDefault?: boolean;
32
+ enabled?: boolean;
33
+ source?: "builtin" | "project" | "global";
34
+ }
35
+ /** Agent record — tracks a running agent. */
36
+ export interface AgentRecord {
37
+ id: string;
38
+ type: AgentType;
39
+ description: string;
40
+ status: "queued" | "running" | "completed" | "aborted" | "stopped" | "error";
41
+ result?: string;
42
+ error?: string;
43
+ toolUses: number;
44
+ startedAt: number;
45
+ completedAt?: number;
46
+ session?: AgentSession;
47
+ abortController?: AbortController;
48
+ promise?: Promise<string>;
49
+ /** Set when result consumed via get_result — suppresses notification. */
50
+ resultConsumed?: boolean;
51
+ /** Files locked by this agent. */
52
+ lockedFiles: Set<string>;
53
+ }
54
+ /** File lock entry. */
55
+ export interface FileLockEntry {
56
+ agentId: string;
57
+ filePath: string;
58
+ promise: Promise<void>;
59
+ release: () => void;
60
+ }
61
+ /** Extension config. */
62
+ export interface SubagentsConfig {
63
+ maxConcurrent: number;
64
+ enabled: boolean;
65
+ types: Record<string, {
66
+ enabled?: boolean;
67
+ }>;
68
+ }
69
+ /** Agent activity for widget display. */
70
+ export interface AgentActivity {
71
+ activeTools: Map<string, string>;
72
+ toolUses: number;
73
+ turnCount: number;
74
+ maxTurns?: number;
75
+ tokens: string;
76
+ responseText: string;
77
+ session?: AgentSession;
78
+ }
79
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @pi-unipi/subagents — Type definitions
3
+ */
4
+ /** Built-in agent type names. */
5
+ export const BUILTIN_TYPES = ["explore", "work"];
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,iCAAiC;AACjC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,CAAU,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @pi-unipi/subagents — Live widget
3
+ *
4
+ * Shows running agents above the editor.
5
+ * Adapted from pi-subagents.
6
+ */
7
+ import type { AgentManager } from "./agent-manager.js";
8
+ import type { AgentActivity } from "./types.js";
9
+ export declare class AgentWidget {
10
+ private manager;
11
+ private activity;
12
+ private spinnerFrame;
13
+ private timer?;
14
+ private uiCtx?;
15
+ constructor(manager: AgentManager, activity: Map<string, AgentActivity>);
16
+ setUICtx(ctx: any): void;
17
+ ensureTimer(): void;
18
+ markFinished(_id: string): void;
19
+ update(): void;
20
+ private render;
21
+ }
22
+ //# sourceMappingURL=widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqChD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAC,CAAM;gBAER,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;IAKvE,QAAQ,CAAC,GAAG,EAAE,GAAG;IAIjB,WAAW;IAQX,YAAY,CAAC,GAAG,EAAE,MAAM;IAUxB,MAAM;IAIN,OAAO,CAAC,MAAM;CAuCf"}
package/dist/widget.js ADDED
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @pi-unipi/subagents — Live widget
3
+ *
4
+ * Shows running agents above the editor.
5
+ * Adapted from pi-subagents.
6
+ */
7
+ /** Spinner frames (braille). */
8
+ const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
9
+ /** Format token count. */
10
+ function formatTokens(n) {
11
+ if (n >= 1_000_000)
12
+ return `${(n / 1_000_000).toFixed(1)}M`;
13
+ if (n >= 1_000)
14
+ return `${(n / 1_000).toFixed(1)}k`;
15
+ return `${n}`;
16
+ }
17
+ /** Format duration. */
18
+ function formatMs(ms) {
19
+ if (ms >= 60_000)
20
+ return `${(ms / 60_000).toFixed(1)}m`;
21
+ if (ms >= 1_000)
22
+ return `${(ms / 1_000).toFixed(1)}s`;
23
+ return `${ms}ms`;
24
+ }
25
+ /** Format turns. */
26
+ function formatTurns(turn, max) {
27
+ return max ? `⟳${turn}≤${max}` : `⟳${turn}`;
28
+ }
29
+ /** Describe current activity from active tools. */
30
+ function describeActivity(activeTools, responseText) {
31
+ if (activeTools.size > 0) {
32
+ const names = [...new Set(activeTools.values())];
33
+ return names.join(", ") + "…";
34
+ }
35
+ if (responseText) {
36
+ const lastLine = responseText.split("\n").pop()?.trim() ?? "";
37
+ if (lastLine.length > 0)
38
+ return lastLine.slice(0, 60) + (lastLine.length > 60 ? "…" : "");
39
+ }
40
+ return "thinking…";
41
+ }
42
+ export class AgentWidget {
43
+ manager;
44
+ activity;
45
+ spinnerFrame = 0;
46
+ timer;
47
+ uiCtx;
48
+ constructor(manager, activity) {
49
+ this.manager = manager;
50
+ this.activity = activity;
51
+ }
52
+ setUICtx(ctx) {
53
+ this.uiCtx = ctx;
54
+ }
55
+ ensureTimer() {
56
+ if (this.timer)
57
+ return;
58
+ this.timer = setInterval(() => {
59
+ this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
60
+ this.render();
61
+ }, 80);
62
+ }
63
+ markFinished(_id) {
64
+ // Check if any agents still running
65
+ if (!this.manager.hasRunning()) {
66
+ if (this.timer) {
67
+ clearInterval(this.timer);
68
+ this.timer = undefined;
69
+ }
70
+ }
71
+ }
72
+ update() {
73
+ this.render();
74
+ }
75
+ render() {
76
+ const agents = this.manager.listAgents();
77
+ const running = agents.filter((a) => a.status === "running" || a.status === "queued");
78
+ if (running.length === 0) {
79
+ // Clear widget
80
+ this.uiCtx?.setIndicator?.("");
81
+ return;
82
+ }
83
+ const lines = [];
84
+ const frame = SPINNER[this.spinnerFrame];
85
+ for (const agent of running) {
86
+ const act = this.activity.get(agent.id);
87
+ const toolCount = agent.toolUses;
88
+ const tokens = act?.tokens ?? "";
89
+ const duration = formatMs(Date.now() - agent.startedAt);
90
+ const activity = act ? describeActivity(act.activeTools, act.responseText) : "starting…";
91
+ const parts = [];
92
+ if (act?.turnCount)
93
+ parts.push(formatTurns(act.turnCount, act.maxTurns));
94
+ if (toolCount > 0)
95
+ parts.push(`${toolCount} tool uses`);
96
+ if (tokens)
97
+ parts.push(tokens);
98
+ parts.push(duration);
99
+ lines.push(`${frame} ${agent.type} ${agent.description} · ${parts.join(" · ")}`, ` ⎿ ${activity}`);
100
+ }
101
+ const queued = agents.filter((a) => a.status === "queued").length;
102
+ if (queued > 0) {
103
+ lines.push(` ${queued} queued`);
104
+ }
105
+ this.uiCtx?.setIndicator?.(lines.join("\n"));
106
+ }
107
+ }
108
+ //# sourceMappingURL=widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@pi-unipi/subagents",
3
+ "version": "0.1.0",
4
+ "description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch"
17
+ },
18
+ "dependencies": {
19
+ "@pi-unipi/core": "*",
20
+ "@pi-unipi/workflow": "*"
21
+ },
22
+ "devDependencies": {
23
+ "typescript": "^5.8.3"
24
+ },
25
+ "peerDependencies": {
26
+ "@mariozechner/pi-coding-agent": "*",
27
+ "@mariozechner/pi-tui": "*",
28
+ "@sinclair/typebox": "*"
29
+ }
30
+ }
@@ -0,0 +1,302 @@
1
+ /**
2
+ * @pi-unipi/subagents — Agent manager
3
+ *
4
+ * Tracks agents, manages concurrency queue, handles spawn/resume/abort.
5
+ * Background agents subject to concurrency limit. Foreground bypass queue.
6
+ */
7
+
8
+ import { randomUUID } from "node:crypto";
9
+ import type { Model } from "@mariozechner/pi-ai";
10
+ import type { AgentSession, ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
11
+ import { runAgent, type ToolActivity } from "./agent-runner.js";
12
+ import type { AgentRecord, AgentType, ThinkingLevel } from "./types.js";
13
+ import { FileLock } from "./file-lock.js";
14
+
15
+ export type OnAgentComplete = (record: AgentRecord) => void;
16
+ export type OnAgentStart = (record: AgentRecord) => void;
17
+
18
+ /** Default max concurrent background agents. */
19
+ const DEFAULT_MAX_CONCURRENT = 4;
20
+
21
+ interface SpawnArgs {
22
+ pi: ExtensionAPI;
23
+ ctx: ExtensionContext;
24
+ type: AgentType;
25
+ prompt: string;
26
+ options: SpawnOptions;
27
+ }
28
+
29
+ interface SpawnOptions {
30
+ description: string;
31
+ model?: Model<any>;
32
+ maxTurns?: number;
33
+ isolated?: boolean;
34
+ inheritContext?: boolean;
35
+ thinkingLevel?: ThinkingLevel;
36
+ isBackground?: boolean;
37
+ onToolActivity?: (activity: ToolActivity) => void;
38
+ onTextDelta?: (delta: string, fullText: string) => void;
39
+ onSessionCreated?: (session: AgentSession) => void;
40
+ onTurnEnd?: (turnCount: number) => void;
41
+ }
42
+
43
+ export class AgentManager {
44
+ private agents = new Map<string, AgentRecord>();
45
+ private cleanupInterval: ReturnType<typeof setInterval>;
46
+ private onComplete?: OnAgentComplete;
47
+ private onStart?: OnAgentStart;
48
+ private maxConcurrent: number;
49
+
50
+ /** Per-file transparent locking for write agents. */
51
+ readonly fileLock = new FileLock();
52
+
53
+ /** Queue of background agents waiting to start. */
54
+ private queue: { id: string; args: SpawnArgs }[] = [];
55
+ /** Number of currently running background agents. */
56
+ private runningBackground = 0;
57
+
58
+ constructor(onComplete?: OnAgentComplete, maxConcurrent = DEFAULT_MAX_CONCURRENT, onStart?: OnAgentStart) {
59
+ this.onComplete = onComplete;
60
+ this.onStart = onStart;
61
+ this.maxConcurrent = maxConcurrent;
62
+ this.cleanupInterval = setInterval(() => this.cleanup(), 60_000);
63
+ }
64
+
65
+ setMaxConcurrent(n: number) {
66
+ this.maxConcurrent = Math.max(1, n);
67
+ this.drainQueue();
68
+ }
69
+
70
+ getMaxConcurrent(): number {
71
+ return this.maxConcurrent;
72
+ }
73
+
74
+ /**
75
+ * Spawn an agent. Returns ID immediately for background, waits for foreground.
76
+ */
77
+ spawn(
78
+ pi: ExtensionAPI,
79
+ ctx: ExtensionContext,
80
+ type: AgentType,
81
+ prompt: string,
82
+ options: SpawnOptions,
83
+ ): string {
84
+ const id = randomUUID().slice(0, 17);
85
+ const abortController = new AbortController();
86
+ const record: AgentRecord = {
87
+ id,
88
+ type,
89
+ description: options.description,
90
+ status: options.isBackground ? "queued" : "running",
91
+ toolUses: 0,
92
+ startedAt: Date.now(),
93
+ abortController,
94
+ lockedFiles: new Set(),
95
+ };
96
+ this.agents.set(id, record);
97
+
98
+ const args: SpawnArgs = { pi, ctx, type, prompt, options };
99
+
100
+ if (options.isBackground && this.runningBackground >= this.maxConcurrent) {
101
+ this.queue.push({ id, args });
102
+ return id;
103
+ }
104
+
105
+ this.startAgent(id, record, args);
106
+ return id;
107
+ }
108
+
109
+ /** Actually start an agent. */
110
+ private startAgent(id: string, record: AgentRecord, { pi, ctx, type, prompt, options }: SpawnArgs) {
111
+ record.status = "running";
112
+ record.startedAt = Date.now();
113
+ if (options.isBackground) this.runningBackground++;
114
+ this.onStart?.(record);
115
+
116
+ const promise = runAgent(ctx, type, prompt, {
117
+ pi,
118
+ model: options.model,
119
+ maxTurns: options.maxTurns,
120
+ isolated: options.isolated,
121
+ inheritContext: options.inheritContext,
122
+ thinkingLevel: options.thinkingLevel,
123
+ signal: record.abortController!.signal,
124
+ onToolActivity: (activity) => {
125
+ if (activity.type === "end") record.toolUses++;
126
+ options.onToolActivity?.(activity);
127
+ },
128
+ onTurnEnd: options.onTurnEnd,
129
+ onTextDelta: options.onTextDelta,
130
+ onSessionCreated: (session) => {
131
+ record.session = session;
132
+ options.onSessionCreated?.(session);
133
+ },
134
+ })
135
+ .then(({ responseText, session, aborted, steered }) => {
136
+ if (record.status !== "stopped") {
137
+ record.status = aborted ? "aborted" : steered ? "completed" : "completed";
138
+ }
139
+ record.result = responseText;
140
+ record.session = session;
141
+ record.completedAt ??= Date.now();
142
+
143
+ // Release any held file locks
144
+ this.fileLock.releaseAll(id);
145
+ record.lockedFiles.clear();
146
+
147
+ if (options.isBackground) {
148
+ this.runningBackground--;
149
+ this.onComplete?.(record);
150
+ this.drainQueue();
151
+ }
152
+ return responseText;
153
+ })
154
+ .catch((err) => {
155
+ if (record.status !== "stopped") {
156
+ record.status = "error";
157
+ }
158
+ record.error = err instanceof Error ? err.message : String(err);
159
+ record.completedAt ??= Date.now();
160
+
161
+ // Release any held file locks
162
+ this.fileLock.releaseAll(id);
163
+ record.lockedFiles.clear();
164
+
165
+ if (options.isBackground) {
166
+ this.runningBackground--;
167
+ this.onComplete?.(record);
168
+ this.drainQueue();
169
+ }
170
+ return "";
171
+ });
172
+
173
+ record.promise = promise;
174
+ }
175
+
176
+ /** Start queued agents up to concurrency limit. */
177
+ private drainQueue() {
178
+ while (this.queue.length > 0 && this.runningBackground < this.maxConcurrent) {
179
+ const next = this.queue.shift()!;
180
+ const record = this.agents.get(next.id);
181
+ if (!record || record.status !== "queued") continue;
182
+ this.startAgent(next.id, record, next.args);
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Spawn and wait (foreground).
188
+ */
189
+ async spawnAndWait(
190
+ pi: ExtensionAPI,
191
+ ctx: ExtensionContext,
192
+ type: AgentType,
193
+ prompt: string,
194
+ options: Omit<SpawnOptions, "isBackground">,
195
+ ): Promise<AgentRecord> {
196
+ const id = this.spawn(pi, ctx, type, prompt, { ...options, isBackground: false });
197
+ const record = this.agents.get(id)!;
198
+ await record.promise;
199
+ return record;
200
+ }
201
+
202
+ getRecord(id: string): AgentRecord | undefined {
203
+ return this.agents.get(id);
204
+ }
205
+
206
+ listAgents(): AgentRecord[] {
207
+ return [...this.agents.values()].sort((a, b) => b.startedAt - a.startedAt);
208
+ }
209
+
210
+ abort(id: string): boolean {
211
+ const record = this.agents.get(id);
212
+ if (!record) return false;
213
+
214
+ if (record.status === "queued") {
215
+ this.queue = this.queue.filter((q) => q.id !== id);
216
+ record.status = "stopped";
217
+ record.completedAt = Date.now();
218
+ return true;
219
+ }
220
+
221
+ if (record.status !== "running") return false;
222
+ record.abortController?.abort();
223
+ record.status = "stopped";
224
+ record.completedAt = Date.now();
225
+ this.fileLock.releaseAll(id);
226
+ record.lockedFiles.clear();
227
+ return true;
228
+ }
229
+
230
+ /** Abort all agents (for ESC propagation). */
231
+ abortAll(): number {
232
+ let count = 0;
233
+ for (const queued of this.queue) {
234
+ const record = this.agents.get(queued.id);
235
+ if (record) {
236
+ record.status = "stopped";
237
+ record.completedAt = Date.now();
238
+ count++;
239
+ }
240
+ }
241
+ this.queue = [];
242
+ for (const record of this.agents.values()) {
243
+ if (record.status === "running") {
244
+ record.abortController?.abort();
245
+ record.status = "stopped";
246
+ record.completedAt = Date.now();
247
+ count++;
248
+ }
249
+ }
250
+ this.fileLock.clear();
251
+ return count;
252
+ }
253
+
254
+ /** Wait for all agents. */
255
+ async waitForAll(): Promise<void> {
256
+ while (true) {
257
+ this.drainQueue();
258
+ const pending = [...this.agents.values()]
259
+ .filter((r) => r.status === "running" || r.status === "queued")
260
+ .map((r) => r.promise)
261
+ .filter(Boolean);
262
+ if (pending.length === 0) break;
263
+ await Promise.allSettled(pending);
264
+ }
265
+ }
266
+
267
+ /** Whether any agents running or queued. */
268
+ hasRunning(): boolean {
269
+ return [...this.agents.values()].some((r) => r.status === "running" || r.status === "queued");
270
+ }
271
+
272
+ /** Remove completed records. */
273
+ clearCompleted(): void {
274
+ for (const [id, record] of this.agents) {
275
+ if (record.status === "running" || record.status === "queued") continue;
276
+ record.session?.dispose?.();
277
+ record.session = undefined;
278
+ this.agents.delete(id);
279
+ }
280
+ }
281
+
282
+ private cleanup() {
283
+ const cutoff = Date.now() - 10 * 60_000;
284
+ for (const [id, record] of this.agents) {
285
+ if (record.status === "running" || record.status === "queued") continue;
286
+ if ((record.completedAt ?? 0) >= cutoff) continue;
287
+ record.session?.dispose?.();
288
+ record.session = undefined;
289
+ this.agents.delete(id);
290
+ }
291
+ }
292
+
293
+ dispose() {
294
+ clearInterval(this.cleanupInterval);
295
+ this.queue = [];
296
+ this.abortAll();
297
+ for (const record of this.agents.values()) {
298
+ record.session?.dispose();
299
+ }
300
+ this.agents.clear();
301
+ }
302
+ }