@claudexor/cli 3.6.0 → 3.8.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/accounts-projection.d.ts +4 -2
- package/dist/accounts-projection.d.ts.map +1 -1
- package/dist/accounts-projection.js +49 -2
- package/dist/accounts-projection.js.map +1 -1
- package/dist/accounts-services.d.ts +7 -1
- package/dist/accounts-services.d.ts.map +1 -1
- package/dist/accounts-services.js +7 -2
- package/dist/accounts-services.js.map +1 -1
- package/dist/agy-quota-source.d.ts +1 -0
- package/dist/agy-quota-source.d.ts.map +1 -1
- package/dist/agy-quota-source.js +61 -108
- package/dist/agy-quota-source.js.map +1 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +6 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/claudexord-entry.d.ts +7 -2
- package/dist/claudexord-entry.d.ts.map +1 -1
- package/dist/claudexord-entry.js +33 -11
- package/dist/claudexord-entry.js.map +1 -1
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/command-flags.d.ts.map +1 -1
- package/dist/command-flags.js +1 -0
- package/dist/command-flags.js.map +1 -1
- package/dist/control-services.d.ts +28 -14
- package/dist/control-services.d.ts.map +1 -1
- package/dist/control-services.js +16 -5
- package/dist/control-services.js.map +1 -1
- package/dist/credential-commands.d.ts +16 -0
- package/dist/credential-commands.d.ts.map +1 -1
- package/dist/credential-commands.js +47 -13
- package/dist/credential-commands.js.map +1 -1
- package/dist/credential-profile-mutations.d.ts +7 -0
- package/dist/credential-profile-mutations.d.ts.map +1 -1
- package/dist/credential-profile-mutations.js +63 -31
- package/dist/credential-profile-mutations.js.map +1 -1
- package/dist/delegation-belt-descriptor.d.ts +2 -1
- package/dist/delegation-belt-descriptor.d.ts.map +1 -1
- package/dist/delegation-belt-descriptor.js +2 -1
- package/dist/delegation-belt-descriptor.js.map +1 -1
- package/dist/harness-command-specs.d.ts.map +1 -1
- package/dist/harness-command-specs.js +4 -4
- package/dist/harness-command-specs.js.map +1 -1
- package/dist/harness-command.d.ts +5 -3
- package/dist/harness-command.d.ts.map +1 -1
- package/dist/harness-command.js +5 -3
- package/dist/harness-command.js.map +1 -1
- package/dist/harness-install-lease.d.ts +11 -0
- package/dist/harness-install-lease.d.ts.map +1 -0
- package/dist/harness-install-lease.js +98 -0
- package/dist/harness-install-lease.js.map +1 -0
- package/dist/harness-install-proof.d.ts +36 -0
- package/dist/harness-install-proof.d.ts.map +1 -0
- package/dist/harness-install-proof.js +148 -0
- package/dist/harness-install-proof.js.map +1 -0
- package/dist/harness-install-recipes.d.ts +80 -0
- package/dist/harness-install-recipes.d.ts.map +1 -0
- package/dist/harness-install-recipes.js +130 -0
- package/dist/harness-install-recipes.js.map +1 -0
- package/dist/harness-installer.d.ts +45 -46
- package/dist/harness-installer.d.ts.map +1 -1
- package/dist/harness-installer.js +248 -156
- package/dist/harness-installer.js.map +1 -1
- package/dist/native-login.d.ts +7 -0
- package/dist/native-login.d.ts.map +1 -1
- package/dist/native-login.js +29 -13
- package/dist/native-login.js.map +1 -1
- package/dist/profile-registration.d.ts +2 -0
- package/dist/profile-registration.d.ts.map +1 -1
- package/dist/profile-registration.js +48 -5
- package/dist/profile-registration.js.map +1 -1
- package/dist/quota-services.d.ts +2 -2
- package/dist/remote-command.d.ts +0 -2
- package/dist/remote-command.d.ts.map +1 -1
- package/dist/remote-command.js +3 -74
- package/dist/remote-command.js.map +1 -1
- package/dist/setup-attach-command.d.ts +30 -0
- package/dist/setup-attach-command.d.ts.map +1 -0
- package/dist/setup-attach-command.js +118 -0
- package/dist/setup-attach-command.js.map +1 -0
- package/dist/setup-job-store.d.ts +2 -2
- package/dist/setup-job-support.d.ts +23 -13
- package/dist/setup-job-support.d.ts.map +1 -1
- package/dist/setup-job-support.js +55 -13
- package/dist/setup-job-support.js.map +1 -1
- package/dist/setup-jobs.d.ts +4 -4
- package/dist/setup-jobs.d.ts.map +1 -1
- package/dist/setup-jobs.js +50 -47
- package/dist/setup-jobs.js.map +1 -1
- package/dist/setup-login-capability.d.ts +37 -0
- package/dist/setup-login-capability.d.ts.map +1 -0
- package/dist/setup-login-capability.js +96 -0
- package/dist/setup-login-capability.js.map +1 -0
- package/dist/setup-login-io.d.ts +4 -1
- package/dist/setup-login-io.d.ts.map +1 -1
- package/dist/setup-login-io.js +22 -3
- package/dist/setup-login-io.js.map +1 -1
- package/dist/setup-login-pty.d.ts +64 -22
- package/dist/setup-login-pty.d.ts.map +1 -1
- package/dist/setup-login-pty.js +289 -48
- package/dist/setup-login-pty.js.map +1 -1
- package/dist/setup-login-runner-support.d.ts +12 -0
- package/dist/setup-login-runner-support.d.ts.map +1 -0
- package/dist/setup-login-runner-support.js +65 -0
- package/dist/setup-login-runner-support.js.map +1 -0
- package/dist/setup-login-runner.d.ts +2 -0
- package/dist/setup-login-runner.d.ts.map +1 -1
- package/dist/setup-login-runner.js +119 -116
- package/dist/setup-login-runner.js.map +1 -1
- package/dist/setup-runner-outcome.d.ts +10 -0
- package/dist/setup-runner-outcome.d.ts.map +1 -0
- package/dist/setup-runner-outcome.js +49 -0
- package/dist/setup-runner-outcome.js.map +1 -0
- package/package.json +24 -24
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export const INSTALLABLE_HARNESSES = ["agy", "claude", "codex", "cursor", "opencode"];
|
|
4
4
|
/** The `harness` argument shape: rendered by `claudexor help` and reprinted by
|
|
5
5
|
* the dispatcher when a verb is unknown. */
|
|
6
|
-
export const HARNESS_USAGE_ARGS = `list [--all] | install <${INSTALLABLE_HARNESSES.join("|")}> [--dry-run] [--yes]`;
|
|
6
|
+
export const HARNESS_USAGE_ARGS = `list [--all] | install <${INSTALLABLE_HARNESSES.join("|")}> [--target <local|remote>] [--dry-run] [--yes]`;
|
|
7
7
|
export const HARNESS_COMMAND_SPECS = [
|
|
8
8
|
{
|
|
9
9
|
id: "harness",
|
|
@@ -12,9 +12,9 @@ export const HARNESS_COMMAND_SPECS = [
|
|
|
12
12
|
{ prefix: ["install"], min: 2, max: 2 },
|
|
13
13
|
],
|
|
14
14
|
usageArgs: HARNESS_USAGE_ARGS,
|
|
15
|
-
summary: "List harnesses, or install one vendor CLI
|
|
16
|
-
flags: ["all", "dry-run", "yes", "json"],
|
|
17
|
-
subcommandFlags: { list: ["all"], install: ["dry-run", "yes"] },
|
|
15
|
+
summary: "List harnesses, or install one vendor CLI through the disclosed producer",
|
|
16
|
+
flags: ["all", "target", "dry-run", "yes", "json"],
|
|
17
|
+
subcommandFlags: { list: ["all"], install: ["target", "dry-run", "yes"] },
|
|
18
18
|
mutability: "ops",
|
|
19
19
|
stability: "stable",
|
|
20
20
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-command-specs.js","sourceRoot":"","sources":["../src/harness-command-specs.ts"],"names":[],"mappings":"AAUA;kFACkF;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAE/F;4CAC4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,2BAA2B,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"harness-command-specs.js","sourceRoot":"","sources":["../src/harness-command-specs.ts"],"names":[],"mappings":"AAUA;kFACkF;AAClF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,CAAC;AAE/F;4CAC4C;AAC5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,2BAA2B,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,iDAAiD,CAAC;AAE9I,MAAM,CAAC,MAAM,qBAAqB,GAA8B;IAC9D;QACE,EAAE,EAAE,SAAS;QACb,kBAAkB,EAAE;YAClB,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;YACpC,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;SACxC;QACD,SAAS,EAAE,kBAAkB;QAC7B,OAAO,EAAE,0EAA0E;QACnF,KAAK,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC;QAClD,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE;QACzE,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,QAAQ;KACpB;CACF,CAAC"}
|
|
@@ -2,9 +2,11 @@ import { type ParsedArgs } from "./args.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* `claudexor harness list [--all]` and `claudexor harness install <id>`.
|
|
4
4
|
* Fakes are test fixtures, not real harnesses; `--all` reveals them. The
|
|
5
|
-
* install verb is the disclosed installer (harness-installer.ts,
|
|
6
|
-
* exact npm pins for claude/codex/opencode,
|
|
7
|
-
*
|
|
5
|
+
* install verb is the target-aware disclosed installer (harness-installer.ts,
|
|
6
|
+
* issue #89): exact npm pins for claude/codex/opencode, and for the script
|
|
7
|
+
* vendors (cursor, agy) either the human-verified remote PTY path or, under an
|
|
8
|
+
* explicit `--target local --yes`, receipt-bound unattended execution. Nothing
|
|
9
|
+
* executes without disclosure and explicit authorization.
|
|
8
10
|
* Flags are verb-owned (registry `subcommandFlags`): `harness list --yes` or
|
|
9
11
|
* `harness install --all` is a loud exit-2 usage error, never a silently
|
|
10
12
|
* ignored flag (INV-021).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-command.d.ts","sourceRoot":"","sources":["../src/harness-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAOtD
|
|
1
|
+
{"version":3,"file":"harness-command.d.ts","sourceRoot":"","sources":["../src/harness-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAOtD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAetE"}
|
package/dist/harness-command.js
CHANGED
|
@@ -7,9 +7,11 @@ import { buildRegistry } from "./registry.js";
|
|
|
7
7
|
/**
|
|
8
8
|
* `claudexor harness list [--all]` and `claudexor harness install <id>`.
|
|
9
9
|
* Fakes are test fixtures, not real harnesses; `--all` reveals them. The
|
|
10
|
-
* install verb is the disclosed installer (harness-installer.ts,
|
|
11
|
-
* exact npm pins for claude/codex/opencode,
|
|
12
|
-
*
|
|
10
|
+
* install verb is the target-aware disclosed installer (harness-installer.ts,
|
|
11
|
+
* issue #89): exact npm pins for claude/codex/opencode, and for the script
|
|
12
|
+
* vendors (cursor, agy) either the human-verified remote PTY path or, under an
|
|
13
|
+
* explicit `--target local --yes`, receipt-bound unattended execution. Nothing
|
|
14
|
+
* executes without disclosure and explicit authorization.
|
|
13
15
|
* Flags are verb-owned (registry `subcommandFlags`): `harness list --yes` or
|
|
14
16
|
* `harness install --all` is a loud exit-2 usage error, never a silently
|
|
15
17
|
* ignored flag (INV-021).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-command.js","sourceRoot":"","sources":["../src/harness-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C
|
|
1
|
+
{"version":3,"file":"harness-command.js","sourceRoot":"","sources":["../src/harness-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAgB,EAAE,IAAa;IAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,UAAU,GAAG,wBAAwB,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACrF,IAAI,UAAU;QAAE,OAAO,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,CAAC,GAAG,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,IAAI,IAAI;YAAE,SAAS,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;;YACnC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,EAAE,4BAA4B,kBAAkB,EAAE,CAAC,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface HarnessInstallLease {
|
|
2
|
+
release(): void;
|
|
3
|
+
}
|
|
4
|
+
export declare const HARNESS_INSTALL_LOCK_TIMEOUT_MS = 120000;
|
|
5
|
+
/** One user-scoped, cross-process lease covers every shared install prefix.
|
|
6
|
+
* Waiters never unlink or rename a stale observation: doing so cannot be made
|
|
7
|
+
* compare-and-swap safe with Node's portable filesystem API and could delete a
|
|
8
|
+
* replacement owner's live lease. A dead or old owner-less lock fails closed
|
|
9
|
+
* with an exact manual remedy; ordinary live owners retain the bounded wait. */
|
|
10
|
+
export declare function acquireHarnessInstallLease(home: string, timeoutMs: number): HarnessInstallLease;
|
|
11
|
+
//# sourceMappingURL=harness-install-lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-lease.d.ts","sourceRoot":"","sources":["../src/harness-install-lease.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,OAAO,IAAI,IAAI,CAAC;CACjB;AAOD,eAAO,MAAM,+BAA+B,SAAU,CAAC;AA0CvD;;;;gFAIgF;AAChF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,CA+C/F"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export const HARNESS_INSTALL_LOCK_TIMEOUT_MS = 120_000;
|
|
5
|
+
const INSTALL_LOCK_POLL_MS = 100;
|
|
6
|
+
const INSTALL_LOCK_OWNER_GRACE_MS = 5_000;
|
|
7
|
+
const sleepCell = new Int32Array(new SharedArrayBuffer(4));
|
|
8
|
+
function readInstallLeaseOwner(path) {
|
|
9
|
+
try {
|
|
10
|
+
const value = JSON.parse(readFileSync(path, "utf8"));
|
|
11
|
+
if (!Number.isSafeInteger(value.pid) ||
|
|
12
|
+
Number(value.pid) <= 0 ||
|
|
13
|
+
typeof value.token !== "string" ||
|
|
14
|
+
value.token.length === 0) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return { pid: Number(value.pid), token: value.token };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function processIsAlive(pid) {
|
|
24
|
+
try {
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return error.code === "EPERM";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function installLockError(path, stale) {
|
|
33
|
+
const code = stale ? "install_lock_stale" : "install_lock_busy";
|
|
34
|
+
const message = stale
|
|
35
|
+
? `a stale claudexor harness install lock remains at ${path}; verify no installer is running, remove that exact directory, and retry`
|
|
36
|
+
: `another claudexor harness install still owns ${path}; if this persists after that installer exits, verify no installer is running, remove that exact directory, and retry`;
|
|
37
|
+
return Object.assign(new Error(message), { code });
|
|
38
|
+
}
|
|
39
|
+
/** One user-scoped, cross-process lease covers every shared install prefix.
|
|
40
|
+
* Waiters never unlink or rename a stale observation: doing so cannot be made
|
|
41
|
+
* compare-and-swap safe with Node's portable filesystem API and could delete a
|
|
42
|
+
* replacement owner's live lease. A dead or old owner-less lock fails closed
|
|
43
|
+
* with an exact manual remedy; ordinary live owners retain the bounded wait. */
|
|
44
|
+
export function acquireHarnessInstallLease(home, timeoutMs) {
|
|
45
|
+
const lockRoot = join(home, ".claudexor");
|
|
46
|
+
const path = join(lockRoot, "harness-install.lock");
|
|
47
|
+
const ownerPath = join(path, "owner.json");
|
|
48
|
+
const token = randomUUID();
|
|
49
|
+
const owner = { pid: process.pid, token };
|
|
50
|
+
const deadline = Date.now() + Math.max(0, timeoutMs);
|
|
51
|
+
mkdirSync(lockRoot, { recursive: true, mode: 0o700 });
|
|
52
|
+
for (;;) {
|
|
53
|
+
try {
|
|
54
|
+
mkdirSync(path, { mode: 0o700 });
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(ownerPath, `${JSON.stringify(owner)}\n`, { mode: 0o600, flag: "wx" });
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
rmSync(path, { recursive: true, force: true });
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
let released = false;
|
|
63
|
+
return {
|
|
64
|
+
release: () => {
|
|
65
|
+
if (released)
|
|
66
|
+
return;
|
|
67
|
+
released = true;
|
|
68
|
+
const current = readInstallLeaseOwner(ownerPath);
|
|
69
|
+
if (current?.pid === process.pid && current.token === token) {
|
|
70
|
+
rmSync(path, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error.code !== "EEXIST")
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
const existing = readInstallLeaseOwner(ownerPath);
|
|
80
|
+
let stale = existing !== null && !processIsAlive(existing.pid);
|
|
81
|
+
if (existing === null) {
|
|
82
|
+
try {
|
|
83
|
+
stale = Date.now() - statSync(path).mtimeMs >= INSTALL_LOCK_OWNER_GRACE_MS;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error.code === "ENOENT")
|
|
87
|
+
continue;
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (stale)
|
|
92
|
+
throw installLockError(path, true);
|
|
93
|
+
if (Date.now() >= deadline)
|
|
94
|
+
throw installLockError(path, false);
|
|
95
|
+
Atomics.wait(sleepCell, 0, 0, Math.min(INSTALL_LOCK_POLL_MS, deadline - Date.now()));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=harness-install-lease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-lease.js","sourceRoot":"","sources":["../src/harness-install-lease.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
export interface InstalledHarnessProof {
|
|
3
|
+
installedBinary: string;
|
|
4
|
+
installedVersion: string;
|
|
5
|
+
}
|
|
6
|
+
export type HarnessProofResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
proof: InstalledHarnessProof;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
reason: string;
|
|
12
|
+
};
|
|
13
|
+
export interface InstallProofRuntime {
|
|
14
|
+
runnerNodePath: string;
|
|
15
|
+
platform: NodeJS.Platform;
|
|
16
|
+
resolutionSource: NodeJS.ProcessEnv;
|
|
17
|
+
environment: NodeJS.ProcessEnv;
|
|
18
|
+
spawn: typeof spawnSync;
|
|
19
|
+
}
|
|
20
|
+
export interface NpmInstallProofSpec {
|
|
21
|
+
vendorRoot: string;
|
|
22
|
+
npmPackage: string;
|
|
23
|
+
binaryNames: readonly string[];
|
|
24
|
+
expectedVersion: string;
|
|
25
|
+
}
|
|
26
|
+
/** Prove an exact npm package and its target-owned launcher, then execute the
|
|
27
|
+
* absolute launcher for a matching version receipt. */
|
|
28
|
+
export declare function proveInstalledNpm(spec: NpmInstallProofSpec, runtime: InstallProofRuntime): HarnessProofResult;
|
|
29
|
+
/** Prove a script vendor's launcher (cursor-agent, agy). These installers pick
|
|
30
|
+
* their own destination and ship no pinnable version, so the proof is the
|
|
31
|
+
* resolvable launcher plus its own `--version` line — ONE body for every such
|
|
32
|
+
* vendor, so a third one is a caller, not a fork. The official launcher may be
|
|
33
|
+
* a symlink into a version directory outside bin, which is why resolution goes
|
|
34
|
+
* through the same helper the run path uses. */
|
|
35
|
+
export declare function proveInstalledScriptVendor(binaryName: string, runtime: InstallProofRuntime): HarnessProofResult;
|
|
36
|
+
//# sourceMappingURL=harness-install-proof.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-proof.d.ts","sourceRoot":"","sources":["../src/harness-install-proof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAU/C,MAAM,WAAW,qBAAqB;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,kBAAkB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC;IAC/B,KAAK,EAAE,OAAO,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;CACzB;AA2ED;uDACuD;AACvD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAyDpB;AAED;;;;;gDAKgD;AAChD,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,CAmBpB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import { inspectExecutable, isBoundedRegularExecutable, isLaunchableExecutable, resolveHarnessBinary, } from "@claudexor/core";
|
|
4
|
+
const VERSION_PROBE_MAX_BYTES = 1024 * 1024;
|
|
5
|
+
const VERSION_PROBE_TIMEOUT_MS = 10_000;
|
|
6
|
+
const SCRIPT_VENDOR_VERSION_MAX_CHARS = 256;
|
|
7
|
+
const SEMVER_TOKEN = /(?:^|[^0-9A-Za-z.+-])(\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?)(?=$|[^0-9A-Za-z.+-])/g;
|
|
8
|
+
function isStrictlyContained(root, candidate) {
|
|
9
|
+
const remainder = relative(root, candidate);
|
|
10
|
+
return (remainder !== "" &&
|
|
11
|
+
remainder !== ".." &&
|
|
12
|
+
!remainder.startsWith(`..${sep}`) &&
|
|
13
|
+
!isAbsolute(remainder));
|
|
14
|
+
}
|
|
15
|
+
function outputText(value) {
|
|
16
|
+
if (typeof value === "string")
|
|
17
|
+
return value;
|
|
18
|
+
return Buffer.isBuffer(value) ? value.toString("utf8") : "";
|
|
19
|
+
}
|
|
20
|
+
function exactSemverTokens(value) {
|
|
21
|
+
return [...value.matchAll(SEMVER_TOKEN)].map((match) => match[1] ?? "");
|
|
22
|
+
}
|
|
23
|
+
function proveVersion(installedBinary, runtime, expectedVersion) {
|
|
24
|
+
const absoluteBinary = resolve(installedBinary);
|
|
25
|
+
const versionResult = runtime.spawn(absoluteBinary, ["--version"], {
|
|
26
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
27
|
+
env: runtime.environment,
|
|
28
|
+
encoding: "utf8",
|
|
29
|
+
timeout: VERSION_PROBE_TIMEOUT_MS,
|
|
30
|
+
maxBuffer: VERSION_PROBE_MAX_BYTES,
|
|
31
|
+
});
|
|
32
|
+
if (versionResult.status !== 0) {
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
reason: `the absolute --version probe exited ${versionResult.status ?? "without a status"}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const versionOutput = outputText(versionResult.stdout).trim();
|
|
39
|
+
if (versionOutput.length === 0) {
|
|
40
|
+
return { ok: false, reason: "the absolute --version probe returned empty stdout" };
|
|
41
|
+
}
|
|
42
|
+
if (expectedVersion !== null && !exactSemverTokens(versionOutput).includes(expectedVersion)) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
reason: `the absolute --version probe did not report exact semver token ${expectedVersion}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (expectedVersion !== null) {
|
|
49
|
+
return {
|
|
50
|
+
ok: true,
|
|
51
|
+
proof: { installedBinary: absoluteBinary, installedVersion: expectedVersion },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const reportedVersion = versionOutput.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
55
|
+
if (reportedVersion.length === 0 || reportedVersion.length > SCRIPT_VENDOR_VERSION_MAX_CHARS) {
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
reason: `the --version line must contain 1-${SCRIPT_VENDOR_VERSION_MAX_CHARS} characters`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
proof: { installedBinary: absoluteBinary, installedVersion: reportedVersion },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** Prove an exact npm package and its target-owned launcher, then execute the
|
|
67
|
+
* absolute launcher for a matching version receipt. */
|
|
68
|
+
export function proveInstalledNpm(spec, runtime) {
|
|
69
|
+
const packageRoot = join(spec.vendorRoot, "lib", "node_modules", ...spec.npmPackage.split("/"));
|
|
70
|
+
let canonicalRoot;
|
|
71
|
+
let canonicalPackageRoot;
|
|
72
|
+
let canonicalPackageJson;
|
|
73
|
+
try {
|
|
74
|
+
canonicalRoot = realpathSync(spec.vendorRoot);
|
|
75
|
+
canonicalPackageRoot = realpathSync(packageRoot);
|
|
76
|
+
canonicalPackageJson = realpathSync(join(packageRoot, "package.json"));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { ok: false, reason: "the exact npm package root is missing or unreadable" };
|
|
80
|
+
}
|
|
81
|
+
if (!isStrictlyContained(canonicalRoot, canonicalPackageRoot)) {
|
|
82
|
+
return { ok: false, reason: "the exact npm package root escapes the install prefix" };
|
|
83
|
+
}
|
|
84
|
+
if (!isStrictlyContained(canonicalPackageRoot, canonicalPackageJson)) {
|
|
85
|
+
return { ok: false, reason: "the npm package manifest escapes the exact package root" };
|
|
86
|
+
}
|
|
87
|
+
let packageVersion = null;
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(readFileSync(canonicalPackageJson, "utf8"));
|
|
90
|
+
packageVersion = typeof parsed.version === "string" ? parsed.version : null;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { ok: false, reason: "the exact npm package manifest is unreadable" };
|
|
94
|
+
}
|
|
95
|
+
if (packageVersion !== spec.expectedVersion) {
|
|
96
|
+
return {
|
|
97
|
+
ok: false,
|
|
98
|
+
reason: `the npm package version is ${packageVersion ?? "missing"}, expected ${spec.expectedVersion}`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
let installedBinary = null;
|
|
102
|
+
for (const binaryName of spec.binaryNames) {
|
|
103
|
+
const base = resolve(spec.vendorRoot, "bin", binaryName);
|
|
104
|
+
const candidates = runtime.platform === "win32" ? [base, `${base}.exe`, `${base}.cmd`, `${base}.bat`] : [base];
|
|
105
|
+
installedBinary = candidates.find((candidate) => isLaunchableExecutable(candidate)) ?? null;
|
|
106
|
+
if (installedBinary !== null)
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (installedBinary === null) {
|
|
110
|
+
return { ok: false, reason: "the expected npm launcher is missing or not launchable" };
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const inspection = inspectExecutable(installedBinary);
|
|
114
|
+
if (!isBoundedRegularExecutable(inspection) || inspection.size === 0) {
|
|
115
|
+
return { ok: false, reason: "the npm launcher target is empty or not a bounded file" };
|
|
116
|
+
}
|
|
117
|
+
if (!isStrictlyContained(canonicalRoot, inspection.realpath)) {
|
|
118
|
+
return { ok: false, reason: "the npm launcher canonical target escapes the install prefix" };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return { ok: false, reason: "the npm launcher could not be inspected safely" };
|
|
123
|
+
}
|
|
124
|
+
return proveVersion(installedBinary, runtime, spec.expectedVersion);
|
|
125
|
+
}
|
|
126
|
+
/** Prove a script vendor's launcher (cursor-agent, agy). These installers pick
|
|
127
|
+
* their own destination and ship no pinnable version, so the proof is the
|
|
128
|
+
* resolvable launcher plus its own `--version` line — ONE body for every such
|
|
129
|
+
* vendor, so a third one is a caller, not a fork. The official launcher may be
|
|
130
|
+
* a symlink into a version directory outside bin, which is why resolution goes
|
|
131
|
+
* through the same helper the run path uses. */
|
|
132
|
+
export function proveInstalledScriptVendor(binaryName, runtime) {
|
|
133
|
+
const installedBinary = resolveHarnessBinary(binaryName, runtime.resolutionSource, runtime.runnerNodePath, runtime.platform);
|
|
134
|
+
if (installedBinary === null) {
|
|
135
|
+
return { ok: false, reason: `the exact ${binaryName} launcher is missing or not launchable` };
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const inspection = inspectExecutable(installedBinary);
|
|
139
|
+
if (!isBoundedRegularExecutable(inspection) || inspection.size === 0) {
|
|
140
|
+
return { ok: false, reason: `the ${binaryName} target is empty or not a bounded file` };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return { ok: false, reason: `the ${binaryName} launcher could not be inspected safely` };
|
|
145
|
+
}
|
|
146
|
+
return proveVersion(installedBinary, runtime, null);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=harness-install-proof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-proof.js","sourceRoot":"","sources":["../src/harness-install-proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { PinnedVendorCliVersion } from "@claudexor/util";
|
|
2
|
+
import { INSTALLABLE_HARNESSES } from "./harness-command-specs.js";
|
|
3
|
+
export type InstallableHarness = (typeof INSTALLABLE_HARNESSES)[number];
|
|
4
|
+
export declare function isInstallableHarness(value: string): value is InstallableHarness;
|
|
5
|
+
/** Install destinations. `remote` is the historical issue-#89 SSH-host prefix;
|
|
6
|
+
* `local` is the managed toolchain root this host's own binary resolution and
|
|
7
|
+
* confinement already read, so an install there is immediately runnable. */
|
|
8
|
+
export declare const HARNESS_INSTALL_TARGETS: readonly ["local", "remote"];
|
|
9
|
+
export type HarnessInstallTarget = (typeof HARNESS_INSTALL_TARGETS)[number];
|
|
10
|
+
export declare function isHarnessInstallTarget(value: string): value is HarnessInstallTarget;
|
|
11
|
+
/** ONE table owns each target's npm prefix and how it is disclosed. */
|
|
12
|
+
export declare const TARGET_LAYOUTS: Record<HarnessInstallTarget, {
|
|
13
|
+
displayRoot: string;
|
|
14
|
+
root(home: string): string;
|
|
15
|
+
}>;
|
|
16
|
+
/** Exact npm pins. Each version ALIASES the harness package's vendor-version
|
|
17
|
+
* SSOT (vendor-cli-version.ts there). For claude/codex that is the version
|
|
18
|
+
* this release's freshness gates verified; the opencode pin is a
|
|
19
|
+
* deterministic install target only — no recorded verification fixture
|
|
20
|
+
* vouches for it (its vendor-cli-version.ts discloses this). Cursor and agy
|
|
21
|
+
* are absent deliberately: they ship no npm artifact (see SCRIPT_INSTALLERS
|
|
22
|
+
* below). */
|
|
23
|
+
export type HarnessInstallVerification = "release_verified" | "deterministic_only" | "human_observed"
|
|
24
|
+
/** A script vendor installed unattended under an explicit local `--yes`:
|
|
25
|
+
* pinned to nothing and watched by nobody, so the receipt carries the exact
|
|
26
|
+
* installer bytes instead of a human's attention. */
|
|
27
|
+
| "unattended_unpinned";
|
|
28
|
+
export declare const NPM_PINS: Partial<Record<InstallableHarness, {
|
|
29
|
+
npmPackage: string;
|
|
30
|
+
/** Launcher names the post-install proof executes, in preference order. */
|
|
31
|
+
binaryNames: readonly string[];
|
|
32
|
+
version: PinnedVendorCliVersion;
|
|
33
|
+
verification: Exclude<HarnessInstallVerification, "human_observed" | "unattended_unpinned">;
|
|
34
|
+
}>>;
|
|
35
|
+
export declare const CURSOR_INSTALL_URL = "https://cursor.com/install";
|
|
36
|
+
/**
|
|
37
|
+
* Google's official Antigravity CLI installer, as published on
|
|
38
|
+
* antigravity.google/docs/cli/install (`curl -fsSL <this url> | bash`, which
|
|
39
|
+
* Claudexor deliberately does NOT do — see the header). Verified end to end on
|
|
40
|
+
* 2026-08-16: the script fetched from this URL installed agy 1.1.13 to
|
|
41
|
+
* `~/.local/bin/agy`, which is the destination disclosed below. The vendor
|
|
42
|
+
* ships one signed Go binary and no npm package, so it takes the same
|
|
43
|
+
* human-observed path as cursor.
|
|
44
|
+
*/
|
|
45
|
+
export declare const AGY_INSTALL_URL = "https://antigravity.google/cli/install.sh";
|
|
46
|
+
/** The vendor's Windows installer, from the same documentation page. */
|
|
47
|
+
export declare const AGY_INSTALL_URL_WINDOWS = "https://antigravity.google/cli/install.ps1";
|
|
48
|
+
/** Vendors distributed as a shell installer instead of a pinnable npm
|
|
49
|
+
* artifact. ONE branch serves both entries; the per-harness text below is the
|
|
50
|
+
* only thing that differs, so a third such vendor is a row, not a fork. */
|
|
51
|
+
declare const SCRIPT_INSTALLERS: Record<"agy" | "cursor", {
|
|
52
|
+
url: string;
|
|
53
|
+
windowsUrl?: string;
|
|
54
|
+
installLocation: string;
|
|
55
|
+
pinNote: string;
|
|
56
|
+
/** Launcher the post-install proof resolves and version-probes. */
|
|
57
|
+
binaryName: string;
|
|
58
|
+
}>;
|
|
59
|
+
type ScriptInstaller = (typeof SCRIPT_INSTALLERS)[keyof typeof SCRIPT_INSTALLERS];
|
|
60
|
+
/** Membership is asked of the TABLE, never re-typed: a third script vendor is
|
|
61
|
+
* one row, and cannot be added to the table yet fall through here. */
|
|
62
|
+
export declare function scriptInstaller(harness: InstallableHarness): ScriptInstaller | null;
|
|
63
|
+
export interface HarnessInstallerDisclosure {
|
|
64
|
+
harness: InstallableHarness;
|
|
65
|
+
/** Which prefix this disclosure describes; echoed into every receipt. */
|
|
66
|
+
target: HarnessInstallTarget;
|
|
67
|
+
command: string;
|
|
68
|
+
installLocation: string;
|
|
69
|
+
/** Exact vendor version the command installs; null exactly for the script
|
|
70
|
+
* vendors (cursor, agy), which have no pinnable artifact — disclosed, never
|
|
71
|
+
* faked. */
|
|
72
|
+
pinnedVersion: string | null;
|
|
73
|
+
/** Evidence behind the install target. Package-registry integrity verifies
|
|
74
|
+
* downloaded bytes for every npm pin, but only release_verified means the
|
|
75
|
+
* exact vendor version was exercised by this release's freshness gates. */
|
|
76
|
+
verification: HarnessInstallVerification;
|
|
77
|
+
}
|
|
78
|
+
export declare function harnessInstallerDisclosure(harness: InstallableHarness, target?: HarnessInstallTarget): HarnessInstallerDisclosure;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=harness-install-recipes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-recipes.d.ts","sourceRoot":"","sources":["../src/harness-install-recipes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,kBAAkB,CAE/E;AAED;;4EAE4E;AAC5E,eAAO,MAAM,uBAAuB,YAAI,OAAO,EAAE,QAAQ,CAAU,CAAC;AACpE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,oBAAoB,CAEnF;AAED,uEAAuE;AACvE,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,oBAAoB,EACpB;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,CAOpD,CAAC;AAEF;;;;;;aAMa;AACb,MAAM,MAAM,0BAA0B,GAClC,kBAAkB,GAClB,oBAAoB,GACpB,gBAAgB;AAClB;;qDAEqD;GACnD,qBAAqB,CAAC;AAE1B,eAAO,MAAM,QAAQ,EAAE,OAAO,CAC5B,MAAM,CACJ,kBAAkB,EAClB;IACE,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,OAAO,EAAE,sBAAsB,CAAC;IAChC,YAAY,EAAE,OAAO,CAAC,0BAA0B,EAAE,gBAAgB,GAAG,qBAAqB,CAAC,CAAC;CAC7F,CACF,CAoBF,CAAC;AAEF,eAAO,MAAM,kBAAkB,+BAA+B,CAAC;AAC/D;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,8CAA8C,CAAC;AAC3E,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,+CAA+C,CAAC;AAEpF;;2EAE2E;AAC3E,QAAA,MAAM,iBAAiB,EAAE,MAAM,CAC7B,KAAK,GAAG,QAAQ,EAChB;IACE,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;CACpB,CAoBF,CAAC;AAEF,KAAK,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC;AAElF;sEACsE;AACtE,wBAAgB,eAAe,CAAC,OAAO,EAAE,kBAAkB,GAAG,eAAe,GAAG,IAAI,CAInF;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,yEAAyE;IACzE,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB;;gBAEY;IACZ,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;+EAE2E;IAC3E,YAAY,EAAE,0BAA0B,CAAC;CAC1C;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,kBAAkB,EAC3B,MAAM,GAAE,oBAA+B,GACtC,0BAA0B,CAqC5B"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The vendor RECIPES `claudexor harness install` executes, and the disclosure
|
|
3
|
+
* it prints before executing anything. Split from harness-installer.ts so the
|
|
4
|
+
* WHAT (which artifact, from where, into which prefix, with what evidence)
|
|
5
|
+
* stays readable next to itself, while the installer file owns the HOW
|
|
6
|
+
* (lease, spawn, proof, CLI surface). A new vendor is a row in one of the two
|
|
7
|
+
* tables here, never a new branch there.
|
|
8
|
+
*/
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { CLAUDE_VENDOR_CLI_VERSION } from "@claudexor/harness-claude";
|
|
11
|
+
import { CODEX_VENDOR_CLI_VERSION } from "@claudexor/harness-codex";
|
|
12
|
+
import { OPENCODE_VENDOR_CLI_VERSION } from "@claudexor/harness-opencode";
|
|
13
|
+
import { managedNodeRoot } from "@claudexor/core";
|
|
14
|
+
import { INSTALLABLE_HARNESSES } from "./harness-command-specs.js";
|
|
15
|
+
export function isInstallableHarness(value) {
|
|
16
|
+
return INSTALLABLE_HARNESSES.includes(value);
|
|
17
|
+
}
|
|
18
|
+
/** Install destinations. `remote` is the historical issue-#89 SSH-host prefix;
|
|
19
|
+
* `local` is the managed toolchain root this host's own binary resolution and
|
|
20
|
+
* confinement already read, so an install there is immediately runnable. */
|
|
21
|
+
export const HARNESS_INSTALL_TARGETS = ["local", "remote"];
|
|
22
|
+
export function isHarnessInstallTarget(value) {
|
|
23
|
+
return HARNESS_INSTALL_TARGETS.includes(value);
|
|
24
|
+
}
|
|
25
|
+
/** ONE table owns each target's npm prefix and how it is disclosed. */
|
|
26
|
+
export const TARGET_LAYOUTS = {
|
|
27
|
+
local: { displayRoot: "~/.claudexor/node", root: managedNodeRoot },
|
|
28
|
+
remote: {
|
|
29
|
+
displayRoot: "~/.claudexor/remote/vendor",
|
|
30
|
+
root: (home) => join(home, ".claudexor", "remote", "vendor"),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export const NPM_PINS = {
|
|
34
|
+
claude: {
|
|
35
|
+
npmPackage: "@anthropic-ai/claude-code",
|
|
36
|
+
binaryNames: ["claude"],
|
|
37
|
+
version: CLAUDE_VENDOR_CLI_VERSION,
|
|
38
|
+
verification: "release_verified",
|
|
39
|
+
},
|
|
40
|
+
codex: {
|
|
41
|
+
npmPackage: "@openai/codex",
|
|
42
|
+
binaryNames: ["codex"],
|
|
43
|
+
version: CODEX_VENDOR_CLI_VERSION,
|
|
44
|
+
verification: "release_verified",
|
|
45
|
+
},
|
|
46
|
+
opencode: {
|
|
47
|
+
npmPackage: "opencode-ai",
|
|
48
|
+
binaryNames: ["opencode"],
|
|
49
|
+
version: OPENCODE_VENDOR_CLI_VERSION,
|
|
50
|
+
verification: "deterministic_only",
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
export const CURSOR_INSTALL_URL = "https://cursor.com/install";
|
|
54
|
+
/**
|
|
55
|
+
* Google's official Antigravity CLI installer, as published on
|
|
56
|
+
* antigravity.google/docs/cli/install (`curl -fsSL <this url> | bash`, which
|
|
57
|
+
* Claudexor deliberately does NOT do — see the header). Verified end to end on
|
|
58
|
+
* 2026-08-16: the script fetched from this URL installed agy 1.1.13 to
|
|
59
|
+
* `~/.local/bin/agy`, which is the destination disclosed below. The vendor
|
|
60
|
+
* ships one signed Go binary and no npm package, so it takes the same
|
|
61
|
+
* human-observed path as cursor.
|
|
62
|
+
*/
|
|
63
|
+
export const AGY_INSTALL_URL = "https://antigravity.google/cli/install.sh";
|
|
64
|
+
/** The vendor's Windows installer, from the same documentation page. */
|
|
65
|
+
export const AGY_INSTALL_URL_WINDOWS = "https://antigravity.google/cli/install.ps1";
|
|
66
|
+
/** Vendors distributed as a shell installer instead of a pinnable npm
|
|
67
|
+
* artifact. ONE branch serves both entries; the per-harness text below is the
|
|
68
|
+
* only thing that differs, so a third such vendor is a row, not a fork. */
|
|
69
|
+
const SCRIPT_INSTALLERS = {
|
|
70
|
+
agy: {
|
|
71
|
+
binaryName: "agy",
|
|
72
|
+
url: AGY_INSTALL_URL,
|
|
73
|
+
// The one vendor here that publishes a Windows installer of its own; the
|
|
74
|
+
// POSIX row would otherwise be all Claudexor could honestly offer.
|
|
75
|
+
windowsUrl: AGY_INSTALL_URL_WINDOWS,
|
|
76
|
+
installLocation: "~/.local/bin (as selected by Google's Antigravity installer)",
|
|
77
|
+
pinNote: "none — Antigravity ships no pinnable npm artifact; the vendor script is downloaded in full, its size and sha256 print, and it runs in this terminal where you watch it",
|
|
78
|
+
},
|
|
79
|
+
cursor: {
|
|
80
|
+
// The legacy alias every Cursor login/run surface already consumes.
|
|
81
|
+
binaryName: "cursor-agent",
|
|
82
|
+
url: CURSOR_INSTALL_URL,
|
|
83
|
+
installLocation: "~/.local/bin (or ~/.cursor/bin, as selected by Cursor's installer)",
|
|
84
|
+
pinNote: "none — Cursor ships no pinnable npm artifact; the vendor script is downloaded in full, its size and sha256 print, and it runs in this terminal where you watch it",
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
/** Membership is asked of the TABLE, never re-typed: a third script vendor is
|
|
88
|
+
* one row, and cannot be added to the table yet fall through here. */
|
|
89
|
+
export function scriptInstaller(harness) {
|
|
90
|
+
return Object.hasOwn(SCRIPT_INSTALLERS, harness)
|
|
91
|
+
? SCRIPT_INSTALLERS[harness]
|
|
92
|
+
: null;
|
|
93
|
+
}
|
|
94
|
+
export function harnessInstallerDisclosure(harness, target = "remote") {
|
|
95
|
+
const layout = TARGET_LAYOUTS[target];
|
|
96
|
+
const pin = NPM_PINS[harness];
|
|
97
|
+
if (pin) {
|
|
98
|
+
return {
|
|
99
|
+
harness,
|
|
100
|
+
target,
|
|
101
|
+
command: `npm install --global --prefix ${layout.displayRoot} ${pin.npmPackage}@${pin.version}`,
|
|
102
|
+
installLocation: `${layout.displayRoot}/bin`,
|
|
103
|
+
pinnedVersion: pin.version,
|
|
104
|
+
verification: pin.verification,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const script = scriptInstaller(harness);
|
|
108
|
+
/* c8 ignore next -- every non-npm harness has a script row; this is the
|
|
109
|
+
unreachable guard that keeps the two tables honest. */
|
|
110
|
+
if (!script)
|
|
111
|
+
throw new Error(`harness ${harness} has neither an npm pin nor a script installer`);
|
|
112
|
+
const windows = process.platform === "win32";
|
|
113
|
+
const url = windows ? (script.windowsUrl ?? script.url) : script.url;
|
|
114
|
+
const file = windows && script.windowsUrl ? "install.ps1" : "install.sh";
|
|
115
|
+
const runner = windows && script.windowsUrl ? "powershell -ExecutionPolicy Bypass -File" : "/bin/sh";
|
|
116
|
+
return {
|
|
117
|
+
harness,
|
|
118
|
+
target,
|
|
119
|
+
command: `curl --fail --silent --show-error --location ${url} ` +
|
|
120
|
+
`--output <private-tmpdir>/${file} && ${runner} <private-tmpdir>/${file}`,
|
|
121
|
+
// The vendor script picks its own destination, so the local target cannot
|
|
122
|
+
// move it; only the WITNESS differs between the two targets.
|
|
123
|
+
installLocation: windows && script.windowsUrl
|
|
124
|
+
? "%LOCALAPPDATA%\\agy\\bin (as selected by Google's Antigravity installer)"
|
|
125
|
+
: script.installLocation,
|
|
126
|
+
pinnedVersion: null,
|
|
127
|
+
verification: target === "local" ? "unattended_unpinned" : "human_observed",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=harness-install-recipes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-install-recipes.js","sourceRoot":"","sources":["../src/harness-install-recipes.ts"],"names":[],"mappings":"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"}
|