svamp-cli 0.2.273 → 0.2.275
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/{agentCommands-BRY74Q0h.mjs → agentCommands-DGT-1wjo.mjs} +5 -5
- package/dist/{auth-cez4R4me.mjs → auth-CT55Rse4.mjs} +1 -1
- package/dist/{cli-C-19p_H4.mjs → cli-DYTmO9JL.mjs} +63 -63
- package/dist/cli.mjs +2 -2
- package/dist/{commands-eua1Gt4_.mjs → commands-BV_9mFkz.mjs} +2 -2
- package/dist/{commands-BAr_4xB1.mjs → commands-BvmFXAmu.mjs} +2 -2
- package/dist/{commands-CobhxPGy.mjs → commands-C0rRjhMD.mjs} +41 -18
- package/dist/{commands-BZokG8vu.mjs → commands-C8Zc5axO.mjs} +11 -9
- package/dist/{commands-2aatLLjq.mjs → commands-CVPcbtWV.mjs} +1 -1
- package/dist/{commands-C8ceYKji.mjs → commands-CXHZapLH.mjs} +1 -1
- package/dist/{commands-CZqQryOD.mjs → commands-D7fIWAgz.mjs} +4 -4
- package/dist/{fleet-CzrL5O69.mjs → fleet-BCel6ZVc.mjs} +2 -2
- package/dist/{frpc-CFKdshLL.mjs → frpc-D3faR6iR.mjs} +73 -32
- package/dist/{headlessCli-DG4HyG2F.mjs → headlessCli-DVBFm7og.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/package-DIuZ7Wfp.mjs +64 -0
- package/dist/{pinnedClaudeCode-B9O-hKxm.mjs → pinnedClaudeCode-CgEtGkX2.mjs} +1 -1
- package/dist/{rpc-Bbnunkmx.mjs → rpc-BQ8zLSUc.mjs} +1 -1
- package/dist/{rpc-fy0bKbnH.mjs → rpc-xlV-4-BG.mjs} +1 -1
- package/dist/{run-fDelGoR-.mjs → run-C3Fcbk-H.mjs} +211 -41
- package/dist/{run-vr8PHjL1.mjs → run-DMPVho7i.mjs} +1 -1
- package/dist/{scheduler-C_3x4bEj.mjs → scheduler-DaFZY2ob.mjs} +1 -1
- package/dist/{serveCommands-DglJYzYC.mjs → serveCommands-B9Yhx1fl.mjs} +5 -5
- package/dist/{sideband-Mqkuef0c.mjs → sideband-CYqmMG_m.mjs} +1 -1
- package/package.json +2 -2
- package/dist/package-BU9leRlh.mjs +0 -64
|
@@ -1158,8 +1158,14 @@ async function readProcessTable() {
|
|
|
1158
1158
|
let stdout;
|
|
1159
1159
|
try {
|
|
1160
1160
|
const result = await execFileAsync$1("ps", ["-A", "-o", "pid=,ppid=,etime=,%cpu=,rss=,command="], {
|
|
1161
|
-
maxBuffer: 8 * 1024 * 1024
|
|
1161
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
1162
1162
|
// 8MB — plenty for any realistic process table
|
|
1163
|
+
// Hard wall-clock deadline: on a wedged host (D-state / stuck FS) `ps` can block
|
|
1164
|
+
// forever; maxBuffer bounds size, not time. Without this the awaited promise never
|
|
1165
|
+
// settles and callers (killDescendant admin RPC, Tasks-panel detectDescendants) hang.
|
|
1166
|
+
// On timeout execFile rejects → the catch below returns [] (best-effort, no crash).
|
|
1167
|
+
timeout: 5e3,
|
|
1168
|
+
killSignal: "SIGKILL"
|
|
1163
1169
|
});
|
|
1164
1170
|
stdout = result.stdout;
|
|
1165
1171
|
} catch {
|
|
@@ -1390,9 +1396,15 @@ function serveStaticMount(req, res, opts) {
|
|
|
1390
1396
|
return;
|
|
1391
1397
|
}
|
|
1392
1398
|
const indexPath = realContainedPath(rootDir, path.join(target, "index.html"));
|
|
1393
|
-
if (indexPath
|
|
1394
|
-
|
|
1395
|
-
|
|
1399
|
+
if (indexPath) {
|
|
1400
|
+
try {
|
|
1401
|
+
const ist = fs.statSync(indexPath);
|
|
1402
|
+
if (ist.isFile()) {
|
|
1403
|
+
sendFile(req, res, indexPath, ist);
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
} catch {
|
|
1407
|
+
}
|
|
1396
1408
|
}
|
|
1397
1409
|
if (!browse) {
|
|
1398
1410
|
res.writeHead(403, { ...CORS, "Content-Type": "text/plain" });
|
|
@@ -1596,16 +1608,19 @@ function isStructurallyLiveJwt(token) {
|
|
|
1596
1608
|
async function verifyTokenViaHypha(token, hyphaServerUrl) {
|
|
1597
1609
|
try {
|
|
1598
1610
|
const baseUrl = hyphaServerUrl.replace(/\/$/, "");
|
|
1599
|
-
const url = `${baseUrl}/public/services/ws/
|
|
1611
|
+
const url = `${baseUrl}/public/services/ws/parse_token`;
|
|
1600
1612
|
const resp = await fetch(url, {
|
|
1601
|
-
method: "
|
|
1613
|
+
method: "POST",
|
|
1602
1614
|
headers: {
|
|
1603
|
-
Authorization: `Bearer ${token}
|
|
1615
|
+
Authorization: `Bearer ${token}`,
|
|
1616
|
+
"Content-Type": "application/json"
|
|
1604
1617
|
},
|
|
1618
|
+
body: JSON.stringify({ token }),
|
|
1605
1619
|
signal: AbortSignal.timeout(1e4)
|
|
1606
1620
|
});
|
|
1607
1621
|
if (!resp.ok) return null;
|
|
1608
1622
|
const data = await resp.json();
|
|
1623
|
+
if (data?.is_anonymous === true) return null;
|
|
1609
1624
|
const email = data?.email;
|
|
1610
1625
|
if (typeof email === "string" && email) return email.toLowerCase();
|
|
1611
1626
|
return null;
|
|
@@ -2397,7 +2412,12 @@ class ServeManager {
|
|
|
2397
2412
|
cwd: cfg.workdir ?? process.cwd(),
|
|
2398
2413
|
env: { ...process.env, ...cfg.env ?? {} },
|
|
2399
2414
|
stdio: ["ignore", "pipe", "pipe"],
|
|
2400
|
-
|
|
2415
|
+
// #0483: run in its OWN process group so we can kill the whole tree. Managed mounts
|
|
2416
|
+
// are typically wrappers (npm start / npm run dev / python -m …) whose real listener
|
|
2417
|
+
// is a GRANDCHILD; killing only the direct pid leaves the grandchild holding the port
|
|
2418
|
+
// → next warmup hits EADDRINUSE → mount permanently broken + orphan accumulation.
|
|
2419
|
+
// killManagedTree() below signals -pid (the group).
|
|
2420
|
+
detached: true
|
|
2401
2421
|
});
|
|
2402
2422
|
child.stdout?.on("data", (d) => {
|
|
2403
2423
|
const line = d.toString().trimEnd();
|
|
@@ -2423,10 +2443,7 @@ class ServeManager {
|
|
|
2423
2443
|
this.log(`Managed process '${name}' ready on 127.0.0.1:${cfg.port}`);
|
|
2424
2444
|
}).catch((err) => {
|
|
2425
2445
|
this.log(`Managed process '${name}' warmup failed: ${err.message}`);
|
|
2426
|
-
|
|
2427
|
-
child.kill("SIGTERM");
|
|
2428
|
-
} catch {
|
|
2429
|
-
}
|
|
2446
|
+
this.killManagedTree(child, "SIGTERM");
|
|
2430
2447
|
this.managedProcs.delete(name);
|
|
2431
2448
|
throw err;
|
|
2432
2449
|
});
|
|
@@ -2434,12 +2451,33 @@ class ServeManager {
|
|
|
2434
2451
|
child,
|
|
2435
2452
|
pid: child.pid ?? 0,
|
|
2436
2453
|
lastRequestAt: Date.now(),
|
|
2454
|
+
activeConns: 0,
|
|
2437
2455
|
warmupPromise
|
|
2438
2456
|
};
|
|
2439
2457
|
this.managedProcs.set(name, newHandle);
|
|
2440
2458
|
this.log(`Managed process '${name}' starting: ${cfg.command} ${(cfg.args ?? []).join(" ")} (port ${cfg.port})`);
|
|
2441
2459
|
return warmupPromise;
|
|
2442
2460
|
}
|
|
2461
|
+
/**
|
|
2462
|
+
* #0483: kill the managed child's whole PROCESS GROUP (it was spawned detached, so it leads
|
|
2463
|
+
* its own group). This reaps grandchildren (the real listener behind an npm/python wrapper)
|
|
2464
|
+
* that a direct child.kill() would orphan, leaving the port bound. Falls back to a direct
|
|
2465
|
+
* child.kill() if the group signal fails (e.g. pid already gone).
|
|
2466
|
+
*/
|
|
2467
|
+
killManagedTree(child, signal) {
|
|
2468
|
+
const pid = child.pid;
|
|
2469
|
+
if (pid && pid > 0) {
|
|
2470
|
+
try {
|
|
2471
|
+
process.kill(-pid, signal);
|
|
2472
|
+
return;
|
|
2473
|
+
} catch {
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
try {
|
|
2477
|
+
child.kill(signal);
|
|
2478
|
+
} catch {
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2443
2481
|
/** Poll a URL until it returns <500 or the deadline passes. */
|
|
2444
2482
|
async warmupProbe(url, timeoutMs) {
|
|
2445
2483
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -2472,17 +2510,11 @@ class ServeManager {
|
|
|
2472
2510
|
const h = this.managedProcs.get(name);
|
|
2473
2511
|
if (!h) return;
|
|
2474
2512
|
this.managedProcs.delete(name);
|
|
2475
|
-
try {
|
|
2476
|
-
h.child.kill("SIGTERM");
|
|
2477
|
-
} catch {
|
|
2478
|
-
}
|
|
2479
2513
|
const child = h.child;
|
|
2514
|
+
this.killManagedTree(child, "SIGTERM");
|
|
2480
2515
|
await new Promise((resolve) => {
|
|
2481
2516
|
const t = setTimeout(() => {
|
|
2482
|
-
|
|
2483
|
-
child.kill("SIGKILL");
|
|
2484
|
-
} catch {
|
|
2485
|
-
}
|
|
2517
|
+
this.killManagedTree(child, "SIGKILL");
|
|
2486
2518
|
resolve();
|
|
2487
2519
|
}, 5e3);
|
|
2488
2520
|
child.once("exit", () => {
|
|
@@ -2502,6 +2534,10 @@ class ServeManager {
|
|
|
2502
2534
|
if (!cfg || !cfg.idleTimeoutSec || cfg.idleTimeoutSec <= 0) continue;
|
|
2503
2535
|
const h = this.managedProcs.get(name);
|
|
2504
2536
|
if (!h || h.warmupPromise) continue;
|
|
2537
|
+
if (h.activeConns > 0) {
|
|
2538
|
+
h.lastRequestAt = now;
|
|
2539
|
+
continue;
|
|
2540
|
+
}
|
|
2505
2541
|
if (now - h.lastRequestAt >= cfg.idleTimeoutSec * 1e3) {
|
|
2506
2542
|
this.log(`Idle eviction: stopping '${name}' (idle ${Math.round((now - h.lastRequestAt) / 1e3)}s \u2265 ${cfg.idleTimeoutSec}s)`);
|
|
2507
2543
|
this.stopManagedProcess(name).catch(() => {
|
|
@@ -2532,7 +2568,9 @@ class ServeManager {
|
|
|
2532
2568
|
...this.port > 0 ? { port: this.port } : {}
|
|
2533
2569
|
};
|
|
2534
2570
|
try {
|
|
2535
|
-
|
|
2571
|
+
const tmp = `${this.persistFile}.${process.pid}.${crypto.randomBytes(4).toString("hex")}.tmp`;
|
|
2572
|
+
fs.writeFileSync(tmp, JSON.stringify(state, null, 2));
|
|
2573
|
+
fs.renameSync(tmp, this.persistFile);
|
|
2536
2574
|
} catch (err) {
|
|
2537
2575
|
this.log(`Error persisting serve state: ${err.message}`);
|
|
2538
2576
|
}
|
|
@@ -2703,7 +2741,18 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
|
|
|
2703
2741
|
}
|
|
2704
2742
|
}
|
|
2705
2743
|
const handle = this.managedProcs.get(mount.name);
|
|
2706
|
-
if (handle)
|
|
2744
|
+
if (handle) {
|
|
2745
|
+
handle.lastRequestAt = Date.now();
|
|
2746
|
+
handle.activeConns++;
|
|
2747
|
+
let released = false;
|
|
2748
|
+
const release = () => {
|
|
2749
|
+
if (released) return;
|
|
2750
|
+
released = true;
|
|
2751
|
+
handle.activeConns = Math.max(0, handle.activeConns - 1);
|
|
2752
|
+
handle.lastRequestAt = Date.now();
|
|
2753
|
+
};
|
|
2754
|
+
res.on("close", release);
|
|
2755
|
+
}
|
|
2707
2756
|
const targetPath = mountResolvedByHost ? req.url || "/" : (basePath || "/") + (url.search || "");
|
|
2708
2757
|
const proxyReq = http.request({
|
|
2709
2758
|
hostname: "127.0.0.1",
|
|
@@ -2804,7 +2853,17 @@ Connection: close\r
|
|
|
2804
2853
|
}
|
|
2805
2854
|
}
|
|
2806
2855
|
const handle = this.managedProcs.get(mount.name);
|
|
2807
|
-
if (handle)
|
|
2856
|
+
if (handle) {
|
|
2857
|
+
handle.lastRequestAt = Date.now();
|
|
2858
|
+
handle.activeConns++;
|
|
2859
|
+
let released = false;
|
|
2860
|
+
clientSocket.on("close", () => {
|
|
2861
|
+
if (released) return;
|
|
2862
|
+
released = true;
|
|
2863
|
+
handle.activeConns = Math.max(0, handle.activeConns - 1);
|
|
2864
|
+
handle.lastRequestAt = Date.now();
|
|
2865
|
+
});
|
|
2866
|
+
}
|
|
2808
2867
|
const targetPath = mountResolvedByHost ? req.url || "/" : (url.pathname.slice(`/${mountName}`.length) || "/") + (url.search || "");
|
|
2809
2868
|
const upstream = net.connect(cfg.port, "127.0.0.1", () => {
|
|
2810
2869
|
const lines = [`${req.method} ${targetPath} HTTP/1.1`];
|
|
@@ -2896,7 +2955,7 @@ Connection: close\r
|
|
|
2896
2955
|
const mount = this.mounts.get(mountName);
|
|
2897
2956
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
|
|
2898
2957
|
try {
|
|
2899
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2958
|
+
const { FrpcTunnel } = await import('./frpc-D3faR6iR.mjs');
|
|
2900
2959
|
let tunnel;
|
|
2901
2960
|
tunnel = new FrpcTunnel({
|
|
2902
2961
|
name: tunnelName,
|
|
@@ -4388,6 +4447,7 @@ class ChannelOutbox {
|
|
|
4388
4447
|
}
|
|
4389
4448
|
/** Append a reply addressed to `to`. Assigns seq + ts, persists, and wakes waiters. */
|
|
4390
4449
|
append(channelId, r) {
|
|
4450
|
+
this.reload();
|
|
4391
4451
|
const seq = (this.seqByChannel.get(channelId) || 0) + 1;
|
|
4392
4452
|
this.seqByChannel.set(channelId, seq);
|
|
4393
4453
|
const reply = { seq, ts: Date.now(), to: r.to, body: r.body, ...r.correlationId ? { correlationId: r.correlationId } : {} };
|
|
@@ -4406,6 +4466,7 @@ class ChannelOutbox {
|
|
|
4406
4466
|
}
|
|
4407
4467
|
if (++this.appendsSinceCompact >= COMPACT_EVERY) {
|
|
4408
4468
|
this.appendsSinceCompact = 0;
|
|
4469
|
+
this.reload();
|
|
4409
4470
|
this._compact();
|
|
4410
4471
|
}
|
|
4411
4472
|
this.emitter.emit(channelId, reply);
|
|
@@ -4463,6 +4524,7 @@ class ChannelOutbox {
|
|
|
4463
4524
|
}
|
|
4464
4525
|
/** Drop a channel's outbox (on channel delete) — best-effort rewrite of the log. */
|
|
4465
4526
|
purge(channelId) {
|
|
4527
|
+
if (existsSync(this.file)) this.reload();
|
|
4466
4528
|
this.byChannel.delete(channelId);
|
|
4467
4529
|
this.seqByChannel.delete(channelId);
|
|
4468
4530
|
if (!existsSync(this.file)) return;
|
|
@@ -5698,7 +5760,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
5698
5760
|
const tunnels = handlers.tunnels;
|
|
5699
5761
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
5700
5762
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
5701
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
5763
|
+
const { FrpcTunnel } = await import('./frpc-D3faR6iR.mjs');
|
|
5702
5764
|
const tunnel = new FrpcTunnel({
|
|
5703
5765
|
name: params.name,
|
|
5704
5766
|
ports: params.ports,
|
|
@@ -6172,7 +6234,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6172
6234
|
}
|
|
6173
6235
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
6174
6236
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
6175
|
-
const { toolsForRole } = await import('./sideband-
|
|
6237
|
+
const { toolsForRole } = await import('./sideband-CYqmMG_m.mjs');
|
|
6176
6238
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
6177
6239
|
return fmt(r2);
|
|
6178
6240
|
}
|
|
@@ -6271,7 +6333,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6271
6333
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
6272
6334
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
6273
6335
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
6274
|
-
const { queryCore } = await import('./commands-
|
|
6336
|
+
const { queryCore } = await import('./commands-D7fIWAgz.mjs');
|
|
6275
6337
|
const timeout = c.reply?.timeout_sec || 120;
|
|
6276
6338
|
let result;
|
|
6277
6339
|
try {
|
|
@@ -6366,7 +6428,9 @@ ${d?.error || "not found"}`;
|
|
|
6366
6428
|
});
|
|
6367
6429
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
6368
6430
|
const cursor = Math.max(0, Number(kwargs.cursor) || 0);
|
|
6369
|
-
const
|
|
6431
|
+
const waitRaw = Number(kwargs.wait ?? 25);
|
|
6432
|
+
const waitSec = Number.isFinite(waitRaw) ? waitRaw : 25;
|
|
6433
|
+
const waitMs = Math.min(Math.max(0, waitSec * 1e3), 6e4);
|
|
6370
6434
|
const outbox = new ChannelOutbox(dir);
|
|
6371
6435
|
const deadline = Date.now() + waitMs;
|
|
6372
6436
|
for (; ; ) {
|
|
@@ -6477,7 +6541,7 @@ function writeInboundContext(sessionId, ctx) {
|
|
|
6477
6541
|
try {
|
|
6478
6542
|
const p = ctxPath(sessionId);
|
|
6479
6543
|
mkdirSync$1(join$1(SVAMP_HOME$2, "inbound"), { recursive: true });
|
|
6480
|
-
const tmp = p
|
|
6544
|
+
const tmp = `${p}.${process.pid}.${randomUUID()}.tmp`;
|
|
6481
6545
|
writeFileSync$1(tmp, JSON.stringify({ ...ctx, deliveredAt: Date.now() }));
|
|
6482
6546
|
renameSync(tmp, p);
|
|
6483
6547
|
} catch {
|
|
@@ -6637,6 +6701,12 @@ function classifyInbound(message, now = Date.now(), opts) {
|
|
|
6637
6701
|
const tripped = recordWake(now);
|
|
6638
6702
|
return { action: "wake", reason: "urgent", breakerTripped: tripped };
|
|
6639
6703
|
}
|
|
6704
|
+
function isHopCapParked(message, opts) {
|
|
6705
|
+
const hop = message.hopCount ?? 0;
|
|
6706
|
+
const human = senderIsHuman(message);
|
|
6707
|
+
const self = false;
|
|
6708
|
+
return !human && !self && !message.channel && hop > MAX_AGENT_HOPS;
|
|
6709
|
+
}
|
|
6640
6710
|
function applyInboxClear(inbox, opts) {
|
|
6641
6711
|
let kept;
|
|
6642
6712
|
if (opts?.messageId) kept = inbox.filter((m) => m.messageId !== opts.messageId);
|
|
@@ -6670,6 +6740,9 @@ function saveInbox(projectDir, sessionId, inbox) {
|
|
|
6670
6740
|
} catch {
|
|
6671
6741
|
}
|
|
6672
6742
|
}
|
|
6743
|
+
function isPending(m) {
|
|
6744
|
+
return !m.handled && !m.read;
|
|
6745
|
+
}
|
|
6673
6746
|
|
|
6674
6747
|
function envInt(name, fallback) {
|
|
6675
6748
|
const raw = process.env[name];
|
|
@@ -7654,10 +7727,13 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
7654
7727
|
},
|
|
7655
7728
|
// Agent/owner answers a queued (async) channel message → channel outbox, addressed
|
|
7656
7729
|
// to the original external caller. Routed here by `inbox reply` for channel-origin
|
|
7657
|
-
// inbox messages (which carry channelId + correlationId + from).
|
|
7658
|
-
//
|
|
7730
|
+
// inbox messages (which carry channelId + correlationId + from). #0466: owner-gated
|
|
7731
|
+
// (admin tier — the highest shared role; owner + same-owner-workspace still pass
|
|
7732
|
+
// above) since this speaks AS the session to EXTERNAL parties, recorded verified:true.
|
|
7733
|
+
// A mere interact-tier collaborator must not be able to emit outbound replies as the
|
|
7734
|
+
// session — that would be attribution spoofing to third parties.
|
|
7659
7735
|
channelReply: async (params, context) => {
|
|
7660
|
-
authorizeRequest(context, metadata.sharing, "
|
|
7736
|
+
authorizeRequest(context, metadata.sharing, "admin");
|
|
7661
7737
|
const c = channelStore.get(params.channel);
|
|
7662
7738
|
if (!c) return { ok: false, error: "channel not found" };
|
|
7663
7739
|
if (!params.to || !params.body) return { ok: false, error: "to and body are required" };
|
|
@@ -15939,7 +16015,7 @@ async function startDaemon(options) {
|
|
|
15939
16015
|
try {
|
|
15940
16016
|
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
15941
16017
|
if (!dir) return;
|
|
15942
|
-
const { reconcileServiceLinks } = await import('./agentCommands-
|
|
16018
|
+
const { reconcileServiceLinks } = await import('./agentCommands-DGT-1wjo.mjs');
|
|
15943
16019
|
const configPath = getSvampConfigPath(dir, sessionId);
|
|
15944
16020
|
const config = readSvampConfig(configPath);
|
|
15945
16021
|
const entries = Array.from(urls.entries());
|
|
@@ -15957,7 +16033,7 @@ async function startDaemon(options) {
|
|
|
15957
16033
|
}
|
|
15958
16034
|
}
|
|
15959
16035
|
async function createExposedTunnel(spec) {
|
|
15960
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
16036
|
+
const { FrpcTunnel } = await import('./frpc-D3faR6iR.mjs');
|
|
15961
16037
|
const tunnel = new FrpcTunnel({
|
|
15962
16038
|
name: spec.name,
|
|
15963
16039
|
ports: spec.ports,
|
|
@@ -15985,7 +16061,7 @@ async function startDaemon(options) {
|
|
|
15985
16061
|
ensureAutoInstalledCommands(logger);
|
|
15986
16062
|
(async () => {
|
|
15987
16063
|
try {
|
|
15988
|
-
const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-
|
|
16064
|
+
const { beginClaudeVersionReconcile } = await import('./pinnedClaudeCode-CgEtGkX2.mjs');
|
|
15989
16065
|
beginClaudeVersionReconcile((msg) => logger.log(msg));
|
|
15990
16066
|
} catch (e) {
|
|
15991
16067
|
logger.log(`[claude-version] check failed: ${e?.message || e}`);
|
|
@@ -18147,11 +18223,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18147
18223
|
});
|
|
18148
18224
|
},
|
|
18149
18225
|
onIssue: async (params) => {
|
|
18150
|
-
const { issueRpc } = await import('./rpc-
|
|
18226
|
+
const { issueRpc } = await import('./rpc-BQ8zLSUc.mjs');
|
|
18151
18227
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
18152
18228
|
},
|
|
18153
18229
|
onWorkflow: async (params) => {
|
|
18154
|
-
const { workflowRpc } = await import('./rpc-
|
|
18230
|
+
const { workflowRpc } = await import('./rpc-xlV-4-BG.mjs');
|
|
18155
18231
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
18156
18232
|
},
|
|
18157
18233
|
onRipgrep: async (args, cwd) => {
|
|
@@ -18368,6 +18444,47 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18368
18444
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
18369
18445
|
sessionService.updateMetadata(sessionMetadata);
|
|
18370
18446
|
logger.log(`Session ${sessionId} registered on Hypha, waiting for first message to spawn Claude`);
|
|
18447
|
+
const inboxReconcileMs = Number(process.env.SVAMP_INBOX_RECONCILE_MS);
|
|
18448
|
+
const INBOX_RECONCILE_INTERVAL_MS = Number.isFinite(inboxReconcileMs) && inboxReconcileMs >= 0 ? inboxReconcileMs : 15e3;
|
|
18449
|
+
let inboxReconcileTimer = null;
|
|
18450
|
+
const reconcileIdleInbox = () => {
|
|
18451
|
+
if (trackedSession.stopped) {
|
|
18452
|
+
if (inboxReconcileTimer) clearInterval(inboxReconcileTimer);
|
|
18453
|
+
return;
|
|
18454
|
+
}
|
|
18455
|
+
if (sessionWasProcessing) return;
|
|
18456
|
+
if (isKillingClaude || isRestartingClaude || isSwitchingMode) return;
|
|
18457
|
+
const queue = sessionMetadata.messageQueue;
|
|
18458
|
+
if (queue && queue.length > 0) {
|
|
18459
|
+
processMessageQueueRef?.();
|
|
18460
|
+
return;
|
|
18461
|
+
}
|
|
18462
|
+
let inbox = [];
|
|
18463
|
+
try {
|
|
18464
|
+
inbox = loadInbox(directory, sessionId);
|
|
18465
|
+
} catch {
|
|
18466
|
+
return;
|
|
18467
|
+
}
|
|
18468
|
+
const deliverable = inbox.filter((m) => isPending(m) && !isHopCapParked(m));
|
|
18469
|
+
if (deliverable.length === 0) return;
|
|
18470
|
+
logger.log(`[Session ${sessionId}] Idle-inbox reconcile: ${deliverable.length} undelivered pending message(s) on an idle agent \u2014 delivering`);
|
|
18471
|
+
const existing = sessionMetadata.messageQueue || [];
|
|
18472
|
+
const seen = new Set(existing.map((e) => e.id));
|
|
18473
|
+
const additions = deliverable.filter((m) => !seen.has(m.messageId)).map((m) => {
|
|
18474
|
+
const formatted = formatInboxMessageXml(m);
|
|
18475
|
+
return { id: m.messageId, text: formatted, displayText: formatted, createdAt: Date.now(), inboxHop: m.hopCount ?? 0, inboxThreadId: m.threadId || m.messageId };
|
|
18476
|
+
});
|
|
18477
|
+
if (additions.length === 0) {
|
|
18478
|
+
processMessageQueueRef?.();
|
|
18479
|
+
return;
|
|
18480
|
+
}
|
|
18481
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: [...existing, ...additions] };
|
|
18482
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
18483
|
+
processMessageQueueRef?.();
|
|
18484
|
+
};
|
|
18485
|
+
if (INBOX_RECONCILE_INTERVAL_MS > 0) {
|
|
18486
|
+
inboxReconcileTimer = setInterval(reconcileIdleInbox, INBOX_RECONCILE_INTERVAL_MS);
|
|
18487
|
+
}
|
|
18371
18488
|
return {
|
|
18372
18489
|
type: "success",
|
|
18373
18490
|
sessionId,
|
|
@@ -18721,11 +18838,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18721
18838
|
});
|
|
18722
18839
|
},
|
|
18723
18840
|
onIssue: async (params) => {
|
|
18724
|
-
const { issueRpc } = await import('./rpc-
|
|
18841
|
+
const { issueRpc } = await import('./rpc-BQ8zLSUc.mjs');
|
|
18725
18842
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
18726
18843
|
},
|
|
18727
18844
|
onWorkflow: async (params) => {
|
|
18728
|
-
const { workflowRpc } = await import('./rpc-
|
|
18845
|
+
const { workflowRpc } = await import('./rpc-xlV-4-BG.mjs');
|
|
18729
18846
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
18730
18847
|
},
|
|
18731
18848
|
onRipgrep: async (args, cwd) => {
|
|
@@ -19161,6 +19278,59 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
19161
19278
|
}
|
|
19162
19279
|
};
|
|
19163
19280
|
pidToTrackedSession.set(randomUUID$1(), trackedSession);
|
|
19281
|
+
let acpInboxReconcileTimer = null;
|
|
19282
|
+
const reconcileAcpIdleInbox = () => {
|
|
19283
|
+
if (acpStopped) {
|
|
19284
|
+
if (acpInboxReconcileTimer) clearInterval(acpInboxReconcileTimer);
|
|
19285
|
+
return;
|
|
19286
|
+
}
|
|
19287
|
+
if (!acpBackendReady) return;
|
|
19288
|
+
if (sessionMetadata.lifecycleState !== "idle") return;
|
|
19289
|
+
let inbox = [];
|
|
19290
|
+
try {
|
|
19291
|
+
inbox = loadInbox(directory, sessionId);
|
|
19292
|
+
} catch {
|
|
19293
|
+
return;
|
|
19294
|
+
}
|
|
19295
|
+
const existing = sessionMetadata.messageQueue || [];
|
|
19296
|
+
const seen = new Set(existing.map((e) => e.id));
|
|
19297
|
+
const deliverable = inbox.filter((m) => isPending(m) && !isHopCapParked(m) && !seen.has(m.messageId));
|
|
19298
|
+
let queue = existing;
|
|
19299
|
+
if (deliverable.length > 0) {
|
|
19300
|
+
const additions = deliverable.map((m) => {
|
|
19301
|
+
const formatted = formatInboxMessageXml(m);
|
|
19302
|
+
return { id: m.messageId, text: formatted, displayText: formatted, createdAt: Date.now(), inboxHop: m.hopCount ?? 0, inboxThreadId: m.threadId || m.messageId };
|
|
19303
|
+
});
|
|
19304
|
+
queue = [...existing, ...additions];
|
|
19305
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: queue };
|
|
19306
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
19307
|
+
}
|
|
19308
|
+
if (!queue || queue.length === 0) return;
|
|
19309
|
+
const next = queue[0];
|
|
19310
|
+
const remaining = queue.slice(1);
|
|
19311
|
+
sessionMetadata = { ...sessionMetadata, messageQueue: remaining.length > 0 ? remaining : void 0, lifecycleState: "running" };
|
|
19312
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
19313
|
+
if (typeof next.inboxHop === "number") {
|
|
19314
|
+
writeInboundContext(sessionId, { hopCount: next.inboxHop, threadId: next.inboxThreadId });
|
|
19315
|
+
sessionService.markInboxHandled(next.id);
|
|
19316
|
+
}
|
|
19317
|
+
logger.log(`[${agentName} Session ${sessionId}] Idle-inbox reconcile: delivering queued message to idle agent`);
|
|
19318
|
+
sessionService.pushMessage(next.displayText || next.text, "user");
|
|
19319
|
+
sessionService.sendKeepAlive(true);
|
|
19320
|
+
agentBackend.sendPrompt(sessionId, next.text).catch((err) => {
|
|
19321
|
+
logger.error(`[${agentName} Session ${sessionId}] Error delivering reconciled inbox message: ${err.message}`);
|
|
19322
|
+
if (!acpStopped) {
|
|
19323
|
+
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
19324
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
19325
|
+
sessionService.sendSessionEnd();
|
|
19326
|
+
}
|
|
19327
|
+
});
|
|
19328
|
+
};
|
|
19329
|
+
{
|
|
19330
|
+
const acpReconcileMs = Number(process.env.SVAMP_INBOX_RECONCILE_MS);
|
|
19331
|
+
const acpReconcileInterval = Number.isFinite(acpReconcileMs) && acpReconcileMs >= 0 ? acpReconcileMs : 15e3;
|
|
19332
|
+
if (acpReconcileInterval > 0) acpInboxReconcileTimer = setInterval(reconcileAcpIdleInbox, acpReconcileInterval);
|
|
19333
|
+
}
|
|
19164
19334
|
logger.log(`[Agent Session ${sessionId}] Starting ${agentName} backend...`);
|
|
19165
19335
|
agentBackend.startSession().then(() => {
|
|
19166
19336
|
acpBackendReady = true;
|
|
@@ -19564,7 +19734,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
19564
19734
|
}
|
|
19565
19735
|
if (persistedSessions.length > 0) {
|
|
19566
19736
|
try {
|
|
19567
|
-
const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-
|
|
19737
|
+
const { awaitClaudeVersionReady } = await import('./pinnedClaudeCode-CgEtGkX2.mjs');
|
|
19568
19738
|
await awaitClaudeVersionReady();
|
|
19569
19739
|
} catch {
|
|
19570
19740
|
}
|
|
@@ -19761,7 +19931,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
19761
19931
|
const PING_TIMEOUT_MS = 15e3;
|
|
19762
19932
|
const POST_RECONNECT_GRACE_MS = 2e4;
|
|
19763
19933
|
const RECONNECT_JITTER_MS = 2500;
|
|
19764
|
-
const { WorkflowScheduler } = await import('./scheduler-
|
|
19934
|
+
const { WorkflowScheduler } = await import('./scheduler-DaFZY2ob.mjs');
|
|
19765
19935
|
const workflowScheduler = new WorkflowScheduler({
|
|
19766
19936
|
projectRoots: () => {
|
|
19767
19937
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ad as applyClaudeProxyEnv, ae as composeSessionId, af as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, ag as generateHookSettings } from './run-
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { ad as applyClaudeProxyEnv, ae as composeSessionId, af as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, ag as generateHookSettings } from './run-C3Fcbk-H.mjs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { existsSync, readFileSync, watch } from 'node:fs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { j as resolveProjectRoot, D as listWorkflows, E as isWorkflowEnabled, F as workflowCrons, y as runWorkflow, G as cronMatches } from './run-
|
|
1
|
+
import { j as resolveProjectRoot, D as listWorkflows, E as isWorkflowEnabled, F as workflowCrons, y as runWorkflow, G as cronMatches } from './run-C3Fcbk-H.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -54,7 +54,7 @@ async function handleServeCommand() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
async function serveAdd(args, machineId) {
|
|
57
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
57
|
+
const { connectAndGetMachine } = await import('./commands-D7fIWAgz.mjs');
|
|
58
58
|
const pos = positionalArgs(args);
|
|
59
59
|
const name = pos[0];
|
|
60
60
|
if (!name) {
|
|
@@ -93,7 +93,7 @@ async function serveAdd(args, machineId) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
async function serveApply(args, machineId) {
|
|
96
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
96
|
+
const { connectAndGetMachine } = await import('./commands-D7fIWAgz.mjs');
|
|
97
97
|
const fs = await import('fs');
|
|
98
98
|
const yaml = await import('yaml');
|
|
99
99
|
const file = positionalArgs(args)[0];
|
|
@@ -182,7 +182,7 @@ async function serveApply(args, machineId) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
async function serveRemove(args, machineId) {
|
|
185
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
185
|
+
const { connectAndGetMachine } = await import('./commands-D7fIWAgz.mjs');
|
|
186
186
|
const pos = positionalArgs(args);
|
|
187
187
|
const name = pos[0];
|
|
188
188
|
if (!name) {
|
|
@@ -202,7 +202,7 @@ async function serveRemove(args, machineId) {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
async function serveList(args, machineId) {
|
|
205
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
205
|
+
const { connectAndGetMachine } = await import('./commands-D7fIWAgz.mjs');
|
|
206
206
|
const all = hasFlag(args, "--all", "-a");
|
|
207
207
|
const json = hasFlag(args, "--json");
|
|
208
208
|
const sessionId = getFlag(args, "--session");
|
|
@@ -235,7 +235,7 @@ async function serveList(args, machineId) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
async function serveInfo(machineId) {
|
|
238
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
238
|
+
const { connectAndGetMachine } = await import('./commands-D7fIWAgz.mjs');
|
|
239
239
|
const { machine, server } = await connectAndGetMachine(machineId);
|
|
240
240
|
try {
|
|
241
241
|
const info = await machine.serveInfo();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as READ_ONLY_TOOLS, J as loadMachineContext, K as buildMachineInstructions, L as machineToolsForRole, M as buildMachineTools } from './run-
|
|
1
|
+
import { R as READ_ONLY_TOOLS, J as loadMachineContext, K as buildMachineInstructions, L as machineToolsForRole, M as buildMachineTools } from './run-C3Fcbk-H.mjs';
|
|
2
2
|
import 'node:child_process';
|
|
3
3
|
import 'os';
|
|
4
4
|
import 'fs/promises';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svamp-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.275",
|
|
4
4
|
"description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
|
|
5
5
|
"author": "Amun AI AB",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "rm -rf dist bin/skills bin/commands && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/crew bin/skills/crew && cp -r ../../commands bin/commands && tsc --noEmit && pkgroll",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
|
-
"test": "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-sharing-notify-sync.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-backend-accounts.mjs && npx tsx test/test-backend-oauth.mjs && npx tsx test/test-btw-proxy-env.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-session-access-fallback.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-app-server.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-compact-detect.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-loop-verify.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-issue-pause.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-cron.mjs && npx tsx test/test-workflow-runs.mjs && npx tsx test/test-workflow-idle.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-ws-upgrade.mjs && npx tsx test/test-serve-auth.mjs && npx tsx test/test-static-file-server.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-hotreload-seam.mjs && npx tsx test/test-hot-reload.mjs && npx tsx test/test-hot-reload-live.mjs && npx tsx test/test-session-core.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-outbox-reload.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs && npx tsx test/test-session-links.mjs && npx tsx test/test-issue-loop-pause-guard.mjs && npx tsx test/test-artifact-guard.mjs && npx tsx test/test-graceful-restart.mjs && npx tsx test/test-flush-exit.mjs",
|
|
23
|
+
"test": "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-sharing-notify-sync.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-backend-accounts.mjs && npx tsx test/test-backend-oauth.mjs && npx tsx test/test-btw-proxy-env.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-inbox-reconcile.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-session-access-fallback.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-app-server.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-compact-detect.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-loop-verify.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-issue-pause.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-cron.mjs && npx tsx test/test-workflow-runs.mjs && npx tsx test/test-workflow-idle.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-ws-upgrade.mjs && npx tsx test/test-serve-auth.mjs && npx tsx test/test-static-file-server.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-hotreload-seam.mjs && npx tsx test/test-hot-reload.mjs && npx tsx test/test-hot-reload-live.mjs && npx tsx test/test-session-core.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-outbox-reload.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs && npx tsx test/test-session-links.mjs && npx tsx test/test-issue-loop-pause-guard.mjs && npx tsx test/test-artifact-guard.mjs && npx tsx test/test-graceful-restart.mjs && npx tsx test/test-flush-exit.mjs",
|
|
24
24
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
25
25
|
"dev": "tsx src/cli.ts",
|
|
26
26
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|