mcp-codex-subagent 2.0.9 → 2.0.11

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 (111) hide show
  1. package/dist/event/bus.d.ts +53 -0
  2. package/dist/event/bus.d.ts.map +1 -0
  3. package/dist/event/bus.js +94 -0
  4. package/dist/event/bus.js.map +1 -0
  5. package/dist/event/throttle.d.ts +36 -0
  6. package/dist/event/throttle.d.ts.map +1 -0
  7. package/dist/event/throttle.js +66 -0
  8. package/dist/event/throttle.js.map +1 -0
  9. package/dist/index.js +32 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/process/event-parser.d.ts +37 -0
  12. package/dist/process/event-parser.d.ts.map +1 -0
  13. package/dist/process/event-parser.js +141 -0
  14. package/dist/process/event-parser.js.map +1 -0
  15. package/dist/process/runner.d.ts +48 -0
  16. package/dist/process/runner.d.ts.map +1 -0
  17. package/dist/process/runner.js +227 -0
  18. package/dist/process/runner.js.map +1 -0
  19. package/dist/process/types.d.ts +74 -0
  20. package/dist/process/types.d.ts.map +1 -0
  21. package/dist/process/types.js +5 -0
  22. package/dist/process/types.js.map +1 -0
  23. package/dist/server.d.ts.map +1 -1
  24. package/dist/server.js +128 -36
  25. package/dist/server.js.map +1 -1
  26. package/dist/services/account-rotator.d.ts +28 -0
  27. package/dist/services/account-rotator.d.ts.map +1 -0
  28. package/dist/services/account-rotator.js +216 -0
  29. package/dist/services/account-rotator.js.map +1 -0
  30. package/dist/services/output-file.d.ts.map +1 -1
  31. package/dist/services/output-file.js +80 -36
  32. package/dist/services/output-file.js.map +1 -1
  33. package/dist/services/template-init.d.ts +10 -0
  34. package/dist/services/template-init.d.ts.map +1 -0
  35. package/dist/services/template-init.js +41 -0
  36. package/dist/services/template-init.js.map +1 -0
  37. package/dist/session/file-storage.d.ts +27 -0
  38. package/dist/session/file-storage.d.ts.map +1 -0
  39. package/dist/session/file-storage.js +281 -0
  40. package/dist/session/file-storage.js.map +1 -0
  41. package/dist/session/storage.js +1 -1
  42. package/dist/session/storage.js.map +1 -1
  43. package/dist/task/state-machine.d.ts +27 -0
  44. package/dist/task/state-machine.d.ts.map +1 -0
  45. package/dist/task/state-machine.js +59 -0
  46. package/dist/task/state-machine.js.map +1 -0
  47. package/dist/task/store.d.ts +91 -0
  48. package/dist/task/store.d.ts.map +1 -0
  49. package/dist/task/store.js +317 -0
  50. package/dist/task/store.js.map +1 -0
  51. package/dist/task/types.d.ts +72 -0
  52. package/dist/task/types.d.ts.map +1 -0
  53. package/dist/task/types.js +13 -0
  54. package/dist/task/types.js.map +1 -0
  55. package/dist/templates/index.d.ts +16 -0
  56. package/dist/templates/index.d.ts.map +1 -1
  57. package/dist/templates/index.js +57 -5
  58. package/dist/templates/index.js.map +1 -1
  59. package/dist/tools/definitions.d.ts +5 -1
  60. package/dist/tools/definitions.d.ts.map +1 -1
  61. package/dist/tools/definitions.js +253 -179
  62. package/dist/tools/definitions.js.map +1 -1
  63. package/dist/tools/description-builder.d.ts +18 -0
  64. package/dist/tools/description-builder.d.ts.map +1 -0
  65. package/dist/tools/description-builder.js +88 -0
  66. package/dist/tools/description-builder.js.map +1 -0
  67. package/dist/tools/handlers.d.ts +19 -17
  68. package/dist/tools/handlers.d.ts.map +1 -1
  69. package/dist/tools/handlers.js +287 -341
  70. package/dist/tools/handlers.js.map +1 -1
  71. package/dist/types.d.ts +5 -12
  72. package/dist/types.d.ts.map +1 -1
  73. package/dist/types.js +7 -10
  74. package/dist/types.js.map +1 -1
  75. package/dist/utils/ring-buffer.d.ts +41 -0
  76. package/dist/utils/ring-buffer.d.ts.map +1 -0
  77. package/dist/utils/ring-buffer.js +83 -0
  78. package/dist/utils/ring-buffer.js.map +1 -0
  79. package/dist/wave/dag.d.ts +32 -0
  80. package/dist/wave/dag.d.ts.map +1 -0
  81. package/dist/wave/dag.js +186 -0
  82. package/dist/wave/dag.js.map +1 -0
  83. package/dist/wave/git.d.ts +57 -0
  84. package/dist/wave/git.d.ts.map +1 -0
  85. package/dist/wave/git.js +227 -0
  86. package/dist/wave/git.js.map +1 -0
  87. package/dist/wave/orchestrator.d.ts +15 -0
  88. package/dist/wave/orchestrator.d.ts.map +1 -0
  89. package/dist/wave/orchestrator.js +565 -0
  90. package/dist/wave/orchestrator.js.map +1 -0
  91. package/dist/wave/progress.d.ts +51 -0
  92. package/dist/wave/progress.d.ts.map +1 -0
  93. package/dist/wave/progress.js +176 -0
  94. package/dist/wave/progress.js.map +1 -0
  95. package/dist/wave/registry.d.ts +66 -0
  96. package/dist/wave/registry.d.ts.map +1 -0
  97. package/dist/wave/registry.js +340 -0
  98. package/dist/wave/registry.js.map +1 -0
  99. package/dist/wave/semaphore.d.ts +42 -0
  100. package/dist/wave/semaphore.d.ts.map +1 -0
  101. package/dist/wave/semaphore.js +119 -0
  102. package/dist/wave/semaphore.js.map +1 -0
  103. package/dist/wave/types.d.ts +197 -0
  104. package/dist/wave/types.d.ts.map +1 -0
  105. package/dist/wave/types.js +147 -0
  106. package/dist/wave/types.js.map +1 -0
  107. package/package.json +1 -1
  108. package/dist/services/task-manager.d.ts +0 -69
  109. package/dist/services/task-manager.d.ts.map +0 -1
  110. package/dist/services/task-manager.js +0 -173
  111. package/dist/services/task-manager.js.map +0 -1
@@ -0,0 +1,176 @@
1
+ /**
2
+ * GroupProgressCollector — per-group event aggregation for streaming.
3
+ *
4
+ * Subscribes to TaskEventBus for each agent's taskId and sends
5
+ * throttled progress notifications to the MCP client.
6
+ *
7
+ * One instance per orchestrate() call (NOT a singleton).
8
+ */
9
+ import { taskEventBus } from '../event/bus.js';
10
+ import { NotificationThrottle } from '../event/throttle.js';
11
+ import { getStreamVerbosity, } from './types.js';
12
+ export class GroupProgressCollector {
13
+ groupId;
14
+ sendProgress;
15
+ verbosity;
16
+ aliasMap = new Map(); // taskId → alias
17
+ unsubscribes = [];
18
+ throttle;
19
+ // Aggregate counters
20
+ commandsRun = 0;
21
+ filesChanged = 0;
22
+ errorCount = 0;
23
+ agentsDone = 0;
24
+ totalAgents = 0;
25
+ progressCount = 0;
26
+ constructor(groupId, sendProgress, totalAgents) {
27
+ this.groupId = groupId;
28
+ this.sendProgress = sendProgress;
29
+ this.totalAgents = totalAgents;
30
+ this.verbosity = getStreamVerbosity();
31
+ this.throttle = new NotificationThrottle({
32
+ intervalMs: 500,
33
+ send: async () => {
34
+ await this.emitSummary();
35
+ },
36
+ });
37
+ }
38
+ /**
39
+ * Register an agent and subscribe to its TaskEventBus events.
40
+ */
41
+ registerAgent(taskId, alias) {
42
+ this.aliasMap.set(taskId, alias);
43
+ const unsub = taskEventBus.subscribe(taskId, (taskEvent) => {
44
+ this.onAgentEvent(taskId, taskEvent.event);
45
+ });
46
+ this.unsubscribes.push(unsub);
47
+ }
48
+ /**
49
+ * Send a group-level progress event (e.g., waiting, worktree created).
50
+ * Not throttled — sent immediately.
51
+ */
52
+ async emitGroupEvent(type, detail) {
53
+ this.progressCount++;
54
+ const message = detail ? `${type}: ${detail}` : type;
55
+ await this.sendProgress(message, this.progressCount).catch(() => { });
56
+ }
57
+ /**
58
+ * Send the markdown agent mapping table.
59
+ */
60
+ async emitAgentTable(group) {
61
+ const lines = [
62
+ `group.agent_table: ${group.id}`,
63
+ '',
64
+ '| Agent | Role | Status |',
65
+ '|-------|------|--------|',
66
+ ];
67
+ for (const agent of group.agents) {
68
+ lines.push(`| ${agent.alias} | ${agent.role ?? '-'} | ${agent.state} |`);
69
+ }
70
+ this.progressCount++;
71
+ await this.sendProgress(lines.join('\n'), this.progressCount).catch(() => { });
72
+ }
73
+ /**
74
+ * Notify that an agent completed (success or failure).
75
+ * Flushes the throttle immediately for state changes.
76
+ */
77
+ agentCompleted(alias, success) {
78
+ this.agentsDone++;
79
+ if (!success)
80
+ this.errorCount++;
81
+ // Flush immediately on state changes
82
+ this.throttle.flush().catch(() => { });
83
+ }
84
+ /**
85
+ * Clean up all subscriptions and the throttle timer.
86
+ */
87
+ async dispose() {
88
+ for (const unsub of this.unsubscribes) {
89
+ unsub();
90
+ }
91
+ this.unsubscribes.length = 0;
92
+ await this.throttle.flush().catch(() => { });
93
+ this.throttle.dispose();
94
+ }
95
+ // -----------------------------------------------------------------------
96
+ // Private
97
+ // -----------------------------------------------------------------------
98
+ onAgentEvent(taskId, event) {
99
+ const alias = this.aliasMap.get(taskId) ?? taskId;
100
+ switch (event.type) {
101
+ case 'command_execution':
102
+ this.commandsRun++;
103
+ if (this.verbosity !== 'low') {
104
+ const cmd = truncate(String(event.command ?? ''), 100);
105
+ this.emitDetailEvent(`agent.tool_call: ${alias}: ${cmd}`);
106
+ }
107
+ break;
108
+ case 'file_change': {
109
+ const changes = event.changes;
110
+ if (Array.isArray(changes)) {
111
+ this.filesChanged += changes.length;
112
+ }
113
+ else {
114
+ this.filesChanged++;
115
+ }
116
+ if (this.verbosity !== 'low') {
117
+ const path = truncate(String(event.file ?? ''), 100);
118
+ this.emitDetailEvent(`agent.file_change: ${alias}: ${path}`);
119
+ }
120
+ break;
121
+ }
122
+ case 'mcp_tool_call':
123
+ if (this.verbosity !== 'low') {
124
+ const tool = String(event.tool ?? '');
125
+ this.emitDetailEvent(`agent.tool_call: ${alias}: ${tool}`);
126
+ }
127
+ break;
128
+ case 'error':
129
+ case 'turn_failed':
130
+ this.errorCount++;
131
+ if (this.verbosity !== 'low') {
132
+ const msg = truncate(String(event.message ?? ''), 100);
133
+ this.emitDetailEvent(`agent.error: ${alias}: ${msg}`);
134
+ }
135
+ break;
136
+ case 'agent_message':
137
+ if (this.verbosity === 'high') {
138
+ const text = truncate(String(event.text ?? ''), 100);
139
+ this.emitDetailEvent(`agent.message: ${alias}: ${text}`);
140
+ }
141
+ break;
142
+ case 'reasoning':
143
+ if (this.verbosity === 'high') {
144
+ const text = truncate(String(event.text ??
145
+ event.content ??
146
+ ''), 100);
147
+ this.emitDetailEvent(`agent.reasoning: ${alias}: ${text}`);
148
+ }
149
+ break;
150
+ default:
151
+ break;
152
+ }
153
+ // Trigger throttled summary
154
+ this.throttle.notify();
155
+ }
156
+ emitDetailEvent(message) {
157
+ this.progressCount++;
158
+ this.sendProgress(message, this.progressCount).catch(() => { });
159
+ }
160
+ async emitSummary() {
161
+ const running = this.totalAgents - this.agentsDone;
162
+ const aliases = [...this.aliasMap.values()];
163
+ const runningAliases = aliases.slice(0, 5).join(', ');
164
+ const more = aliases.length > 5 ? ` +${aliases.length - 5} more` : '';
165
+ const summary = `[${this.agentsDone}/${this.totalAgents} done] ` +
166
+ (running > 0 ? `running: ${runningAliases}${more} | ` : '') +
167
+ `${this.commandsRun} cmds, ${this.filesChanged} files` +
168
+ (this.errorCount > 0 ? ` | ${this.errorCount} errors` : '');
169
+ this.progressCount++;
170
+ await this.sendProgress(summary, this.progressCount).catch(() => { });
171
+ }
172
+ }
173
+ function truncate(s, maxLen) {
174
+ return s.length > maxLen ? s.slice(0, maxLen) + '...' : s;
175
+ }
176
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/wave/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * GroupRegistry — single authoritative source for group state.
3
+ *
4
+ * Module-level singleton with JSONL persistence at
5
+ * ~/.mcp-codex-subagent/groups/<groupId>.jsonl
6
+ *
7
+ * Mirrors TaskStore patterns: explicit state machine, bounded,
8
+ * deterministic transitions.
9
+ */
10
+ import { type GroupState, type AgentState, type GroupRecord, type AgentRecord, type AgentSpec } from './types.js';
11
+ export interface CreateGroupOptions {
12
+ agents: AgentSpec[];
13
+ baseCwd: string;
14
+ dependsOn: string[];
15
+ groupName?: string;
16
+ }
17
+ export declare class GroupRegistry {
18
+ private readonly groups;
19
+ createGroup(opts: CreateGroupOptions): GroupRecord;
20
+ transitionGroup(id: string, newState: GroupState, opts?: {
21
+ error?: string;
22
+ commitSha?: string;
23
+ baseCommit?: string;
24
+ }): boolean;
25
+ transitionAgent(groupId: string, alias: string, newState: AgentState, opts?: {
26
+ error?: string;
27
+ taskId?: string;
28
+ pid?: number;
29
+ }): boolean;
30
+ /**
31
+ * Increment the attempt counter for an agent.
32
+ */
33
+ incrementAttempts(groupId: string, alias: string): void;
34
+ getGroup(id: string): GroupRecord | undefined;
35
+ getAllGroups(): GroupRecord[];
36
+ getAllNonTerminal(): GroupRecord[];
37
+ getAgent(groupId: string, alias: string): AgentRecord | undefined;
38
+ /**
39
+ * Check if all agents in a group have reached terminal states.
40
+ */
41
+ allAgentsTerminal(groupId: string): boolean;
42
+ /**
43
+ * Check whether all dependencies are met for a group.
44
+ * Returns 'met' if all dep groups are done_success,
45
+ * 'failed' if any dep group is done_failed or done_timeout,
46
+ * 'pending' if any dep group is still running.
47
+ */
48
+ areDependenciesMet(dependsOn: string[]): 'met' | 'pending' | 'failed';
49
+ /**
50
+ * Check if all agents that completed successfully.
51
+ */
52
+ allAgentsSucceeded(groupId: string): boolean;
53
+ /**
54
+ * Write the group record to disk as JSONL.
55
+ * Full rewrite (groups are small; simpler than append-only).
56
+ */
57
+ persist(id: string): void;
58
+ /**
59
+ * Load all group records from disk on startup.
60
+ */
61
+ loadAll(): void;
62
+ resetForTesting(): void;
63
+ private generateUniqueId;
64
+ }
65
+ export declare const groupRegistry: GroupRegistry;
66
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/wave/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,SAAS,EAMf,MAAM,YAAY,CAAC;AAoBpB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IAMzD,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,WAAW;IA0ClD,eAAe,CACb,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,UAAU,EACpB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GACjE,OAAO;IAwBV,eAAe,CACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,UAAU,EACpB,IAAI,CAAC,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GACA,OAAO;IA2BV;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAWvD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAI7C,YAAY,IAAI,WAAW,EAAE;IAI7B,iBAAiB,IAAI,WAAW,EAAE;IAIlC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAIjE;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAM3C;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ;IAgBrE;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAU5C;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAuDzB;;OAEG;IACH,OAAO,IAAI,IAAI;IA0Ef,eAAe,IAAI,IAAI;IASvB,OAAO,CAAC,gBAAgB;CAYzB;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,340 @@
1
+ /**
2
+ * GroupRegistry — single authoritative source for group state.
3
+ *
4
+ * Module-level singleton with JSONL persistence at
5
+ * ~/.mcp-codex-subagent/groups/<groupId>.jsonl
6
+ *
7
+ * Mirrors TaskStore patterns: explicit state machine, bounded,
8
+ * deterministic transitions.
9
+ */
10
+ import { mkdirSync, writeFileSync, readdirSync, readFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { CONFIG_HOME } from '../types.js';
13
+ import { generateTaskId, normalizeTaskId } from '../utils/task-id-generator.js';
14
+ import { isValidGroupTransition, isGroupTerminal, isValidAgentTransition, isAgentTerminal, DEFAULT_MAX_ATTEMPTS, } from './types.js';
15
+ const GROUPS_DIR = join(CONFIG_HOME, 'groups');
16
+ // Ensure groups directory exists
17
+ let groupsDirReady = false;
18
+ function ensureGroupsDir() {
19
+ if (groupsDirReady)
20
+ return;
21
+ try {
22
+ mkdirSync(GROUPS_DIR, { recursive: true });
23
+ groupsDirReady = true;
24
+ }
25
+ catch {
26
+ // Best-effort
27
+ }
28
+ }
29
+ // ---------------------------------------------------------------------------
30
+ // GroupRegistry Class
31
+ // ---------------------------------------------------------------------------
32
+ export class GroupRegistry {
33
+ groups = new Map();
34
+ // -----------------------------------------------------------------------
35
+ // Group creation
36
+ // -----------------------------------------------------------------------
37
+ createGroup(opts) {
38
+ const id = this.generateUniqueId();
39
+ const groupName = opts.groupName || id;
40
+ const branch = `sub-agent/${id}`;
41
+ const worktreePath = join(opts.baseCwd, '.worktree', `${id}-${groupName}`);
42
+ const agents = opts.agents.map((spec) => ({
43
+ alias: spec.alias,
44
+ state: 'pending',
45
+ prompt: spec.prompt.length > 200
46
+ ? spec.prompt.slice(0, 200) + '...'
47
+ : spec.prompt,
48
+ role: spec.role,
49
+ specialization: spec.specialization,
50
+ dependsOn: spec.depends_on ?? [],
51
+ attempts: 0,
52
+ maxAttempts: spec.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
53
+ }));
54
+ const group = {
55
+ id,
56
+ state: 'waiting_deps',
57
+ agents,
58
+ branch,
59
+ worktreePath,
60
+ baseCwd: opts.baseCwd,
61
+ baseCommit: '', // set during worktree creation
62
+ dependsOn: opts.dependsOn,
63
+ groupName,
64
+ createdAt: new Date().toISOString(),
65
+ };
66
+ this.groups.set(normalizeTaskId(id), group);
67
+ this.persist(id);
68
+ return group;
69
+ }
70
+ // -----------------------------------------------------------------------
71
+ // Group state transitions
72
+ // -----------------------------------------------------------------------
73
+ transitionGroup(id, newState, opts) {
74
+ const group = this.getGroup(id);
75
+ if (!group)
76
+ return false;
77
+ if (!isValidGroupTransition(group.state, newState))
78
+ return false;
79
+ group.state = newState;
80
+ if (opts?.error)
81
+ group.error = opts.error;
82
+ if (opts?.commitSha)
83
+ group.commitSha = opts.commitSha;
84
+ if (opts?.baseCommit)
85
+ group.baseCommit = opts.baseCommit;
86
+ if (isGroupTerminal(newState)) {
87
+ group.completedAt = new Date().toISOString();
88
+ }
89
+ this.persist(id);
90
+ return true;
91
+ }
92
+ // -----------------------------------------------------------------------
93
+ // Agent state transitions
94
+ // -----------------------------------------------------------------------
95
+ transitionAgent(groupId, alias, newState, opts) {
96
+ const group = this.getGroup(groupId);
97
+ if (!group)
98
+ return false;
99
+ const agent = group.agents.find((a) => a.alias === alias);
100
+ if (!agent)
101
+ return false;
102
+ if (!isValidAgentTransition(agent.state, newState))
103
+ return false;
104
+ agent.state = newState;
105
+ if (opts?.error)
106
+ agent.error = opts.error;
107
+ if (opts?.taskId)
108
+ agent.taskId = opts.taskId;
109
+ if (opts?.pid)
110
+ agent.pid = opts.pid;
111
+ if (newState === 'running' && !agent.startedAt) {
112
+ agent.startedAt = new Date().toISOString();
113
+ }
114
+ if (isAgentTerminal(newState)) {
115
+ agent.completedAt = new Date().toISOString();
116
+ }
117
+ // Don't persist on every agent transition (too frequent)
118
+ // Caller can call persist() explicitly when needed
119
+ return true;
120
+ }
121
+ /**
122
+ * Increment the attempt counter for an agent.
123
+ */
124
+ incrementAttempts(groupId, alias) {
125
+ const group = this.getGroup(groupId);
126
+ if (!group)
127
+ return;
128
+ const agent = group.agents.find((a) => a.alias === alias);
129
+ if (agent)
130
+ agent.attempts++;
131
+ }
132
+ // -----------------------------------------------------------------------
133
+ // Queries
134
+ // -----------------------------------------------------------------------
135
+ getGroup(id) {
136
+ return this.groups.get(normalizeTaskId(id));
137
+ }
138
+ getAllGroups() {
139
+ return [...this.groups.values()];
140
+ }
141
+ getAllNonTerminal() {
142
+ return [...this.groups.values()].filter((g) => !isGroupTerminal(g.state));
143
+ }
144
+ getAgent(groupId, alias) {
145
+ return this.getGroup(groupId)?.agents.find((a) => a.alias === alias);
146
+ }
147
+ /**
148
+ * Check if all agents in a group have reached terminal states.
149
+ */
150
+ allAgentsTerminal(groupId) {
151
+ const group = this.getGroup(groupId);
152
+ if (!group)
153
+ return true;
154
+ return group.agents.every((a) => isAgentTerminal(a.state));
155
+ }
156
+ /**
157
+ * Check whether all dependencies are met for a group.
158
+ * Returns 'met' if all dep groups are done_success,
159
+ * 'failed' if any dep group is done_failed or done_timeout,
160
+ * 'pending' if any dep group is still running.
161
+ */
162
+ areDependenciesMet(dependsOn) {
163
+ if (dependsOn.length === 0)
164
+ return 'met';
165
+ for (const depId of dependsOn) {
166
+ const dep = this.getGroup(depId);
167
+ if (!dep)
168
+ return 'failed'; // dep doesn't exist
169
+ if (dep.state === 'done_success')
170
+ continue;
171
+ if (dep.state === 'done_failed' || dep.state === 'done_timeout') {
172
+ return 'failed';
173
+ }
174
+ return 'pending'; // still running
175
+ }
176
+ return 'met';
177
+ }
178
+ /**
179
+ * Check if all agents that completed successfully.
180
+ */
181
+ allAgentsSucceeded(groupId) {
182
+ const group = this.getGroup(groupId);
183
+ if (!group)
184
+ return false;
185
+ return group.agents.every((a) => a.state === 'done_success');
186
+ }
187
+ // -----------------------------------------------------------------------
188
+ // Persistence (JSONL)
189
+ // -----------------------------------------------------------------------
190
+ /**
191
+ * Write the group record to disk as JSONL.
192
+ * Full rewrite (groups are small; simpler than append-only).
193
+ */
194
+ persist(id) {
195
+ const group = this.getGroup(id);
196
+ if (!group)
197
+ return;
198
+ ensureGroupsDir();
199
+ const lines = [];
200
+ // Meta line (group-level state without agent details)
201
+ const meta = {
202
+ type: 'meta',
203
+ id: group.id,
204
+ state: group.state,
205
+ branch: group.branch,
206
+ worktreePath: group.worktreePath,
207
+ baseCwd: group.baseCwd,
208
+ baseCommit: group.baseCommit,
209
+ dependsOn: group.dependsOn,
210
+ groupName: group.groupName,
211
+ createdAt: group.createdAt,
212
+ completedAt: group.completedAt,
213
+ commitSha: group.commitSha,
214
+ error: group.error,
215
+ };
216
+ lines.push(JSON.stringify(meta));
217
+ // Agent lines
218
+ for (const agent of group.agents) {
219
+ const agentLine = {
220
+ type: 'agent',
221
+ alias: agent.alias,
222
+ state: agent.state,
223
+ taskId: agent.taskId,
224
+ prompt: agent.prompt,
225
+ role: agent.role,
226
+ specialization: agent.specialization,
227
+ dependsOn: agent.dependsOn,
228
+ attempts: agent.attempts,
229
+ maxAttempts: agent.maxAttempts,
230
+ error: agent.error,
231
+ startedAt: agent.startedAt,
232
+ completedAt: agent.completedAt,
233
+ pid: agent.pid,
234
+ };
235
+ lines.push(JSON.stringify(agentLine));
236
+ }
237
+ try {
238
+ const filePath = join(GROUPS_DIR, `${group.id}.jsonl`);
239
+ writeFileSync(filePath, lines.join('\n') + '\n', 'utf-8');
240
+ }
241
+ catch {
242
+ // Best-effort persistence
243
+ }
244
+ }
245
+ /**
246
+ * Load all group records from disk on startup.
247
+ */
248
+ loadAll() {
249
+ ensureGroupsDir();
250
+ let files;
251
+ try {
252
+ files = readdirSync(GROUPS_DIR).filter((f) => f.endsWith('.jsonl'));
253
+ }
254
+ catch {
255
+ return;
256
+ }
257
+ for (const file of files) {
258
+ try {
259
+ const content = readFileSync(join(GROUPS_DIR, file), 'utf-8');
260
+ const lines = content.split('\n').filter((l) => l.trim());
261
+ let group = null;
262
+ const agents = [];
263
+ for (const line of lines) {
264
+ try {
265
+ const parsed = JSON.parse(line);
266
+ if (parsed.type === 'meta') {
267
+ group = {
268
+ id: parsed.id,
269
+ state: parsed.state,
270
+ agents: [], // filled below
271
+ branch: parsed.branch,
272
+ worktreePath: parsed.worktreePath,
273
+ baseCwd: parsed.baseCwd,
274
+ baseCommit: parsed.baseCommit ?? '',
275
+ dependsOn: parsed.dependsOn ?? [],
276
+ groupName: parsed.groupName,
277
+ createdAt: parsed.createdAt,
278
+ completedAt: parsed.completedAt,
279
+ commitSha: parsed.commitSha,
280
+ error: parsed.error,
281
+ };
282
+ }
283
+ else if (parsed.type === 'agent') {
284
+ agents.push({
285
+ alias: parsed.alias,
286
+ state: parsed.state,
287
+ taskId: parsed.taskId,
288
+ prompt: parsed.prompt ?? '',
289
+ role: parsed.role,
290
+ specialization: parsed.specialization,
291
+ dependsOn: parsed.dependsOn ?? [],
292
+ attempts: parsed.attempts ?? 0,
293
+ maxAttempts: parsed.maxAttempts ?? DEFAULT_MAX_ATTEMPTS,
294
+ error: parsed.error,
295
+ startedAt: parsed.startedAt,
296
+ completedAt: parsed.completedAt,
297
+ pid: parsed.pid,
298
+ });
299
+ }
300
+ }
301
+ catch {
302
+ // Skip malformed lines
303
+ }
304
+ }
305
+ if (group) {
306
+ group.agents = agents;
307
+ this.groups.set(normalizeTaskId(group.id), group);
308
+ }
309
+ }
310
+ catch {
311
+ // Skip unreadable files
312
+ }
313
+ }
314
+ }
315
+ // -----------------------------------------------------------------------
316
+ // Testing
317
+ // -----------------------------------------------------------------------
318
+ resetForTesting() {
319
+ this.groups.clear();
320
+ groupsDirReady = false;
321
+ }
322
+ // -----------------------------------------------------------------------
323
+ // Private helpers
324
+ // -----------------------------------------------------------------------
325
+ generateUniqueId() {
326
+ let id = generateTaskId();
327
+ let attempts = 0;
328
+ while (this.groups.has(normalizeTaskId(id)) && attempts < 20) {
329
+ id = generateTaskId();
330
+ attempts++;
331
+ }
332
+ if (this.groups.has(normalizeTaskId(id))) {
333
+ id = `group-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
334
+ }
335
+ return id;
336
+ }
337
+ }
338
+ // Module-level singleton
339
+ export const groupRegistry = new GroupRegistry();
340
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/wave/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Async counting semaphore with FIFO fairness for global concurrency control.
3
+ *
4
+ * Module-level singleton shared across all groups.
5
+ * Supports AbortSignal for timeout/shutdown cancellation.
6
+ */
7
+ export declare class AsyncSemaphore {
8
+ private permits;
9
+ readonly maxPermits: number;
10
+ private readonly queue;
11
+ private disposed;
12
+ constructor(maxPermits?: number);
13
+ /**
14
+ * Acquire a permit. Resolves immediately if available,
15
+ * otherwise FIFO-queues until a permit is released.
16
+ *
17
+ * Rejects if:
18
+ * - The semaphore has been disposed
19
+ * - The provided AbortSignal fires while queued
20
+ */
21
+ acquire(signal?: AbortSignal): Promise<void>;
22
+ /**
23
+ * Release a permit. Wakes the oldest queued waiter (FIFO)
24
+ * or increments the available permit count.
25
+ */
26
+ release(): void;
27
+ /**
28
+ * Dispose the semaphore: reject all queued waiters and prevent
29
+ * future acquisitions. Called on server shutdown.
30
+ */
31
+ dispose(): void;
32
+ /** Number of permits currently available. */
33
+ get available(): number;
34
+ /** Number of waiters currently queued. */
35
+ get waiting(): number;
36
+ /** Whether the semaphore has been disposed. */
37
+ get isDisposed(): boolean;
38
+ /** Reset for testing. */
39
+ resetForTesting(): void;
40
+ }
41
+ export declare const concurrencySemaphore: AsyncSemaphore;
42
+ //# sourceMappingURL=semaphore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semaphore.d.ts","sourceRoot":"","sources":["../../src/wave/semaphore.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAS;gBAEb,UAAU,CAAC,EAAE,MAAM;IAK/B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC5C;;;OAGG;IACH,OAAO,IAAI,IAAI;IAef;;;OAGG;IACH,OAAO,IAAI,IAAI;IAYf,6CAA6C;IAC7C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,0CAA0C;IAC1C,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,+CAA+C;IAC/C,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,yBAAyB;IACzB,eAAe,IAAI,IAAI;CAWxB;AAGD,eAAO,MAAM,oBAAoB,gBAAuB,CAAC"}