@scp-dev/cli 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Q5UI4Z7H.js → chunk-2342GTME.js} +2 -2
- package/dist/{chunk-3SHVJIXP.js → chunk-7RA7E5WR.js} +5 -5
- package/dist/{chunk-2LIJXXTL.js → chunk-AAFHLHXG.js} +84 -19
- package/dist/{chunk-IEFXYBX7.js → chunk-H2XQXMZU.js} +1 -1
- package/dist/{chunk-2OSUVJ2J.js → chunk-UKQBH4AQ.js} +3 -3
- package/dist/{chunk-QRWQIHV6.js → chunk-XQHPDNVG.js} +17 -4
- package/dist/{claude-EQVLST73.js → claude-RNH2E4GU.js} +4 -4
- package/dist/cli.js +1 -1
- package/dist/{codex-5GZ7YPES.js → codex-OSGHQMK6.js} +33 -26
- package/dist/{hooks-B34E2HIP.js → hooks-BZANUJPY.js} +2 -2
- package/dist/{install-6KXJY27V.js → install-25J5QB63.js} +3 -3
- package/dist/{join-FITJVZCA.js → join-EOLHE3LJ.js} +6 -2
- package/dist/{login-AUMLI4FS.js → login-6MVD3VLC.js} +2 -2
- package/dist/{main-ZAYVXFAG.js → main-F2NFQ2KC.js} +66 -28
- package/dist/{mcp-VXBRMQB7.js → mcp-BH526TOG.js} +31 -20
- package/dist/mesh-OZILTV5P.js +53 -0
- package/dist/{opencode-ORLGNHWR.js → opencode-XV33XTL5.js} +4 -4
- package/dist/{peek-YTCWVPF7.js → peek-LFQR6TCS.js} +1 -1
- package/dist/{pi-QEZVFDNR.js → pi-N3DX37PD.js} +1 -1
- package/dist/{relay-QWJM372C.js → relay-SF3UWIPM.js} +1 -1
- package/dist/{remote-P4GFUIAP.js → remote-UQJ5YYCC.js} +2 -2
- package/dist/{setup-MGDWKCNU.js → setup-UJCIMYU4.js} +4 -4
- package/dist/{spawn-GG7VFZA6.js → spawn-JYD7NCQT.js} +5 -5
- package/dist/{up-B2NEOOC6.js → up-3YJU7YX6.js} +5 -5
- package/package.json +6 -6
- package/dist/mesh-H4KL5XAR.js +0 -28
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
mergeHooks,
|
|
11
11
|
musePlugin,
|
|
12
12
|
opencodePlugin
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XQHPDNVG.js";
|
|
14
14
|
import {
|
|
15
15
|
RelayUsage,
|
|
16
16
|
gitToplevel
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-AAFHLHXG.js";
|
|
18
18
|
|
|
19
19
|
// src/install.ts
|
|
20
20
|
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
agySettingsFile,
|
|
4
4
|
mcpFile,
|
|
5
5
|
mountedEntry
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-UKQBH4AQ.js";
|
|
7
7
|
import {
|
|
8
8
|
steerPrompt
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XQHPDNVG.js";
|
|
10
10
|
import {
|
|
11
11
|
OPTIONS,
|
|
12
12
|
RelayUsage,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
selectorList,
|
|
19
19
|
spawnerKey,
|
|
20
20
|
walkNow
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-AAFHLHXG.js";
|
|
22
22
|
import {
|
|
23
23
|
SELF,
|
|
24
24
|
note
|
|
@@ -44,8 +44,8 @@ import {
|
|
|
44
44
|
} from "@scp-dev/core";
|
|
45
45
|
var SERVER = "scp";
|
|
46
46
|
var SPAWN_RUNNER = "SCP_SPAWN_RUNNER";
|
|
47
|
-
var SPAWNER_IDENTITY = ["SCP_NAME", "SCP_SESSION", "SCP_GRANT", "SCP_PARENT", "SCP_HARNESS", SPAWN_RUNNER];
|
|
48
|
-
var SHIM_ENV = ["SCP_GRANT", "SCP_NAME", "SCP_LABELS", "SCP_DIR", "XDG_STATE_HOME"];
|
|
47
|
+
var SPAWNER_IDENTITY = ["SCP_NAME", "SCP_SESSION", "SCP_GRANT", "SCP_PARENT", "SCP_HARNESS", "SCP_SHIM_BINDING", SPAWN_RUNNER];
|
|
48
|
+
var SHIM_ENV = ["SCP_GRANT", "SCP_NAME", "SCP_LABELS", "SCP_DIR", "XDG_STATE_HOME", "SCP_SHIM_BINDING"];
|
|
49
49
|
function spawnEnvironment(parent, grant, labels) {
|
|
50
50
|
const env = {};
|
|
51
51
|
for (const [key, value] of Object.entries(parent)) if (value !== void 0 && !SPAWNER_IDENTITY.includes(key)) env[key] = value;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-MNTIEWKF.js";
|
|
7
7
|
|
|
8
8
|
// src/relay.ts
|
|
9
|
-
import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
9
|
+
import { chmodSync as chmodSync2, mkdirSync, readFileSync as readFileSync2, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
10
10
|
import { join as join3, dirname as dirname2 } from "path";
|
|
11
11
|
import { randomUUID } from "crypto";
|
|
12
12
|
import { CLI_NAME as CLI_NAME3 } from "@scp-dev/core";
|
|
@@ -16,13 +16,13 @@ import { spawn } from "child_process";
|
|
|
16
16
|
import { closeSync, openSync, statSync, truncateSync } from "fs";
|
|
17
17
|
import { join as join2 } from "path";
|
|
18
18
|
import { CLI_NAME as CLI_NAME2 } from "@scp-dev/core";
|
|
19
|
-
import { connectBroker, privateDir, relayDir as
|
|
19
|
+
import { connectBroker, privateDir as privateDir2, relayDir as relayDir3 } from "@scp-dev/broker";
|
|
20
20
|
|
|
21
21
|
// src/identity.ts
|
|
22
|
-
import { existsSync, realpathSync } from "fs";
|
|
22
|
+
import { chmodSync, existsSync, readFileSync, realpathSync, rmSync, writeFileSync } from "fs";
|
|
23
23
|
import { tmpdir } from "os";
|
|
24
24
|
import { basename, dirname, isAbsolute, join, resolve } from "path";
|
|
25
|
-
import { shortHostname } from "@scp-dev/broker";
|
|
25
|
+
import { privateDir, relayDir, shortHostname } from "@scp-dev/broker";
|
|
26
26
|
import { GENERIC_HARNESSES, LIMITS, validHandle, validHarness } from "@scp-dev/core";
|
|
27
27
|
var SHORT = { "claude-code": "claude" };
|
|
28
28
|
var SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash", "fish"]);
|
|
@@ -34,6 +34,61 @@ function detectHarness(env) {
|
|
|
34
34
|
if (env.ANTIGRAVITY_AGENT === "1" || env.ANTIGRAVITY_CONVERSATION_ID) return "agy";
|
|
35
35
|
if (env.CLAUDECODE === "1") return "claude-code";
|
|
36
36
|
if (env.CODEX_THREAD_ID) return "codex";
|
|
37
|
+
if (inferring(env) && (env.CODEX_SANDBOX || env.CODEX_SANDBOX_NETWORK_DISABLED)) return "codex";
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
var BINDING_KEY = /^[0-9a-f]{1,128}$/;
|
|
41
|
+
var BINDING_PROCESS = /^pid:([1-9][0-9]*):[A-Za-z0-9:-]{1,64}$/;
|
|
42
|
+
function codexShell(env) {
|
|
43
|
+
return env.SCP_HARNESS === "codex" || inferring(env) && detectHarness(env) === "codex";
|
|
44
|
+
}
|
|
45
|
+
function writeShimBinding(claim, env) {
|
|
46
|
+
const pid = BINDING_PROCESS.exec(claim.process)?.[1];
|
|
47
|
+
if (claim.harness !== "codex" || !pid) return () => {
|
|
48
|
+
};
|
|
49
|
+
const text = JSON.stringify({ process: claim.process, handle: claim.handle, harness: claim.harness });
|
|
50
|
+
const names = [`pid-${pid}`, ...BINDING_KEY.test(env.SCP_SHIM_BINDING ?? "") ? [`key-${env.SCP_SHIM_BINDING}`] : []];
|
|
51
|
+
const paths = [];
|
|
52
|
+
for (const name of names) {
|
|
53
|
+
try {
|
|
54
|
+
const path = join(privateDir(join(relayDir(env), "bindings")), `${name}.json`);
|
|
55
|
+
writeFileSync(path, text, { mode: 384 });
|
|
56
|
+
chmodSync(path, 384);
|
|
57
|
+
paths.push(path);
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return () => {
|
|
62
|
+
for (const path of paths) {
|
|
63
|
+
try {
|
|
64
|
+
if (readFileSync(path, "utf8") === text) rmSync(path);
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function readShimBinding(env, pid, table) {
|
|
71
|
+
const read = (name, expectedPid) => {
|
|
72
|
+
try {
|
|
73
|
+
const binding = JSON.parse(readFileSync(join(relayDir(env), "bindings", `${name}.json`), "utf8"));
|
|
74
|
+
const match = typeof binding.process === "string" ? BINDING_PROCESS.exec(binding.process) : null;
|
|
75
|
+
if (match && Number(match[1]) > 1 && (expectedPid === void 0 || Number(match[1]) === expectedPid) && binding.harness === "codex" && typeof binding.handle === "string" && validHandle(binding.handle))
|
|
76
|
+
return binding;
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
return void 0;
|
|
80
|
+
};
|
|
81
|
+
if (BINDING_KEY.test(env.SCP_SHIM_BINDING ?? "")) {
|
|
82
|
+
const binding = read(`key-${env.SCP_SHIM_BINDING}`);
|
|
83
|
+
if (binding) return binding;
|
|
84
|
+
}
|
|
85
|
+
const seen = /* @__PURE__ */ new Set();
|
|
86
|
+
while (pid > 1 && !seen.has(pid)) {
|
|
87
|
+
seen.add(pid);
|
|
88
|
+
const entry = table?.get(pid);
|
|
89
|
+
if (!entry) return read(`pid-${pid}`, pid);
|
|
90
|
+
pid = entry.ppid;
|
|
91
|
+
}
|
|
37
92
|
return void 0;
|
|
38
93
|
}
|
|
39
94
|
function normalizeHarness(raw, fallback) {
|
|
@@ -342,9 +397,9 @@ function relayIdentity(input) {
|
|
|
342
397
|
|
|
343
398
|
// src/session.ts
|
|
344
399
|
import { CLI_NAME } from "@scp-dev/core";
|
|
345
|
-
import { readSessionMarker, relayDir } from "@scp-dev/broker";
|
|
400
|
+
import { readSessionMarker, relayDir as relayDir2 } from "@scp-dev/broker";
|
|
346
401
|
function membership(env, session) {
|
|
347
|
-
const marker = readSessionMarker(
|
|
402
|
+
const marker = readSessionMarker(relayDir2(env), session);
|
|
348
403
|
if (marker?.joined === false) return { dark: `this session left the relay; ${CLI_NAME} join (or relay_join) joins it again` };
|
|
349
404
|
if (!marker?.joined && joinMode(env) === "manual") return { dark: `this session has not joined the relay; ${CLI_NAME} join <name> (or relay_join) joins it` };
|
|
350
405
|
return marker?.handle ? { handle: marker.handle } : {};
|
|
@@ -471,7 +526,7 @@ var DAEMON_ENV = [
|
|
|
471
526
|
];
|
|
472
527
|
var LOG_MAX_BYTES = 1024 * 1024;
|
|
473
528
|
function startDaemon(dir) {
|
|
474
|
-
|
|
529
|
+
privateDir2(dir);
|
|
475
530
|
const logFile = join2(dir, "broker.log");
|
|
476
531
|
if ((statSync(logFile, { throwIfNoEntry: false })?.size ?? 0) > LOG_MAX_BYTES) truncateSync(logFile, 0);
|
|
477
532
|
const log = openSync(logFile, "a", 384);
|
|
@@ -499,11 +554,18 @@ function localHandle(raw) {
|
|
|
499
554
|
if (handle.includes("/")) throw new RelayUsage(`--as names a local handle, not ${JSON.stringify(raw)}`);
|
|
500
555
|
return handle;
|
|
501
556
|
}
|
|
502
|
-
function walkNow() {
|
|
503
|
-
const
|
|
504
|
-
const self = harnessLineage(
|
|
557
|
+
function walkNow(env = process.env, pid = process.ppid, table = readPsTable()) {
|
|
558
|
+
const keys = lineage(pid, table);
|
|
559
|
+
const self = harnessLineage(pid, table);
|
|
560
|
+
if (!self.length && codexShell(env)) {
|
|
561
|
+
const binding = readShimBinding(env, pid, table);
|
|
562
|
+
if (binding) {
|
|
563
|
+
const bound = [...keys, binding.process];
|
|
564
|
+
return { keys: bound, self: bound, harness: "codex" };
|
|
565
|
+
}
|
|
566
|
+
}
|
|
505
567
|
const harness = self.length ? harnessAt(Number(/^pid:(\d+)/.exec(self.at(-1))?.[1]), table) : void 0;
|
|
506
|
-
return { keys
|
|
568
|
+
return { keys, self, ...harness ? { harness } : {} };
|
|
507
569
|
}
|
|
508
570
|
function claimHarness(values, env, walk) {
|
|
509
571
|
return values.harness ?? env.SCP_HARNESS ?? (inferring(env) ? walk?.harness ?? detectHarness(env) : void 0) ?? "cli";
|
|
@@ -529,7 +591,7 @@ async function open(verb, values, cwd, bodyFromStdin, walk) {
|
|
|
529
591
|
`${CLI_NAME2} ${verb} needs an identity: --as HANDLE (or $SCP_NAME) for an agent, or --human for your own inbox me/ (no terminal is attached, so me/ is not assumed)`
|
|
530
592
|
);
|
|
531
593
|
}
|
|
532
|
-
const { machineName, openCloud } = await import("./remote-
|
|
594
|
+
const { machineName, openCloud } = await import("./remote-UQJ5YYCC.js");
|
|
533
595
|
const handle2 = named ? localHandle(named) : void 0;
|
|
534
596
|
const claim = handle2 ? {
|
|
535
597
|
handle: handle2,
|
|
@@ -558,7 +620,7 @@ async function open(verb, values, cwd, bodyFromStdin, walk) {
|
|
|
558
620
|
const handle = "handle" in joined && joined.handle ? joined.handle : named ? localHandle(named) : void 0;
|
|
559
621
|
const harnessPid2 = self.length ? Number(/^pid:(\d+)/.exec(self.at(-1))?.[1]) : void 0;
|
|
560
622
|
const lineageClaim = keys.length ? { lineage: keys } : {};
|
|
561
|
-
const dir =
|
|
623
|
+
const dir = relayDir3();
|
|
562
624
|
const client = await connectBroker(dir, () => startDaemon(dir));
|
|
563
625
|
try {
|
|
564
626
|
let bound;
|
|
@@ -688,7 +750,7 @@ function checkRelayUrl(text, what = "relay URL") {
|
|
|
688
750
|
function readObject(path) {
|
|
689
751
|
let text;
|
|
690
752
|
try {
|
|
691
|
-
text =
|
|
753
|
+
text = readFileSync2(path, "utf8");
|
|
692
754
|
} catch (error) {
|
|
693
755
|
if (error.code === "ENOENT") return void 0;
|
|
694
756
|
throw new RelayUsage(`could not read ${path}`);
|
|
@@ -704,15 +766,15 @@ function readObject(path) {
|
|
|
704
766
|
function writePrivateJson(path, value) {
|
|
705
767
|
const dir = dirname2(path);
|
|
706
768
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
707
|
-
|
|
769
|
+
chmodSync2(dir, 448);
|
|
708
770
|
const temp = join3(dir, `.${randomUUID()}.tmp`);
|
|
709
771
|
try {
|
|
710
|
-
|
|
772
|
+
writeFileSync2(temp, `${JSON.stringify(value, null, 2)}
|
|
711
773
|
`, { mode: 384, flag: "wx" });
|
|
712
|
-
|
|
774
|
+
chmodSync2(temp, 384);
|
|
713
775
|
renameSync(temp, path);
|
|
714
776
|
} finally {
|
|
715
|
-
|
|
777
|
+
rmSync2(temp, { force: true });
|
|
716
778
|
}
|
|
717
779
|
}
|
|
718
780
|
function activeRelay(env = process.env) {
|
|
@@ -787,7 +849,7 @@ function relayVerb(positionals, asJson, env = process.env) {
|
|
|
787
849
|
}
|
|
788
850
|
async function loginMain(positionals, values) {
|
|
789
851
|
if (positionals.length) throw new RelayUsage(`${CLI_NAME3} login takes only flags`);
|
|
790
|
-
return (await import("./login-
|
|
852
|
+
return (await import("./login-6MVD3VLC.js")).login(values);
|
|
791
853
|
}
|
|
792
854
|
function logoutMain(positionals, asJson, env = process.env) {
|
|
793
855
|
if (positionals.length) throw new RelayUsage(`${CLI_NAME3} logout takes no arguments`);
|
|
@@ -802,6 +864,8 @@ function logoutMain(positionals, asJson, env = process.env) {
|
|
|
802
864
|
export {
|
|
803
865
|
shortHostname,
|
|
804
866
|
detectHarness,
|
|
867
|
+
codexShell,
|
|
868
|
+
writeShimBinding,
|
|
805
869
|
normalizeHarness,
|
|
806
870
|
hookHarness,
|
|
807
871
|
gitToplevel,
|
|
@@ -835,6 +899,7 @@ export {
|
|
|
835
899
|
OPTIONS,
|
|
836
900
|
SPAWN_OPTIONS,
|
|
837
901
|
startDaemon,
|
|
902
|
+
terminalAttached,
|
|
838
903
|
localHandle,
|
|
839
904
|
walkNow,
|
|
840
905
|
open,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
hooksTarget
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2342GTME.js";
|
|
4
4
|
import {
|
|
5
5
|
AGY_HOOK_SET,
|
|
6
6
|
BLOCK_STOP,
|
|
@@ -12,12 +12,12 @@ import {
|
|
|
12
12
|
mergeHooks,
|
|
13
13
|
musePlugin,
|
|
14
14
|
opencodePlugin
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-XQHPDNVG.js";
|
|
16
16
|
import {
|
|
17
17
|
RelayUsage,
|
|
18
18
|
gitToplevel,
|
|
19
19
|
setJoinMode
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-AAFHLHXG.js";
|
|
21
21
|
|
|
22
22
|
// src/setup.ts
|
|
23
23
|
import { spawnSync } from "child_process";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
psStart,
|
|
14
14
|
relayIdentity,
|
|
15
15
|
sessionKey
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-AAFHLHXG.js";
|
|
17
17
|
|
|
18
18
|
// src/hooks.ts
|
|
19
19
|
import { Readable } from "stream";
|
|
@@ -545,13 +545,26 @@ async function runHook(args, options) {
|
|
|
545
545
|
}
|
|
546
546
|
async function wakeHook(harnessArg, payload, waitS, options) {
|
|
547
547
|
if (options.env.SCP_TRANSPORT === "cloud" || field(payload, "agent_id", "agentId", "agent_type", "agentType", "subagentType")) return;
|
|
548
|
+
const harness = normalizeHarness(hookHarness(harnessArg, options.env), "hook");
|
|
549
|
+
const pid = (options.harnessPid ?? ((h) => hookHarnessPid(options.env, h)))(harness);
|
|
550
|
+
const started = psStart(pid);
|
|
551
|
+
const joined = membership(
|
|
552
|
+
options.env,
|
|
553
|
+
sessionKey(
|
|
554
|
+
options.env,
|
|
555
|
+
processKey(pid, () => started)
|
|
556
|
+
)
|
|
557
|
+
);
|
|
558
|
+
if ("dark" in joined) return;
|
|
548
559
|
const claim = relayIdentity({
|
|
549
|
-
|
|
560
|
+
...joined.handle ? { as: joined.handle } : {},
|
|
561
|
+
harness,
|
|
550
562
|
fallbackHarness: "hook",
|
|
551
563
|
cwd: asString(payload.cwd) ?? options.cwd,
|
|
552
564
|
env: options.env,
|
|
553
|
-
harnessPid:
|
|
554
|
-
...options.harnessPid ? {} : { inferHarness: (at) => harnessAt(at) }
|
|
565
|
+
harnessPid: () => pid,
|
|
566
|
+
...options.harnessPid ? {} : { inferHarness: (at) => harnessAt(at) },
|
|
567
|
+
startOf: () => started
|
|
555
568
|
});
|
|
556
569
|
if (!validHandle(claim.handle)) return;
|
|
557
570
|
const waitMs = Math.min(waitS, LIMITS.waitMaxS) * 1e3;
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
mcpFile,
|
|
4
4
|
mountedEntry,
|
|
5
5
|
whichOnPath
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-UKQBH4AQ.js";
|
|
7
|
+
import "./chunk-2342GTME.js";
|
|
8
|
+
import "./chunk-XQHPDNVG.js";
|
|
9
9
|
import "./chunk-YYSLYVNZ.js";
|
|
10
10
|
import {
|
|
11
11
|
CHANNELS_ENV,
|
|
12
12
|
RelayUsage,
|
|
13
13
|
deriveHandle,
|
|
14
14
|
joinMode
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-AAFHLHXG.js";
|
|
16
16
|
import "./chunk-MNTIEWKF.js";
|
|
17
17
|
|
|
18
18
|
// src/claude.ts
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,6 @@ function quietSqliteWarning() {
|
|
|
17
17
|
// src/cli.ts
|
|
18
18
|
if (!await subagentFastPath(process.argv.slice(2))) {
|
|
19
19
|
quietSqliteWarning();
|
|
20
|
-
const { run } = await import("./main-
|
|
20
|
+
const { run } = await import("./main-F2NFQ2KC.js");
|
|
21
21
|
await run(process.argv.slice(2));
|
|
22
22
|
}
|
|
@@ -3,18 +3,18 @@ import {
|
|
|
3
3
|
codexMount,
|
|
4
4
|
codexOverrides,
|
|
5
5
|
toml
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7RA7E5WR.js";
|
|
7
7
|
import "./chunk-KN7WEIE4.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-UKQBH4AQ.js";
|
|
9
|
+
import "./chunk-2342GTME.js";
|
|
10
|
+
import "./chunk-XQHPDNVG.js";
|
|
11
11
|
import "./chunk-YYSLYVNZ.js";
|
|
12
12
|
import {
|
|
13
13
|
RelayUsage,
|
|
14
14
|
readPsTable,
|
|
15
15
|
relayIdentity,
|
|
16
16
|
startDaemon
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-AAFHLHXG.js";
|
|
18
18
|
import {
|
|
19
19
|
SELF
|
|
20
20
|
} from "./chunk-MNTIEWKF.js";
|
|
@@ -29,7 +29,7 @@ import { join } from "path";
|
|
|
29
29
|
import { PassThrough } from "stream";
|
|
30
30
|
import { setTimeout as sleep } from "timers/promises";
|
|
31
31
|
import { connectBroker, relayDir } from "@scp-dev/broker";
|
|
32
|
-
import { CLI_NAME, validHandle } from "@scp-dev/core";
|
|
32
|
+
import { CLI_NAME, RelayError, validHandle } from "@scp-dev/core";
|
|
33
33
|
import { MCP_PROTOCOLS, runRelayMcp } from "@scp-dev/mcp";
|
|
34
34
|
import { parse } from "smol-toml";
|
|
35
35
|
var CODEX_HELP = `${CLI_NAME} codex [--name N | --as N] [--headless] [--resume THREAD] [--] [codex args...]
|
|
@@ -61,13 +61,13 @@ function codexLaunch(args, env, _self) {
|
|
|
61
61
|
}
|
|
62
62
|
name = name?.replace(/^me\//, "");
|
|
63
63
|
if (name !== void 0 && !validHandle(name)) throw new RelayUsage(`${JSON.stringify(name)} is not a valid agent handle`);
|
|
64
|
-
const { SCP_SESSION: _session,
|
|
64
|
+
const { SCP_SESSION: _session, SCP_PARENT: _parent, ...clean } = env;
|
|
65
65
|
return {
|
|
66
66
|
...name !== void 0 ? { name } : {},
|
|
67
67
|
headless,
|
|
68
68
|
...resume !== void 0 ? { resume } : {},
|
|
69
69
|
codexArgs: resume !== void 0 && !headless ? ["resume", resume, ...codexArgs] : codexArgs,
|
|
70
|
-
env: { ...clean, SCP_HARNESS: "codex", ...name !== void 0 ? { SCP_NAME: name } : {} }
|
|
70
|
+
env: { ...clean, SCP_HARNESS: "codex", SCP_SHIM_BINDING: randomBytes(16).toString("hex"), ...name !== void 0 ? { SCP_NAME: name } : {} }
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
var CodexSocket = class {
|
|
@@ -398,6 +398,24 @@ function appServerPid(pid) {
|
|
|
398
398
|
}
|
|
399
399
|
return pid;
|
|
400
400
|
}
|
|
401
|
+
async function connectCodexChannel(connect2, claim, cwd, stopped) {
|
|
402
|
+
while (!stopped()) {
|
|
403
|
+
const client = await connect2();
|
|
404
|
+
try {
|
|
405
|
+
const hello = await client.hello({ observe: true, self: [claim.process], ...claim.grant ? { grant: claim.grant } : {}, cwd });
|
|
406
|
+
if (hello.endpoint) {
|
|
407
|
+
client.hello = async () => hello;
|
|
408
|
+
return client;
|
|
409
|
+
}
|
|
410
|
+
} catch (error) {
|
|
411
|
+
client.close();
|
|
412
|
+
if (!claim.grant || !(error instanceof RelayError) || error.code !== "unauthorized") throw error;
|
|
413
|
+
}
|
|
414
|
+
client.close();
|
|
415
|
+
await sleep(100);
|
|
416
|
+
}
|
|
417
|
+
throw new Error("codex channel stopped");
|
|
418
|
+
}
|
|
401
419
|
async function codexCommand(args) {
|
|
402
420
|
if (args[0] === "--help" || args[0] === "-h") {
|
|
403
421
|
process.stdout.write(`${CODEX_HELP}
|
|
@@ -514,24 +532,12 @@ ${stderr.toString().trim()}` : ""}`
|
|
|
514
532
|
const broker = relayDir(launch.env);
|
|
515
533
|
let lines = "";
|
|
516
534
|
channel = runRelayMcp({
|
|
517
|
-
connect:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
client.hello = async () => hello;
|
|
524
|
-
return client;
|
|
525
|
-
}
|
|
526
|
-
} catch (error) {
|
|
527
|
-
client.close();
|
|
528
|
-
throw error;
|
|
529
|
-
}
|
|
530
|
-
client.close();
|
|
531
|
-
await sleep(100);
|
|
532
|
-
}
|
|
533
|
-
throw new Error("codex channel stopped");
|
|
534
|
-
},
|
|
535
|
+
connect: () => connectCodexChannel(
|
|
536
|
+
() => connectBroker(broker, () => startDaemon(broker)),
|
|
537
|
+
claim,
|
|
538
|
+
cwd,
|
|
539
|
+
() => input.writableEnded
|
|
540
|
+
),
|
|
535
541
|
claim,
|
|
536
542
|
channels: true,
|
|
537
543
|
wake: "codex-app-server",
|
|
@@ -611,5 +617,6 @@ export {
|
|
|
611
617
|
CodexWaker,
|
|
612
618
|
codexCommand,
|
|
613
619
|
codexLaunch,
|
|
620
|
+
connectCodexChannel,
|
|
614
621
|
serverOptions
|
|
615
622
|
};
|
|
@@ -40,11 +40,11 @@ import {
|
|
|
40
40
|
tldrEvery,
|
|
41
41
|
transcriptTitle,
|
|
42
42
|
unreadPointer
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-XQHPDNVG.js";
|
|
44
44
|
import {
|
|
45
45
|
SUBAGENT
|
|
46
46
|
} from "./chunk-YYSLYVNZ.js";
|
|
47
|
-
import "./chunk-
|
|
47
|
+
import "./chunk-AAFHLHXG.js";
|
|
48
48
|
import "./chunk-MNTIEWKF.js";
|
|
49
49
|
export {
|
|
50
50
|
AGY_HOOK_SET,
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
hooksTarget,
|
|
3
3
|
installHooks,
|
|
4
4
|
mcpInstall
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-2342GTME.js";
|
|
6
|
+
import "./chunk-XQHPDNVG.js";
|
|
7
7
|
import "./chunk-YYSLYVNZ.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-AAFHLHXG.js";
|
|
9
9
|
import "./chunk-MNTIEWKF.js";
|
|
10
10
|
export {
|
|
11
11
|
hooksTarget,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RelayUsage,
|
|
3
|
+
codexShell,
|
|
3
4
|
harnessAt,
|
|
4
5
|
localHandle,
|
|
5
6
|
relayIdentity,
|
|
6
7
|
sessionKey,
|
|
7
8
|
startDaemon,
|
|
8
9
|
walkNow
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AAFHLHXG.js";
|
|
10
11
|
import "./chunk-MNTIEWKF.js";
|
|
11
12
|
|
|
12
13
|
// src/join.ts
|
|
@@ -18,7 +19,10 @@ async function joinCommand(values, positionals, cwd, out) {
|
|
|
18
19
|
const { keys, self } = walkNow();
|
|
19
20
|
const key = self.at(-1);
|
|
20
21
|
const match = key === void 0 ? null : /^pid:(\d+):(.+)$/.exec(key);
|
|
21
|
-
if (!match)
|
|
22
|
+
if (!match) {
|
|
23
|
+
if (codexShell(process.env)) throw new RelayUsage(`${CLI_NAME} join: the codex sandbox hides the harness; use relay_join (MCP) instead`);
|
|
24
|
+
throw new RelayUsage(`${CLI_NAME} join runs in an agent session's shell: no harness process runs this shell`);
|
|
25
|
+
}
|
|
22
26
|
const dir = relayDir();
|
|
23
27
|
const known = readSessionMarker(dir, sessionKey(process.env, key))?.handle;
|
|
24
28
|
const claim = relayIdentity({
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
machineName
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-H2XQXMZU.js";
|
|
4
4
|
import {
|
|
5
5
|
RelayUsage,
|
|
6
6
|
activeRelay,
|
|
7
7
|
saveCredential
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-AAFHLHXG.js";
|
|
9
9
|
import {
|
|
10
10
|
note
|
|
11
11
|
} from "./chunk-MNTIEWKF.js";
|
|
@@ -14,8 +14,9 @@ import {
|
|
|
14
14
|
shortHostname,
|
|
15
15
|
stamp,
|
|
16
16
|
startDaemon,
|
|
17
|
+
terminalAttached,
|
|
17
18
|
time
|
|
18
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-AAFHLHXG.js";
|
|
19
20
|
import {
|
|
20
21
|
FAILED,
|
|
21
22
|
exitFlushed,
|
|
@@ -34,7 +35,7 @@ import { parseArgs } from "util";
|
|
|
34
35
|
// package.json
|
|
35
36
|
var package_default = {
|
|
36
37
|
name: "@scp-dev/cli",
|
|
37
|
-
version: "0.
|
|
38
|
+
version: "0.5.0",
|
|
38
39
|
description: "The swarm command line tool.",
|
|
39
40
|
license: "Apache-2.0",
|
|
40
41
|
homepage: "https://scp.dev",
|
|
@@ -105,6 +106,8 @@ results back, as with native subagents.
|
|
|
105
106
|
${CLI_NAME} list [--all] agents on the relay: address, title, presence, wake, status; --all adds offline ones
|
|
106
107
|
${CLI_NAME} join [name] put this session on the relay, named once: ${CLI_NAME} join lead (${CLI_NAME} name renames it)
|
|
107
108
|
${CLI_NAME} join --under <parent> link this session under an orchestrator, as a spawned worker sits: ${CLI_NAME} join --under lead
|
|
109
|
+
${CLI_NAME} adopt <child> ask a local root agent to link under you; it accepts with ${CLI_NAME} link accept <id>
|
|
110
|
+
${CLI_NAME} link accept <id> accept a link request and sit under its sender as a worker
|
|
108
111
|
${CLI_NAME} status [id] the fleet in short; with the id of a message you sent: who read it when
|
|
109
112
|
${CLI_NAME} peek <ep> a short, redacted view of a peekable agent's last turns: ${CLI_NAME} peek rev
|
|
110
113
|
${CLI_NAME} set-status <state> [note] working, waiting, blocked or done: ${CLI_NAME} set-status done "PR open"
|
|
@@ -286,13 +289,20 @@ agent sessions:
|
|
|
286
289
|
and title stay; a handle another endpoint holds, live or offline, is refused;
|
|
287
290
|
a spawned worker is named by its spawner (policy defaults.rename: self lets it);
|
|
288
291
|
--endpoint renames another agent, for the human at a terminal
|
|
289
|
-
${CLI_NAME} join [<handle>] --under <parent> link the session under the agent <parent> (
|
|
292
|
+
${CLI_NAME} join [<handle>] --under <parent> link the session under the agent <parent> (one it may message), as if
|
|
290
293
|
<parent> had spawned it: it shows under <parent> in list --tree, the dashboard
|
|
291
294
|
and the graph, and takes on a worker's scope (the policy's child_default: by
|
|
292
|
-
default it reaches only what <parent> reaches). Narrowing, so always allowed
|
|
295
|
+
default it reaches only what <parent> reaches). Narrowing, so always allowed.
|
|
296
|
+
<parent> may be on another machine of the account (me/<machine>/<handle>):
|
|
297
|
+
the session stays a root there, takes no child scope, and the two reach
|
|
298
|
+
each other both ways
|
|
293
299
|
${CLI_NAME} adopt <child> [--parent <p>] link a local root agent and its subtree under <p>, for the human at a terminal;
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
<p> may be on another machine of the account (me/<machine>/<handle>).
|
|
301
|
+
With --parent and a terminal, inherited $SCP_NAME and $SCP_GRANT are ignored
|
|
302
|
+
unless --as is explicit. An agent without a terminal asks the child to consent,
|
|
303
|
+
under itself only; the child accepts with link accept or join --under
|
|
304
|
+
${CLI_NAME} link accept <id> accept a link request delivered to this session and sit under its sender as a worker;
|
|
305
|
+
<id> is the full or short message id. Only the session itself may accept
|
|
296
306
|
${CLI_NAME} unlink [<child>] put a linked agent back at the root, its subtree along and the child scope off;
|
|
297
307
|
widening, so the human at a terminal only (policy defaults.unlink: self lets
|
|
298
308
|
an agent unlink itself). A link that would put a parent under its own child
|
|
@@ -383,6 +393,7 @@ var VERBS = {
|
|
|
383
393
|
send: [...IDENTITY, "reply-to", "thread", "private", "attach", "live"],
|
|
384
394
|
join: ["harness", "json", "under"],
|
|
385
395
|
adopt: [...IDENTITY, "parent"],
|
|
396
|
+
link: IDENTITY,
|
|
386
397
|
unlink: IDENTITY,
|
|
387
398
|
leave: [...IDENTITY, "endpoint"],
|
|
388
399
|
name: [...IDENTITY, "endpoint"],
|
|
@@ -558,14 +569,14 @@ async function relayMain(argv, cwd = process.cwd()) {
|
|
|
558
569
|
out(cliVersion());
|
|
559
570
|
return 0;
|
|
560
571
|
}
|
|
561
|
-
if (verb === "hook") return (await import("./hooks-
|
|
562
|
-
if (verb === "setup") return (await import("./setup-
|
|
563
|
-
if (verb === "claude") return (await import("./claude-
|
|
564
|
-
if (verb === "pi") return (await import("./pi-
|
|
565
|
-
if (verb === "codex") return (await import("./codex-
|
|
566
|
-
if (verb === "opencode") return (await import("./opencode-
|
|
572
|
+
if (verb === "hook") return (await import("./hooks-BZANUJPY.js")).relayHookCommand(rest, startDaemon);
|
|
573
|
+
if (verb === "setup") return (await import("./setup-UJCIMYU4.js")).relaySetupCommand(rest, cwd, out);
|
|
574
|
+
if (verb === "claude") return (await import("./claude-RNH2E4GU.js")).claudeCommand(rest);
|
|
575
|
+
if (verb === "pi") return (await import("./pi-N3DX37PD.js")).piCommand(rest);
|
|
576
|
+
if (verb === "codex") return (await import("./codex-OSGHQMK6.js")).codexCommand(rest);
|
|
577
|
+
if (verb === "opencode") return (await import("./opencode-XV33XTL5.js")).opencodeCommand(rest, process.env, void 0, cwd);
|
|
567
578
|
if (verb === "spawn") {
|
|
568
|
-
const { splitSpawn, spawnCommand } = await import("./spawn-
|
|
579
|
+
const { splitSpawn, spawnCommand } = await import("./spawn-JYD7NCQT.js");
|
|
569
580
|
const { flags } = splitSpawn(rest);
|
|
570
581
|
if (flags.includes("--help") || flags.includes("-h")) {
|
|
571
582
|
out(flags.includes("--all") ? RELAY_HELP : SPAWN_HELP);
|
|
@@ -573,7 +584,7 @@ async function relayMain(argv, cwd = process.cwd()) {
|
|
|
573
584
|
}
|
|
574
585
|
return spawnCommand(rest, cwd);
|
|
575
586
|
}
|
|
576
|
-
if (verb === "mesh") return (await import("./mesh-
|
|
587
|
+
if (verb === "mesh") return (await import("./mesh-OZILTV5P.js")).meshCommand(rest);
|
|
577
588
|
const allowed = VERBS[verb];
|
|
578
589
|
if (!allowed) throw new RelayUsage(`unknown command "${verb}"`);
|
|
579
590
|
let parsed;
|
|
@@ -593,11 +604,11 @@ async function relayMain(argv, cwd = process.cwd()) {
|
|
|
593
604
|
return daemon(values.idle, values.policy);
|
|
594
605
|
}
|
|
595
606
|
if (verb === "mcp")
|
|
596
|
-
return (await import("./mcp-
|
|
607
|
+
return (await import("./mcp-BH526TOG.js")).relayMcpCommand(values, positionals);
|
|
597
608
|
if (verb === "hooks") {
|
|
598
609
|
if (positionals[0] !== "install" || positionals.length > 1) throw new RelayUsage(`${CLI_NAME} hooks takes install --harness claude|codex|opencode|agy|muse`);
|
|
599
610
|
if (values.write && values.print) throw new RelayUsage("--print and --write: pick one");
|
|
600
|
-
return (await import("./install-
|
|
611
|
+
return (await import("./install-25J5QB63.js")).installHooks({
|
|
601
612
|
harness: values.harness,
|
|
602
613
|
scope: values.scope,
|
|
603
614
|
write: values.write === true,
|
|
@@ -608,31 +619,48 @@ async function relayMain(argv, cwd = process.cwd()) {
|
|
|
608
619
|
out
|
|
609
620
|
});
|
|
610
621
|
}
|
|
611
|
-
if (verb === "relay") return (await import("./relay-
|
|
612
|
-
if (verb === "up") return (await import("./up-
|
|
622
|
+
if (verb === "relay") return (await import("./relay-SF3UWIPM.js")).relayVerb(positionals, values.json === true);
|
|
623
|
+
if (verb === "up") return (await import("./up-3YJU7YX6.js")).up(positionals, values, cwd, relinkBroker);
|
|
613
624
|
if (verb === "login") {
|
|
614
|
-
const code = await (await import("./relay-
|
|
625
|
+
const code = await (await import("./relay-SF3UWIPM.js")).loginMain(positionals, values);
|
|
615
626
|
if (code === 0) await relinkRunning();
|
|
616
627
|
return code;
|
|
617
628
|
}
|
|
618
|
-
if (verb === "logout") return (await import("./relay-
|
|
629
|
+
if (verb === "logout") return (await import("./relay-SF3UWIPM.js")).logoutMain(positionals, values.json === true);
|
|
619
630
|
if (verb === "cloud") {
|
|
620
|
-
const code = await (await import("./remote-
|
|
631
|
+
const code = await (await import("./remote-UQJ5YYCC.js")).cloudMain(positionals, values, cloudStatus);
|
|
621
632
|
if (code === 0 && positionals[0] === "enable") await relinkRunning();
|
|
622
633
|
return code;
|
|
623
634
|
}
|
|
624
|
-
if (verb === "join") return (await import("./join-
|
|
635
|
+
if (verb === "join") return (await import("./join-EOLHE3LJ.js")).joinCommand(values, positionals, cwd, out);
|
|
625
636
|
if (verb === "holds") holdsArgs(values, positionals);
|
|
626
637
|
const bodyFromStdin = (verb === "send" || verb === "ask" || verb === "reply") && (positionals[1] === void 0 || positionals[1] === "-");
|
|
627
|
-
const
|
|
638
|
+
const humanAdopt = verb === "adopt" && values.parent !== void 0 && values.as === void 0 && terminalAttached(process, false);
|
|
639
|
+
const opened = humanAdopt ? await openAdoptHuman(cwd, values) : await open(verb, values, cwd, bodyFromStdin);
|
|
628
640
|
const { client } = opened;
|
|
629
641
|
try {
|
|
630
|
-
if (verb === "machines") return await (await import("./remote-
|
|
642
|
+
if (verb === "machines") return await (await import("./remote-UQJ5YYCC.js")).machinesVerb(client, positionals, values.json === true);
|
|
631
643
|
return await runVerb(opened, verb, values, positionals, cwd);
|
|
632
644
|
} finally {
|
|
633
645
|
client.close();
|
|
634
646
|
}
|
|
635
647
|
}
|
|
648
|
+
async function openAdoptHuman(cwd, values) {
|
|
649
|
+
if (values.cloud || process.env.SCP_TRANSPORT === "cloud") {
|
|
650
|
+
const { openCloud } = await import("./remote-UQJ5YYCC.js");
|
|
651
|
+
return { ...await openCloud({ tty: true, ...values.machine !== void 0 ? { machine: values.machine } : {} }), broker: null, bound: "human" };
|
|
652
|
+
}
|
|
653
|
+
if (values.machine !== void 0) throw new RelayUsage("--machine names the machine of the cloud transport: add --cloud");
|
|
654
|
+
const dir = relayDir();
|
|
655
|
+
const client = await connectBroker(dir, () => startDaemon(dir));
|
|
656
|
+
try {
|
|
657
|
+
const hello = await client.hello({ human: true, tty: true, cwd, brief: true });
|
|
658
|
+
return { client, me: hello.endpoint, broker: hello.broker, where: brokerLine(hello.broker), bound: "human" };
|
|
659
|
+
} catch (error) {
|
|
660
|
+
client.close();
|
|
661
|
+
throw error;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
636
664
|
async function cloudStatus() {
|
|
637
665
|
const dir = relayDir();
|
|
638
666
|
const client = await connectBroker(dir, () => startDaemon(dir));
|
|
@@ -804,9 +832,9 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
|
|
|
804
832
|
return 0;
|
|
805
833
|
}
|
|
806
834
|
case "peek":
|
|
807
|
-
return (await import("./peek-
|
|
835
|
+
return (await import("./peek-LFQR6TCS.js")).peekCommand(localClient(client, broker, verb), values, positionals);
|
|
808
836
|
case "set-peek":
|
|
809
|
-
return (await import("./peek-
|
|
837
|
+
return (await import("./peek-LFQR6TCS.js")).setPeekCommand(localClient(client, broker, verb), values, positionals);
|
|
810
838
|
case "why": {
|
|
811
839
|
const [from, to] = positionals;
|
|
812
840
|
if (!from || !to || positionals.length > 2) throw new RelayUsage(`${CLI_NAME} why takes <from> <to>`);
|
|
@@ -1045,6 +1073,16 @@ async function runVerb({ client, me, broker, where, bound, harnessPid }, verb, v
|
|
|
1045
1073
|
...parent !== void 0 ? { parent } : {}
|
|
1046
1074
|
});
|
|
1047
1075
|
if (asJson) json(result);
|
|
1076
|
+
else if (result.held) out(heldText(result.held));
|
|
1077
|
+
else if (result.requested)
|
|
1078
|
+
out(`asked ${result.endpoint.address} to link under ${result.parent}; it accepts with ${CLI_NAME} link accept ${shortId(result.requested)}`);
|
|
1079
|
+
else out(`${result.endpoint.address} now sits under ${result.parent}`);
|
|
1080
|
+
return 0;
|
|
1081
|
+
}
|
|
1082
|
+
case "link": {
|
|
1083
|
+
if (positionals.length !== 2 || positionals[0] !== "accept") throw new RelayUsage(`${CLI_NAME} link takes accept <id>`);
|
|
1084
|
+
const result = await client.request("link_accept", { id: positionals[1] });
|
|
1085
|
+
if (asJson) json(result);
|
|
1048
1086
|
else out(`${result.endpoint.address} now sits under ${result.parent}`);
|
|
1049
1087
|
return 0;
|
|
1050
1088
|
}
|
|
@@ -1416,11 +1454,11 @@ async function daemon(idle, policyFile) {
|
|
|
1416
1454
|
});
|
|
1417
1455
|
let broker;
|
|
1418
1456
|
try {
|
|
1419
|
-
const { daemonBridge } = await import("./remote-
|
|
1457
|
+
const { daemonBridge } = await import("./remote-UQJ5YYCC.js");
|
|
1420
1458
|
const bridge = await daemonBridge();
|
|
1421
1459
|
broker = await startBroker({
|
|
1422
1460
|
dir: relayDir(),
|
|
1423
|
-
...bridge ? { bridge } : await (await import("./mesh-
|
|
1461
|
+
...bridge ? { bridge } : await (await import("./mesh-OZILTV5P.js")).meshBrokerOptions(),
|
|
1424
1462
|
bridgeConfig: () => daemonBridge(),
|
|
1425
1463
|
...idleMs !== void 0 ? { idleMs } : {},
|
|
1426
1464
|
...policyFile ? { policyPath: resolve(policyFile) } : {}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
spawnDetached
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7RA7E5WR.js";
|
|
4
4
|
import "./chunk-KN7WEIE4.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-UKQBH4AQ.js";
|
|
6
6
|
import {
|
|
7
7
|
mcpInstall
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-2342GTME.js";
|
|
9
|
+
import "./chunk-XQHPDNVG.js";
|
|
10
10
|
import "./chunk-YYSLYVNZ.js";
|
|
11
11
|
import {
|
|
12
12
|
CHANNELS_ENV,
|
|
@@ -16,14 +16,15 @@ import {
|
|
|
16
16
|
membership,
|
|
17
17
|
psParent,
|
|
18
18
|
relayIdentity,
|
|
19
|
-
startDaemon
|
|
20
|
-
|
|
19
|
+
startDaemon,
|
|
20
|
+
writeShimBinding
|
|
21
|
+
} from "./chunk-AAFHLHXG.js";
|
|
21
22
|
import "./chunk-MNTIEWKF.js";
|
|
22
23
|
|
|
23
24
|
// src/mcp.ts
|
|
24
25
|
import { CLI_NAME, validHandle } from "@scp-dev/core";
|
|
25
26
|
import { connectBroker, relayDir } from "@scp-dev/broker";
|
|
26
|
-
import { runRelayMcp } from "@scp-dev/mcp";
|
|
27
|
+
import { runRelayMcp, sessionInboxOf } from "@scp-dev/mcp";
|
|
27
28
|
var ORPHAN_CHECK_MS = 5e3;
|
|
28
29
|
async function relayMcpCommand(values, positionals) {
|
|
29
30
|
if (positionals[0] === "install") {
|
|
@@ -43,25 +44,35 @@ async function relayMcpCommand(values, positionals) {
|
|
|
43
44
|
inferHarness: (pid) => harnessAt(pid)
|
|
44
45
|
});
|
|
45
46
|
if (!validHandle(claim.handle)) throw new RelayUsage(`${JSON.stringify(claim.handle)} is not a valid agent handle (me, user and relay are reserved)`);
|
|
46
|
-
const dir = relayDir();
|
|
47
|
+
const dir = relayDir(process.env);
|
|
48
|
+
const unbind = writeShimBinding(claim, process.env);
|
|
49
|
+
process.on("exit", unbind);
|
|
47
50
|
const parent = process.ppid;
|
|
48
51
|
const orphaned = setInterval(() => {
|
|
49
52
|
if (process.ppid !== parent) process.exit(0);
|
|
50
53
|
}, ORPHAN_CHECK_MS);
|
|
51
54
|
orphaned.unref();
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
const inbox = sessionInboxOf(process.env);
|
|
56
|
+
try {
|
|
57
|
+
await runRelayMcp({
|
|
58
|
+
connect: () => connectBroker(dir, () => startDaemon(dir)),
|
|
59
|
+
claim,
|
|
60
|
+
membership: () => membership(process.env, claim.session),
|
|
61
|
+
input: process.stdin,
|
|
62
|
+
output: (line) => void process.stdout.write(line),
|
|
63
|
+
env: process.env,
|
|
64
|
+
channels: values.channels === true,
|
|
65
|
+
launchedWithChannels: values.channels === true && launchedWithChannels(process.env),
|
|
66
|
+
...inbox ? { sessionInbox: inbox } : {},
|
|
67
|
+
spawn: (request) => spawnDetached(spawnWords(request), request.cwd ?? claim.cwd),
|
|
68
|
+
log: (line) => void process.stderr.write(`${line}
|
|
63
69
|
`)
|
|
64
|
-
|
|
70
|
+
});
|
|
71
|
+
} finally {
|
|
72
|
+
clearInterval(orphaned);
|
|
73
|
+
process.off("exit", unbind);
|
|
74
|
+
unbind();
|
|
75
|
+
}
|
|
65
76
|
return 0;
|
|
66
77
|
}
|
|
67
78
|
function spawnWords(request) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RelayUsage
|
|
3
|
+
} from "./chunk-AAFHLHXG.js";
|
|
4
|
+
import "./chunk-MNTIEWKF.js";
|
|
5
|
+
|
|
6
|
+
// src/mesh.ts
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
import { relayDir } from "@scp-dev/broker";
|
|
10
|
+
var MESH_MODULE = "@scp-dev/mesh";
|
|
11
|
+
async function importMesh() {
|
|
12
|
+
return await import(MESH_MODULE);
|
|
13
|
+
}
|
|
14
|
+
async function load() {
|
|
15
|
+
try {
|
|
16
|
+
return await importMesh();
|
|
17
|
+
} catch {
|
|
18
|
+
throw new RelayUsage("swarm mesh is experimental and runs only from a source checkout of the swarm CLI");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async function meshCommand(argv) {
|
|
22
|
+
return (await load()).meshCommand(argv);
|
|
23
|
+
}
|
|
24
|
+
function meshEnabled(path) {
|
|
25
|
+
let text;
|
|
26
|
+
try {
|
|
27
|
+
text = readFileSync(path, "utf8");
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(text)?.enabled === true;
|
|
33
|
+
} catch {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function meshBrokerOptions(dir = join(relayDir(), "mesh"), options = {}) {
|
|
38
|
+
const path = join(dir, "mesh.json");
|
|
39
|
+
if (!meshEnabled(path)) return {};
|
|
40
|
+
let mesh;
|
|
41
|
+
try {
|
|
42
|
+
mesh = await (options.importMesh ?? importMesh)();
|
|
43
|
+
} catch {
|
|
44
|
+
const warn = options.warn ?? console.error;
|
|
45
|
+
warn(`mesh is enabled in ${path} but this CLI has no mesh module; running without it`);
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
return mesh.meshBrokerOptions(dir);
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
meshBrokerOptions,
|
|
52
|
+
meshCommand
|
|
53
|
+
};
|
|
@@ -2,18 +2,18 @@ import {
|
|
|
2
2
|
mcpFile,
|
|
3
3
|
mountedEntry,
|
|
4
4
|
whichOnPath
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-UKQBH4AQ.js";
|
|
6
6
|
import {
|
|
7
7
|
hooksTarget
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2342GTME.js";
|
|
9
9
|
import {
|
|
10
10
|
opencodePlugin
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XQHPDNVG.js";
|
|
12
12
|
import "./chunk-YYSLYVNZ.js";
|
|
13
13
|
import {
|
|
14
14
|
RelayUsage,
|
|
15
15
|
gitToplevel
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-AAFHLHXG.js";
|
|
17
17
|
import "./chunk-MNTIEWKF.js";
|
|
18
18
|
|
|
19
19
|
// src/opencode.ts
|
|
@@ -15,11 +15,11 @@ import {
|
|
|
15
15
|
verifyMount,
|
|
16
16
|
verifyMusePlugin,
|
|
17
17
|
whichOnPath
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-UKQBH4AQ.js";
|
|
19
|
+
import "./chunk-2342GTME.js";
|
|
20
|
+
import "./chunk-XQHPDNVG.js";
|
|
21
21
|
import "./chunk-YYSLYVNZ.js";
|
|
22
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-AAFHLHXG.js";
|
|
23
23
|
import "./chunk-MNTIEWKF.js";
|
|
24
24
|
export {
|
|
25
25
|
SETUP_HARNESSES,
|
|
@@ -31,15 +31,15 @@ import {
|
|
|
31
31
|
toml,
|
|
32
32
|
transcriptReplies,
|
|
33
33
|
workerName
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-7RA7E5WR.js";
|
|
35
35
|
import {
|
|
36
36
|
SPAWN_HELP
|
|
37
37
|
} from "./chunk-KN7WEIE4.js";
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import "./chunk-
|
|
40
|
-
import "./chunk-
|
|
38
|
+
import "./chunk-UKQBH4AQ.js";
|
|
39
|
+
import "./chunk-2342GTME.js";
|
|
40
|
+
import "./chunk-XQHPDNVG.js";
|
|
41
41
|
import "./chunk-YYSLYVNZ.js";
|
|
42
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-AAFHLHXG.js";
|
|
43
43
|
import "./chunk-MNTIEWKF.js";
|
|
44
44
|
export {
|
|
45
45
|
CODEX_VALUED,
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
RelayUsage,
|
|
3
3
|
activeRelay,
|
|
4
4
|
relayCredential
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AAFHLHXG.js";
|
|
6
6
|
import "./chunk-MNTIEWKF.js";
|
|
7
7
|
|
|
8
8
|
// src/up.ts
|
|
@@ -29,21 +29,21 @@ async function up(positionals, values, cwd, brokerStatus) {
|
|
|
29
29
|
const { url } = activeRelay(process.env);
|
|
30
30
|
const headless = values.token !== void 0 || Boolean(process.env.SCP_TOKEN?.trim());
|
|
31
31
|
if (headless || !relayCredential(process.env, url).token) {
|
|
32
|
-
const code = await (await import("./login-
|
|
32
|
+
const code = await (await import("./login-6MVD3VLC.js")).login({
|
|
33
33
|
...values.token !== void 0 ? { token: values.token } : {},
|
|
34
34
|
...values.label !== void 0 ? { label: values.label } : {},
|
|
35
35
|
...values["no-browser"] ? { "no-browser": true } : {}
|
|
36
36
|
});
|
|
37
37
|
if (code !== 0) return code;
|
|
38
38
|
} else out(`already logged in to ${url}`);
|
|
39
|
-
const enabled = await (await import("./remote-
|
|
39
|
+
const enabled = await (await import("./remote-UQJ5YYCC.js")).cloudMain(["enable"], values.machine !== void 0 ? { machine: values.machine } : {}, brokerStatus);
|
|
40
40
|
if (enabled !== 0) return enabled;
|
|
41
|
-
const setup = (await import("./setup-
|
|
41
|
+
const setup = (await import("./setup-UJCIMYU4.js")).relaySetupCommand(["--write"], cwd, out);
|
|
42
42
|
if (setup !== 0) return setup;
|
|
43
43
|
const broker = await brokerStatus();
|
|
44
44
|
if (!broker.enabled) out(`the broker is still local-only; run \`${CLI_NAME} daemon restart\` to link it to ${url}`);
|
|
45
45
|
else out(`broker linked to ${broker.url ?? url}${broker.connected ? "" : " (connecting)"}`);
|
|
46
|
-
const { detectHarnesses, whichOnPath } = await import("./setup-
|
|
46
|
+
const { detectHarnesses, whichOnPath } = await import("./setup-UJCIMYU4.js");
|
|
47
47
|
const which = (name) => whichOnPath(name, process.env);
|
|
48
48
|
const installed = new Set(detectHarnesses(process.env, which).keys());
|
|
49
49
|
if (which("pi")) installed.add("pi");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scp-dev/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The swarm command line tool.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://scp.dev",
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
"typecheck": "tsc -p ."
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@scp-dev/core": "0.
|
|
28
|
-
"@scp-dev/broker": "0.
|
|
29
|
-
"@scp-dev/hub": "0.
|
|
30
|
-
"@scp-dev/mcp": "0.
|
|
27
|
+
"@scp-dev/core": "0.3.0",
|
|
28
|
+
"@scp-dev/broker": "0.4.0",
|
|
29
|
+
"@scp-dev/hub": "0.6.1",
|
|
30
|
+
"@scp-dev/mcp": "0.2.0",
|
|
31
31
|
"smol-toml": "^1.9.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@openai/codex": "0.159.0",
|
|
35
|
-
"@scp-dev/mesh": "0.0.
|
|
35
|
+
"@scp-dev/mesh": "0.0.7",
|
|
36
36
|
"opencode-ai": "1.18.34",
|
|
37
37
|
"tsup": "^8.5.1"
|
|
38
38
|
},
|
package/dist/mesh-H4KL5XAR.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RelayUsage
|
|
3
|
-
} from "./chunk-2LIJXXTL.js";
|
|
4
|
-
import "./chunk-MNTIEWKF.js";
|
|
5
|
-
|
|
6
|
-
// src/mesh.ts
|
|
7
|
-
import { existsSync } from "fs";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import { relayDir } from "@scp-dev/broker";
|
|
10
|
-
var MESH_MODULE = "@scp-dev/mesh";
|
|
11
|
-
async function load() {
|
|
12
|
-
try {
|
|
13
|
-
return await import(MESH_MODULE);
|
|
14
|
-
} catch {
|
|
15
|
-
throw new RelayUsage("swarm mesh is experimental and runs only from a source checkout of the swarm CLI");
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
async function meshCommand(argv) {
|
|
19
|
-
return (await load()).meshCommand(argv);
|
|
20
|
-
}
|
|
21
|
-
async function meshBrokerOptions() {
|
|
22
|
-
if (!existsSync(join(relayDir(), "mesh", "mesh.json"))) return {};
|
|
23
|
-
return (await load()).meshBrokerOptions();
|
|
24
|
-
}
|
|
25
|
-
export {
|
|
26
|
-
meshBrokerOptions,
|
|
27
|
-
meshCommand
|
|
28
|
-
};
|