@gjczone/pi-swarm 0.3.5 → 0.5.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 +33 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/shared/controller.d.ts +10 -4
- package/dist/shared/controller.d.ts.map +1 -1
- package/dist/shared/controller.js +139 -6
- package/dist/shared/controller.js.map +1 -1
- package/dist/shared/render.d.ts +0 -11
- package/dist/shared/render.d.ts.map +1 -1
- package/dist/shared/render.js +3 -36
- package/dist/shared/render.js.map +1 -1
- package/dist/shared/spawner.d.ts.map +1 -1
- package/dist/shared/spawner.js +212 -17
- package/dist/shared/spawner.js.map +1 -1
- package/dist/shared/types.d.ts +58 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/shared/worktree.d.ts +81 -0
- package/dist/shared/worktree.d.ts.map +1 -0
- package/dist/shared/worktree.js +417 -0
- package/dist/shared/worktree.js.map +1 -0
- package/dist/shared/xml.d.ts +18 -0
- package/dist/shared/xml.d.ts.map +1 -0
- package/dist/shared/xml.js +31 -0
- package/dist/shared/xml.js.map +1 -0
- package/dist/swarm/tool.d.ts.map +1 -1
- package/dist/swarm/tool.js +69 -15
- package/dist/swarm/tool.js.map +1 -1
- package/dist/team/mailbox.d.ts +5 -0
- package/dist/team/mailbox.d.ts.map +1 -1
- package/dist/team/mailbox.js +43 -2
- package/dist/team/mailbox.js.map +1 -1
- package/dist/team/supervisor.d.ts +27 -2
- package/dist/team/supervisor.d.ts.map +1 -1
- package/dist/team/supervisor.js +93 -50
- package/dist/team/supervisor.js.map +1 -1
- package/dist/team/task-graph.d.ts +5 -2
- package/dist/team/task-graph.d.ts.map +1 -1
- package/dist/team/task-graph.js +27 -1
- package/dist/team/task-graph.js.map +1 -1
- package/dist/team/tool.d.ts.map +1 -1
- package/dist/team/tool.js +102 -18
- package/dist/team/tool.js.map +1 -1
- package/dist/tui/progress.d.ts +56 -44
- package/dist/tui/progress.d.ts.map +1 -1
- package/dist/tui/progress.js +497 -179
- package/dist/tui/progress.js.map +1 -1
- package/dist/tui/team-dashboard.d.ts +39 -23
- package/dist/tui/team-dashboard.d.ts.map +1 -1
- package/dist/tui/team-dashboard.js +506 -143
- package/dist/tui/team-dashboard.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pi-swarm
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Agent Swarm & Team extension for pi-coding-agent. Run 1 to 128 parallel subagents or collaborative role-based teams — no preset configuration needed.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## What It Does
|
|
8
|
-
|
|
9
|
-
**Swarm** — 1 to 128 parallel agents. Like kimi-code's AgentSwarm: one template, many items, running simultaneously. Also works for single subagent delegation. Each agent is an isolated `pi --print` child process with its own context window.
|
|
10
|
-
|
|
11
|
-
**Team** — collaborative agents. Like Claude Code's agent teams or pi-crew: role-based agents (explorer, planner, coder, reviewer, tester) working in sequence. Each phase agent receives context from previous phases via a shared mailbox. Every agent runs as an independent child process. Optional per-role model tier routing: use a cheaper/faster model for exploration while keeping reasoning-heavy roles on the default model.
|
|
12
|
-
|
|
13
|
-
All agents are created on-the-fly. No `agents/*.md` files. The main agent decides what to spawn based on the task.
|
|
14
|
-
|
|
15
|
-
## Install
|
|
5
|
+
## Installation
|
|
16
6
|
|
|
17
7
|
```bash
|
|
18
8
|
pi install npm:@gjczone/pi-swarm@latest
|
|
19
9
|
```
|
|
20
10
|
|
|
21
|
-
##
|
|
11
|
+
## Core Features
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
| Feature | When to Use | What It Does |
|
|
14
|
+
|---------|-------------|--------------|
|
|
15
|
+
| **AgentSwarm** | Run the same task across many items in parallel | Spawns 1-128 isolated subagents from an item template. Each runs in its own `pi --print` process. |
|
|
16
|
+
| **SwarmTeam** | Execute multi-step workflows with specialized roles | Role-based agents (explorer, planner, coder, reviewer, tester) collaborate in phases with a shared mailbox. Each phase receives context from previous phases. |
|
|
17
|
+
| **/swarm command** | Trigger a swarm from the chat | Shortcut for the AgentSwarm tool. `on` / `off` to toggle swarm mode. |
|
|
18
|
+
| **/swarm-team command** | Trigger a team from the chat | Shortcut for the SwarmTeam tool. |
|
|
19
|
+
| **Worktree Isolation** | Parallel agents modifying the same repo | Each subagent runs in a temporary git worktree. Changes commit to named branches for safe merging. Non-git repos fall back to regular directories. |
|
|
20
|
+
| **Live TUI Progress** | Monitor long-running swarms or teams | Braille progress bars for swarm agents, phase dashboard for teams. Updates in real time. |
|
|
21
|
+
| **Rate-Limit Retry** | Avoid API quota exhaustion | Auto-suspends on rate-limit errors and retries with exponential backoff (3s, 6s, 12s...). |
|
|
22
|
+
| **Crash Recovery** | Survive unexpected termination | Durable file-based state. Resume incomplete runs automatically. Completed runs auto-clean after 7 days. |
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
## Usage Examples
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
Audit src/auth.ts for security issues — use a subagent
|
|
29
|
-
```
|
|
26
|
+
### Swarm — run the same task across many items
|
|
30
27
|
|
|
31
28
|
```
|
|
32
29
|
Review every file in src/ for bugs — use a swarm
|
|
@@ -36,13 +33,7 @@ Review every file in src/ for bugs — use a swarm
|
|
|
36
33
|
Run a security audit on these five packages in parallel: auth, api, db, cache, middleware
|
|
37
34
|
```
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
/swarm Find deprecated API usage across the codebase
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Team — "Plan this, build it, review it"
|
|
36
|
+
### Team — plan, build, and review in phases
|
|
46
37
|
|
|
47
38
|
```
|
|
48
39
|
Implement user login with JWT — use a team with planner, coder, and reviewer
|
|
@@ -52,52 +43,21 @@ Implement user login with JWT — use a team with planner, coder, and reviewer
|
|
|
52
43
|
Add Redis caching — explore the codebase first, then plan, implement, review, test
|
|
53
44
|
```
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```
|
|
58
|
-
/swarm-team Refactor the auth module end-to-end
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Resume Failed Work
|
|
46
|
+
### Resume failed work
|
|
62
47
|
|
|
63
|
-
If agents fail, the LLM
|
|
48
|
+
If agents fail, the LLM receives `resume_agent_ids` and can retry:
|
|
64
49
|
|
|
65
50
|
```
|
|
66
51
|
Two of the five swarm reviews failed — retry those
|
|
67
52
|
```
|
|
68
53
|
|
|
69
|
-
### Cancel
|
|
70
|
-
|
|
71
|
-
Press `Ctrl+C` during a swarm or team run. Completed agents are preserved and results are final (no post-cancellation mutation). In-progress agents are cancelled gracefully and their partial work discarded. For teams, completed phases are saved and returned as partial results. Timeout errors are correctly surfaced instead of being lost in abort/exit races.
|
|
72
|
-
|
|
73
|
-
## Runtime Files
|
|
74
|
-
|
|
75
|
-
State is stored under `.pi/swarm/state/`. The extension auto-creates `.pi/` if it doesn't exist, and auto-appends `.pi/swarm/state/` to the project's `.gitignore`.
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
.pi/swarm/state/runs/{runId}/
|
|
79
|
-
manifest.json # Run metadata, agent IDs, timestamps
|
|
80
|
-
tasks.json # Task graph, per-phase status
|
|
81
|
-
events.jsonl # Append-only event log
|
|
82
|
-
agents/{agentId}/
|
|
83
|
-
status.json # Per-agent status snapshot
|
|
84
|
-
output.log # Full agent session output (header, raw stdout, footer)
|
|
85
|
-
mailbox/ # Team inter-agent messages
|
|
86
|
-
inbox.jsonl
|
|
87
|
-
outbox.jsonl
|
|
88
|
-
delivery.json
|
|
89
|
-
```
|
|
54
|
+
### Cancel mid-run
|
|
90
55
|
|
|
91
|
-
|
|
56
|
+
Press `Ctrl+C` during a swarm or team run. Completed agents are preserved, in-progress agents are cancelled gracefully.
|
|
92
57
|
|
|
93
58
|
## Settings
|
|
94
59
|
|
|
95
|
-
Default max concurrency is **5**.
|
|
96
|
-
|
|
97
|
-
| Settings file | Scope |
|
|
98
|
-
| --------------------------- | --------------------------- |
|
|
99
|
-
| `.pi/settings.json` | Project (current directory) |
|
|
100
|
-
| `~/.pi/agent/settings.json` | Global (all projects) |
|
|
60
|
+
Default max concurrency is **5**. Adjust in `.pi/settings.json` (project) or `~/.pi/agent/settings.json` (global):
|
|
101
61
|
|
|
102
62
|
```json
|
|
103
63
|
{
|
|
@@ -107,13 +67,7 @@ Default max concurrency is **5**. Recommended: **3-10**. Can be set to any posit
|
|
|
107
67
|
}
|
|
108
68
|
```
|
|
109
69
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Lower values (3-5) are safer for API rate limits. Values above 10 work if your provider allows high concurrent requests. No hard upper limit.
|
|
113
|
-
|
|
114
|
-
## Team Model Tier
|
|
115
|
-
|
|
116
|
-
When using `SwarmTeam`, you can configure a lightweight model for exploration roles to reduce costs:
|
|
70
|
+
For team mode, configure a lightweight model for exploration roles to reduce costs:
|
|
117
71
|
|
|
118
72
|
```json
|
|
119
73
|
{
|
|
@@ -123,12 +77,20 @@ When using `SwarmTeam`, you can configure a lightweight model for exploration ro
|
|
|
123
77
|
}
|
|
124
78
|
```
|
|
125
79
|
|
|
126
|
-
|
|
80
|
+
## Supported Platforms
|
|
81
|
+
|
|
82
|
+
| Platform | Status |
|
|
83
|
+
|----------|--------|
|
|
84
|
+
| pi-coding-agent | Required runtime |
|
|
85
|
+
| Node.js >= 18 | Required |
|
|
86
|
+
| Linux / macOS / Windows | Supported |
|
|
127
87
|
|
|
128
88
|
## Credits
|
|
129
89
|
|
|
130
|
-
|
|
90
|
+
Architecture ported from [MoonshotAI/kimi-code](https://github.com/MoonshotAI/kimi-code). Team communication patterns inspired by [pi-crew](https://github.com/baphuongna/pi-crew). Agent team workflow approach inspired by Claude Code.
|
|
131
91
|
|
|
132
92
|
## License
|
|
133
93
|
|
|
134
94
|
[MIT](LICENSE)
|
|
95
|
+
|
|
96
|
+
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AA6FpE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAKxE;AAED,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,GAAG,IAAI,CAuH/C"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { registerSwarmTeamTool } from "./team/tool.js";
|
|
|
14
14
|
import { registerTeamCommand } from "./team/command.js";
|
|
15
15
|
import { recoverRuns } from "./state/recovery.js";
|
|
16
16
|
import { SwarmModeMarkerComponent, } from "./tui/swarm-markers.js";
|
|
17
|
+
import { pruneWorktrees } from "./shared/worktree.js";
|
|
17
18
|
import * as fs from "node:fs";
|
|
18
19
|
import * as path from "node:path";
|
|
19
20
|
// ---------------------------------------------------------------------------
|
|
@@ -141,6 +142,13 @@ export default function (pi) {
|
|
|
141
142
|
swarmMode = null;
|
|
142
143
|
// Ensure .pi/swarm/state/ is gitignored
|
|
143
144
|
ensureGitignore(process.cwd());
|
|
145
|
+
// Best-effort cleanup of orphaned worktrees from previous crashes
|
|
146
|
+
try {
|
|
147
|
+
pruneWorktrees(process.cwd());
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Non-git repos or worktree prune failures are non-fatal
|
|
151
|
+
}
|
|
144
152
|
// Run recovery: detect stale/abandoned runs, clean up expired ones
|
|
145
153
|
try {
|
|
146
154
|
const result = recoverRuns(process.cwd());
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EACL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,wBAAwB,GAEzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAE3C;;;;GAIG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,aAAa,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,wCAAwC;QACxC,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAC5B,GAAG,eAAe,IAAI,EACtB,OAAO,CACR,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,OAAO,CAAC,kBAAkB;QAEjE,iEAAiE;QACjE,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACrD,EAAE,CAAC,cAAc,CACf,aAAa,EACb,GAAG,SAAS,GAAG,eAAe,IAAI,EAClC,OAAO,CACR,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,cAAc;IAChB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,sBAAsB;IACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE7C,2DAA2D;IAC3D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;gBACvD,mFAAmF;gBACnF,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAE9E,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,MAAM,CAAC;IACxE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,OAAO,WAAW,EAAgB;IACvC,kBAAkB;IAElB,IAAI,SAAS,GAA4B,IAAI,CAAC;IAE9C,MAAM,GAAG,GAAG,CAAC,IAAY,EAAQ,EAAE;QACjC,oEAAoE;QACpE,uDAAuD;IACzD,CAAC,CAAC;IAEF,yBAAyB;IAEzB,MAAM,WAAW,GAAqB;QACpC,EAAE;QACF,IAAI,WAAW;YACb,OAAO,SAAS,KAAK,IAAI,CAAC;QAC5B,CAAC;QACD,cAAc,CAAC,MAAe,EAAE,QAAoC;YAClE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,mBAAmB,CAAC,MAAc;YAChC,EAAE,CAAC,WAAW,CAAC;gBACb,UAAU,EAAE,kBAAkB;gBAC9B,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;QACL,CAAC;QACD,UAAU,CAAC,OAAe;YACxB,GAAG,CAAC,OAAO,CAAC,CAAC;QACf,CAAC;QACD,SAAS,CAAC,OAAe;YACvB,OAAO,CAAC,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,QAAQ;YACN,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC;gBACpC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;KACF,CAAC;IAEF,4BAA4B;IAE5B,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAChC,SAAS,GAAG,IAAI,CAAC;QAEjB,wCAAwC;QACxC,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAE/B,kEAAkE;QAClE,IAAI,CAAC;YACH,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;QAC3D,CAAC;QAED,mEAAmE;QACnE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1C,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,GAAG,CAAC,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,2BAA2B,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,GAAG,CAAC,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,6BAA6B,CAAC,CAAC;YACzE,CAAC;YACD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,GAAG,CACD,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,+BAA+B,CACpE,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,+BAA+B,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE;QAC5B,sDAAsD;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QACnC,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,4EAA4E;IAE5E,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACvB,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa;YAAE,OAAO;QAC3C,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QAC1B,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,CAAC,iBAAiB;QAEjD,SAAS,GAAG,IAAI,CAAC;QACjB,GAAG,CAAC,uCAAuC,IAAI,IAAI,CAAC,CAAC;QACrD,EAAE,CAAC,WAAW,EAAE,CAAC;YACf,UAAU,EAAE,cAAc;YAC1B,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,wCAAwC;IAExC,8DAA8D;IAC9D,mEAAmE;IACnE,yDAAyD;IACzD,iDAAiD;IACjD,cAAc;IACd,EAAE,CAAC,uBAAuB,CAAU,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE;QAC9D,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO,IAAI,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC3B,oBAAoB,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACtC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAC1B,mBAAmB,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACvC,CAAC;AAED,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,mEAAmE;AACnE,SAAS,kBAAkB,CAAC,OAAe;IACzC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -35,8 +35,12 @@ export declare class SubagentBatchController<T> {
|
|
|
35
35
|
private reject;
|
|
36
36
|
private finished;
|
|
37
37
|
private started;
|
|
38
|
+
private startedAt;
|
|
38
39
|
private startedSuccessCount;
|
|
39
40
|
private readonly onProgress?;
|
|
41
|
+
private eventLog;
|
|
42
|
+
private nextEventId;
|
|
43
|
+
private completionTimesMs;
|
|
40
44
|
constructor(launcher: SubagentBatchLauncher, tasks: readonly QueuedSubagentTask<T>[], options?: SubagentBatchOptions);
|
|
41
45
|
/**
|
|
42
46
|
* Run the batch. Returns a promise that resolves when all tasks
|
|
@@ -59,6 +63,8 @@ export declare class SubagentBatchController<T> {
|
|
|
59
63
|
private recoverRateLimitCapacity;
|
|
60
64
|
private finishIfComplete;
|
|
61
65
|
private emitProgress;
|
|
66
|
+
/** Add an event to the event log, keeping it bounded. */
|
|
67
|
+
private addEvent;
|
|
62
68
|
private finish;
|
|
63
69
|
private finishWithUserCancellation;
|
|
64
70
|
private fail;
|
|
@@ -81,9 +87,9 @@ export declare class SubagentBatchController<T> {
|
|
|
81
87
|
* 2. `~/.pi/agent/settings.json` → `pi-swarm.maxConcurrency` (global)
|
|
82
88
|
* 3. `PI_SWARM_MAX_CONCURRENCY` env var
|
|
83
89
|
*
|
|
84
|
-
*
|
|
85
|
-
* integer; invalid input throws so a
|
|
86
|
-
* reverts to uncapped.
|
|
90
|
+
* Falls back to DEFAULT_MAX_CONCURRENCY (5) when unset. A present
|
|
91
|
+
* value must be a positive integer; invalid input throws so a
|
|
92
|
+
* misconfigured cap never silently reverts to uncapped.
|
|
87
93
|
*/
|
|
88
|
-
export declare function resolveSwarmMaxConcurrency(cwd?: string): number
|
|
94
|
+
export declare function resolveSwarmMaxConcurrency(cwd?: string): number;
|
|
89
95
|
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/shared/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/shared/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EAUtB,MAAM,YAAY,CAAC;AA+FpB,qBAAa,uBAAuB,CAAC,CAAC;IAyClC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAxC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,YAAY,CAAS;IAG7B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,iBAAiB,CAA4C;IAGrE,OAAO,CAAC,oBAAoB,CAA4C;IACxE,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,oBAAoB,CAAqB;IACjD,OAAO,CAAC,sBAAsB,CAAqB;IACnD,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,qBAAqB,CAAK;IAGlC,OAAO,CAAC,OAAO,CAA4D;IAC3E,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA4C;IAGxE,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAK;IAGxB,OAAO,CAAC,iBAAiB,CAAgB;gBAGtB,QAAQ,EAAE,qBAAqB,EAChD,KAAK,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC,EAAE,EACvC,OAAO,GAAE,oBAAyB;IAqCpC;;;OAGG;IACH,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAoCxC,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,oBAAoB;IAwC5B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,uBAAuB;IA2C/B,OAAO,CAAC,YAAY;YAyCN,UAAU;IAoHxB,OAAO,CAAC,oBAAoB;IAoB5B,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,oBAAoB;IAoC5B,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;IA8FpB,yDAAyD;IACzD,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,0BAA0B;IAoClC,OAAO,CAAC,IAAI;IAsBZ,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,uBAAuB;IAQ/B,OAAO,CAAC,2BAA2B;IAkBnC,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,+BAA+B;IAQvC,OAAO,CAAC,kBAAkB;CAsC3B;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CA4B/D"}
|
|
@@ -23,6 +23,7 @@ const RATE_LIMIT_CAPACITY_SHRINK_INTERVAL_MS = 2000;
|
|
|
23
23
|
const RATE_LIMIT_CAPACITY_RECOVERY_INTERVAL_MS = 3 * 60 * 1000; // 3 minutes
|
|
24
24
|
const AGENT_SWARM_MAX_CONCURRENCY_ENV = "PI_SWARM_MAX_CONCURRENCY";
|
|
25
25
|
const DEFAULT_MAX_CONCURRENCY = 5;
|
|
26
|
+
const RATE_LIMIT_SUSPENDED_REASON = "Rate limit reached — agent suspended";
|
|
26
27
|
// ---------------------------------------------------------------------------
|
|
27
28
|
// Abort helpers
|
|
28
29
|
// ---------------------------------------------------------------------------
|
|
@@ -88,8 +89,14 @@ export class SubagentBatchController {
|
|
|
88
89
|
reject;
|
|
89
90
|
finished = false;
|
|
90
91
|
started = false;
|
|
92
|
+
startedAt = 0;
|
|
91
93
|
startedSuccessCount = 0;
|
|
92
94
|
onProgress;
|
|
95
|
+
// Event log
|
|
96
|
+
eventLog = [];
|
|
97
|
+
nextEventId = 1;
|
|
98
|
+
// ETA tracking: track completion timestamps for average calculation
|
|
99
|
+
completionTimesMs = [];
|
|
93
100
|
constructor(launcher, tasks, options = {}) {
|
|
94
101
|
this.launcher = launcher;
|
|
95
102
|
this.maxConcurrency = options.maxConcurrency;
|
|
@@ -100,6 +107,13 @@ export class SubagentBatchController {
|
|
|
100
107
|
retryCount: 0,
|
|
101
108
|
retryReadyAt: 0,
|
|
102
109
|
started: false,
|
|
110
|
+
usage: {
|
|
111
|
+
input: 0,
|
|
112
|
+
output: 0,
|
|
113
|
+
cacheRead: 0,
|
|
114
|
+
cacheWrite: 0,
|
|
115
|
+
totalTokens: 0,
|
|
116
|
+
},
|
|
103
117
|
}));
|
|
104
118
|
this.pending = [...this.states];
|
|
105
119
|
this.results = Array.from({
|
|
@@ -126,6 +140,7 @@ export class SubagentBatchController {
|
|
|
126
140
|
throw new Error("SubagentBatchController.run() can only be called once.");
|
|
127
141
|
}
|
|
128
142
|
this.started = true;
|
|
143
|
+
this.startedAt = Date.now();
|
|
129
144
|
return new Promise((resolve, reject) => {
|
|
130
145
|
this.resolve = resolve;
|
|
131
146
|
this.reject = reject;
|
|
@@ -262,6 +277,21 @@ export class SubagentBatchController {
|
|
|
262
277
|
attempt.cleanup = this.linkAttemptSignals(attempt, state.task);
|
|
263
278
|
this.active.add(attempt);
|
|
264
279
|
attempt.state.started = true;
|
|
280
|
+
attempt.state.startedAt = Date.now();
|
|
281
|
+
// Add event to log
|
|
282
|
+
this.addEvent({
|
|
283
|
+
id: this.nextEventId++,
|
|
284
|
+
agentId: undefined,
|
|
285
|
+
timestamp: Date.now(),
|
|
286
|
+
type: "started",
|
|
287
|
+
detail: state.task.swarmItem
|
|
288
|
+
? `Started: ${state.task.swarmItem.slice(0, 60)}`
|
|
289
|
+
: `Started task ${state.index + 1}`,
|
|
290
|
+
});
|
|
291
|
+
// Trim event log to last 50 entries
|
|
292
|
+
if (this.eventLog.length > 50) {
|
|
293
|
+
this.eventLog = this.eventLog.slice(-50);
|
|
294
|
+
}
|
|
265
295
|
// A task transitioned from queued to working
|
|
266
296
|
this.emitProgress();
|
|
267
297
|
this.runAttempt(attempt).then((outcome) => {
|
|
@@ -283,6 +313,16 @@ export class SubagentBatchController {
|
|
|
283
313
|
onReady: () => {
|
|
284
314
|
this.markAttemptReady(attempt);
|
|
285
315
|
},
|
|
316
|
+
onUsage: (usage) => {
|
|
317
|
+
attempt.state.usage = { ...usage };
|
|
318
|
+
this.emitProgress();
|
|
319
|
+
},
|
|
320
|
+
onActivity: (tool, activity) => {
|
|
321
|
+
attempt.state.currentTool = tool;
|
|
322
|
+
attempt.state.activity = activity;
|
|
323
|
+
this.emitProgress();
|
|
324
|
+
},
|
|
325
|
+
onMessage: task.onMessage,
|
|
286
326
|
suppressRateLimitFailureEvent: true,
|
|
287
327
|
timeout: task.timeout,
|
|
288
328
|
swarmRoot: task.swarmRoot,
|
|
@@ -291,6 +331,9 @@ export class SubagentBatchController {
|
|
|
291
331
|
model: task.model,
|
|
292
332
|
tools: task.tools,
|
|
293
333
|
cwd: task.cwd,
|
|
334
|
+
useWorktree: task.useWorktree,
|
|
335
|
+
mailboxPath: task.mailboxPath,
|
|
336
|
+
roleName: task.roleName,
|
|
294
337
|
};
|
|
295
338
|
let handle;
|
|
296
339
|
try {
|
|
@@ -308,6 +351,10 @@ export class SubagentBatchController {
|
|
|
308
351
|
model: task.model,
|
|
309
352
|
tools: task.tools,
|
|
310
353
|
cwd: task.cwd,
|
|
354
|
+
useWorktree: task.useWorktree,
|
|
355
|
+
mailboxPath: task.mailboxPath,
|
|
356
|
+
roleName: task.roleName,
|
|
357
|
+
onMessage: task.onMessage,
|
|
311
358
|
...runOptions,
|
|
312
359
|
};
|
|
313
360
|
handle = await this.launcher.spawn(spawnOptions);
|
|
@@ -319,11 +366,31 @@ export class SubagentBatchController {
|
|
|
319
366
|
attempt.state.agentId = handle.agentId;
|
|
320
367
|
try {
|
|
321
368
|
const completion = await handle.completion;
|
|
369
|
+
if (completion.usage) {
|
|
370
|
+
attempt.state.usage = { ...completion.usage };
|
|
371
|
+
}
|
|
372
|
+
const completedAt = Date.now();
|
|
373
|
+
attempt.state.completedAt = completedAt;
|
|
374
|
+
if (attempt.state.startedAt) {
|
|
375
|
+
this.completionTimesMs.push(completedAt - attempt.state.startedAt);
|
|
376
|
+
}
|
|
377
|
+
// Add event to log
|
|
378
|
+
this.addEvent({
|
|
379
|
+
id: this.nextEventId++,
|
|
380
|
+
agentId: handle.agentId,
|
|
381
|
+
timestamp: completedAt,
|
|
382
|
+
type: "completed",
|
|
383
|
+
detail: attempt.state.task.swarmItem
|
|
384
|
+
? `Agent completed: ${attempt.state.task.swarmItem.slice(0, 60)}`
|
|
385
|
+
: `Agent completed`,
|
|
386
|
+
});
|
|
322
387
|
return {
|
|
323
388
|
task,
|
|
324
389
|
agentId: handle.agentId,
|
|
325
390
|
status: "completed",
|
|
326
391
|
result: completion.result,
|
|
392
|
+
usage: attempt.state.usage,
|
|
393
|
+
worktreeBranch: completion.worktreeBranch,
|
|
327
394
|
};
|
|
328
395
|
}
|
|
329
396
|
catch (error) {
|
|
@@ -382,6 +449,13 @@ export class SubagentBatchController {
|
|
|
382
449
|
// Save agent id for retry and requeue at front
|
|
383
450
|
state.retryAgentId = state.agentId ?? state.retryAgentId;
|
|
384
451
|
state.retryCount += 1;
|
|
452
|
+
// Notify external listeners that this agent was suspended
|
|
453
|
+
if (state.agentId) {
|
|
454
|
+
this.launcher.suspended?.({
|
|
455
|
+
agentId: state.agentId,
|
|
456
|
+
reason: RATE_LIMIT_SUSPENDED_REASON,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
385
459
|
// Exponential backoff
|
|
386
460
|
const delay = RATE_LIMIT_RETRY_BASE_MS *
|
|
387
461
|
Math.pow(RATE_LIMIT_RETRY_FACTOR, state.retryCount - 1);
|
|
@@ -419,6 +493,7 @@ export class SubagentBatchController {
|
|
|
419
493
|
status,
|
|
420
494
|
state: attempt.state.started ? "started" : "not_started",
|
|
421
495
|
error: errorMessage,
|
|
496
|
+
usage: { ...attempt.state.usage },
|
|
422
497
|
};
|
|
423
498
|
}
|
|
424
499
|
// -----------------------------------------------------------------------
|
|
@@ -427,7 +502,10 @@ export class SubagentBatchController {
|
|
|
427
502
|
enterRateLimitPhase() {
|
|
428
503
|
this.rateLimitMode = true;
|
|
429
504
|
this.clearNormalTimer();
|
|
430
|
-
|
|
505
|
+
// Use startedSuccessCount (count of agents that fully booted during
|
|
506
|
+
// the normal phase) so capacity reflects true past throughput rather
|
|
507
|
+
// than only currently-active attempts (which may already be finishing).
|
|
508
|
+
this.rateLimitCapacity = Math.max(1, this.startedSuccessCount);
|
|
431
509
|
this.lastRateLimitAt = Date.now();
|
|
432
510
|
this.globalRetryIntervalMs = RATE_LIMIT_RETRY_BASE_MS;
|
|
433
511
|
this.nextRateLimitLaunchAt = Date.now() + RATE_LIMIT_RETRY_BASE_MS;
|
|
@@ -470,6 +548,13 @@ export class SubagentBatchController {
|
|
|
470
548
|
let completed = 0;
|
|
471
549
|
let failed = 0;
|
|
472
550
|
let active = 0;
|
|
551
|
+
const totalUsage = {
|
|
552
|
+
input: 0,
|
|
553
|
+
output: 0,
|
|
554
|
+
cacheRead: 0,
|
|
555
|
+
cacheWrite: 0,
|
|
556
|
+
totalTokens: 0,
|
|
557
|
+
};
|
|
473
558
|
const members = [];
|
|
474
559
|
const activeIndices = new Set(Array.from(this.active, (a) => a.state.index));
|
|
475
560
|
for (const state of this.states) {
|
|
@@ -477,6 +562,15 @@ export class SubagentBatchController {
|
|
|
477
562
|
const isActiveState = activeIndices.has(state.index);
|
|
478
563
|
let phase = "queued";
|
|
479
564
|
let error;
|
|
565
|
+
// Accumulate usage from live state or completed result
|
|
566
|
+
const memberUsage = result?.usage ?? state.usage;
|
|
567
|
+
if (memberUsage) {
|
|
568
|
+
totalUsage.input += memberUsage.input;
|
|
569
|
+
totalUsage.output += memberUsage.output;
|
|
570
|
+
totalUsage.cacheRead += memberUsage.cacheRead;
|
|
571
|
+
totalUsage.cacheWrite += memberUsage.cacheWrite;
|
|
572
|
+
totalUsage.totalTokens += memberUsage.totalTokens;
|
|
573
|
+
}
|
|
480
574
|
if (result) {
|
|
481
575
|
if (result.status === "completed") {
|
|
482
576
|
phase = "completed";
|
|
@@ -500,9 +594,25 @@ export class SubagentBatchController {
|
|
|
500
594
|
phase,
|
|
501
595
|
item: state.task.swarmItem,
|
|
502
596
|
error,
|
|
597
|
+
usage: memberUsage,
|
|
598
|
+
currentTool: state.currentTool,
|
|
599
|
+
activity: state.activity,
|
|
503
600
|
});
|
|
504
601
|
}
|
|
505
602
|
const queued = this.states.length - completed - failed - active;
|
|
603
|
+
// Calculate ETA based on average completion time
|
|
604
|
+
let estimatedRemainingMs;
|
|
605
|
+
const totalFinished = completed + failed;
|
|
606
|
+
const totalRemaining = queued + active;
|
|
607
|
+
if (totalFinished > 0 && totalRemaining > 0) {
|
|
608
|
+
const avgTimeMs = this.completionTimesMs.length > 0
|
|
609
|
+
? this.completionTimesMs.reduce((a, b) => a + b, 0) /
|
|
610
|
+
this.completionTimesMs.length
|
|
611
|
+
: 0;
|
|
612
|
+
if (avgTimeMs > 0) {
|
|
613
|
+
estimatedRemainingMs = avgTimeMs * totalRemaining;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
506
616
|
this.onProgress({
|
|
507
617
|
total: this.states.length,
|
|
508
618
|
completed,
|
|
@@ -510,8 +620,20 @@ export class SubagentBatchController {
|
|
|
510
620
|
active,
|
|
511
621
|
queued,
|
|
512
622
|
members,
|
|
623
|
+
totalUsage,
|
|
624
|
+
startedAt: this.startedAt,
|
|
625
|
+
estimatedRemainingMs,
|
|
626
|
+
eventLog: [...this.eventLog],
|
|
513
627
|
});
|
|
514
628
|
}
|
|
629
|
+
/** Add an event to the event log, keeping it bounded. */
|
|
630
|
+
addEvent(event) {
|
|
631
|
+
this.eventLog.push(event);
|
|
632
|
+
// Keep max 100 events
|
|
633
|
+
if (this.eventLog.length > 100) {
|
|
634
|
+
this.eventLog = this.eventLog.slice(-100);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
515
637
|
finish(results) {
|
|
516
638
|
if (this.finished)
|
|
517
639
|
return;
|
|
@@ -609,6 +731,17 @@ export class SubagentBatchController {
|
|
|
609
731
|
return;
|
|
610
732
|
attempt.ready = true;
|
|
611
733
|
this.startedSuccessCount += 1;
|
|
734
|
+
// If we are in rate-limit mode, reset the global retry interval
|
|
735
|
+
// so the next launch uses the base delay rather than an accumulated
|
|
736
|
+
// exponential backoff, and re-arm the scheduler immediately.
|
|
737
|
+
if (this.rateLimitMode) {
|
|
738
|
+
this.globalRetryIntervalMs = RATE_LIMIT_RETRY_BASE_MS;
|
|
739
|
+
this.nextRateLimitLaunchAt = Date.now() + this.globalRetryIntervalMs;
|
|
740
|
+
// Clear any pending rate-limit timer so schedule() re-computes
|
|
741
|
+
// the next wakeup from the new (shorter) interval.
|
|
742
|
+
this.clearRateLimitTimer();
|
|
743
|
+
this.schedule();
|
|
744
|
+
}
|
|
612
745
|
}
|
|
613
746
|
countReadyActive() {
|
|
614
747
|
let count = 0;
|
|
@@ -682,9 +815,9 @@ export class SubagentBatchController {
|
|
|
682
815
|
* 2. `~/.pi/agent/settings.json` → `pi-swarm.maxConcurrency` (global)
|
|
683
816
|
* 3. `PI_SWARM_MAX_CONCURRENCY` env var
|
|
684
817
|
*
|
|
685
|
-
*
|
|
686
|
-
* integer; invalid input throws so a
|
|
687
|
-
* reverts to uncapped.
|
|
818
|
+
* Falls back to DEFAULT_MAX_CONCURRENCY (5) when unset. A present
|
|
819
|
+
* value must be a positive integer; invalid input throws so a
|
|
820
|
+
* misconfigured cap never silently reverts to uncapped.
|
|
688
821
|
*/
|
|
689
822
|
export function resolveSwarmMaxConcurrency(cwd) {
|
|
690
823
|
// 1. Project-local settings
|
|
@@ -705,12 +838,12 @@ export function resolveSwarmMaxConcurrency(cwd) {
|
|
|
705
838
|
if (raw !== undefined && raw.trim() !== "") {
|
|
706
839
|
return validateConcurrency(Number(raw), AGENT_SWARM_MAX_CONCURRENCY_ENV);
|
|
707
840
|
}
|
|
708
|
-
// 4. Default
|
|
841
|
+
// 4. Default (always reached — value guaranteed)
|
|
709
842
|
return DEFAULT_MAX_CONCURRENCY;
|
|
710
843
|
}
|
|
711
844
|
function validateConcurrency(value, source) {
|
|
712
845
|
if (value === undefined || value === null)
|
|
713
|
-
return
|
|
846
|
+
return DEFAULT_MAX_CONCURRENCY;
|
|
714
847
|
const num = Number(value);
|
|
715
848
|
if (!Number.isInteger(num) || num <= 0) {
|
|
716
849
|
throw new Error(`pi-swarm.maxConcurrency in ${source} must be a positive integer, got ${JSON.stringify(value)}.`);
|