svamp-cli 0.2.258 → 0.2.260

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/{agentCommands-CQ89BZon.mjs → agentCommands-BSv2sDdC.mjs} +6 -9
  2. package/dist/{auth-CaFsKYbx.mjs → auth-U2OQhXs1.mjs} +2 -5
  3. package/dist/cli.mjs +156 -69
  4. package/dist/{commands-DutfM3U7.mjs → commands-8qHg0szr.mjs} +8 -9
  5. package/dist/{commands-D8l74hsL.mjs → commands-BCMW-NM7.mjs} +2 -5
  6. package/dist/{commands-Dd8xEIf0.mjs → commands-BG8UHYMk.mjs} +2 -5
  7. package/dist/{commands-DrfYv705.mjs → commands-C3tM_vKp.mjs} +3 -6
  8. package/dist/{commands--X8f4eSr.mjs → commands-CMGqjCrU.mjs} +8 -16
  9. package/dist/{commands-B6eGMF5H.mjs → commands-DAZVK3MR.mjs} +2 -5
  10. package/dist/{commands-BgX0W0uK.mjs → commands-ql8AZ56B.mjs} +2 -5
  11. package/dist/{fleet-UvQnIWT1.mjs → fleet-CRR4JSTJ.mjs} +3 -6
  12. package/dist/{frpc-IXxyfgPn.mjs → frpc-k3ZLz2Mu.mjs} +11 -10
  13. package/dist/{headlessCli-BK7WSS3D.mjs → headlessCli-B78gc29T.mjs} +3 -6
  14. package/dist/index.mjs +2 -5
  15. package/dist/{package-BdZX5mDv.mjs → package-CKFmfq0u.mjs} +2 -2
  16. package/dist/{pinnedClaudeCode-DuLXaoGP.mjs → pinnedClaudeCode-B9O-hKxm.mjs} +1 -1
  17. package/dist/{rpc-CyACkgY1.mjs → rpc-BXrKU30m.mjs} +2 -5
  18. package/dist/{rpc-D7DB3XCH.mjs → rpc-DlioTx05.mjs} +2 -5
  19. package/dist/{run-C1ufZjIW.mjs → run-B8LDPH9R.mjs} +1 -5
  20. package/dist/{run-C1Unk4Zx.mjs → run-DggHONYC.mjs} +735 -423
  21. package/dist/{scheduler-7wve0Fy3.mjs → scheduler-B9WW7XGk.mjs} +2 -5
  22. package/dist/{serveCommands-iQJJLsMJ.mjs → serveCommands-DCA54z5Q.mjs} +5 -5
  23. package/dist/{serveManager-BszV0oIl.mjs → serveManager-BL3aySTV.mjs} +122 -7
  24. package/dist/{sideband-DMPZ-ZoR.mjs → sideband-COyK5_4F.mjs} +2 -5
  25. package/dist/{staticFileServer-FCEOLIYH.mjs → staticFileServer-CbYnj2bH.mjs} +21 -5
  26. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { n as resolveProjectRoot, H as listWorkflows, I as isWorkflowEnabled, J as workflowCrons, C as runWorkflow, K as cronMatches } from './run-C1Unk4Zx.mjs';
1
+ import { n as resolveProjectRoot, H as listWorkflows, I as isWorkflowEnabled, J as workflowCrons, C as runWorkflow, K as cronMatches } from './run-DggHONYC.mjs';
2
2
  import 'os';
3
3
  import 'fs/promises';
4
4
  import 'fs';
@@ -14,10 +14,7 @@ import 'node:path';
14
14
  import 'node:events';
15
15
  import 'node:os';
16
16
  import '@agentclientprotocol/sdk';
17
- import '@modelcontextprotocol/sdk/client/index.js';
18
- import '@modelcontextprotocol/sdk/client/stdio.js';
19
- import '@modelcontextprotocol/sdk/types.js';
20
- import 'zod';
17
+ import 'node:readline';
21
18
  import 'node:fs/promises';
22
19
  import 'node:util';
23
20
  import 'yaml';
@@ -54,7 +54,7 @@ async function handleServeCommand() {
54
54
  }
55
55
  }
56
56
  async function serveAdd(args, machineId) {
57
- const { connectAndGetMachine } = await import('./commands-D8l74hsL.mjs');
57
+ const { connectAndGetMachine } = await import('./commands-BCMW-NM7.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-D8l74hsL.mjs');
96
+ const { connectAndGetMachine } = await import('./commands-BCMW-NM7.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-D8l74hsL.mjs');
185
+ const { connectAndGetMachine } = await import('./commands-BCMW-NM7.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-D8l74hsL.mjs');
205
+ const { connectAndGetMachine } = await import('./commands-BCMW-NM7.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-D8l74hsL.mjs');
238
+ const { connectAndGetMachine } = await import('./commands-BCMW-NM7.mjs');
239
239
  const { machine, server } = await connectAndGetMachine(machineId);
240
240
  try {
241
241
  const info = await machine.serveInfo();
@@ -4,8 +4,8 @@ import * as fs from 'fs';
4
4
  import * as http from 'http';
5
5
  import * as net from 'net';
6
6
  import * as path from 'path';
7
- import { serveStaticMount } from './staticFileServer-FCEOLIYH.mjs';
8
- import { l as getHyphaServerUrl, S as ServeAuth, m as hasCookieToken } from './run-C1Unk4Zx.mjs';
7
+ import { serveStaticMount } from './staticFileServer-CbYnj2bH.mjs';
8
+ import { l as getHyphaServerUrl, S as ServeAuth, m as hasCookieToken } from './run-DggHONYC.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -17,10 +17,7 @@ import 'node:path';
17
17
  import 'node:events';
18
18
  import 'node:os';
19
19
  import '@agentclientprotocol/sdk';
20
- import '@modelcontextprotocol/sdk/client/index.js';
21
- import '@modelcontextprotocol/sdk/client/stdio.js';
22
- import '@modelcontextprotocol/sdk/types.js';
23
- import 'zod';
20
+ import 'node:readline';
24
21
  import 'node:fs/promises';
25
22
  import 'node:util';
26
23
  import 'yaml';
@@ -597,6 +594,21 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
597
594
  const base = path.resolve(mount.directory);
598
595
  const fp = path.resolve(path.join(base, basePath));
599
596
  if (fp !== base && !fp.startsWith(base + path.sep)) return null;
597
+ try {
598
+ const realRoot = fs.realpathSync(base);
599
+ let ancestor = fp;
600
+ while (!fs.existsSync(ancestor) && path.dirname(ancestor) !== ancestor) {
601
+ ancestor = path.dirname(ancestor);
602
+ }
603
+ const realAncestor = fs.realpathSync(ancestor);
604
+ if (realAncestor !== realRoot && !realAncestor.startsWith(realRoot + path.sep)) return null;
605
+ if (fs.existsSync(fp) && fs.lstatSync(fp).isSymbolicLink()) {
606
+ const realTarget = fs.realpathSync(fp);
607
+ if (realTarget !== realRoot && !realTarget.startsWith(realRoot + path.sep)) return null;
608
+ }
609
+ } catch {
610
+ return null;
611
+ }
600
612
  return fp;
601
613
  };
602
614
  if ((req.method === "PUT" || req.method === "DELETE") && mount && mount.directory) {
@@ -667,6 +679,14 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
667
679
  res.end(`Backend error: ${err.message}`);
668
680
  }
669
681
  });
682
+ const abortUpstream = () => {
683
+ if (!proxyReq.destroyed) proxyReq.destroy();
684
+ };
685
+ req.on("aborted", abortUpstream);
686
+ res.on("close", () => {
687
+ if (!res.writableFinished) abortUpstream();
688
+ });
689
+ proxyReq.setTimeout(12e4, abortUpstream);
670
690
  req.pipe(proxyReq);
671
691
  return;
672
692
  }
@@ -688,6 +708,101 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
688
708
  res.end("Not found");
689
709
  }
690
710
  });
711
+ server.on("upgrade", (req, clientSocket, head) => {
712
+ const deny = (code, reason) => {
713
+ try {
714
+ clientSocket.write(`HTTP/1.1 ${code} ${reason}\r
715
+ Connection: close\r
716
+ \r
717
+ `);
718
+ } catch {
719
+ }
720
+ try {
721
+ clientSocket.destroy();
722
+ } catch {
723
+ }
724
+ };
725
+ void (async () => {
726
+ try {
727
+ const url = new URL(req.url || "/", `http://127.0.0.1:${this.port}`);
728
+ const incomingHost = (req.headers.host || "").split(":")[0].toLowerCase();
729
+ const hostMount = this.hostToMount.get(incomingHost);
730
+ let mountName;
731
+ let mountResolvedByHost = false;
732
+ if (hostMount && this.mounts.has(hostMount)) {
733
+ mountName = hostMount;
734
+ mountResolvedByHost = true;
735
+ } else {
736
+ mountName = url.pathname.split("/").filter(Boolean)[0];
737
+ }
738
+ const mount = mountName ? this.mounts.get(mountName) : void 0;
739
+ if (!mount || !mount.process) {
740
+ deny(404, "Not Found");
741
+ return;
742
+ }
743
+ if (mount.access !== "public" && mount.access !== "link") {
744
+ if (mount.access === "owner" && !mount.ownerEmail) {
745
+ deny(403, "Forbidden");
746
+ return;
747
+ }
748
+ const userEmail = this.auth ? await this.auth.authenticate(req).catch(() => null) : null;
749
+ const allowed = userEmail && this.auth ? this.auth.isAuthorized(userEmail, mount.access, mount.ownerEmail) : false;
750
+ if (!allowed) {
751
+ deny(userEmail ? 403 : 401, userEmail ? "Forbidden" : "Unauthorized");
752
+ return;
753
+ }
754
+ }
755
+ const cfg = mount.process;
756
+ if (cfg.wakeOnRequest || !this.managedProcs.has(mount.name)) {
757
+ try {
758
+ await this.ensureManagedRunning(mount.name);
759
+ } catch {
760
+ deny(503, "Backend Not Ready");
761
+ return;
762
+ }
763
+ }
764
+ const handle = this.managedProcs.get(mount.name);
765
+ if (handle) handle.lastRequestAt = Date.now();
766
+ const targetPath = mountResolvedByHost ? req.url || "/" : (url.pathname.slice(`/${mountName}`.length) || "/") + (url.search || "");
767
+ const upstream = net.connect(cfg.port, "127.0.0.1", () => {
768
+ const lines = [`${req.method} ${targetPath} HTTP/1.1`];
769
+ for (let i = 0; i < req.rawHeaders.length; i += 2) {
770
+ lines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`);
771
+ }
772
+ upstream.write(lines.join("\r\n") + "\r\n\r\n");
773
+ if (head && head.length) upstream.write(head);
774
+ upstream.pipe(clientSocket);
775
+ clientSocket.pipe(upstream);
776
+ });
777
+ const teardown = () => {
778
+ try {
779
+ upstream.destroy();
780
+ } catch {
781
+ }
782
+ try {
783
+ clientSocket.destroy();
784
+ } catch {
785
+ }
786
+ };
787
+ upstream.on("error", teardown);
788
+ clientSocket.on("error", teardown);
789
+ upstream.on("close", () => {
790
+ try {
791
+ clientSocket.destroy();
792
+ } catch {
793
+ }
794
+ });
795
+ clientSocket.on("close", () => {
796
+ try {
797
+ upstream.destroy();
798
+ } catch {
799
+ }
800
+ });
801
+ } catch {
802
+ deny(500, "Internal Server Error");
803
+ }
804
+ })();
805
+ });
691
806
  this.proxyServer = server;
692
807
  server.listen(this.port, "127.0.0.1", () => resolve());
693
808
  server.on("error", reject);
@@ -739,7 +854,7 @@ a{color:#0969da;text-decoration:none;font-weight:500}a:hover{text-decoration:und
739
854
  const mount = this.mounts.get(mountName);
740
855
  const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
741
856
  try {
742
- const { FrpcTunnel } = await import('./frpc-IXxyfgPn.mjs');
857
+ const { FrpcTunnel } = await import('./frpc-k3ZLz2Mu.mjs');
743
858
  let tunnel;
744
859
  tunnel = new FrpcTunnel({
745
860
  name: tunnelName,
@@ -1,4 +1,4 @@
1
- import { R as READ_ONLY_TOOLS, N as loadMachineContext, O as buildMachineInstructions, P as machineToolsForRole, Q as buildMachineTools } from './run-C1Unk4Zx.mjs';
1
+ import { R as READ_ONLY_TOOLS, N as loadMachineContext, O as buildMachineInstructions, P as machineToolsForRole, Q as buildMachineTools } from './run-DggHONYC.mjs';
2
2
  import 'node:child_process';
3
3
  import 'os';
4
4
  import 'fs/promises';
@@ -14,10 +14,7 @@ import 'node:path';
14
14
  import 'node:events';
15
15
  import 'node:os';
16
16
  import '@agentclientprotocol/sdk';
17
- import '@modelcontextprotocol/sdk/client/index.js';
18
- import '@modelcontextprotocol/sdk/client/stdio.js';
19
- import '@modelcontextprotocol/sdk/types.js';
20
- import 'zod';
17
+ import 'node:readline';
21
18
  import 'node:fs/promises';
22
19
  import 'node:util';
23
20
  import 'yaml';
@@ -54,6 +54,16 @@ function containedPath(rootDir, relPath) {
54
54
  if (fp !== base && !fp.startsWith(base + path.sep)) return null;
55
55
  return fp;
56
56
  }
57
+ function realContainedPath(rootDir, candidate) {
58
+ try {
59
+ const realRoot = fs.realpathSync(path.resolve(rootDir));
60
+ const real = fs.realpathSync(candidate);
61
+ if (real === realRoot || real.startsWith(realRoot + path.sep)) return real;
62
+ return null;
63
+ } catch {
64
+ return null;
65
+ }
66
+ }
57
67
  function safeDecode(p) {
58
68
  try {
59
69
  return decodeURIComponent(p);
@@ -125,12 +135,18 @@ function serveStaticMount(req, res, opts) {
125
135
  sendFile(req, res, rootDir, rootStat);
126
136
  return;
127
137
  }
128
- const target = containedPath(rootDir, relPath.replace(/^\/+/, ""));
129
- if (!target) {
138
+ const lexTarget = containedPath(rootDir, relPath.replace(/^\/+/, ""));
139
+ if (!lexTarget) {
130
140
  res.writeHead(403, { ...CORS, "Content-Type": "text/plain" });
131
141
  res.end("Forbidden");
132
142
  return;
133
143
  }
144
+ const target = realContainedPath(rootDir, lexTarget);
145
+ if (!target) {
146
+ res.writeHead(404, { ...CORS, "Content-Type": "text/plain" });
147
+ res.end("Not Found");
148
+ return;
149
+ }
134
150
  let st;
135
151
  try {
136
152
  st = fs.statSync(target);
@@ -146,8 +162,8 @@ function serveStaticMount(req, res, opts) {
146
162
  res.end();
147
163
  return;
148
164
  }
149
- const indexPath = path.join(target, "index.html");
150
- if (fs.existsSync(indexPath) && fs.statSync(indexPath).isFile()) {
165
+ const indexPath = realContainedPath(rootDir, path.join(target, "index.html"));
166
+ if (indexPath && fs.statSync(indexPath).isFile()) {
151
167
  sendFile(req, res, indexPath, fs.statSync(indexPath));
152
168
  return;
153
169
  }
@@ -236,4 +252,4 @@ function pipeStream(stream, res) {
236
252
  stream.pipe(res);
237
253
  }
238
254
 
239
- export { containedPath, contentTypeFor, directoryListingHtml, parseRange, serveStaticMount };
255
+ export { containedPath, contentTypeFor, directoryListingHtml, parseRange, realContainedPath, serveStaticMount };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svamp-cli",
3
- "version": "0.2.258",
3
+ "version": "0.2.260",
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-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-interactive-helpers.mjs && npx tsx test/test-codex-backend.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-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-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-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",
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-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-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-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",
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",