@ra3orblade/swarm 0.13.2 → 0.15.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 +15 -12
- package/dist/swarm-hook.js +1155 -175
- package/dist/swarm-mcp.js +2 -1
- package/dist/swarm.js +871 -255
- package/dist/swarmd.js +4872 -1431
- package/package.json +1 -1
- package/web/dashboard.css +1 -1
- package/web/dashboard.js +23 -19
- package/web/icons.js +2 -2
- 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,284 @@ 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
|
+
// packages/core/src/prompt.ts
|
|
200
|
+
var init_prompt = () => {};
|
|
201
|
+
|
|
156
202
|
// packages/core/src/adapters/claude-code/hooks.ts
|
|
157
|
-
var HOOK_EVENTS
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
203
|
+
var HOOK_EVENTS, OWN_SUMMARY;
|
|
204
|
+
var init_hooks = __esm(() => {
|
|
205
|
+
init_prompt();
|
|
206
|
+
HOOK_EVENTS = [
|
|
207
|
+
"SessionStart",
|
|
208
|
+
"UserPromptSubmit",
|
|
209
|
+
"PreToolUse",
|
|
210
|
+
"PostToolUse",
|
|
211
|
+
"SubagentStart",
|
|
212
|
+
"SubagentStop",
|
|
213
|
+
"Stop",
|
|
214
|
+
"SessionEnd",
|
|
215
|
+
"Notification",
|
|
216
|
+
"PreCompact",
|
|
217
|
+
"PermissionRequest",
|
|
218
|
+
"PostToolUseFailure"
|
|
219
|
+
];
|
|
220
|
+
OWN_SUMMARY = new Set([
|
|
221
|
+
"Bash",
|
|
222
|
+
"Read",
|
|
223
|
+
"Edit",
|
|
224
|
+
"Write",
|
|
225
|
+
"MultiEdit",
|
|
226
|
+
"NotebookEdit",
|
|
227
|
+
"Glob",
|
|
228
|
+
"Grep",
|
|
229
|
+
"Agent",
|
|
230
|
+
"Task",
|
|
231
|
+
"WebFetch",
|
|
232
|
+
"WebSearch",
|
|
233
|
+
"AskUserQuestion"
|
|
234
|
+
]);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// packages/core/src/guards.ts
|
|
238
|
+
var FETCHER, INTERP;
|
|
239
|
+
var init_guards = __esm(() => {
|
|
240
|
+
FETCHER = String.raw`\b(curl|wget|fetch|http|xh)\b`;
|
|
241
|
+
INTERP = String.raw`(sudo\s+(-\S+\s+)*)?(env\s+(\w+=\S+\s+)*)?(ba|z|k|da|fi)?sh|python[0-9.]*|node|perl|ruby|php|iex`;
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// packages/core/src/rules.ts
|
|
245
|
+
var LIVE_WINDOW_MS, customRe, WRITE_TOOLS;
|
|
246
|
+
var init_rules = __esm(() => {
|
|
247
|
+
init_guards();
|
|
248
|
+
LIVE_WINDOW_MS = 10 * 60000;
|
|
249
|
+
customRe = new WeakMap;
|
|
250
|
+
WRITE_TOOLS = new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// packages/core/src/policy.ts
|
|
254
|
+
function hookCoverage(settings) {
|
|
255
|
+
const hooks = settings && typeof settings === "object" && !Array.isArray(settings) ? settings.hooks : undefined;
|
|
256
|
+
const missing = [];
|
|
257
|
+
const short = [];
|
|
258
|
+
for (const ev of HOOK_EVENTS) {
|
|
259
|
+
const groups = Array.isArray(hooks?.[ev]) ? hooks?.[ev] : [];
|
|
260
|
+
const ours = groups.flatMap((g) => {
|
|
261
|
+
const list = g?.hooks;
|
|
262
|
+
return Array.isArray(list) ? list.filter((h) => hookIsOurs(h)) : [];
|
|
263
|
+
});
|
|
264
|
+
if (!ours.length)
|
|
265
|
+
missing.push(ev);
|
|
266
|
+
else if (ours.every((h) => typeof h.timeout === "number" && h.timeout < MIN_HOOK_TIMEOUT_S))
|
|
267
|
+
short.push(ev);
|
|
268
|
+
}
|
|
269
|
+
return { missing, short, complete: !missing.length && !short.length };
|
|
270
|
+
}
|
|
271
|
+
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;
|
|
272
|
+
var init_policy = __esm(() => {
|
|
273
|
+
init_hooks();
|
|
274
|
+
init_rules();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// packages/core/src/agenthooks.ts
|
|
278
|
+
var CAN_ASK;
|
|
279
|
+
var init_agenthooks = __esm(() => {
|
|
280
|
+
init_policy();
|
|
281
|
+
CAN_ASK = new Set(["claude-code"]);
|
|
282
|
+
});
|
|
283
|
+
|
|
169
284
|
// 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
|
-
|
|
285
|
+
var ROBOT, HEAD;
|
|
286
|
+
var init_art = __esm(() => {
|
|
287
|
+
ROBOT = [
|
|
288
|
+
" MM MM ",
|
|
289
|
+
" LL LL ",
|
|
290
|
+
" LL LL ",
|
|
291
|
+
" LM MM ",
|
|
292
|
+
" MD MS ",
|
|
293
|
+
" LE LE ",
|
|
294
|
+
" ME ME ",
|
|
295
|
+
" MS MS ",
|
|
296
|
+
" KK KK ",
|
|
297
|
+
" SSDDDSDDDDDDDDDDDDDDDDDDDDDDDDDDDDS ",
|
|
298
|
+
" SSDSDDDDDDDDDDDDDDDDDDDDDDDDDDDDDSS ",
|
|
299
|
+
" SSDOOOOOOOOOOOOOOOOOOOOOOOOOOOOOKSS ",
|
|
300
|
+
" SSOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMOSS ",
|
|
301
|
+
" DDKMMLLLMLLMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
302
|
+
" DDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
303
|
+
" SSSSODDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSSSS ",
|
|
304
|
+
" SSSSODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSSSS ",
|
|
305
|
+
" SMMMMODDOMMLMMMMMMMMMMMMMMMMMMMMMMMMMMODDOSMMMS ",
|
|
306
|
+
" DMSSSODDOMMMMOOOOOOMMMMMMMMMOOOOOOMMMMODDOSSSED ",
|
|
307
|
+
" DSSSSODDOMMMMODDDDDMMMMMMMMMODDDDDMMMMODDOSSSSK ",
|
|
308
|
+
" DSMMSODDOMMMMDDDDDDMMMMMMMMMKDDDDDMMMMODDOSMMSK ",
|
|
309
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDOSSSSK ",
|
|
310
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSK ",
|
|
311
|
+
" DSSSSODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSK ",
|
|
312
|
+
" DSSSKODDOMMMMDDDDDDMMMMMMMMMDDDDDDMMMMODDODSSSD ",
|
|
313
|
+
" OKKKKODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOKKKKO ",
|
|
314
|
+
" KKKKODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOOKKK ",
|
|
315
|
+
" KKKOODDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODDOOKKK ",
|
|
316
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
317
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
318
|
+
" DDOMMMMDDDDDDDDDDDDDDDDDDDDDMMMMODD ",
|
|
319
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
320
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
321
|
+
" DDOMMMMMMMMMMMMMMMMMMMMMMMMMMMMMODD ",
|
|
322
|
+
" DDDOOOOOOOOOOOOOOOOOOOOOOOOOOOOOKDD ",
|
|
323
|
+
" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDKDDDDD ",
|
|
324
|
+
" DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ",
|
|
325
|
+
" OOOOOOOOOOO ",
|
|
326
|
+
" OODDDDDKKOO ",
|
|
327
|
+
" DSMMMMMMSDD ",
|
|
328
|
+
" OOOOOOOOOOO ",
|
|
329
|
+
" KDSMMMMMESSKK ",
|
|
330
|
+
" MMMMMMSSKOOKDSMMMMMSSSDKOODSEMMMMMM ",
|
|
331
|
+
" SSSSDO MMMMMMSSKKOOOOOOOOOOOOOOOOOKSSSMMMMMM ODSSSS ",
|
|
332
|
+
" EEESSSSOOLLLLMMMMMESSSSSSSSSSSSSSSSSSSSMMMMMLLLLOOSSSSMME ",
|
|
333
|
+
" SMMSSSSKOEELLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLEEOOSSSSEMS ",
|
|
334
|
+
" DSSSSSSSOOSEEKSMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMSOEEDOOSSSSSSSK ",
|
|
335
|
+
" DSSSSSSDOOSEOSKEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMEOSDEDOODSSSSSSK ",
|
|
336
|
+
" KSSSSSSKOODSSOSEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEESOEEDOOKSSSSSSK ",
|
|
337
|
+
" DKSSSSKKOODSMEEMLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMSEMSDOOKKSSSSDK ",
|
|
338
|
+
" OKDDKDKKOOKSMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMSKOOKKKKKKKO ",
|
|
339
|
+
" OOOOOKKKOOKSMMMMESSSSSSSSSSSSSMMMMEEEEEESSSSEMMMMSKOOKKKOOOOO ",
|
|
340
|
+
" OOOOOOKKOOKSMMMSSKKKKKKKKKKKKKKMMMDKOOOOOOOODDMMMSKOOKKOOOOOO ",
|
|
341
|
+
" OKSSKOOOOOKSMMMKKMLLLLLLLLLLLMKMMMDDSSSSSSSSDDMMMSKOOOOODSSKO ",
|
|
342
|
+
" SDOKKK KSMMMKDLLLLLLLLLLLLLKMMMKDKKKDDKKKDKMMMSK KKKKDS ",
|
|
343
|
+
" DMLLMKO KSMMMKDLLLLLLLLLLLLLKMMMDDDDDDDDDSKDMMMSK ODMLLMD ",
|
|
344
|
+
" DELLMSD KSMMMKKMLLLLLLLLLLLLKMMMDKKKKKKKKKDDMMMSK DSMLLEO ",
|
|
345
|
+
" KSKKKKDO KSMMMEDDDDKKDDDKKKDKSMMMDDDDDDDDDSDDMMMSK ODDKKKSK ",
|
|
346
|
+
" EMLLMDO KSMMMMLLLLLLLLLLLLLLLMMMDOOOOOOOOODDMMMSK ODMLLME ",
|
|
347
|
+
" KMLLMSD KSMMMMMMMMMMMMMMMMMMMMMMDDSSDDSSSSDDMMMSK SSMLLEK ",
|
|
348
|
+
" KSKKKKSO KSMMMMMOOMMOOMKOEMOOMMMMDOOOOOOOOODDMMMSK OSKKKKSO ",
|
|
349
|
+
" SMLLMDO KSMMMMMKKMMKKMDKEMKKMMMMKDDDDSSSSDDDMMMSK ODMLLMS ",
|
|
350
|
+
" SMMMMSD KSMMMMMEEMMEEMEEMMEEMMMMDSOOOOOOOODDMMSSK DSMMMMD ",
|
|
351
|
+
" OOOOOOO KSSMMMMMMMMMMMMMMMMMMMMMDDDDDDDDDDDDMSSSK OOOOOOO ",
|
|
352
|
+
" KSMLLLMMSKO KSSSSMMMMMMMMMMMMMMMMMMMSOOOOOOOOOOSSSSSK OKSMLLLLMSO ",
|
|
353
|
+
" DSMMMEEESKK KSSKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSOSSK KDSMMMMMESD ",
|
|
354
|
+
" DSMMMMMESKK KSOOKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSOOKSK KKSMMMMMMSD ",
|
|
355
|
+
" DSMMMMMESKK OKSKSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSDSKO KDSMMMMMMSD ",
|
|
356
|
+
" KDDDDDDDDKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKDDDDDDDDO ",
|
|
357
|
+
" OOOOOOOOOOO OOOOOOOOO OOOOOOOOO OOOOOOOOOOO ",
|
|
358
|
+
"DSDO OSSO ODKKKKKKK OKKKKKKKO KEDO ODEK",
|
|
359
|
+
"SMDO OSMD KDSSSSSSK KDSSSSSKO SMDO ODMS",
|
|
360
|
+
"DEKO OOED OOKKKOOO OOOKKOOO SSOO OKMS",
|
|
361
|
+
"DEKO OOED SEMMMMSK OSMMMMED SSKO OKES",
|
|
362
|
+
"DSSO OESK SEMMMMSK OSMMMMED KSSO OSSK",
|
|
363
|
+
"KSMS EEDO OOKKKKKO OOKKKKKO OSEE EMSO",
|
|
364
|
+
" DSS SSK OSEEESDO ODSEEESO KSS SSD ",
|
|
365
|
+
" OOO OO SEMMMMSK OSMMMMED OO OOO ",
|
|
366
|
+
" KSSSSSDO OKSSESSK ",
|
|
367
|
+
" DKKDDDDDDKKDK KDKDDDDDDDKDK ",
|
|
368
|
+
" SSMLLMMMMMMLMSK DSSMMMMMMMLLMSS ",
|
|
369
|
+
" SMLMMMMMMMMLLED SEMMMMMMMMMMLMS ",
|
|
370
|
+
" DMMMMMMMMMMMMMMD SMMMMMMMMMMMMMSK ",
|
|
371
|
+
" ODSSSSSSSSSSSSSSDO ODSSSSSSSSSSSSSSKO ",
|
|
372
|
+
" OOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOO ",
|
|
373
|
+
" OKSSSSSSSSSSSSSSK KSSSSSSSSSSSSSSKO ",
|
|
374
|
+
" OKDDDDDDDDDDDDDDK KDDDDDDDDDDDDDDOO "
|
|
375
|
+
];
|
|
376
|
+
HEAD = ROBOT.slice(0, 37);
|
|
377
|
+
});
|
|
378
|
+
|
|
260
379
|
// 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
|
-
|
|
380
|
+
var AUDIT_TYPES, AUDIT_TYPES_SQL, DEFAULT_PRIVACY;
|
|
381
|
+
var init_audit = __esm(() => {
|
|
382
|
+
AUDIT_TYPES = new Set([
|
|
383
|
+
"session.started",
|
|
384
|
+
"session.ended",
|
|
385
|
+
"tool.denied",
|
|
386
|
+
"claim.acquired",
|
|
387
|
+
"claim.renewed",
|
|
388
|
+
"claim.released",
|
|
389
|
+
"claim.expired",
|
|
390
|
+
"claim.orphaned",
|
|
391
|
+
"claim.denied",
|
|
392
|
+
"rules.changed",
|
|
393
|
+
"worktree.reclaimed",
|
|
394
|
+
"worktree.created",
|
|
395
|
+
"worktree.removed",
|
|
396
|
+
"worktree.bootstrapped",
|
|
397
|
+
"pr.opened",
|
|
398
|
+
"question.asked",
|
|
399
|
+
"question.answered",
|
|
400
|
+
"dispatch.queued",
|
|
401
|
+
"dispatch.started",
|
|
402
|
+
"dispatch.finished",
|
|
403
|
+
"resource.acquired",
|
|
404
|
+
"resource.released",
|
|
405
|
+
"resource.reaped",
|
|
406
|
+
"process.started",
|
|
407
|
+
"process.exited",
|
|
408
|
+
"gate.recorded",
|
|
409
|
+
"gate.blocked",
|
|
410
|
+
"codify.applied",
|
|
411
|
+
"handoff.recorded",
|
|
412
|
+
"permission.requested",
|
|
413
|
+
"permission.resolved",
|
|
414
|
+
"incident.opened",
|
|
415
|
+
"incident.acked",
|
|
416
|
+
"run.result",
|
|
417
|
+
"workflow.started",
|
|
418
|
+
"workflow.finished"
|
|
419
|
+
]);
|
|
420
|
+
AUDIT_TYPES_SQL = [...AUDIT_TYPES].map((t) => `'${t}'`).join(", ");
|
|
421
|
+
DEFAULT_PRIVACY = {
|
|
422
|
+
store_prompts: true,
|
|
423
|
+
store_reasoning: true,
|
|
424
|
+
redact: []
|
|
425
|
+
};
|
|
426
|
+
});
|
|
308
427
|
|
|
428
|
+
// packages/core/src/budget.ts
|
|
429
|
+
var BUDGET_ASK_TOOLS;
|
|
430
|
+
var init_budget = __esm(() => {
|
|
431
|
+
BUDGET_ASK_TOOLS = new Set(["Bash", "Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
432
|
+
});
|
|
309
433
|
// packages/core/src/workflows.ts
|
|
310
|
-
var NAME_RE = /^[a-z0-9][a-z0-9_.-]{0,39}$/i;
|
|
311
434
|
function isRecord(v) {
|
|
312
435
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
313
436
|
}
|
|
@@ -354,10 +477,14 @@ function parseWorkflows(raw) {
|
|
|
354
477
|
}
|
|
355
478
|
return out;
|
|
356
479
|
}
|
|
480
|
+
var NAME_RE;
|
|
481
|
+
var init_workflows = __esm(() => {
|
|
482
|
+
NAME_RE = /^[a-z0-9][a-z0-9_.-]{0,39}$/i;
|
|
483
|
+
});
|
|
357
484
|
|
|
358
485
|
// packages/core/src/config.ts
|
|
359
|
-
|
|
360
|
-
|
|
486
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
487
|
+
import { join as join2 } from "path";
|
|
361
488
|
function parseGateDefs(gates) {
|
|
362
489
|
const out = {};
|
|
363
490
|
if (!isRecord2(gates))
|
|
@@ -382,38 +509,35 @@ function parseGateDefs(gates) {
|
|
|
382
509
|
}
|
|
383
510
|
return out;
|
|
384
511
|
}
|
|
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: [] }
|
|
512
|
+
function parseCustomRules(raw) {
|
|
513
|
+
if (!Array.isArray(raw))
|
|
514
|
+
return [];
|
|
515
|
+
const out = [];
|
|
516
|
+
const seen = new Set;
|
|
517
|
+
for (const v of raw) {
|
|
518
|
+
if (!isRecord2(v))
|
|
519
|
+
continue;
|
|
520
|
+
const name = typeof v.name === "string" ? v.name.trim() : "";
|
|
521
|
+
const match = typeof v.match === "string" ? v.match : "";
|
|
522
|
+
if (!/^[a-z0-9][a-z0-9_.-]{0,39}$/i.test(name) || !match || seen.has(name))
|
|
523
|
+
continue;
|
|
524
|
+
try {
|
|
525
|
+
new RegExp(match);
|
|
526
|
+
} catch {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
const action = REWRITE_MODES.includes(v.action) ? v.action : "ask";
|
|
530
|
+
seen.add(name);
|
|
531
|
+
out.push({
|
|
532
|
+
name,
|
|
533
|
+
match,
|
|
534
|
+
action,
|
|
535
|
+
...typeof v.replace === "string" ? { replace: v.replace } : {},
|
|
536
|
+
...typeof v.reason === "string" && v.reason.trim() ? { reason: v.reason.trim() } : {}
|
|
537
|
+
});
|
|
414
538
|
}
|
|
415
|
-
|
|
416
|
-
|
|
539
|
+
return out;
|
|
540
|
+
}
|
|
417
541
|
function isRecord2(v) {
|
|
418
542
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
419
543
|
}
|
|
@@ -441,12 +565,9 @@ function isRepoRelative(f) {
|
|
|
441
565
|
return false;
|
|
442
566
|
return !t.split(/[/\\]/).some((seg) => seg === "..");
|
|
443
567
|
}
|
|
444
|
-
var days = (v, fallback) => {
|
|
445
|
-
const n = Number(v);
|
|
446
|
-
return Number.isInteger(n) && n >= 0 ? Math.min(n, 3650) : fallback;
|
|
447
|
-
};
|
|
448
568
|
function validate(c) {
|
|
449
569
|
const mode = (v, fallback) => MODES.includes(v) ? v : fallback;
|
|
570
|
+
const rewriteMode = (v, fallback) => REWRITE_MODES.includes(v) ? v : fallback;
|
|
450
571
|
const port = Number(c.daemon?.port);
|
|
451
572
|
const source = c.tasks?.source;
|
|
452
573
|
const setup = c.worktree?.setup;
|
|
@@ -477,13 +598,28 @@ function validate(c) {
|
|
|
477
598
|
gates: {
|
|
478
599
|
required: Array.isArray(rawGates?.required) ? rawGates.required.filter((g) => typeof g === "string" && g.trim() !== "") : [],
|
|
479
600
|
auto: AUTO_MODES.includes(auto) ? auto : "session-end",
|
|
601
|
+
on_stop: rawGates?.on_stop === "block" ? "block" : "record",
|
|
602
|
+
max_blocks: (() => {
|
|
603
|
+
const n = Number(rawGates?.max_blocks);
|
|
604
|
+
return Number.isInteger(n) && n >= 0 && n <= 20 ? n : 3;
|
|
605
|
+
})(),
|
|
606
|
+
stop_timeout: (() => {
|
|
607
|
+
const n = Number(rawGates?.stop_timeout);
|
|
608
|
+
return Number.isFinite(n) && n >= 5 && n <= 1800 ? n : 300;
|
|
609
|
+
})(),
|
|
480
610
|
defs: parseGateDefs(rawGates)
|
|
481
611
|
},
|
|
482
612
|
budget: {
|
|
483
613
|
daily: usd(b.daily),
|
|
484
614
|
weekly: usd(b.weekly),
|
|
485
615
|
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"
|
|
616
|
+
on_exceed: b.on_exceed === "ask" || b.on_exceed === "stop" ? b.on_exceed : "warn",
|
|
617
|
+
window_warn_at: (() => {
|
|
618
|
+
if (b.window_warn_at === false || b.window_warn_at === null || b.window_warn_at === 0)
|
|
619
|
+
return null;
|
|
620
|
+
const w = Number(b.window_warn_at);
|
|
621
|
+
return Number.isFinite(w) && w > 0 && w < 1 ? w : 0.8;
|
|
622
|
+
})()
|
|
487
623
|
},
|
|
488
624
|
workflows: parseWorkflows(c.workflows),
|
|
489
625
|
notify: {
|
|
@@ -492,6 +628,36 @@ function validate(c) {
|
|
|
492
628
|
return typeof w === "string" && /^https?:\/\//.test(w.trim()) ? w.trim() : null;
|
|
493
629
|
})()
|
|
494
630
|
},
|
|
631
|
+
otel: (() => {
|
|
632
|
+
const o = c.otel ?? {};
|
|
633
|
+
const e = typeof o.endpoint === "string" ? o.endpoint.trim().replace(/\/+$/, "") : "";
|
|
634
|
+
const h = o.headers && typeof o.headers === "object" ? o.headers : {};
|
|
635
|
+
const n = Number(o.interval);
|
|
636
|
+
return {
|
|
637
|
+
endpoint: /^https?:\/\//.test(e) ? e : null,
|
|
638
|
+
headers: Object.fromEntries(Object.entries(h).filter((kv) => typeof kv[1] === "string")),
|
|
639
|
+
compat: o.compat === "claude-code" ? "claude-code" : "genai",
|
|
640
|
+
include_content: o.include_content === true,
|
|
641
|
+
interval: Number.isFinite(n) && n >= 5 && n <= 3600 ? Math.round(n) : 30
|
|
642
|
+
};
|
|
643
|
+
})(),
|
|
644
|
+
messages: {
|
|
645
|
+
wake: c.messages?.wake !== false
|
|
646
|
+
},
|
|
647
|
+
codify: {
|
|
648
|
+
target: (() => {
|
|
649
|
+
const t = c.codify?.target;
|
|
650
|
+
return t === "claude-md" || t === "swarm-toml" ? t : "both";
|
|
651
|
+
})()
|
|
652
|
+
},
|
|
653
|
+
broker: {
|
|
654
|
+
interactive_wait: (() => {
|
|
655
|
+
const w = Number(c.broker?.interactive_wait);
|
|
656
|
+
if (!Number.isFinite(w) || w < 0)
|
|
657
|
+
return 30;
|
|
658
|
+
return Math.min(Math.round(w), 120);
|
|
659
|
+
})()
|
|
660
|
+
},
|
|
495
661
|
models: {
|
|
496
662
|
allow: Array.isArray(c.models?.allow) ? c.models.allow.filter((m) => typeof m === "string" && m.trim() !== "") : []
|
|
497
663
|
},
|
|
@@ -538,6 +704,19 @@ function validate(c) {
|
|
|
538
704
|
protected_ports: mode(c.rules?.protected_ports, "ask"),
|
|
539
705
|
no_foreign_worktree: mode(c.rules?.no_foreign_worktree, "ask"),
|
|
540
706
|
claim_required_to_write: mode(c.rules?.claim_required_to_write, "off"),
|
|
707
|
+
no_verify: rewriteMode(c.rules?.no_verify, "off"),
|
|
708
|
+
dry_run_first: rewriteMode(c.rules?.dry_run_first, "off"),
|
|
709
|
+
custom: parseCustomRules(c.rules?.custom),
|
|
710
|
+
destructive_fs: mode(c.rules?.destructive_fs, "off"),
|
|
711
|
+
destructive_infra: mode(c.rules?.destructive_infra, "off"),
|
|
712
|
+
pipe_to_shell: mode(c.rules?.pipe_to_shell, "off"),
|
|
713
|
+
secrets: mode(c.rules?.secrets, "off"),
|
|
714
|
+
config_tamper: mode(c.rules?.config_tamper, "off"),
|
|
715
|
+
collision_context: c.rules?.collision_context !== false,
|
|
716
|
+
collision_window: (() => {
|
|
717
|
+
const n = Number(c.rules?.collision_window);
|
|
718
|
+
return Number.isFinite(n) && n >= 1 && n <= 240 ? Math.round(n) : 15;
|
|
719
|
+
})(),
|
|
541
720
|
protected: {
|
|
542
721
|
ports: Array.isArray(c.rules?.protected?.ports) ? c.rules.protected.ports.filter((p) => Number.isInteger(p) && p > 0 && p < 65536) : []
|
|
543
722
|
}
|
|
@@ -571,7 +750,6 @@ function setPath(obj, path, value) {
|
|
|
571
750
|
}
|
|
572
751
|
cur[segs[segs.length - 1]] = value;
|
|
573
752
|
}
|
|
574
|
-
var isLockedBy = (path, lock) => path === lock || path.startsWith(`${lock}.`);
|
|
575
753
|
function readLayer(path) {
|
|
576
754
|
return existsSync3(path) ? parseToml(readFileSync2(path, "utf8"), path) : null;
|
|
577
755
|
}
|
|
@@ -620,42 +798,361 @@ function loadConfigDetailed(opts = {}) {
|
|
|
620
798
|
policy: { path: policyRaw ? policyPath : null, locked }
|
|
621
799
|
};
|
|
622
800
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
801
|
+
var DEFAULT_GATE_TIMEOUT_S = 900, AUTO_MODES, DEFAULT_CONFIG, MODES, REWRITE_MODES, days = (v, fallback) => {
|
|
802
|
+
const n = Number(v);
|
|
803
|
+
return Number.isInteger(n) && n >= 0 ? Math.min(n, 3650) : fallback;
|
|
804
|
+
}, isLockedBy = (path, lock) => path === lock || path.startsWith(`${lock}.`);
|
|
805
|
+
var init_config = __esm(() => {
|
|
806
|
+
init_audit();
|
|
807
|
+
init_workflows();
|
|
808
|
+
AUTO_MODES = ["session-end", "stop", "off"];
|
|
809
|
+
DEFAULT_CONFIG = {
|
|
810
|
+
daemon: { port: 7777, auth: "loopback-optional" },
|
|
811
|
+
tasks: { source: null, labels: [], team: null },
|
|
812
|
+
gates: {
|
|
813
|
+
required: [],
|
|
814
|
+
auto: "session-end",
|
|
815
|
+
on_stop: "record",
|
|
816
|
+
max_blocks: 3,
|
|
817
|
+
stop_timeout: 300,
|
|
818
|
+
defs: {}
|
|
819
|
+
},
|
|
820
|
+
workflows: {},
|
|
821
|
+
budget: { daily: null, weekly: null, warn_at: 0.8, on_exceed: "warn", window_warn_at: 0.8 },
|
|
822
|
+
models: { allow: [] },
|
|
823
|
+
notify: { webhook: null },
|
|
824
|
+
otel: { endpoint: null, headers: {}, compat: "genai", include_content: false, interval: 30 },
|
|
825
|
+
messages: { wake: true },
|
|
826
|
+
codify: { target: "both" },
|
|
827
|
+
broker: { interactive_wait: 30 },
|
|
828
|
+
team: { url: null, forward: ["ledger", "cost"], interval: 5 },
|
|
829
|
+
events: { retain_days: 30 },
|
|
830
|
+
audit: { retain_days: 0 },
|
|
831
|
+
privacy: DEFAULT_PRIVACY,
|
|
832
|
+
dispatch: {
|
|
833
|
+
max_parallel: 2,
|
|
834
|
+
permission_mode: null,
|
|
835
|
+
model: null,
|
|
836
|
+
max_turns: null,
|
|
837
|
+
require_pr: true,
|
|
838
|
+
profile: null
|
|
839
|
+
},
|
|
840
|
+
worktree: { setup: null, copy: [], open: null },
|
|
841
|
+
rules: {
|
|
842
|
+
shared_tree: "ask",
|
|
843
|
+
destructive_git: "ask",
|
|
844
|
+
pattern_kill: "ask",
|
|
845
|
+
protected_ports: "ask",
|
|
846
|
+
no_foreign_worktree: "ask",
|
|
847
|
+
claim_required_to_write: "off",
|
|
848
|
+
no_verify: "off",
|
|
849
|
+
dry_run_first: "off",
|
|
850
|
+
custom: [],
|
|
851
|
+
destructive_fs: "off",
|
|
852
|
+
destructive_infra: "off",
|
|
853
|
+
pipe_to_shell: "off",
|
|
854
|
+
secrets: "off",
|
|
855
|
+
config_tamper: "off",
|
|
856
|
+
collision_context: true,
|
|
857
|
+
collision_window: 15,
|
|
858
|
+
protected: { ports: [] }
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
MODES = ["ask", "deny", "off"];
|
|
862
|
+
REWRITE_MODES = ["rewrite", "ask", "deny", "off"];
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
// packages/core/src/context.ts
|
|
866
|
+
var init_context = () => {};
|
|
867
|
+
|
|
868
|
+
// packages/core/src/dag.ts
|
|
869
|
+
var init_dag = () => {};
|
|
870
|
+
// packages/core/src/dryrun.ts
|
|
871
|
+
var init_dryrun = __esm(() => {
|
|
872
|
+
init_rules();
|
|
873
|
+
});
|
|
874
|
+
// packages/core/src/gatehealth.ts
|
|
875
|
+
var init_gatehealth = () => {};
|
|
876
|
+
|
|
877
|
+
// packages/core/src/gates.ts
|
|
878
|
+
var init_gates = () => {};
|
|
879
|
+
|
|
880
|
+
// packages/core/src/graphs.ts
|
|
881
|
+
var init_graphs = __esm(() => {
|
|
882
|
+
init_rules();
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
// packages/core/src/heat.ts
|
|
886
|
+
var init_heat = __esm(() => {
|
|
887
|
+
init_rules();
|
|
888
|
+
});
|
|
889
|
+
|
|
890
|
+
// packages/core/src/worktree.ts
|
|
891
|
+
var init_worktree = __esm(() => {
|
|
892
|
+
init_config();
|
|
893
|
+
});
|
|
894
|
+
|
|
626
895
|
// packages/core/src/hygiene.ts
|
|
627
|
-
var HYGIENE_DEFAULTS
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
896
|
+
var HYGIENE_DEFAULTS;
|
|
897
|
+
var init_hygiene = __esm(() => {
|
|
898
|
+
init_worktree();
|
|
899
|
+
HYGIENE_DEFAULTS = {
|
|
900
|
+
staleDays: 2,
|
|
901
|
+
abandonedDays: 30,
|
|
902
|
+
hungryRssKb: 1024 * 1024,
|
|
903
|
+
heavyKb: 2 * 1024 * 1024
|
|
904
|
+
};
|
|
905
|
+
});
|
|
906
|
+
|
|
633
907
|
// packages/core/src/ledger.ts
|
|
634
|
-
var EDIT_TOOLS
|
|
908
|
+
var EDIT_TOOLS;
|
|
909
|
+
var init_ledger = __esm(() => {
|
|
910
|
+
init_prompt();
|
|
911
|
+
EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
|
|
912
|
+
});
|
|
913
|
+
// packages/core/src/lessons-apply.ts
|
|
914
|
+
var init_lessons_apply = () => {};
|
|
915
|
+
|
|
916
|
+
// packages/core/src/lineage.ts
|
|
917
|
+
var init_lineage = __esm(() => {
|
|
918
|
+
init_dag();
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
// packages/core/src/mcphealth.ts
|
|
922
|
+
var init_mcphealth = __esm(() => {
|
|
923
|
+
init_gatehealth();
|
|
924
|
+
});
|
|
925
|
+
// packages/core/src/memory.ts
|
|
926
|
+
var init_memory = () => {};
|
|
927
|
+
// packages/core/src/otel.ts
|
|
928
|
+
var init_otel = () => {};
|
|
929
|
+
|
|
635
930
|
// packages/core/src/outcomes.ts
|
|
636
|
-
var DEFAULT_BRANCHES
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
931
|
+
var DEFAULT_BRANCHES;
|
|
932
|
+
var init_outcomes = __esm(() => {
|
|
933
|
+
DEFAULT_BRANCHES = new Set(["main", "master", "develop", "trunk"]);
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// packages/core/src/pricing.ts
|
|
937
|
+
var init_pricing = () => {};
|
|
938
|
+
// packages/core/src/provenance.ts
|
|
939
|
+
var init_provenance = () => {};
|
|
940
|
+
// packages/core/src/quota.ts
|
|
941
|
+
var BURN_MIN_SPAN_MS, BURN_LOOKBACK_MS;
|
|
942
|
+
var init_quota = __esm(() => {
|
|
943
|
+
BURN_MIN_SPAN_MS = 10 * 60000;
|
|
944
|
+
BURN_LOOKBACK_MS = 60 * 60000;
|
|
945
|
+
});
|
|
946
|
+
// packages/core/src/security.ts
|
|
947
|
+
var init_security = __esm(() => {
|
|
948
|
+
init_rules();
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// packages/core/src/stall.ts
|
|
952
|
+
var init_stall = () => {};
|
|
953
|
+
|
|
954
|
+
// packages/core/src/statusline.ts
|
|
955
|
+
function parseStatuslinePayload(text) {
|
|
956
|
+
try {
|
|
957
|
+
const v = JSON.parse(text);
|
|
958
|
+
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
959
|
+
} catch {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function pct(color, label, value) {
|
|
964
|
+
const s = `${label} ${Math.round(value)}%`;
|
|
965
|
+
if (value >= 90)
|
|
966
|
+
return red(color, s);
|
|
967
|
+
if (value >= 70)
|
|
968
|
+
return yellow(color, s);
|
|
969
|
+
return s;
|
|
970
|
+
}
|
|
971
|
+
function money(usd) {
|
|
972
|
+
return usd >= 10 ? `$${usd.toFixed(0)}` : `$${usd.toFixed(2)}`;
|
|
973
|
+
}
|
|
974
|
+
function renderStatusline(payload, state, opts = {}) {
|
|
975
|
+
const color = opts.color ?? false;
|
|
976
|
+
const local = [];
|
|
977
|
+
const model = payload.model?.display_name ?? payload.model?.id;
|
|
978
|
+
if (model)
|
|
979
|
+
local.push(bold(color, model));
|
|
980
|
+
const ctx = payload.context_window?.used_percentage;
|
|
981
|
+
if (typeof ctx === "number")
|
|
982
|
+
local.push(pct(color, "ctx", ctx));
|
|
983
|
+
const cost = payload.cost?.total_cost_usd;
|
|
984
|
+
if (typeof cost === "number")
|
|
985
|
+
local.push(money(cost));
|
|
986
|
+
const five = payload.rate_limits?.five_hour?.used_percentage;
|
|
987
|
+
if (typeof five === "number")
|
|
988
|
+
local.push(pct(color, "5h", five));
|
|
989
|
+
const week = payload.rate_limits?.seven_day?.used_percentage;
|
|
990
|
+
if (typeof week === "number")
|
|
991
|
+
local.push(pct(color, "7d", week));
|
|
992
|
+
const swarm = [];
|
|
993
|
+
if (state) {
|
|
994
|
+
if (state.task)
|
|
995
|
+
swarm.push(`${state.task.id} ${dim(color, `${state.task.leftMin}m`)}`);
|
|
996
|
+
if (state.budget && state.budget.level !== "ok")
|
|
997
|
+
swarm.push((state.budget.level === "exceeded" ? red : yellow)(color, `budget ${state.budget.level} ${Math.round(state.budget.pct * 100)}%`));
|
|
998
|
+
if (state.incidents > 0)
|
|
999
|
+
swarm.push(yellow(color, `${state.incidents} incident${state.incidents === 1 ? "" : "s"}`));
|
|
1000
|
+
if (state.waitingOn > 0)
|
|
1001
|
+
swarm.push(red(color, `waiting on you${state.waitingOn > 1 ? ` \xD7${state.waitingOn}` : ""}`));
|
|
1002
|
+
if (state.inbox > 0)
|
|
1003
|
+
swarm.push(`inbox ${state.inbox}`);
|
|
1004
|
+
if (state.quota) {
|
|
1005
|
+
const short = { five_hour: "5h", seven_day: "7d", spend_limit: "spend" }[state.quota.window];
|
|
1006
|
+
const h = state.quota.hoursToLimit;
|
|
1007
|
+
if (h == null)
|
|
1008
|
+
swarm.push(red(color, `${short} limit reached`));
|
|
1009
|
+
else {
|
|
1010
|
+
const s = `${short} limit in ${h < 1 ? `${Math.max(1, Math.round(h * 60))}m` : `${Math.round(h)}h`}`;
|
|
1011
|
+
swarm.push(h < 1 ? red(color, s) : h < 3 ? yellow(color, s) : s);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
const sep = dim(color, " \xB7 ");
|
|
1016
|
+
const bar = dim(color, " \u2502 ");
|
|
1017
|
+
const left = local.join(sep);
|
|
1018
|
+
if (!swarm.length)
|
|
1019
|
+
return left;
|
|
1020
|
+
const right = swarm.join(sep);
|
|
1021
|
+
return left ? `${left}${bar}${right}` : right;
|
|
1022
|
+
}
|
|
1023
|
+
function statuslineIsOurs(setting) {
|
|
1024
|
+
if (!setting || typeof setting !== "object")
|
|
1025
|
+
return false;
|
|
1026
|
+
const cmd = setting.command;
|
|
1027
|
+
return typeof cmd === "string" && (cmd.includes("swarm-hook") || cmd.includes("/packages/hook/src/bin.ts")) && /\bstatusline\b/.test(cmd);
|
|
1028
|
+
}
|
|
1029
|
+
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);
|
|
1030
|
+
|
|
1031
|
+
// packages/core/src/tasks.ts
|
|
1032
|
+
var init_tasks = () => {};
|
|
1033
|
+
|
|
1034
|
+
// packages/core/src/team.ts
|
|
1035
|
+
var init_team = () => {};
|
|
1036
|
+
|
|
1037
|
+
// packages/core/src/teamsetup.ts
|
|
1038
|
+
var init_teamsetup = () => {};
|
|
1039
|
+
|
|
1040
|
+
// packages/core/src/transitions.ts
|
|
1041
|
+
var init_transitions = () => {};
|
|
1042
|
+
|
|
1043
|
+
// packages/core/src/types.ts
|
|
1044
|
+
var init_types = () => {};
|
|
1045
|
+
|
|
1046
|
+
// packages/core/src/waiting.ts
|
|
1047
|
+
var init_waiting = () => {};
|
|
1048
|
+
|
|
1049
|
+
// packages/core/src/index.ts
|
|
1050
|
+
var init_src2 = __esm(() => {
|
|
1051
|
+
init_actor();
|
|
1052
|
+
init_adapters();
|
|
1053
|
+
init_hooks();
|
|
1054
|
+
init_agenthooks();
|
|
1055
|
+
init_art();
|
|
1056
|
+
init_audit();
|
|
1057
|
+
init_budget();
|
|
1058
|
+
init_config();
|
|
1059
|
+
init_context();
|
|
1060
|
+
init_dag();
|
|
1061
|
+
init_dryrun();
|
|
1062
|
+
init_gatehealth();
|
|
1063
|
+
init_gates();
|
|
1064
|
+
init_graphs();
|
|
1065
|
+
init_heat();
|
|
1066
|
+
init_hygiene();
|
|
1067
|
+
init_ledger();
|
|
1068
|
+
init_lessons_apply();
|
|
1069
|
+
init_lineage();
|
|
1070
|
+
init_mcphealth();
|
|
1071
|
+
init_memory();
|
|
1072
|
+
init_otel();
|
|
1073
|
+
init_outcomes();
|
|
1074
|
+
init_policy();
|
|
1075
|
+
init_pricing();
|
|
1076
|
+
init_prompt();
|
|
1077
|
+
init_provenance();
|
|
1078
|
+
init_quota();
|
|
1079
|
+
init_rules();
|
|
1080
|
+
init_security();
|
|
1081
|
+
init_stall();
|
|
1082
|
+
init_tasks();
|
|
1083
|
+
init_team();
|
|
1084
|
+
init_teamsetup();
|
|
1085
|
+
init_transitions();
|
|
1086
|
+
init_types();
|
|
1087
|
+
init_waiting();
|
|
1088
|
+
init_workflows();
|
|
1089
|
+
init_worktree();
|
|
1090
|
+
});
|
|
1091
|
+
|
|
1092
|
+
// packages/hook/src/statusline.ts
|
|
1093
|
+
async function fetchStatuslineState(payload, opts = {}) {
|
|
1094
|
+
const timeout = opts.timeoutMs ?? Number(process.env.SWARM_HOOK_TIMEOUT_MS ?? 400);
|
|
1095
|
+
const post = async (base) => {
|
|
1096
|
+
const r = await authedFetch(`${base}/v1/statusline`, {
|
|
1097
|
+
method: "POST",
|
|
1098
|
+
headers: { "content-type": "application/json" },
|
|
1099
|
+
body: JSON.stringify(payload),
|
|
1100
|
+
signal: AbortSignal.timeout(timeout)
|
|
650
1101
|
});
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
1102
|
+
return r.ok ? await r.json() : null;
|
|
1103
|
+
};
|
|
1104
|
+
const base = opts.baseUrl ?? resolveBaseUrl();
|
|
1105
|
+
const fallback = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
1106
|
+
try {
|
|
1107
|
+
const s = await post(base);
|
|
1108
|
+
if (s)
|
|
1109
|
+
return s;
|
|
1110
|
+
} catch {}
|
|
1111
|
+
if (base !== fallback && !opts.baseUrl) {
|
|
1112
|
+
try {
|
|
1113
|
+
return await post(fallback);
|
|
1114
|
+
} catch {}
|
|
655
1115
|
}
|
|
656
|
-
return
|
|
1116
|
+
return null;
|
|
1117
|
+
}
|
|
1118
|
+
async function runStatusline(input, opts = {}) {
|
|
1119
|
+
const payload = parseStatuslinePayload(input) ?? {};
|
|
1120
|
+
const state = await fetchStatuslineState(payload, opts);
|
|
1121
|
+
const color = opts.color ?? !process.env.NO_COLOR;
|
|
1122
|
+
return renderStatusline(payload, state, { color });
|
|
657
1123
|
}
|
|
1124
|
+
var init_statusline = __esm(() => {
|
|
1125
|
+
init_src();
|
|
1126
|
+
init_src2();
|
|
1127
|
+
});
|
|
1128
|
+
|
|
1129
|
+
// packages/hook/src/wait.ts
|
|
1130
|
+
var init_wait = __esm(() => {
|
|
1131
|
+
init_src();
|
|
1132
|
+
});
|
|
1133
|
+
|
|
1134
|
+
// packages/hook/src/index.ts
|
|
1135
|
+
var init_src3 = __esm(() => {
|
|
1136
|
+
init_statusline();
|
|
1137
|
+
init_wait();
|
|
1138
|
+
});
|
|
1139
|
+
|
|
1140
|
+
// packages/cli/src/bin.ts
|
|
1141
|
+
init_src();
|
|
1142
|
+
init_src2();
|
|
1143
|
+
import {
|
|
1144
|
+
copyFileSync,
|
|
1145
|
+
existsSync as existsSync5,
|
|
1146
|
+
mkdirSync as mkdirSync3,
|
|
1147
|
+
readdirSync,
|
|
1148
|
+
unlinkSync,
|
|
1149
|
+
writeFileSync as writeFileSync3
|
|
1150
|
+
} from "fs";
|
|
1151
|
+
import { join as join5, resolve as resolve3 } from "path";
|
|
1152
|
+
|
|
658
1153
|
// packages/cli/src/install.ts
|
|
1154
|
+
init_src();
|
|
1155
|
+
init_src2();
|
|
659
1156
|
import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
660
1157
|
import { homedir as homedir2 } from "os";
|
|
661
1158
|
import { join as join3 } from "path";
|
|
@@ -773,12 +1270,79 @@ function unregisterGemini() {
|
|
|
773
1270
|
return false;
|
|
774
1271
|
}
|
|
775
1272
|
}
|
|
1273
|
+
var codexHooksPath = () => process.env.CODEX_HOOKS ?? join3(codexConfigPath(), "..", "hooks.json");
|
|
1274
|
+
var oursIn = (g) => g.hooks.some((h) => typeof h.command === "string" && isOurs(h));
|
|
1275
|
+
function readShared(p) {
|
|
1276
|
+
try {
|
|
1277
|
+
return existsSync4(p) ? JSON.parse(readFileSync3(p, "utf8")) : {};
|
|
1278
|
+
} catch {
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
function putHook(p, event, group) {
|
|
1283
|
+
const c = readShared(p);
|
|
1284
|
+
if (!c)
|
|
1285
|
+
return false;
|
|
1286
|
+
const hooks = c.hooks ?? {};
|
|
1287
|
+
const kept = (hooks[event] ?? []).filter((g) => !oursIn(g));
|
|
1288
|
+
const had = kept.length !== (hooks[event] ?? []).length;
|
|
1289
|
+
if (group)
|
|
1290
|
+
kept.push(group);
|
|
1291
|
+
else if (!had)
|
|
1292
|
+
return false;
|
|
1293
|
+
if (kept.length)
|
|
1294
|
+
hooks[event] = kept;
|
|
1295
|
+
else
|
|
1296
|
+
delete hooks[event];
|
|
1297
|
+
if (Object.keys(hooks).length)
|
|
1298
|
+
c.hooks = hooks;
|
|
1299
|
+
else
|
|
1300
|
+
delete c.hooks;
|
|
1301
|
+
writeFileSync2(p, `${JSON.stringify(c, null, 2)}
|
|
1302
|
+
`);
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
|
1305
|
+
function guardCodex(on) {
|
|
1306
|
+
const p = codexHooksPath();
|
|
1307
|
+
if (!existsSync4(join3(p, "..")))
|
|
1308
|
+
return false;
|
|
1309
|
+
return putHook(p, "PreToolUse", on ? {
|
|
1310
|
+
matcher: "Bash|apply_patch",
|
|
1311
|
+
hooks: [{ type: "command", command: hookCommand("PreToolUse"), timeout: 5 }]
|
|
1312
|
+
} : null);
|
|
1313
|
+
}
|
|
1314
|
+
function guardGemini(on) {
|
|
1315
|
+
const p = geminiSettingsPath();
|
|
1316
|
+
if (!existsSync4(join3(p, "..")))
|
|
1317
|
+
return false;
|
|
1318
|
+
return putHook(p, "BeforeTool", on ? {
|
|
1319
|
+
matcher: "run_shell_command|write_file|replace|read_file",
|
|
1320
|
+
hooks: [
|
|
1321
|
+
{ name: "swarm", type: "command", command: hookCommand("BeforeTool"), timeout: 5000 }
|
|
1322
|
+
]
|
|
1323
|
+
} : null);
|
|
1324
|
+
}
|
|
1325
|
+
function guardedAgents() {
|
|
1326
|
+
const out = [];
|
|
1327
|
+
const has = (p, event) => {
|
|
1328
|
+
const c = readShared(p);
|
|
1329
|
+
const groups = c?.hooks?.[event] ?? [];
|
|
1330
|
+
return groups.some(oursIn);
|
|
1331
|
+
};
|
|
1332
|
+
if (existsSync4(codexHooksPath()) && has(codexHooksPath(), "PreToolUse"))
|
|
1333
|
+
out.push("codex");
|
|
1334
|
+
if (existsSync4(geminiSettingsPath()) && has(geminiSettingsPath(), "BeforeTool"))
|
|
1335
|
+
out.push("gemini");
|
|
1336
|
+
return out;
|
|
1337
|
+
}
|
|
776
1338
|
function registerOtherAgents() {
|
|
777
1339
|
const out = [];
|
|
778
1340
|
if (registerCodex())
|
|
779
1341
|
out.push("codex");
|
|
780
1342
|
if (registerGemini())
|
|
781
1343
|
out.push("gemini");
|
|
1344
|
+
guardCodex(true);
|
|
1345
|
+
guardGemini(true);
|
|
782
1346
|
return out;
|
|
783
1347
|
}
|
|
784
1348
|
function unregisterOtherAgents() {
|
|
@@ -787,6 +1351,8 @@ function unregisterOtherAgents() {
|
|
|
787
1351
|
out.push("codex");
|
|
788
1352
|
if (unregisterGemini())
|
|
789
1353
|
out.push("gemini");
|
|
1354
|
+
guardCodex(false);
|
|
1355
|
+
guardGemini(false);
|
|
790
1356
|
return out;
|
|
791
1357
|
}
|
|
792
1358
|
var hookCommand = (event) => `${binCommand("swarm-hook")} ${event}`;
|
|
@@ -795,6 +1361,7 @@ function mcpServerConfig() {
|
|
|
795
1361
|
const [command, ...args] = resolveBin("swarm-mcp");
|
|
796
1362
|
return { command, args };
|
|
797
1363
|
}
|
|
1364
|
+
var WAKE_EVENTS = new Set(["Stop"]);
|
|
798
1365
|
function load() {
|
|
799
1366
|
const p = settingsPath();
|
|
800
1367
|
return existsSync4(p) ? JSON.parse(readFileSync3(p, "utf8")) : {};
|
|
@@ -811,7 +1378,14 @@ function install() {
|
|
|
811
1378
|
const list = hooks[ev] ?? [];
|
|
812
1379
|
const clean = list.map((g) => ({ ...g, hooks: g.hooks.filter((h) => !isOurs(h)) })).filter((g) => g.hooks.length);
|
|
813
1380
|
clean.push({
|
|
814
|
-
hooks: [
|
|
1381
|
+
hooks: [
|
|
1382
|
+
{
|
|
1383
|
+
type: "command",
|
|
1384
|
+
command: hookCommand(ev),
|
|
1385
|
+
timeout: ev === "Stop" ? 330 : ev === "PermissionRequest" ? 150 : 5
|
|
1386
|
+
},
|
|
1387
|
+
...WAKE_EVENTS.has(ev) ? [{ type: "command", command: hookCommand("wait"), timeout: 3600, asyncRewake: true }] : []
|
|
1388
|
+
]
|
|
815
1389
|
});
|
|
816
1390
|
hooks[ev] = clean;
|
|
817
1391
|
added.push(ev);
|
|
@@ -830,6 +1404,20 @@ function install() {
|
|
|
830
1404
|
registerOtherAgents();
|
|
831
1405
|
return added;
|
|
832
1406
|
}
|
|
1407
|
+
function installStatusline() {
|
|
1408
|
+
const s = load();
|
|
1409
|
+
const cur = s.statusLine;
|
|
1410
|
+
if (cur && !statuslineIsOurs(cur))
|
|
1411
|
+
return "kept";
|
|
1412
|
+
s.statusLine = { type: "command", command: `${binCommand("swarm-hook")} statusline` };
|
|
1413
|
+
save(s);
|
|
1414
|
+
return cur ? "refreshed" : "installed";
|
|
1415
|
+
}
|
|
1416
|
+
function statuslineStatus(s) {
|
|
1417
|
+
if (!s.statusLine)
|
|
1418
|
+
return "none";
|
|
1419
|
+
return statuslineIsOurs(s.statusLine) ? "ours" : "other";
|
|
1420
|
+
}
|
|
833
1421
|
function uninstall() {
|
|
834
1422
|
const s = load();
|
|
835
1423
|
const hooks = s.hooks ?? {};
|
|
@@ -862,6 +1450,10 @@ function uninstall() {
|
|
|
862
1450
|
s.mcpServers = mcp;
|
|
863
1451
|
else
|
|
864
1452
|
delete s.mcpServers;
|
|
1453
|
+
if (statuslineIsOurs(s.statusLine)) {
|
|
1454
|
+
delete s.statusLine;
|
|
1455
|
+
removed++;
|
|
1456
|
+
}
|
|
865
1457
|
save(s);
|
|
866
1458
|
if (unregisterMcp())
|
|
867
1459
|
removed++;
|
|
@@ -887,7 +1479,9 @@ function status() {
|
|
|
887
1479
|
mcp: mcpRegistered(),
|
|
888
1480
|
path: settingsPath(),
|
|
889
1481
|
shim: shimPath(),
|
|
890
|
-
otherAgents
|
|
1482
|
+
otherAgents,
|
|
1483
|
+
statusline: statuslineStatus(s),
|
|
1484
|
+
guarded: guardedAgents()
|
|
891
1485
|
};
|
|
892
1486
|
}
|
|
893
1487
|
function setTeamUrl(home, url) {
|
|
@@ -912,6 +1506,7 @@ url = "${url}"
|
|
|
912
1506
|
}
|
|
913
1507
|
|
|
914
1508
|
// packages/cli/src/procs.ts
|
|
1509
|
+
init_src();
|
|
915
1510
|
import { mkdirSync as mkdirSync2, openSync } from "fs";
|
|
916
1511
|
import { join as join4, resolve as resolve2 } from "path";
|
|
917
1512
|
async function call(path, init) {
|
|
@@ -1067,7 +1662,8 @@ var help = `swarm \u2014 control plane for AI-agent development
|
|
|
1067
1662
|
login [url] [--token t] log in to the team daemon ([team].url) and register this machine (M8.3c)
|
|
1068
1663
|
backup [dest] | restore <src> snapshot ~/.swarm (VACUUM INTO, zero downtime) / restore it (daemon stopped)
|
|
1069
1664
|
|
|
1070
|
-
install [--config-url <team url>] | uninstall add/remove Swarm hooks in ~/.claude/settings.json (--config-url
|
|
1665
|
+
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)
|
|
1666
|
+
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
1667
|
|
|
1072
1668
|
Env: SWARM_URL, SWARM_PORT (default 7777), SWARM_HOME (~/.swarm)`;
|
|
1073
1669
|
async function api(path, init) {
|
|
@@ -1129,6 +1725,10 @@ Open the dashboard: ${base}`);
|
|
|
1129
1725
|
case "install": {
|
|
1130
1726
|
const evs = install();
|
|
1131
1727
|
console.log(`installed hooks for ${evs.length} events in ${status().path}`);
|
|
1728
|
+
if (rest.includes("--statusline")) {
|
|
1729
|
+
const r = installStatusline();
|
|
1730
|
+
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)`);
|
|
1731
|
+
}
|
|
1132
1732
|
const cuIdx = rest.indexOf("--config-url");
|
|
1133
1733
|
const configUrl = cuIdx >= 0 ? rest[cuIdx + 1] : null;
|
|
1134
1734
|
if (configUrl) {
|
|
@@ -1144,6 +1744,12 @@ Open the dashboard: ${base}`);
|
|
|
1144
1744
|
case "uninstall":
|
|
1145
1745
|
console.log(`removed ${uninstall()} hook entries`);
|
|
1146
1746
|
break;
|
|
1747
|
+
case "statusline": {
|
|
1748
|
+
await Promise.resolve().then(() => init_src3());
|
|
1749
|
+
process.stdout.write(`${await runStatusline(await Bun.stdin.text())}
|
|
1750
|
+
`);
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1147
1753
|
case "doctor": {
|
|
1148
1754
|
if (rest.includes("--migrate"))
|
|
1149
1755
|
await ensureDaemon({ quiet: true });
|
|
@@ -1175,8 +1781,15 @@ Open the dashboard: ${base}`);
|
|
|
1175
1781
|
line(false, `${o.layer} config overrides locked ${o.key}`, `remove it \u2014 policy value stays in effect`);
|
|
1176
1782
|
}
|
|
1177
1783
|
line(st.mcp, "MCP server registered", "run: swarm install");
|
|
1784
|
+
if (st.statusline === "ours")
|
|
1785
|
+
console.log("\u2713 statusLine: swarm statusline");
|
|
1786
|
+
else
|
|
1787
|
+
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
1788
|
if (st.otherAgents.length)
|
|
1179
1789
|
console.log(`\u2713 MCP server also registered for ${st.otherAgents.join(", ")} (swarm_* tools in those CLIs too)`);
|
|
1790
|
+
if (st.guarded.length)
|
|
1791
|
+
console.log(`\u2713 rules also hold on ${st.guarded.join(", ")}${st.guarded.includes("codex") ? " (Codex runs a new hook only after you trust it once: /hooks)" : ""}`);
|
|
1792
|
+
console.log("\xB7 Cursor runs the Claude Code hooks above itself (Settings \u2192 Agents \u2192 Third-Party Imports, on by default); an `ask` rule refuses there, since Cursor's preToolUse cannot ask");
|
|
1180
1793
|
const forge = (bin, auth) => {
|
|
1181
1794
|
const path = Bun.which(bin);
|
|
1182
1795
|
if (!path)
|
|
@@ -1192,6 +1805,9 @@ Open the dashboard: ${base}`);
|
|
|
1192
1805
|
const lag = t.pending ? `${t.pending} pending${t.oldest ? ` since ${t.oldest}` : ""}` : "in sync";
|
|
1193
1806
|
line(!t.lastError, `team forwarding \u2192 ${t.url} (${lag})`, `last error: ${t.lastError} \u2014 check the team daemon and [team].url`);
|
|
1194
1807
|
}
|
|
1808
|
+
const o = await api("/v1/otel").catch(() => null);
|
|
1809
|
+
if (o?.configured)
|
|
1810
|
+
line(!o.lastError, `OTLP export \u2192 ${o.endpoint} (${o.compat}${o.lastOkAt ? `, last sent ${o.lastOkAt}` : ", nothing sent yet"})`, `last error: ${o.lastError} \u2014 check the collector and [otel].endpoint`);
|
|
1195
1811
|
}
|
|
1196
1812
|
if (process.env.GITLAB_TOKEN)
|
|
1197
1813
|
console.log("\xB7 glab uses GITLAB_TOKEN from this shell \u2014 a daemon started by the desktop app won't see it; run `glab auth login` to store it instead");
|