@ra3orblade/swarm 0.13.1 → 0.14.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/dist/swarm-hook.js +687 -166
- package/dist/swarm-mcp.js +996 -1377
- package/dist/swarm.js +758 -286
- package/dist/swarmd.js +2610 -907
- package/package.json +1 -1
- package/web/dashboard.css +1 -1
- package/web/dashboard.js +18 -18
- package/web/menus.js +7 -7
- package/web/release-notes.js +1 -1
package/dist/swarm.js
CHANGED
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// packages/client/src/daemon.ts
|
|
16
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
17
|
-
import { homedir } from "os";
|
|
18
|
-
import { join } from "path";
|
|
3
|
+
var __esm = (fn, res, err) => () => {
|
|
4
|
+
if (fn)
|
|
5
|
+
try {
|
|
6
|
+
res = fn(fn = 0);
|
|
7
|
+
} catch (e) {
|
|
8
|
+
err = [e];
|
|
9
|
+
}
|
|
10
|
+
if (err)
|
|
11
|
+
throw err[0];
|
|
12
|
+
return res;
|
|
13
|
+
};
|
|
19
14
|
|
|
20
15
|
// packages/client/src/bins.ts
|
|
21
16
|
import { existsSync } from "fs";
|
|
22
17
|
import { dirname, resolve } from "path";
|
|
23
18
|
import { fileURLToPath } from "url";
|
|
24
|
-
var SRC = {
|
|
25
|
-
swarm: "cli",
|
|
26
|
-
swarmd: "daemon",
|
|
27
|
-
"swarm-hook": "hook",
|
|
28
|
-
"swarm-mcp": "mcp"
|
|
29
|
-
};
|
|
30
19
|
function resolveBin(name, from = import.meta.url) {
|
|
31
20
|
const here = dirname(fileURLToPath(from));
|
|
32
21
|
const candidates = [
|
|
@@ -41,13 +30,24 @@ function resolveBin(name, from = import.meta.url) {
|
|
|
41
30
|
function binCommand(name, from) {
|
|
42
31
|
return resolveBin(name, from).map((p) => /[\s"']/.test(p) ? JSON.stringify(p) : p).join(" ");
|
|
43
32
|
}
|
|
33
|
+
var SRC;
|
|
34
|
+
var init_bins = __esm(() => {
|
|
35
|
+
SRC = {
|
|
36
|
+
swarm: "cli",
|
|
37
|
+
swarmd: "daemon",
|
|
38
|
+
"swarm-hook": "hook",
|
|
39
|
+
"swarm-mcp": "mcp",
|
|
40
|
+
"swarm-teamd": "team"
|
|
41
|
+
};
|
|
42
|
+
});
|
|
44
43
|
|
|
45
44
|
// packages/client/src/daemon.ts
|
|
45
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
46
|
+
import { homedir } from "os";
|
|
47
|
+
import { join } from "path";
|
|
46
48
|
function swarmHome() {
|
|
47
49
|
return process.env.SWARM_HOME ?? join(homedir(), ".swarm");
|
|
48
50
|
}
|
|
49
|
-
var DEFAULT_PORT = Number(process.env.SWARM_PORT ?? 7777);
|
|
50
|
-
var infoFile = () => join(swarmHome(), "daemon.json");
|
|
51
51
|
function readDaemonInfo() {
|
|
52
52
|
const file = infoFile();
|
|
53
53
|
if (!existsSync2(file))
|
|
@@ -58,7 +58,6 @@ function readDaemonInfo() {
|
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
var tokenFile = (home = swarmHome()) => join(home, "token");
|
|
62
61
|
function readToken(home = swarmHome()) {
|
|
63
62
|
try {
|
|
64
63
|
const t = readFileSync(tokenFile(home), "utf8").trim();
|
|
@@ -67,13 +66,6 @@ function readToken(home = swarmHome()) {
|
|
|
67
66
|
return null;
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
|
-
var authedFetch = (input, init) => {
|
|
71
|
-
const h = new Headers(init?.headers);
|
|
72
|
-
const t = readToken();
|
|
73
|
-
if (t && !h.has("authorization"))
|
|
74
|
-
h.set("authorization", `Bearer ${t}`);
|
|
75
|
-
return fetch(input, { ...init, headers: h });
|
|
76
|
-
};
|
|
77
69
|
function alive(pid) {
|
|
78
70
|
try {
|
|
79
71
|
process.kill(pid, 0);
|
|
@@ -125,6 +117,17 @@ async function ensureDaemon(opts = {}) {
|
|
|
125
117
|
}
|
|
126
118
|
throw new Error("swarmd did not become healthy within 5s");
|
|
127
119
|
}
|
|
120
|
+
var DEFAULT_PORT, infoFile = () => join(swarmHome(), "daemon.json"), tokenFile = (home = swarmHome()) => join(home, "token"), authedFetch = (input, init) => {
|
|
121
|
+
const h = new Headers(init?.headers);
|
|
122
|
+
const t = readToken();
|
|
123
|
+
if (t && !h.has("authorization"))
|
|
124
|
+
h.set("authorization", `Bearer ${t}`);
|
|
125
|
+
return fetch(input, { ...init, headers: h });
|
|
126
|
+
};
|
|
127
|
+
var init_daemon = __esm(() => {
|
|
128
|
+
init_bins();
|
|
129
|
+
DEFAULT_PORT = Number(process.env.SWARM_PORT ?? 7777);
|
|
130
|
+
});
|
|
128
131
|
|
|
129
132
|
// packages/client/src/index.ts
|
|
130
133
|
class SwarmClient {
|
|
@@ -150,164 +153,218 @@ class SwarmClient {
|
|
|
150
153
|
throw new Error(`swarmd: ${r.status}`);
|
|
151
154
|
}
|
|
152
155
|
}
|
|
156
|
+
var init_src = __esm(() => {
|
|
157
|
+
init_daemon();
|
|
158
|
+
init_bins();
|
|
159
|
+
init_daemon();
|
|
160
|
+
});
|
|
153
161
|
// packages/core/src/actor.ts
|
|
154
|
-
var HUMAN_ALIASES
|
|
155
|
-
var
|
|
162
|
+
var HUMAN_ALIASES, DAEMON_ALIASES;
|
|
163
|
+
var init_actor = __esm(() => {
|
|
164
|
+
HUMAN_ALIASES = new Set(["cli", "dashboard", "me", "desktop", "human"]);
|
|
165
|
+
DAEMON_ALIASES = new Set(["daemon", "system", "swarm"]);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// packages/core/src/adapters/aider/history.ts
|
|
169
|
+
var init_history = () => {};
|
|
170
|
+
// packages/core/src/adapters/claude-code/adapter.ts
|
|
171
|
+
var init_adapter = () => {};
|
|
172
|
+
|
|
173
|
+
// packages/core/src/adapters/codex/rollout.ts
|
|
174
|
+
var init_rollout = () => {};
|
|
175
|
+
|
|
176
|
+
// packages/core/src/adapters/gemini/chats.ts
|
|
177
|
+
var init_chats = () => {};
|
|
178
|
+
|
|
179
|
+
// packages/core/src/adapters/grok/updates.ts
|
|
180
|
+
var init_updates = () => {};
|
|
181
|
+
|
|
182
|
+
// packages/core/src/adapters/opencode/db.ts
|
|
183
|
+
var init_db = () => {};
|
|
184
|
+
// packages/core/src/adapters/index.ts
|
|
185
|
+
var init_adapters = __esm(() => {
|
|
186
|
+
init_history();
|
|
187
|
+
init_adapter();
|
|
188
|
+
init_rollout();
|
|
189
|
+
init_chats();
|
|
190
|
+
init_updates();
|
|
191
|
+
init_db();
|
|
192
|
+
init_history();
|
|
193
|
+
init_adapter();
|
|
194
|
+
init_rollout();
|
|
195
|
+
init_chats();
|
|
196
|
+
init_updates();
|
|
197
|
+
init_db();
|
|
198
|
+
});
|
|
199
|
+
|
|
156
200
|
// packages/core/src/adapters/claude-code/hooks.ts
|
|
157
|
-
var HOOK_EVENTS
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
201
|
+
var HOOK_EVENTS;
|
|
202
|
+
var init_hooks = __esm(() => {
|
|
203
|
+
HOOK_EVENTS = [
|
|
204
|
+
"SessionStart",
|
|
205
|
+
"UserPromptSubmit",
|
|
206
|
+
"PreToolUse",
|
|
207
|
+
"PostToolUse",
|
|
208
|
+
"SubagentStart",
|
|
209
|
+
"SubagentStop",
|
|
210
|
+
"Stop",
|
|
211
|
+
"SessionEnd",
|
|
212
|
+
"Notification",
|
|
213
|
+
"PreCompact",
|
|
214
|
+
"PermissionRequest"
|
|
215
|
+
];
|
|
216
|
+
});
|
|
217
|
+
|
|
169
218
|
// packages/core/src/art.ts
|
|
170
|
-
var ROBOT
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
219
|
+
var ROBOT, HEAD;
|
|
220
|
+
var init_art = __esm(() => {
|
|
221
|
+
ROBOT = [
|
|
222
|
+
" MM MM ",
|
|
223
|
+
" LL LL ",
|
|
224
|
+
" LL LL ",
|
|
225
|
+
" LM MM ",
|
|
226
|
+
" MD MS ",
|
|
227
|
+
" LE LE ",
|
|
228
|
+
" ME ME ",
|
|
229
|
+
" MS MS ",
|
|
230
|
+
" KK KK ",
|
|
231
|
+
" SSDDDSDDDDDDDDDDDDDDDDDDDDDDDDDDDDS ",
|
|
232
|
+
" SSDSDDDDDDDDDDDDDDDDDDDDDDDDDDDDDSS ",
|
|
233
|
+
" SSDOOOOOOOOOOOOOOOOOOOOOOOOOOOOOKSS ",
|
|
234
|
+
" SSOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOSS ",
|
|
235
|
+
" DDKMMLLLMLLMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
236
|
+
" DDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
237
|
+
" SSSSODDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSSSS ",
|
|
238
|
+
" SSSSODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSSSS ",
|
|
239
|
+
" SMMMMODDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSMMMS ",
|
|
240
|
+
" DMSSSODDOMMMMOOOOOOMMMMMMMMMOOOOOOMMMMODDOSSSED ",
|
|
241
|
+
" DSSSSODDOMMMMODDDDDMMMMMMMMMODDDDDMMMMODDOSSSSK ",
|
|
242
|
+
" DSMMSODDOMMMMDDDDDDMMMMMMMMMKDDDDDMMMMODDOSMMSK ",
|
|
243
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDOSSSSK ",
|
|
244
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSK ",
|
|
245
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSK ",
|
|
246
|
+
" DSSSKODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSD ",
|
|
247
|
+
" OKKKKODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOKKKKO ",
|
|
248
|
+
" KKKKODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOOKKK ",
|
|
249
|
+
" KKKOODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOOKKK ",
|
|
250
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
251
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
252
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
253
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
254
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
255
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
256
|
+
" DDDOOOOOOOOOOOOOOOOOOOOOOOOOOOOOKDD ",
|
|
257
|
+
" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDKDDDDD ",
|
|
258
|
+
" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ",
|
|
259
|
+
" OOOOOOOOOOO ",
|
|
260
|
+
" OODDDDDKKOO ",
|
|
261
|
+
" DSMMMMMMSDD ",
|
|
262
|
+
" OOOOOOOOOOO ",
|
|
263
|
+
" KDSMMMMMESSKK ",
|
|
264
|
+
" MMMMMMSSKOOKDSMMMMMSSSDKOODSEMMMMMM ",
|
|
265
|
+
" SSSSDO MMMMMMSSKKOOOOOOOOOOOOOOOOOKSSSMMMMMM ODSSSS ",
|
|
266
|
+
" EEESSSSOOLLLLMMMMMESSSSSSSSSSSSSSSSSSSSMMMMMLLLLOOSSSSMME ",
|
|
267
|
+
" SMMSSSSKOEELLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLEEOOSSSSEMS ",
|
|
268
|
+
" DSSSSSSSOOSEEKSMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMSOEEDOOSSSSSSSK ",
|
|
269
|
+
" DSSSSSSDOOSEOSKEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMEOSDEDOODSSSSSSK ",
|
|
270
|
+
" KSSSSSSKOODSSOSEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEESOEEDOOKSSSSSSK ",
|
|
271
|
+
" DKSSSSKKOODSMEEMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMSEMSDOOKKSSSSDK ",
|
|
272
|
+
" OKDDKDKKOOKSMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMSKOOKKKKKKKO ",
|
|
273
|
+
" OOOOOKKKOOKSMMMMESSSSSSSSSSSSSMMMMEEEEEESSSSEMMMMSKOOKKKOOOOO ",
|
|
274
|
+
" OOOOOOKKOOKSMMMSSKKKKKKKKKKKKKKMMMDKOOOOOOOODDMMMSKOOKKOOOOOO ",
|
|
275
|
+
" OKSSKOOOOOKSMMMKKMLLLLLLLLLLLMKMMMDDSSSSSSSSDDMMMSKOOOOODSSKO ",
|
|
276
|
+
" SDOKKK KSMMMKDLLLLLLLLLLLLLKMMMKDKKKDDKKKDKMMMSK KKKKDS ",
|
|
277
|
+
" DMLLMKO KSMMMKDLLLLLLLLLLLLLKMMMDDDDDDDDDSKDMMMSK ODMLLMD ",
|
|
278
|
+
" DELLMSD KSMMMKKMLLLLLLLLLLLLKMMMDKKKKKKKKKDDMMMSK DSMLLEO ",
|
|
279
|
+
" KSKKKKDO KSMMMEDDDDKKDDDKKKDKSMMMDDDDDDDDDSDDMMMSK ODDKKKSK ",
|
|
280
|
+
" EMLLMDO KSMMMMLLLLLLLLLLLLLLLMMMDOOOOOOOOODDMMMSK ODMLLME ",
|
|
281
|
+
" KMLLMSD KSMMMMMMMMMMMMMMMMMMMMMMDDSSDDSSSSDDMMMSK SSMLLEK ",
|
|
282
|
+
" KSKKKKSO KSMMMMMOOMMOOMKOEMOOMMMMDOOOOOOOOODDMMMSK OSKKKKSO ",
|
|
283
|
+
" SMLLMDO KSMMMMMKKMMKKMDKEMKKMMMMKDDDDSSSSDDDMMMSK ODMLLMS ",
|
|
284
|
+
" SMMMMSD KSMMMMMEEMMEEMEEMMEEMMMMDSOOOOOOOODDMMSSK DSMMMMD ",
|
|
285
|
+
" OOOOOOO KSSMMMMMMMMMMMMMMMMMMMMMDDDDDDDDDDDDMSSSK OOOOOOO ",
|
|
286
|
+
" KSMLLLMMSKO KSSSSMMMMMMMMMMMMMMMMMMMSOOOOOOOOOOSSSSSK OKSMLLLLMSO ",
|
|
287
|
+
" DSMMMEEESKK KSSKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSOSSK KDSMMMMMESD ",
|
|
288
|
+
" DSMMMMMESKK KSOOKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSOOKSK KKSMMMMMMSD ",
|
|
289
|
+
" DSMMMMMESKK OKSKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSDSKO KDSMMMMMMSD ",
|
|
290
|
+
" KDDDDDDDDKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKDDDDDDDDO ",
|
|
291
|
+
" OOOOOOOOOOO OOOOOOOOO OOOOOOOOO OOOOOOOOOOO ",
|
|
292
|
+
"DSDO OSSO ODKKKKKKK OKKKKKKKO KEDO ODEK",
|
|
293
|
+
"SMDO OSMD KDSSSSSSK KDSSSSSKO SMDO ODMS",
|
|
294
|
+
"DEKO OOED OOKKKOOO OOOKKOOO SSOO OKMS",
|
|
295
|
+
"DEKO OOED SEMMMMSK OSMMMMED SSKO OKES",
|
|
296
|
+
"DSSO OESK SEMMMMSK OSMMMMED KSSO OSSK",
|
|
297
|
+
"KSMS EEDO OOKKKKKO OOKKKKKO OSEE EMSO",
|
|
298
|
+
" DSS SSK OSEEESDO ODSEEESO KSS SSD ",
|
|
299
|
+
" OOO OO SEMMMMSK OSMMMMED OO OOO ",
|
|
300
|
+
" KSSSSSDO OKSSESSK ",
|
|
301
|
+
" DKKDDDDDDKKDK KDKDDDDDDDKDK ",
|
|
302
|
+
" SSMLLMMMMMMLMSK DSSMMMMMMMLLMSS ",
|
|
303
|
+
" SMLMMMMMMMMLLED SEMMMMMMMMMMLMS ",
|
|
304
|
+
" DMMMMMMMMMMMMMMD SMMMMMMMMMMMMMSK ",
|
|
305
|
+
" ODSSSSSSSSSSSSSSDO ODSSSSSSSSSSSSSSKO ",
|
|
306
|
+
" OOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOO ",
|
|
307
|
+
" OKSSSSSSSSSSSSSSK KSSSSSSSSSSSSSSKO ",
|
|
308
|
+
" OKDDDDDDDDDDDDDDK KDDDDDDDDDDDDDDOO "
|
|
309
|
+
];
|
|
310
|
+
HEAD = ROBOT.slice(0, 37);
|
|
311
|
+
});
|
|
312
|
+
|
|
260
313
|
// packages/core/src/audit.ts
|
|
261
|
-
var AUDIT_TYPES
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
314
|
+
var AUDIT_TYPES, AUDIT_TYPES_SQL, DEFAULT_PRIVACY;
|
|
315
|
+
var init_audit = __esm(() => {
|
|
316
|
+
AUDIT_TYPES = new Set([
|
|
317
|
+
"session.started",
|
|
318
|
+
"session.ended",
|
|
319
|
+
"tool.denied",
|
|
320
|
+
"claim.acquired",
|
|
321
|
+
"claim.renewed",
|
|
322
|
+
"claim.released",
|
|
323
|
+
"claim.expired",
|
|
324
|
+
"claim.orphaned",
|
|
325
|
+
"claim.denied",
|
|
326
|
+
"rules.changed",
|
|
327
|
+
"worktree.reclaimed",
|
|
328
|
+
"worktree.created",
|
|
329
|
+
"worktree.removed",
|
|
330
|
+
"worktree.bootstrapped",
|
|
331
|
+
"pr.opened",
|
|
332
|
+
"question.asked",
|
|
333
|
+
"question.answered",
|
|
334
|
+
"dispatch.queued",
|
|
335
|
+
"dispatch.started",
|
|
336
|
+
"dispatch.finished",
|
|
337
|
+
"resource.acquired",
|
|
338
|
+
"resource.released",
|
|
339
|
+
"resource.reaped",
|
|
340
|
+
"process.started",
|
|
341
|
+
"process.exited",
|
|
342
|
+
"gate.recorded",
|
|
343
|
+
"gate.blocked",
|
|
344
|
+
"codify.applied",
|
|
345
|
+
"handoff.recorded",
|
|
346
|
+
"permission.requested",
|
|
347
|
+
"permission.resolved",
|
|
348
|
+
"incident.opened",
|
|
349
|
+
"incident.acked",
|
|
350
|
+
"run.result",
|
|
351
|
+
"workflow.started",
|
|
352
|
+
"workflow.finished"
|
|
353
|
+
]);
|
|
354
|
+
AUDIT_TYPES_SQL = [...AUDIT_TYPES].map((t) => `'${t}'`).join(", ");
|
|
355
|
+
DEFAULT_PRIVACY = {
|
|
356
|
+
store_prompts: true,
|
|
357
|
+
store_reasoning: true,
|
|
358
|
+
redact: []
|
|
359
|
+
};
|
|
360
|
+
});
|
|
308
361
|
|
|
362
|
+
// packages/core/src/budget.ts
|
|
363
|
+
var BUDGET_ASK_TOOLS;
|
|
364
|
+
var init_budget = __esm(() => {
|
|
365
|
+
BUDGET_ASK_TOOLS = new Set(["Bash", "Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
366
|
+
});
|
|
309
367
|
// packages/core/src/workflows.ts
|
|
310
|
-
var NAME_RE = /^[a-z0-9][a-z0-9_.-]{0,39}$/i;
|
|
311
368
|
function isRecord(v) {
|
|
312
369
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
313
370
|
}
|
|
@@ -354,10 +411,14 @@ function parseWorkflows(raw) {
|
|
|
354
411
|
}
|
|
355
412
|
return out;
|
|
356
413
|
}
|
|
414
|
+
var NAME_RE;
|
|
415
|
+
var init_workflows = __esm(() => {
|
|
416
|
+
NAME_RE = /^[a-z0-9][a-z0-9_.-]{0,39}$/i;
|
|
417
|
+
});
|
|
357
418
|
|
|
358
419
|
// packages/core/src/config.ts
|
|
359
|
-
|
|
360
|
-
|
|
420
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
421
|
+
import { join as join2 } from "path";
|
|
361
422
|
function parseGateDefs(gates) {
|
|
362
423
|
const out = {};
|
|
363
424
|
if (!isRecord2(gates))
|
|
@@ -382,38 +443,35 @@ function parseGateDefs(gates) {
|
|
|
382
443
|
}
|
|
383
444
|
return out;
|
|
384
445
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
no_foreign_worktree: "ask",
|
|
412
|
-
claim_required_to_write: "off",
|
|
413
|
-
protected: { ports: [] }
|
|
446
|
+
function parseCustomRules(raw) {
|
|
447
|
+
if (!Array.isArray(raw))
|
|
448
|
+
return [];
|
|
449
|
+
const out = [];
|
|
450
|
+
const seen = new Set;
|
|
451
|
+
for (const v of raw) {
|
|
452
|
+
if (!isRecord2(v))
|
|
453
|
+
continue;
|
|
454
|
+
const name = typeof v.name === "string" ? v.name.trim() : "";
|
|
455
|
+
const match = typeof v.match === "string" ? v.match : "";
|
|
456
|
+
if (!/^[a-z0-9][a-z0-9_.-]{0,39}$/i.test(name) || !match || seen.has(name))
|
|
457
|
+
continue;
|
|
458
|
+
try {
|
|
459
|
+
new RegExp(match);
|
|
460
|
+
} catch {
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
const action = REWRITE_MODES.includes(v.action) ? v.action : "ask";
|
|
464
|
+
seen.add(name);
|
|
465
|
+
out.push({
|
|
466
|
+
name,
|
|
467
|
+
match,
|
|
468
|
+
action,
|
|
469
|
+
...typeof v.replace === "string" ? { replace: v.replace } : {},
|
|
470
|
+
...typeof v.reason === "string" && v.reason.trim() ? { reason: v.reason.trim() } : {}
|
|
471
|
+
});
|
|
414
472
|
}
|
|
415
|
-
|
|
416
|
-
|
|
473
|
+
return out;
|
|
474
|
+
}
|
|
417
475
|
function isRecord2(v) {
|
|
418
476
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
419
477
|
}
|
|
@@ -441,12 +499,9 @@ function isRepoRelative(f) {
|
|
|
441
499
|
return false;
|
|
442
500
|
return !t.split(/[/\\]/).some((seg) => seg === "..");
|
|
443
501
|
}
|
|
444
|
-
var days = (v, fallback) => {
|
|
445
|
-
const n = Number(v);
|
|
446
|
-
return Number.isInteger(n) && n >= 0 ? Math.min(n, 3650) : fallback;
|
|
447
|
-
};
|
|
448
502
|
function validate(c) {
|
|
449
503
|
const mode = (v, fallback) => MODES.includes(v) ? v : fallback;
|
|
504
|
+
const rewriteMode = (v, fallback) => REWRITE_MODES.includes(v) ? v : fallback;
|
|
450
505
|
const port = Number(c.daemon?.port);
|
|
451
506
|
const source = c.tasks?.source;
|
|
452
507
|
const setup = c.worktree?.setup;
|
|
@@ -477,13 +532,28 @@ function validate(c) {
|
|
|
477
532
|
gates: {
|
|
478
533
|
required: Array.isArray(rawGates?.required) ? rawGates.required.filter((g) => typeof g === "string" && g.trim() !== "") : [],
|
|
479
534
|
auto: AUTO_MODES.includes(auto) ? auto : "session-end",
|
|
535
|
+
on_stop: rawGates?.on_stop === "block" ? "block" : "record",
|
|
536
|
+
max_blocks: (() => {
|
|
537
|
+
const n = Number(rawGates?.max_blocks);
|
|
538
|
+
return Number.isInteger(n) && n >= 0 && n <= 20 ? n : 3;
|
|
539
|
+
})(),
|
|
540
|
+
stop_timeout: (() => {
|
|
541
|
+
const n = Number(rawGates?.stop_timeout);
|
|
542
|
+
return Number.isFinite(n) && n >= 5 && n <= 1800 ? n : 300;
|
|
543
|
+
})(),
|
|
480
544
|
defs: parseGateDefs(rawGates)
|
|
481
545
|
},
|
|
482
546
|
budget: {
|
|
483
547
|
daily: usd(b.daily),
|
|
484
548
|
weekly: usd(b.weekly),
|
|
485
549
|
warn_at: Number.isFinite(warnAt) && warnAt > 0 && warnAt < 1 ? warnAt : 0.8,
|
|
486
|
-
on_exceed: b.on_exceed === "ask" || b.on_exceed === "stop" ? b.on_exceed : "warn"
|
|
550
|
+
on_exceed: b.on_exceed === "ask" || b.on_exceed === "stop" ? b.on_exceed : "warn",
|
|
551
|
+
window_warn_at: (() => {
|
|
552
|
+
if (b.window_warn_at === false || b.window_warn_at === null || b.window_warn_at === 0)
|
|
553
|
+
return null;
|
|
554
|
+
const w = Number(b.window_warn_at);
|
|
555
|
+
return Number.isFinite(w) && w > 0 && w < 1 ? w : 0.8;
|
|
556
|
+
})()
|
|
487
557
|
},
|
|
488
558
|
workflows: parseWorkflows(c.workflows),
|
|
489
559
|
notify: {
|
|
@@ -492,6 +562,23 @@ function validate(c) {
|
|
|
492
562
|
return typeof w === "string" && /^https?:\/\//.test(w.trim()) ? w.trim() : null;
|
|
493
563
|
})()
|
|
494
564
|
},
|
|
565
|
+
messages: {
|
|
566
|
+
wake: c.messages?.wake !== false
|
|
567
|
+
},
|
|
568
|
+
codify: {
|
|
569
|
+
target: (() => {
|
|
570
|
+
const t = c.codify?.target;
|
|
571
|
+
return t === "claude-md" || t === "swarm-toml" ? t : "both";
|
|
572
|
+
})()
|
|
573
|
+
},
|
|
574
|
+
broker: {
|
|
575
|
+
interactive_wait: (() => {
|
|
576
|
+
const w = Number(c.broker?.interactive_wait);
|
|
577
|
+
if (!Number.isFinite(w) || w < 0)
|
|
578
|
+
return 30;
|
|
579
|
+
return Math.min(Math.round(w), 120);
|
|
580
|
+
})()
|
|
581
|
+
},
|
|
495
582
|
models: {
|
|
496
583
|
allow: Array.isArray(c.models?.allow) ? c.models.allow.filter((m) => typeof m === "string" && m.trim() !== "") : []
|
|
497
584
|
},
|
|
@@ -538,6 +625,14 @@ function validate(c) {
|
|
|
538
625
|
protected_ports: mode(c.rules?.protected_ports, "ask"),
|
|
539
626
|
no_foreign_worktree: mode(c.rules?.no_foreign_worktree, "ask"),
|
|
540
627
|
claim_required_to_write: mode(c.rules?.claim_required_to_write, "off"),
|
|
628
|
+
no_verify: rewriteMode(c.rules?.no_verify, "off"),
|
|
629
|
+
dry_run_first: rewriteMode(c.rules?.dry_run_first, "off"),
|
|
630
|
+
custom: parseCustomRules(c.rules?.custom),
|
|
631
|
+
collision_context: c.rules?.collision_context !== false,
|
|
632
|
+
collision_window: (() => {
|
|
633
|
+
const n = Number(c.rules?.collision_window);
|
|
634
|
+
return Number.isFinite(n) && n >= 1 && n <= 240 ? Math.round(n) : 15;
|
|
635
|
+
})(),
|
|
541
636
|
protected: {
|
|
542
637
|
ports: Array.isArray(c.rules?.protected?.ports) ? c.rules.protected.ports.filter((p) => Number.isInteger(p) && p > 0 && p < 65536) : []
|
|
543
638
|
}
|
|
@@ -571,7 +666,6 @@ function setPath(obj, path, value) {
|
|
|
571
666
|
}
|
|
572
667
|
cur[segs[segs.length - 1]] = value;
|
|
573
668
|
}
|
|
574
|
-
var isLockedBy = (path, lock) => path === lock || path.startsWith(`${lock}.`);
|
|
575
669
|
function readLayer(path) {
|
|
576
670
|
return existsSync3(path) ? parseToml(readFileSync2(path, "utf8"), path) : null;
|
|
577
671
|
}
|
|
@@ -620,24 +714,140 @@ function loadConfigDetailed(opts = {}) {
|
|
|
620
714
|
policy: { path: policyRaw ? policyPath : null, locked }
|
|
621
715
|
};
|
|
622
716
|
}
|
|
717
|
+
var DEFAULT_GATE_TIMEOUT_S = 900, AUTO_MODES, DEFAULT_CONFIG, MODES, REWRITE_MODES, days = (v, fallback) => {
|
|
718
|
+
const n = Number(v);
|
|
719
|
+
return Number.isInteger(n) && n >= 0 ? Math.min(n, 3650) : fallback;
|
|
720
|
+
}, isLockedBy = (path, lock) => path === lock || path.startsWith(`${lock}.`);
|
|
721
|
+
var init_config = __esm(() => {
|
|
722
|
+
init_audit();
|
|
723
|
+
init_workflows();
|
|
724
|
+
AUTO_MODES = ["session-end", "stop", "off"];
|
|
725
|
+
DEFAULT_CONFIG = {
|
|
726
|
+
daemon: { port: 7777, auth: "loopback-optional" },
|
|
727
|
+
tasks: { source: null, labels: [], team: null },
|
|
728
|
+
gates: {
|
|
729
|
+
required: [],
|
|
730
|
+
auto: "session-end",
|
|
731
|
+
on_stop: "record",
|
|
732
|
+
max_blocks: 3,
|
|
733
|
+
stop_timeout: 300,
|
|
734
|
+
defs: {}
|
|
735
|
+
},
|
|
736
|
+
workflows: {},
|
|
737
|
+
budget: { daily: null, weekly: null, warn_at: 0.8, on_exceed: "warn", window_warn_at: 0.8 },
|
|
738
|
+
models: { allow: [] },
|
|
739
|
+
notify: { webhook: null },
|
|
740
|
+
messages: { wake: true },
|
|
741
|
+
codify: { target: "both" },
|
|
742
|
+
broker: { interactive_wait: 30 },
|
|
743
|
+
team: { url: null, forward: ["ledger", "cost"], interval: 5 },
|
|
744
|
+
events: { retain_days: 30 },
|
|
745
|
+
audit: { retain_days: 0 },
|
|
746
|
+
privacy: DEFAULT_PRIVACY,
|
|
747
|
+
dispatch: {
|
|
748
|
+
max_parallel: 2,
|
|
749
|
+
permission_mode: null,
|
|
750
|
+
model: null,
|
|
751
|
+
max_turns: null,
|
|
752
|
+
require_pr: true,
|
|
753
|
+
profile: null
|
|
754
|
+
},
|
|
755
|
+
worktree: { setup: null, copy: [], open: null },
|
|
756
|
+
rules: {
|
|
757
|
+
shared_tree: "ask",
|
|
758
|
+
destructive_git: "ask",
|
|
759
|
+
pattern_kill: "ask",
|
|
760
|
+
protected_ports: "ask",
|
|
761
|
+
no_foreign_worktree: "ask",
|
|
762
|
+
claim_required_to_write: "off",
|
|
763
|
+
no_verify: "off",
|
|
764
|
+
dry_run_first: "off",
|
|
765
|
+
custom: [],
|
|
766
|
+
collision_context: true,
|
|
767
|
+
collision_window: 15,
|
|
768
|
+
protected: { ports: [] }
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
MODES = ["ask", "deny", "off"];
|
|
772
|
+
REWRITE_MODES = ["rewrite", "ask", "deny", "off"];
|
|
773
|
+
});
|
|
774
|
+
|
|
775
|
+
// packages/core/src/context.ts
|
|
776
|
+
var init_context = () => {};
|
|
777
|
+
|
|
778
|
+
// packages/core/src/dag.ts
|
|
779
|
+
var init_dag = () => {};
|
|
623
780
|
// packages/core/src/rules.ts
|
|
624
|
-
var LIVE_WINDOW_MS
|
|
625
|
-
var
|
|
781
|
+
var LIVE_WINDOW_MS, customRe, WRITE_TOOLS;
|
|
782
|
+
var init_rules = __esm(() => {
|
|
783
|
+
LIVE_WINDOW_MS = 10 * 60000;
|
|
784
|
+
customRe = new WeakMap;
|
|
785
|
+
WRITE_TOOLS = new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
// packages/core/src/dryrun.ts
|
|
789
|
+
var init_dryrun = __esm(() => {
|
|
790
|
+
init_rules();
|
|
791
|
+
});
|
|
792
|
+
// packages/core/src/gatehealth.ts
|
|
793
|
+
var init_gatehealth = () => {};
|
|
794
|
+
|
|
795
|
+
// packages/core/src/gates.ts
|
|
796
|
+
var init_gates = () => {};
|
|
797
|
+
|
|
798
|
+
// packages/core/src/graphs.ts
|
|
799
|
+
var init_graphs = __esm(() => {
|
|
800
|
+
init_rules();
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
// packages/core/src/heat.ts
|
|
804
|
+
var init_heat = __esm(() => {
|
|
805
|
+
init_rules();
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
// packages/core/src/worktree.ts
|
|
809
|
+
var init_worktree = __esm(() => {
|
|
810
|
+
init_config();
|
|
811
|
+
});
|
|
812
|
+
|
|
626
813
|
// packages/core/src/hygiene.ts
|
|
627
|
-
var HYGIENE_DEFAULTS
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
814
|
+
var HYGIENE_DEFAULTS;
|
|
815
|
+
var init_hygiene = __esm(() => {
|
|
816
|
+
init_worktree();
|
|
817
|
+
HYGIENE_DEFAULTS = {
|
|
818
|
+
staleDays: 2,
|
|
819
|
+
abandonedDays: 30,
|
|
820
|
+
hungryRssKb: 1024 * 1024,
|
|
821
|
+
heavyKb: 2 * 1024 * 1024
|
|
822
|
+
};
|
|
823
|
+
});
|
|
824
|
+
|
|
633
825
|
// packages/core/src/ledger.ts
|
|
634
|
-
var EDIT_TOOLS
|
|
826
|
+
var EDIT_TOOLS;
|
|
827
|
+
var init_ledger = __esm(() => {
|
|
828
|
+
EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
829
|
+
});
|
|
830
|
+
// packages/core/src/lessons-apply.ts
|
|
831
|
+
var init_lessons_apply = () => {};
|
|
832
|
+
|
|
833
|
+
// packages/core/src/lineage.ts
|
|
834
|
+
var init_lineage = __esm(() => {
|
|
835
|
+
init_dag();
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
// packages/core/src/mcphealth.ts
|
|
839
|
+
var init_mcphealth = __esm(() => {
|
|
840
|
+
init_gatehealth();
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// packages/core/src/memory.ts
|
|
844
|
+
var init_memory = () => {};
|
|
635
845
|
// packages/core/src/outcomes.ts
|
|
636
|
-
var DEFAULT_BRANCHES
|
|
846
|
+
var DEFAULT_BRANCHES;
|
|
847
|
+
var init_outcomes = __esm(() => {
|
|
848
|
+
DEFAULT_BRANCHES = new Set(["main", "master", "develop", "trunk"]);
|
|
849
|
+
});
|
|
637
850
|
// packages/core/src/policy.ts
|
|
638
|
-
var HOOK_MARK = "swarm-hook";
|
|
639
|
-
var hookIsOurs = (h) => typeof h.command === "string" && (h.command.includes(HOOK_MARK) || h.command.includes("/packages/hook/src/bin.ts"));
|
|
640
|
-
var MIN_HOOK_TIMEOUT_S = 5;
|
|
641
851
|
function hookCoverage(settings) {
|
|
642
852
|
const hooks = settings && typeof settings === "object" && !Array.isArray(settings) ? settings.hooks : undefined;
|
|
643
853
|
const missing = [];
|
|
@@ -655,7 +865,226 @@ function hookCoverage(settings) {
|
|
|
655
865
|
}
|
|
656
866
|
return { missing, short, complete: !missing.length && !short.length };
|
|
657
867
|
}
|
|
868
|
+
var HOOK_MARK = "swarm-hook", hookIsOurs = (h) => typeof h.command === "string" && (h.command.includes(HOOK_MARK) || h.command.includes("/packages/hook/src/bin.ts")), MIN_HOOK_TIMEOUT_S = 5;
|
|
869
|
+
var init_policy = __esm(() => {
|
|
870
|
+
init_hooks();
|
|
871
|
+
init_rules();
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
// packages/core/src/pricing.ts
|
|
875
|
+
var init_pricing = () => {};
|
|
876
|
+
// packages/core/src/provenance.ts
|
|
877
|
+
var init_provenance = () => {};
|
|
878
|
+
// packages/core/src/quota.ts
|
|
879
|
+
var BURN_MIN_SPAN_MS;
|
|
880
|
+
var init_quota = __esm(() => {
|
|
881
|
+
BURN_MIN_SPAN_MS = 10 * 60000;
|
|
882
|
+
});
|
|
883
|
+
// packages/core/src/security.ts
|
|
884
|
+
var init_security = () => {};
|
|
885
|
+
|
|
886
|
+
// packages/core/src/stall.ts
|
|
887
|
+
var init_stall = () => {};
|
|
888
|
+
|
|
889
|
+
// packages/core/src/statusline.ts
|
|
890
|
+
function parseStatuslinePayload(text) {
|
|
891
|
+
try {
|
|
892
|
+
const v = JSON.parse(text);
|
|
893
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
894
|
+
} catch {
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
function pct(color, label, value) {
|
|
899
|
+
const s = `${label} ${Math.round(value)}%`;
|
|
900
|
+
if (value >= 90)
|
|
901
|
+
return red(color, s);
|
|
902
|
+
if (value >= 70)
|
|
903
|
+
return yellow(color, s);
|
|
904
|
+
return s;
|
|
905
|
+
}
|
|
906
|
+
function money(usd) {
|
|
907
|
+
return usd >= 10 ? `$${usd.toFixed(0)}` : `$${usd.toFixed(2)}`;
|
|
908
|
+
}
|
|
909
|
+
function renderStatusline(payload, state, opts = {}) {
|
|
910
|
+
const color = opts.color ?? false;
|
|
911
|
+
const local = [];
|
|
912
|
+
const model = payload.model?.display_name ?? payload.model?.id;
|
|
913
|
+
if (model)
|
|
914
|
+
local.push(bold(color, model));
|
|
915
|
+
const ctx = payload.context_window?.used_percentage;
|
|
916
|
+
if (typeof ctx === "number")
|
|
917
|
+
local.push(pct(color, "ctx", ctx));
|
|
918
|
+
const cost = payload.cost?.total_cost_usd;
|
|
919
|
+
if (typeof cost === "number")
|
|
920
|
+
local.push(money(cost));
|
|
921
|
+
const five = payload.rate_limits?.five_hour?.used_percentage;
|
|
922
|
+
if (typeof five === "number")
|
|
923
|
+
local.push(pct(color, "5h", five));
|
|
924
|
+
const week = payload.rate_limits?.seven_day?.used_percentage;
|
|
925
|
+
if (typeof week === "number")
|
|
926
|
+
local.push(pct(color, "7d", week));
|
|
927
|
+
const swarm = [];
|
|
928
|
+
if (state) {
|
|
929
|
+
if (state.task)
|
|
930
|
+
swarm.push(`${state.task.id} ${dim(color, `${state.task.leftMin}m`)}`);
|
|
931
|
+
if (state.budget && state.budget.level !== "ok")
|
|
932
|
+
swarm.push((state.budget.level === "exceeded" ? red : yellow)(color, `budget ${state.budget.level} ${Math.round(state.budget.pct * 100)}%`));
|
|
933
|
+
if (state.incidents > 0)
|
|
934
|
+
swarm.push(yellow(color, `${state.incidents} incident${state.incidents === 1 ? "" : "s"}`));
|
|
935
|
+
if (state.waitingOn > 0)
|
|
936
|
+
swarm.push(red(color, `waiting on you${state.waitingOn > 1 ? ` \xD7${state.waitingOn}` : ""}`));
|
|
937
|
+
if (state.inbox > 0)
|
|
938
|
+
swarm.push(`inbox ${state.inbox}`);
|
|
939
|
+
if (state.quota) {
|
|
940
|
+
const short = { five_hour: "5h", seven_day: "7d", spend_limit: "spend" }[state.quota.window];
|
|
941
|
+
const h = state.quota.hoursToLimit;
|
|
942
|
+
if (h == null)
|
|
943
|
+
swarm.push(red(color, `${short} limit reached`));
|
|
944
|
+
else {
|
|
945
|
+
const s = `${short} limit in ${h < 1 ? `${Math.max(1, Math.round(h * 60))}m` : `${Math.round(h)}h`}`;
|
|
946
|
+
swarm.push(h < 1 ? red(color, s) : h < 3 ? yellow(color, s) : s);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
const sep = dim(color, " \xB7 ");
|
|
951
|
+
const bar = dim(color, " \u2502 ");
|
|
952
|
+
const left = local.join(sep);
|
|
953
|
+
if (!swarm.length)
|
|
954
|
+
return left;
|
|
955
|
+
const right = swarm.join(sep);
|
|
956
|
+
return left ? `${left}${bar}${right}` : right;
|
|
957
|
+
}
|
|
958
|
+
function statuslineIsOurs(setting) {
|
|
959
|
+
if (!setting || typeof setting !== "object")
|
|
960
|
+
return false;
|
|
961
|
+
const cmd = setting.command;
|
|
962
|
+
return typeof cmd === "string" && (cmd.includes("swarm-hook") || cmd.includes("/packages/hook/src/bin.ts")) && /\bstatusline\b/.test(cmd);
|
|
963
|
+
}
|
|
964
|
+
var ESC = "\x1B[", paint = (color, code, s) => color ? `${ESC}${code}m${s}${ESC}0m` : s, dim = (c, s) => paint(c, "2", s), yellow = (c, s) => paint(c, "33", s), red = (c, s) => paint(c, "31", s), bold = (c, s) => paint(c, "1", s);
|
|
965
|
+
|
|
966
|
+
// packages/core/src/tasks.ts
|
|
967
|
+
var init_tasks = () => {};
|
|
968
|
+
|
|
969
|
+
// packages/core/src/team.ts
|
|
970
|
+
var init_team = () => {};
|
|
971
|
+
|
|
972
|
+
// packages/core/src/teamsetup.ts
|
|
973
|
+
var init_teamsetup = () => {};
|
|
974
|
+
|
|
975
|
+
// packages/core/src/transitions.ts
|
|
976
|
+
var init_transitions = () => {};
|
|
977
|
+
|
|
978
|
+
// packages/core/src/types.ts
|
|
979
|
+
var init_types = () => {};
|
|
980
|
+
|
|
981
|
+
// packages/core/src/waiting.ts
|
|
982
|
+
var init_waiting = () => {};
|
|
983
|
+
|
|
984
|
+
// packages/core/src/index.ts
|
|
985
|
+
var init_src2 = __esm(() => {
|
|
986
|
+
init_actor();
|
|
987
|
+
init_adapters();
|
|
988
|
+
init_hooks();
|
|
989
|
+
init_art();
|
|
990
|
+
init_audit();
|
|
991
|
+
init_budget();
|
|
992
|
+
init_config();
|
|
993
|
+
init_context();
|
|
994
|
+
init_dag();
|
|
995
|
+
init_dryrun();
|
|
996
|
+
init_gatehealth();
|
|
997
|
+
init_gates();
|
|
998
|
+
init_graphs();
|
|
999
|
+
init_heat();
|
|
1000
|
+
init_hygiene();
|
|
1001
|
+
init_ledger();
|
|
1002
|
+
init_lessons_apply();
|
|
1003
|
+
init_lineage();
|
|
1004
|
+
init_mcphealth();
|
|
1005
|
+
init_memory();
|
|
1006
|
+
init_outcomes();
|
|
1007
|
+
init_policy();
|
|
1008
|
+
init_pricing();
|
|
1009
|
+
init_provenance();
|
|
1010
|
+
init_quota();
|
|
1011
|
+
init_rules();
|
|
1012
|
+
init_security();
|
|
1013
|
+
init_stall();
|
|
1014
|
+
init_tasks();
|
|
1015
|
+
init_team();
|
|
1016
|
+
init_teamsetup();
|
|
1017
|
+
init_transitions();
|
|
1018
|
+
init_types();
|
|
1019
|
+
init_waiting();
|
|
1020
|
+
init_workflows();
|
|
1021
|
+
init_worktree();
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
// packages/hook/src/statusline.ts
|
|
1025
|
+
async function fetchStatuslineState(payload, opts = {}) {
|
|
1026
|
+
const timeout = opts.timeoutMs ?? Number(process.env.SWARM_HOOK_TIMEOUT_MS ?? 400);
|
|
1027
|
+
const post = async (base) => {
|
|
1028
|
+
const r = await authedFetch(`${base}/v1/statusline`, {
|
|
1029
|
+
method: "POST",
|
|
1030
|
+
headers: { "content-type": "application/json" },
|
|
1031
|
+
body: JSON.stringify(payload),
|
|
1032
|
+
signal: AbortSignal.timeout(timeout)
|
|
1033
|
+
});
|
|
1034
|
+
return r.ok ? await r.json() : null;
|
|
1035
|
+
};
|
|
1036
|
+
const base = opts.baseUrl ?? resolveBaseUrl();
|
|
1037
|
+
const fallback = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
1038
|
+
try {
|
|
1039
|
+
const s = await post(base);
|
|
1040
|
+
if (s)
|
|
1041
|
+
return s;
|
|
1042
|
+
} catch {}
|
|
1043
|
+
if (base !== fallback && !opts.baseUrl) {
|
|
1044
|
+
try {
|
|
1045
|
+
return await post(fallback);
|
|
1046
|
+
} catch {}
|
|
1047
|
+
}
|
|
1048
|
+
return null;
|
|
1049
|
+
}
|
|
1050
|
+
async function runStatusline(input, opts = {}) {
|
|
1051
|
+
const payload = parseStatuslinePayload(input) ?? {};
|
|
1052
|
+
const state = await fetchStatuslineState(payload, opts);
|
|
1053
|
+
const color = opts.color ?? !process.env.NO_COLOR;
|
|
1054
|
+
return renderStatusline(payload, state, { color });
|
|
1055
|
+
}
|
|
1056
|
+
var init_statusline = __esm(() => {
|
|
1057
|
+
init_src();
|
|
1058
|
+
init_src2();
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
// packages/hook/src/wait.ts
|
|
1062
|
+
var init_wait = __esm(() => {
|
|
1063
|
+
init_src();
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
// packages/hook/src/index.ts
|
|
1067
|
+
var init_src3 = __esm(() => {
|
|
1068
|
+
init_statusline();
|
|
1069
|
+
init_wait();
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
// packages/cli/src/bin.ts
|
|
1073
|
+
init_src();
|
|
1074
|
+
init_src2();
|
|
1075
|
+
import {
|
|
1076
|
+
copyFileSync,
|
|
1077
|
+
existsSync as existsSync5,
|
|
1078
|
+
mkdirSync as mkdirSync3,
|
|
1079
|
+
readdirSync,
|
|
1080
|
+
unlinkSync,
|
|
1081
|
+
writeFileSync as writeFileSync3
|
|
1082
|
+
} from "fs";
|
|
1083
|
+
import { join as join5, resolve as resolve3 } from "path";
|
|
1084
|
+
|
|
658
1085
|
// packages/cli/src/install.ts
|
|
1086
|
+
init_src();
|
|
1087
|
+
init_src2();
|
|
659
1088
|
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
660
1089
|
import { homedir as homedir2 } from "os";
|
|
661
1090
|
import { join as join3 } from "path";
|
|
@@ -795,6 +1224,7 @@ function mcpServerConfig() {
|
|
|
795
1224
|
const [command, ...args] = resolveBin("swarm-mcp");
|
|
796
1225
|
return { command, args };
|
|
797
1226
|
}
|
|
1227
|
+
var WAKE_EVENTS = new Set(["Stop"]);
|
|
798
1228
|
function load() {
|
|
799
1229
|
const p = settingsPath();
|
|
800
1230
|
return existsSync4(p) ? JSON.parse(readFileSync3(p, "utf8")) : {};
|
|
@@ -805,18 +1235,25 @@ function save(s) {
|
|
|
805
1235
|
}
|
|
806
1236
|
function install() {
|
|
807
1237
|
const s = load();
|
|
808
|
-
const
|
|
1238
|
+
const hooks = s.hooks ?? {};
|
|
809
1239
|
const added = [];
|
|
810
1240
|
for (const ev of HOOK_EVENTS) {
|
|
811
|
-
const list =
|
|
1241
|
+
const list = hooks[ev] ?? [];
|
|
812
1242
|
const clean = list.map((g) => ({ ...g, hooks: g.hooks.filter((h) => !isOurs(h)) })).filter((g) => g.hooks.length);
|
|
813
1243
|
clean.push({
|
|
814
|
-
hooks: [
|
|
1244
|
+
hooks: [
|
|
1245
|
+
{
|
|
1246
|
+
type: "command",
|
|
1247
|
+
command: hookCommand(ev),
|
|
1248
|
+
timeout: ev === "Stop" ? 330 : ev === "PermissionRequest" ? 150 : 5
|
|
1249
|
+
},
|
|
1250
|
+
...WAKE_EVENTS.has(ev) ? [{ type: "command", command: hookCommand("wait"), timeout: 3600, asyncRewake: true }] : []
|
|
1251
|
+
]
|
|
815
1252
|
});
|
|
816
|
-
|
|
1253
|
+
hooks[ev] = clean;
|
|
817
1254
|
added.push(ev);
|
|
818
1255
|
}
|
|
819
|
-
s.hooks =
|
|
1256
|
+
s.hooks = hooks;
|
|
820
1257
|
const stale = s.mcpServers ?? {};
|
|
821
1258
|
if (stale.swarm) {
|
|
822
1259
|
delete stale.swarm;
|
|
@@ -830,12 +1267,26 @@ function install() {
|
|
|
830
1267
|
registerOtherAgents();
|
|
831
1268
|
return added;
|
|
832
1269
|
}
|
|
1270
|
+
function installStatusline() {
|
|
1271
|
+
const s = load();
|
|
1272
|
+
const cur = s.statusLine;
|
|
1273
|
+
if (cur && !statuslineIsOurs(cur))
|
|
1274
|
+
return "kept";
|
|
1275
|
+
s.statusLine = { type: "command", command: `${binCommand("swarm-hook")} statusline` };
|
|
1276
|
+
save(s);
|
|
1277
|
+
return cur ? "refreshed" : "installed";
|
|
1278
|
+
}
|
|
1279
|
+
function statuslineStatus(s) {
|
|
1280
|
+
if (!s.statusLine)
|
|
1281
|
+
return "none";
|
|
1282
|
+
return statuslineIsOurs(s.statusLine) ? "ours" : "other";
|
|
1283
|
+
}
|
|
833
1284
|
function uninstall() {
|
|
834
1285
|
const s = load();
|
|
835
|
-
const
|
|
1286
|
+
const hooks = s.hooks ?? {};
|
|
836
1287
|
let removed = 0;
|
|
837
|
-
for (const ev of Object.keys(
|
|
838
|
-
const before =
|
|
1288
|
+
for (const ev of Object.keys(hooks)) {
|
|
1289
|
+
const before = hooks[ev] ?? [];
|
|
839
1290
|
const after = before.map((g) => ({
|
|
840
1291
|
...g,
|
|
841
1292
|
hooks: g.hooks.filter((h) => {
|
|
@@ -847,12 +1298,12 @@ function uninstall() {
|
|
|
847
1298
|
})
|
|
848
1299
|
})).filter((g) => g.hooks.length);
|
|
849
1300
|
if (after.length)
|
|
850
|
-
|
|
1301
|
+
hooks[ev] = after;
|
|
851
1302
|
else
|
|
852
|
-
delete
|
|
1303
|
+
delete hooks[ev];
|
|
853
1304
|
}
|
|
854
|
-
if (Object.keys(
|
|
855
|
-
s.hooks =
|
|
1305
|
+
if (Object.keys(hooks).length)
|
|
1306
|
+
s.hooks = hooks;
|
|
856
1307
|
else
|
|
857
1308
|
delete s.hooks;
|
|
858
1309
|
const mcp = s.mcpServers ?? {};
|
|
@@ -862,6 +1313,10 @@ function uninstall() {
|
|
|
862
1313
|
s.mcpServers = mcp;
|
|
863
1314
|
else
|
|
864
1315
|
delete s.mcpServers;
|
|
1316
|
+
if (statuslineIsOurs(s.statusLine)) {
|
|
1317
|
+
delete s.statusLine;
|
|
1318
|
+
removed++;
|
|
1319
|
+
}
|
|
865
1320
|
save(s);
|
|
866
1321
|
if (unregisterMcp())
|
|
867
1322
|
removed++;
|
|
@@ -870,8 +1325,8 @@ function uninstall() {
|
|
|
870
1325
|
}
|
|
871
1326
|
function status() {
|
|
872
1327
|
const s = load();
|
|
873
|
-
const
|
|
874
|
-
const installed = Object.values(
|
|
1328
|
+
const hooks = s.hooks ?? {};
|
|
1329
|
+
const installed = Object.values(hooks).some((l) => l.some((g) => g.hooks.some(isOurs)));
|
|
875
1330
|
const otherAgents = [];
|
|
876
1331
|
const cp = codexConfigPath();
|
|
877
1332
|
if (existsSync4(cp) && CODEX_BLOCK_RE.test(readFileSync3(cp, "utf8")))
|
|
@@ -887,7 +1342,8 @@ function status() {
|
|
|
887
1342
|
mcp: mcpRegistered(),
|
|
888
1343
|
path: settingsPath(),
|
|
889
1344
|
shim: shimPath(),
|
|
890
|
-
otherAgents
|
|
1345
|
+
otherAgents,
|
|
1346
|
+
statusline: statuslineStatus(s)
|
|
891
1347
|
};
|
|
892
1348
|
}
|
|
893
1349
|
function setTeamUrl(home, url) {
|
|
@@ -912,6 +1368,7 @@ url = "${url}"
|
|
|
912
1368
|
}
|
|
913
1369
|
|
|
914
1370
|
// packages/cli/src/procs.ts
|
|
1371
|
+
init_src();
|
|
915
1372
|
import { mkdirSync as mkdirSync2, openSync } from "fs";
|
|
916
1373
|
import { join as join4, resolve as resolve2 } from "path";
|
|
917
1374
|
async function call(path, init) {
|
|
@@ -1067,7 +1524,8 @@ var help = `swarm \u2014 control plane for AI-agent development
|
|
|
1067
1524
|
login [url] [--token t] log in to the team daemon ([team].url) and register this machine (M8.3c)
|
|
1068
1525
|
backup [dest] | restore <src> snapshot ~/.swarm (VACUUM INTO, zero downtime) / restore it (daemon stopped)
|
|
1069
1526
|
|
|
1070
|
-
install [--config-url <team url>] | uninstall add/remove Swarm hooks in ~/.claude/settings.json (--config-url
|
|
1527
|
+
install [--statusline] [--config-url <team url>] | uninstall add/remove Swarm hooks in ~/.claude/settings.json (--statusline also sets Claude Code's status line; --config-url points this machine at a team daemon)
|
|
1528
|
+
statusline Claude Code's statusLine command: its JSON on stdin \u2192 one line (model, context, cost, plan windows \u2502 task, lease, budget, incidents, waiting). Installed by: install --statusline
|
|
1071
1529
|
|
|
1072
1530
|
Env: SWARM_URL, SWARM_PORT (default 7777), SWARM_HOME (~/.swarm)`;
|
|
1073
1531
|
async function api(path, init) {
|
|
@@ -1129,6 +1587,10 @@ Open the dashboard: ${base}`);
|
|
|
1129
1587
|
case "install": {
|
|
1130
1588
|
const evs = install();
|
|
1131
1589
|
console.log(`installed hooks for ${evs.length} events in ${status().path}`);
|
|
1590
|
+
if (rest.includes("--statusline")) {
|
|
1591
|
+
const r = installStatusline();
|
|
1592
|
+
console.log(r === "kept" ? "statusLine left alone \u2014 another status line is set; remove it first, then rerun with --statusline" : `statusLine ${r}: swarm statusline (restart claude to see it)`);
|
|
1593
|
+
}
|
|
1132
1594
|
const cuIdx = rest.indexOf("--config-url");
|
|
1133
1595
|
const configUrl = cuIdx >= 0 ? rest[cuIdx + 1] : null;
|
|
1134
1596
|
if (configUrl) {
|
|
@@ -1144,6 +1606,12 @@ Open the dashboard: ${base}`);
|
|
|
1144
1606
|
case "uninstall":
|
|
1145
1607
|
console.log(`removed ${uninstall()} hook entries`);
|
|
1146
1608
|
break;
|
|
1609
|
+
case "statusline": {
|
|
1610
|
+
await Promise.resolve().then(() => init_src3());
|
|
1611
|
+
process.stdout.write(`${await runStatusline(await Bun.stdin.text())}
|
|
1612
|
+
`);
|
|
1613
|
+
break;
|
|
1614
|
+
}
|
|
1147
1615
|
case "doctor": {
|
|
1148
1616
|
if (rest.includes("--migrate"))
|
|
1149
1617
|
await ensureDaemon({ quiet: true });
|
|
@@ -1175,17 +1643,21 @@ Open the dashboard: ${base}`);
|
|
|
1175
1643
|
line(false, `${o.layer} config overrides locked ${o.key}`, `remove it \u2014 policy value stays in effect`);
|
|
1176
1644
|
}
|
|
1177
1645
|
line(st.mcp, "MCP server registered", "run: swarm install");
|
|
1646
|
+
if (st.statusline === "ours")
|
|
1647
|
+
console.log("\u2713 statusLine: swarm statusline");
|
|
1648
|
+
else
|
|
1649
|
+
console.log(st.statusline === "other" ? "\xB7 statusLine: another status line is set (swarm install --statusline would leave it alone)" : "\xB7 statusLine not set \u2014 swarm install --statusline puts task, lease, budget and plan windows in Claude Code's footer");
|
|
1178
1650
|
if (st.otherAgents.length)
|
|
1179
1651
|
console.log(`\u2713 MCP server also registered for ${st.otherAgents.join(", ")} (swarm_* tools in those CLIs too)`);
|
|
1180
|
-
const
|
|
1652
|
+
const forge = (bin, auth) => {
|
|
1181
1653
|
const path = Bun.which(bin);
|
|
1182
1654
|
if (!path)
|
|
1183
1655
|
return console.log(`\xB7 ${bin} not found \u2014 PRs view skips ${bin === "gh" ? "GitHub" : "GitLab"} repos`);
|
|
1184
1656
|
const ok = Bun.spawnSync([path, ...auth], { stdout: "ignore", stderr: "ignore" }).exitCode === 0;
|
|
1185
1657
|
line(ok, `${bin} authenticated (${path})`, `run: ${bin} auth login`);
|
|
1186
1658
|
};
|
|
1187
|
-
|
|
1188
|
-
|
|
1659
|
+
forge("gh", ["auth", "status", "--active", "-h", "github.com"]);
|
|
1660
|
+
forge("glab", ["auth", "status"]);
|
|
1189
1661
|
if (running) {
|
|
1190
1662
|
const t = await api("/v1/team").catch(() => null);
|
|
1191
1663
|
if (t?.configured) {
|
|
@@ -1279,7 +1751,7 @@ url: ${resolveBaseUrl()}`);
|
|
|
1279
1751
|
headers: { "content-type": "application/json" },
|
|
1280
1752
|
body: JSON.stringify({ path: resolve3(".") })
|
|
1281
1753
|
});
|
|
1282
|
-
const
|
|
1754
|
+
const post = (path, body) => authedFetch(`${new SwarmClient().baseUrl}${path}`, {
|
|
1283
1755
|
method: "POST",
|
|
1284
1756
|
headers: { "content-type": "application/json" },
|
|
1285
1757
|
body: JSON.stringify({ projectId: proj.id, ...body })
|
|
@@ -1304,7 +1776,7 @@ url: ${resolveBaseUrl()}`);
|
|
|
1304
1776
|
case "create": {
|
|
1305
1777
|
if (!target)
|
|
1306
1778
|
throw new Error("usage: swarm wt create <name> [--base ref] [--branch name]");
|
|
1307
|
-
const r = await
|
|
1779
|
+
const r = await post("/v1/worktrees", {
|
|
1308
1780
|
name: target,
|
|
1309
1781
|
baseRef: flag("--base"),
|
|
1310
1782
|
branch: flag("--branch")
|
|
@@ -1339,7 +1811,7 @@ url: ${resolveBaseUrl()}`);
|
|
|
1339
1811
|
case "open": {
|
|
1340
1812
|
if (!target)
|
|
1341
1813
|
throw new Error("usage: swarm wt open <name|path>");
|
|
1342
|
-
const r = await
|
|
1814
|
+
const r = await post("/v1/worktrees/open", { worktree: target });
|
|
1343
1815
|
if (refuse(r) || json)
|
|
1344
1816
|
break;
|
|
1345
1817
|
console.log(`opened ${r.worktree}`);
|
|
@@ -1348,7 +1820,7 @@ url: ${resolveBaseUrl()}`);
|
|
|
1348
1820
|
case "rm": {
|
|
1349
1821
|
if (!target)
|
|
1350
1822
|
throw new Error("usage: swarm wt rm <name|path> [--force]");
|
|
1351
|
-
const r = await
|
|
1823
|
+
const r = await post("/v1/worktrees/remove", {
|
|
1352
1824
|
worktree: target,
|
|
1353
1825
|
force: rest.includes("--force")
|
|
1354
1826
|
});
|
|
@@ -1385,7 +1857,7 @@ url: ${resolveBaseUrl()}`);
|
|
|
1385
1857
|
break;
|
|
1386
1858
|
}
|
|
1387
1859
|
case "gc": {
|
|
1388
|
-
const r = await
|
|
1860
|
+
const r = await post("/v1/worktrees/gc", { apply: rest.includes("--apply") });
|
|
1389
1861
|
if (json)
|
|
1390
1862
|
console.log(JSON.stringify(r));
|
|
1391
1863
|
else if (!r.candidates.length)
|
|
@@ -1487,12 +1959,12 @@ url: ${resolveBaseUrl()}`);
|
|
|
1487
1959
|
break;
|
|
1488
1960
|
}
|
|
1489
1961
|
if (sub === "clear") {
|
|
1490
|
-
const
|
|
1962
|
+
const r = await authedFetch(`${new SwarmClient().baseUrl}/v1/dispatch`, {
|
|
1491
1963
|
method: "DELETE",
|
|
1492
1964
|
headers: { "content-type": "application/json" },
|
|
1493
1965
|
body: JSON.stringify({ projectId: proj.id, task: positional[1] })
|
|
1494
1966
|
}).then((x) => x.json());
|
|
1495
|
-
console.log(json ? JSON.stringify(
|
|
1967
|
+
console.log(json ? JSON.stringify(r) : `cleared ${r.cleared}`);
|
|
1496
1968
|
break;
|
|
1497
1969
|
}
|
|
1498
1970
|
const r = await authedFetch(`${new SwarmClient().baseUrl}/v1/dispatch`, {
|
|
@@ -1645,20 +2117,20 @@ ${flag("--body") ?? d.body}`);
|
|
|
1645
2117
|
else if (!runs.length)
|
|
1646
2118
|
console.log("no live runs here");
|
|
1647
2119
|
else
|
|
1648
|
-
for (const
|
|
1649
|
-
console.log(`${
|
|
2120
|
+
for (const r of runs)
|
|
2121
|
+
console.log(`${r.id} ${r.task.padEnd(12)} pid ${String(r.pid).padEnd(7)} ${r.owner.padEnd(10)} ${r.result ? `$${r.result.costUsd.toFixed(2)} \xB7 ${r.result.turns} turns${r.result.isError ? " \xB7 error" : ""}` : "starting\u2026"}`);
|
|
1650
2122
|
break;
|
|
1651
2123
|
}
|
|
1652
2124
|
if (sub === "send" || sub === "stop") {
|
|
1653
2125
|
const target = positionals[1];
|
|
1654
2126
|
if (!target)
|
|
1655
2127
|
throw new Error(`usage: swarm run ${sub} <task|id>${sub === "send" ? ' "text"' : ""}`);
|
|
1656
|
-
const
|
|
2128
|
+
const r = sub === "send" ? await authedFetch(`${base}/v1/runs/${encodeURIComponent(target)}/send`, {
|
|
1657
2129
|
method: "POST",
|
|
1658
2130
|
headers: { "content-type": "application/json" },
|
|
1659
2131
|
body: JSON.stringify({ text: positionals.slice(2).join(" ") })
|
|
1660
2132
|
}) : await authedFetch(`${base}/v1/runs/${encodeURIComponent(target)}`, { method: "DELETE" });
|
|
1661
|
-
const j = await
|
|
2133
|
+
const j = await r.json();
|
|
1662
2134
|
if (json)
|
|
1663
2135
|
console.log(JSON.stringify(j));
|
|
1664
2136
|
else if (j.ok)
|
|
@@ -1720,8 +2192,8 @@ ${flag("--body") ?? d.body}`);
|
|
|
1720
2192
|
body: JSON.stringify({ path: resolve3(".") })
|
|
1721
2193
|
});
|
|
1722
2194
|
if (cmd === "resume") {
|
|
1723
|
-
const
|
|
1724
|
-
const j = await
|
|
2195
|
+
const r = await authedFetch(`${new SwarmClient().baseUrl}/v1/handoffs?project=${proj.id}&task=${encodeURIComponent(task)}`);
|
|
2196
|
+
const j = await r.json();
|
|
1725
2197
|
if (json)
|
|
1726
2198
|
console.log(JSON.stringify(j.handoff));
|
|
1727
2199
|
else
|
|
@@ -1805,7 +2277,7 @@ ${flag("--body") ?? d.body}`);
|
|
|
1805
2277
|
break;
|
|
1806
2278
|
}
|
|
1807
2279
|
if (sub === "run") {
|
|
1808
|
-
const [, task, ...
|
|
2280
|
+
const [, task, ...gates] = positionals;
|
|
1809
2281
|
if (!task)
|
|
1810
2282
|
throw new Error("usage: swarm gate run <task> [gate\u2026] (default: the required gates that have a cmd)");
|
|
1811
2283
|
const r = await authedFetch(`${new SwarmClient().baseUrl}/v1/gates/run`, {
|
|
@@ -1814,7 +2286,7 @@ ${flag("--body") ?? d.body}`);
|
|
|
1814
2286
|
body: JSON.stringify({
|
|
1815
2287
|
projectId: proj.id,
|
|
1816
2288
|
task,
|
|
1817
|
-
gates
|
|
2289
|
+
gates,
|
|
1818
2290
|
sessionId: process.env.CLAUDE_SESSION_ID ?? null
|
|
1819
2291
|
})
|
|
1820
2292
|
}).then((x) => x.json());
|
|
@@ -1903,22 +2375,22 @@ ${flag("--body") ?? d.body}`);
|
|
|
1903
2375
|
const w = await api(`/v1/workflows?project=${proj.id}`);
|
|
1904
2376
|
const names = Object.keys(w.defs);
|
|
1905
2377
|
console.log(names.length ? `declared: ${names.join(", ")}` : "no [[workflows]] declared in .swarm.toml");
|
|
1906
|
-
for (const
|
|
1907
|
-
console.log(`#${
|
|
2378
|
+
for (const r of w.runs.slice(0, 20))
|
|
2379
|
+
console.log(`#${r.id} ${r.task} \xB7 ${r.workflow} \xB7 ${r.state === "running" ? `${r.stepLabel} (${r.step + 1}/${r.steps.length})` : r.state}${r.detail ? ` \u2014 ${r.detail.slice(0, 80)}` : ""}`);
|
|
1908
2380
|
break;
|
|
1909
2381
|
}
|
|
1910
2382
|
if (rest[0] === "stop") {
|
|
1911
|
-
const
|
|
1912
|
-
if (!
|
|
2383
|
+
const task = rest[1];
|
|
2384
|
+
if (!task)
|
|
1913
2385
|
throw new Error("usage: swarm workflow stop <task>");
|
|
1914
|
-
const
|
|
2386
|
+
const r = await api("/v1/workflows/stop", {
|
|
1915
2387
|
method: "POST",
|
|
1916
2388
|
headers: { "content-type": "application/json" },
|
|
1917
|
-
body: JSON.stringify({ projectId: proj.id, task
|
|
2389
|
+
body: JSON.stringify({ projectId: proj.id, task })
|
|
1918
2390
|
});
|
|
1919
|
-
if (!
|
|
1920
|
-
throw new Error(
|
|
1921
|
-
console.log(`stopped the workflow on ${
|
|
2391
|
+
if (!r.ok)
|
|
2392
|
+
throw new Error(r.error ?? "stop failed");
|
|
2393
|
+
console.log(`stopped the workflow on ${task}`);
|
|
1922
2394
|
break;
|
|
1923
2395
|
}
|
|
1924
2396
|
const [name, task] = rest;
|
|
@@ -2318,13 +2790,13 @@ would have fired (newest last):`);
|
|
|
2318
2790
|
return x != null && Number.isFinite(x) ? x : undefined;
|
|
2319
2791
|
};
|
|
2320
2792
|
if (sub === "ls" || !sub) {
|
|
2321
|
-
const
|
|
2793
|
+
const list = await api("/v1/resources");
|
|
2322
2794
|
if (json)
|
|
2323
|
-
console.log(JSON.stringify(
|
|
2324
|
-
else if (!
|
|
2795
|
+
console.log(JSON.stringify(list));
|
|
2796
|
+
else if (!list.length)
|
|
2325
2797
|
console.log("no resources held");
|
|
2326
2798
|
else
|
|
2327
|
-
for (const r of
|
|
2799
|
+
for (const r of list)
|
|
2328
2800
|
console.log(`${r.kind.padEnd(8)} ${r.name.padEnd(16)} ${r.owner.padEnd(12)} ${r.port != null ? `:${r.port}` : r.pid != null ? `pid ${r.pid}` : ""}`);
|
|
2329
2801
|
break;
|
|
2330
2802
|
}
|
|
@@ -2424,13 +2896,13 @@ would have fired (newest last):`);
|
|
|
2424
2896
|
case "demo": {
|
|
2425
2897
|
const home = join5(swarmHome(), "demo");
|
|
2426
2898
|
const port = "7799";
|
|
2427
|
-
const [
|
|
2428
|
-
if (!
|
|
2899
|
+
const [cmd, ...args] = daemonCommand();
|
|
2900
|
+
if (!cmd)
|
|
2429
2901
|
throw new Error("could not resolve the daemon command");
|
|
2430
2902
|
const env = { ...process.env, SWARM_HOME: home, SWARM_PORT: port, SWARM_DEMO: "1" };
|
|
2431
2903
|
const up = await authedFetch(`http://127.0.0.1:${port}/v1/health`).then((r) => r.ok).catch(() => false);
|
|
2432
2904
|
if (!up) {
|
|
2433
|
-
Bun.spawn([
|
|
2905
|
+
Bun.spawn([cmd, ...args], {
|
|
2434
2906
|
stdin: "ignore",
|
|
2435
2907
|
stdout: "ignore",
|
|
2436
2908
|
stderr: "ignore",
|