@tangle-network/cli-agent-registry 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/dist/{backend-types-CREj4iOY.mjs → backend-types-CNo_Zj_K.mjs} +3 -12
- package/dist/{backend-types-CJH-wHS3.d.mts → backend-types-DRmLR1e0.d.mts} +4 -13
- package/dist/backend-types.d.mts +1 -1
- package/dist/backend-types.mjs +1 -1
- package/dist/cli-auth-bundle-C6DtK7GX.mjs +95 -0
- package/dist/cli-auth-bundle-CwAaH0Ap.d.mts +51 -0
- package/dist/cli-auth-bundle.d.mts +2 -49
- package/dist/cli-auth-bundle.mjs +1 -91
- package/dist/cli-auth-placeholder.d.mts +1 -1
- package/dist/cli-auth-placeholder.mjs +2 -2
- package/dist/cli-backend-auth-env.mjs +3 -3
- package/dist/default-backend.d.mts +1 -1
- package/dist/default-backend.mjs +2 -2
- package/dist/{harness-DIdVNSwl.mjs → harness-D1fTxnDD.mjs} +66 -34
- package/dist/{native-session-contracts-DWFzgoye.mjs → harness-contracts-BZoECCMc.mjs} +87 -173
- package/dist/host-contracts.d.mts +30 -0
- package/dist/host-contracts.json +422 -0
- package/dist/host-contracts.mjs +63 -0
- package/dist/index.d.mts +117 -120
- package/dist/index.mjs +17 -12
- package/dist/local-cli-auth.d.mts +1 -1
- package/dist/local-cli-auth.mjs +1 -1
- package/dist/native-session-contracts.d.mts +57 -62
- package/dist/native-session-contracts.mjs +40 -2
- package/dist/servable-models.d.mts +5 -6
- package/dist/servable-models.mjs +6 -22
- package/dist/{session-contract-BC75JdnA.d.mts → session-contract-BhzcbPRW.d.mts} +10 -44
- package/dist/session-contract.d.mts +1 -1
- package/dist/session-contract.mjs +14 -62
- package/dist/{specs-BSELpX1h.d.mts → spec-CcvTM7-j.d.mts} +22 -91
- package/dist/{specs-Bbiay_8K.mjs → specs-BBF55TnM.mjs} +125 -94
- package/dist/specs.d.mts +72 -3
- package/dist/specs.mjs +2 -2
- package/package.json +14 -8
package/README.md
CHANGED
|
@@ -23,6 +23,36 @@ overrides unless `env` is also supplied. Returned contents are sensitive raw fil
|
|
|
23
23
|
not proof of a valid OAuth subscription. Callers own consent and native login
|
|
24
24
|
validation before enrollment. This filesystem reader does not read macOS Keychain.
|
|
25
25
|
|
|
26
|
+
## Native HOME layouts (0.15)
|
|
27
|
+
|
|
28
|
+
`CliDirLayout.configAllow` accepts strings or `{ path, kind: "symlink" }` rules.
|
|
29
|
+
Consumers must narrow an entry before calling string methods and apply its kind
|
|
30
|
+
constraint. The maintained Orchestrator classifier does both; arbitrary external
|
|
31
|
+
string-only consumers require migration. `mergeCliDirLayout` keeps its four keys,
|
|
32
|
+
key order and fresh default-plus-addition arrays.
|
|
33
|
+
|
|
34
|
+
Codex's known cache and plugin trees and coordination files are preserved as
|
|
35
|
+
auxiliary source bytes. Only its four generated arg0 symlink aliases are named
|
|
36
|
+
configuration; regular files at those names and unknown siblings remain held.
|
|
37
|
+
Credential exclusions, native-store identity and conservation still apply.
|
|
38
|
+
|
|
39
|
+
## Host registry export
|
|
40
|
+
|
|
41
|
+
`host-contracts.json` is the generated data-only projection of the canonical
|
|
42
|
+
`harness-contracts/` session stores, store environment, CLI versions and model
|
|
43
|
+
environment names. Non-JavaScript Git consumers can pin this committed file by
|
|
44
|
+
commit and hash. Build emits its byte-identical package copy in `dist`; the public
|
|
45
|
+
`/host-contracts.json` export resolves there, and prepack rejects drift in either copy.
|
|
46
|
+
The real CLI/Python
|
|
47
|
+
boundary check is `node tests/host-contracts.integration.mjs`.
|
|
48
|
+
|
|
49
|
+
The `/host-contracts` entry also exports `HOST_CONTRACTS`. Host-only `cursor-cli`
|
|
50
|
+
and the Cursor CLI declaration describes its native on-disk stores; it does not
|
|
51
|
+
register sandbox backends, change Cursor SDK's unsupported status, or establish
|
|
52
|
+
sandbox recovery conformance. Per-store `env` selects its base-directory override;
|
|
53
|
+
`xdg` supplies a lower-priority XDG base. `session.storeEnv` declares each override's
|
|
54
|
+
default home-relative base; append the remaining suffix of `store.root`.
|
|
55
|
+
|
|
26
56
|
## Identity, availability and implementation
|
|
27
57
|
|
|
28
58
|
Interface describes recognized identities, including historical ones. This
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
//#region ../runtime-contracts/dist/backend-types.js
|
|
3
|
-
/**
|
|
4
|
-
* This distribution's backend vocabulary, declared positively. The shared
|
|
5
|
-
* Interface vocabulary also contains historical and differently hosted harnesses;
|
|
6
|
-
* knowing one upstream must not require installing it here or make this module
|
|
7
|
-
* throw at import time. Keep old wire identities readable when retiring execution.
|
|
8
|
-
*
|
|
9
|
-
* Gemini is not a direct Sandbox backend; it is available only through a backing
|
|
10
|
-
* transport. Adding it upstream never implicitly makes it dispatchable here.
|
|
11
|
-
* The spec/adapter composition must still prove every backend it actually enables.
|
|
12
|
-
*/
|
|
3
|
+
/** This distribution's backend vocabulary. Gemini is only a backing transport, not a direct backend. */
|
|
13
4
|
const BACKEND_TYPE = {
|
|
14
5
|
OPENCODE: "opencode",
|
|
15
6
|
CLAUDE_CODE: "claude-code",
|
|
@@ -20,11 +11,11 @@ const BACKEND_TYPE = {
|
|
|
20
11
|
PI: "pi",
|
|
21
12
|
PRIME: "prime",
|
|
22
13
|
HERMES: "hermes",
|
|
23
|
-
FORGE: "forge",
|
|
24
14
|
OPENCLAW: "openclaw",
|
|
25
15
|
NANOCLAW: "nanoclaw",
|
|
26
16
|
ACP: "acp",
|
|
27
17
|
CURSOR: "cursor",
|
|
18
|
+
GROK: "grok",
|
|
28
19
|
CLI_BASE: "cli-base"
|
|
29
20
|
};
|
|
30
21
|
/** Stable declaration order; registry tests check the shipped spec composition. */
|
|
@@ -42,4 +33,4 @@ function parseBackendType(value) {
|
|
|
42
33
|
//#endregion
|
|
43
34
|
export { parseBackendType as a, isBackendType as i, BACKEND_TYPE as n, backendTypeSchema as r, ALL_BACKEND_TYPES as t };
|
|
44
35
|
|
|
45
|
-
//# sourceMappingURL=backend-types-
|
|
36
|
+
//# sourceMappingURL=backend-types-CNo_Zj_K.mjs.map
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
//#region ../runtime-contracts/dist/backend-types.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* This distribution's backend vocabulary, declared positively. The shared
|
|
6
|
-
* Interface vocabulary also contains historical and differently hosted harnesses;
|
|
7
|
-
* knowing one upstream must not require installing it here or make this module
|
|
8
|
-
* throw at import time. Keep old wire identities readable when retiring execution.
|
|
9
|
-
*
|
|
10
|
-
* Gemini is not a direct Sandbox backend; it is available only through a backing
|
|
11
|
-
* transport. Adding it upstream never implicitly makes it dispatchable here.
|
|
12
|
-
* The spec/adapter composition must still prove every backend it actually enables.
|
|
13
|
-
*/
|
|
4
|
+
/** This distribution's backend vocabulary. Gemini is only a backing transport, not a direct backend. */
|
|
14
5
|
declare const BACKEND_TYPE: {
|
|
15
6
|
readonly OPENCODE: "opencode";
|
|
16
7
|
readonly CLAUDE_CODE: "claude-code";
|
|
@@ -21,11 +12,11 @@ declare const BACKEND_TYPE: {
|
|
|
21
12
|
readonly PI: "pi";
|
|
22
13
|
readonly PRIME: "prime";
|
|
23
14
|
readonly HERMES: "hermes";
|
|
24
|
-
readonly FORGE: "forge";
|
|
25
15
|
readonly OPENCLAW: "openclaw";
|
|
26
16
|
readonly NANOCLAW: "nanoclaw";
|
|
27
17
|
readonly ACP: "acp";
|
|
28
18
|
readonly CURSOR: "cursor";
|
|
19
|
+
readonly GROK: "grok";
|
|
29
20
|
readonly CLI_BASE: "cli-base";
|
|
30
21
|
};
|
|
31
22
|
/** Derived from the local declaration, not the complement of the upstream enum. */
|
|
@@ -44,8 +35,8 @@ declare const backendTypeSchema: z.ZodEnum<{
|
|
|
44
35
|
openclaw: "openclaw";
|
|
45
36
|
amp: "amp";
|
|
46
37
|
"factory-droids": "factory-droids";
|
|
47
|
-
forge: "forge";
|
|
48
38
|
cursor: "cursor";
|
|
39
|
+
grok: "grok";
|
|
49
40
|
acp: "acp";
|
|
50
41
|
"cli-base": "cli-base";
|
|
51
42
|
}>;
|
|
@@ -53,4 +44,4 @@ declare function isBackendType(value: string): value is BackendType;
|
|
|
53
44
|
declare function parseBackendType(value: string): BackendType;
|
|
54
45
|
//#endregion
|
|
55
46
|
export { isBackendType as a, backendTypeSchema as i, BACKEND_TYPE as n, parseBackendType as o, BackendType as r, ALL_BACKEND_TYPES as t };
|
|
56
|
-
//# sourceMappingURL=backend-types-
|
|
47
|
+
//# sourceMappingURL=backend-types-DRmLR1e0.d.mts.map
|
package/dist/backend-types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as isBackendType, i as backendTypeSchema, n as BACKEND_TYPE, o as parseBackendType, r as BackendType, t as ALL_BACKEND_TYPES } from "./backend-types-
|
|
1
|
+
import { a as isBackendType, i as backendTypeSchema, n as BACKEND_TYPE, o as parseBackendType, r as BackendType, t as ALL_BACKEND_TYPES } from "./backend-types-DRmLR1e0.mjs";
|
|
2
2
|
export { ALL_BACKEND_TYPES, BACKEND_TYPE, BackendType, backendTypeSchema, isBackendType, parseBackendType };
|
package/dist/backend-types.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseBackendType, i as isBackendType, n as BACKEND_TYPE, r as backendTypeSchema, t as ALL_BACKEND_TYPES } from "./backend-types-
|
|
1
|
+
import { a as parseBackendType, i as isBackendType, n as BACKEND_TYPE, r as backendTypeSchema, t as ALL_BACKEND_TYPES } from "./backend-types-CNo_Zj_K.mjs";
|
|
2
2
|
export { ALL_BACKEND_TYPES, BACKEND_TYPE, backendTypeSchema, isBackendType, parseBackendType };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { l as getSpec } from "./specs-BBF55TnM.mjs";
|
|
2
|
+
import "@tangle-network/agent-interface";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
//#region ../runtime-contracts/dist/public-profile-request.js
|
|
5
|
+
const cliAuthReferenceSchema = z.strictObject({
|
|
6
|
+
account: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9@._+-]{0,127}$/),
|
|
7
|
+
secretEnv: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,63}$/),
|
|
8
|
+
format: z.enum([
|
|
9
|
+
"token",
|
|
10
|
+
"bundle",
|
|
11
|
+
"files"
|
|
12
|
+
])
|
|
13
|
+
});
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/cli-auth-bundle.ts
|
|
16
|
+
const DEFAULT_MODE = 384;
|
|
17
|
+
const AUTH_BUNDLE_PATHS = Object.freeze({
|
|
18
|
+
codex: ".codex/auth.json",
|
|
19
|
+
"claude-code": ".claude/.credentials.json"
|
|
20
|
+
});
|
|
21
|
+
/** Convert a native credential JSON bundle without reading host credentials. */
|
|
22
|
+
function materializeCliAuthBundle(backendType, rawBundle) {
|
|
23
|
+
if (backendType !== "codex" && backendType !== "claude-code") throw new Error("CLI auth bundle is not supported for the selected backend");
|
|
24
|
+
if (typeof rawBundle !== "string") throw new Error("CLI auth bundle must be a JSON object");
|
|
25
|
+
let value;
|
|
26
|
+
try {
|
|
27
|
+
value = JSON.parse(rawBundle);
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error("CLI auth bundle must be a JSON object");
|
|
30
|
+
}
|
|
31
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("CLI auth bundle must be a JSON object");
|
|
32
|
+
return [{
|
|
33
|
+
path: AUTH_BUNDLE_PATHS[backendType],
|
|
34
|
+
content: rawBundle,
|
|
35
|
+
mode: DEFAULT_MODE
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
const CLI_AUTH_REFERENCE_ENV_VAR = "AGENT_INTERNAL_CLI_AUTH_REF";
|
|
39
|
+
const cliAuthFilesSchema = z.array(z.object({
|
|
40
|
+
path: z.string().min(1).max(4096).refine((value) => !value.startsWith("/") && !/^[A-Za-z]:/.test(value) && !/[\\\0]/.test(value) && value.split("/").every((part) => part !== "" && part !== "." && part !== "..")),
|
|
41
|
+
content: z.string().max(1024 * 1024),
|
|
42
|
+
mode: z.number().int().min(0).max(448).refine((mode) => (mode & 63) === 0).optional()
|
|
43
|
+
}).strict()).min(1).max(128);
|
|
44
|
+
function assertCliAuthReferenceSupported(backendType, model) {
|
|
45
|
+
if (model.cliAuth === void 0) return void 0;
|
|
46
|
+
const parsedReference = cliAuthReferenceSchema.safeParse(model.cliAuth);
|
|
47
|
+
if (!parsedReference.success) throw new Error("Invalid native authentication reference");
|
|
48
|
+
const reference = parsedReference.data;
|
|
49
|
+
if (model.authMode === "api-key" || model.apiKey !== void 0 || model.apiKeyEnv !== void 0 || model.baseUrl !== void 0 || model.authFiles !== void 0) throw new Error("cliAuth cannot be combined with API credentials, baseUrl, or inline authFiles");
|
|
50
|
+
const spec = getSpec(backendType);
|
|
51
|
+
if (!spec?.hasCliAuth) throw new Error(`Native CLI authentication is unsupported by ${backendType}`);
|
|
52
|
+
if (reference.format === "token" && !spec.envVars.oauthToken) throw new Error(`Native subscription tokens are unsupported by ${backendType}`);
|
|
53
|
+
if (reference.format === "bundle" && backendType !== "codex" && backendType !== "claude-code") throw new Error(`Native credential bundles are unsupported by ${backendType}`);
|
|
54
|
+
return reference;
|
|
55
|
+
}
|
|
56
|
+
/** Resolve only the selected injected secret, without copying it into a public config. */
|
|
57
|
+
function resolveCliAuthReference(backendType, model, environment) {
|
|
58
|
+
const reference = assertCliAuthReferenceSupported(backendType, model);
|
|
59
|
+
if (!reference) return void 0;
|
|
60
|
+
const value = environment[reference.secretEnv];
|
|
61
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`Missing native credential environment variable: ${reference.secretEnv}`);
|
|
62
|
+
if (reference.format === "token") {
|
|
63
|
+
const tokenEnv = getSpec(backendType)?.envVars.oauthToken;
|
|
64
|
+
if (!tokenEnv) throw new Error(`Native subscription tokens are unsupported by ${backendType}`);
|
|
65
|
+
if (/\s/.test(value) || value.startsWith("{") || value.startsWith("[")) throw new Error("Native token authentication requires a raw token, not a credential wrapper");
|
|
66
|
+
return {
|
|
67
|
+
reference,
|
|
68
|
+
authFiles: [],
|
|
69
|
+
tokenEnvironment: { [tokenEnv]: value }
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (reference.format === "bundle") return {
|
|
73
|
+
reference,
|
|
74
|
+
authFiles: materializeCliAuthBundle(backendType, value),
|
|
75
|
+
tokenEnvironment: {}
|
|
76
|
+
};
|
|
77
|
+
let parsed;
|
|
78
|
+
try {
|
|
79
|
+
parsed = JSON.parse(value);
|
|
80
|
+
} catch {
|
|
81
|
+
throw new Error("Native authFiles secret must contain a JSON array of auth files");
|
|
82
|
+
}
|
|
83
|
+
const files = cliAuthFilesSchema.safeParse(parsed);
|
|
84
|
+
if (!files.success) throw new Error("Native authFiles secret must contain a JSON array of auth files");
|
|
85
|
+
if (backendType === "codex" && (files.data.length !== 1 || files.data[0]?.path !== AUTH_BUNDLE_PATHS.codex || files.data[0]?.content.trim().length === 0)) throw new Error("Codex native auth files require only .codex/auth.json");
|
|
86
|
+
return {
|
|
87
|
+
reference,
|
|
88
|
+
authFiles: files.data,
|
|
89
|
+
tokenEnvironment: {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { materializeCliAuthBundle as a, cliAuthFilesSchema as i, CLI_AUTH_REFERENCE_ENV_VAR as n, resolveCliAuthReference as o, assertCliAuthReferenceSupported as r, cliAuthReferenceSchema as s, AUTH_BUNDLE_PATHS as t };
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=cli-auth-bundle-C6DtK7GX.mjs.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region ../runtime-contracts/dist/public-profile-request.d.ts
|
|
4
|
+
declare const cliAuthReferenceSchema: z.ZodObject<{
|
|
5
|
+
account: z.ZodString;
|
|
6
|
+
secretEnv: z.ZodString;
|
|
7
|
+
format: z.ZodEnum<{
|
|
8
|
+
files: "files";
|
|
9
|
+
token: "token";
|
|
10
|
+
bundle: "bundle";
|
|
11
|
+
}>;
|
|
12
|
+
}, z.core.$strict>;
|
|
13
|
+
/** A supplied account binding label, not a verified native account principal. */
|
|
14
|
+
type CliAuthReference = z.infer<typeof cliAuthReferenceSchema>;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/cli-auth-bundle.d.ts
|
|
17
|
+
type LocalCliAuthFile = {
|
|
18
|
+
path: string;
|
|
19
|
+
content: string;
|
|
20
|
+
mode?: number;
|
|
21
|
+
};
|
|
22
|
+
declare const AUTH_BUNDLE_PATHS: Readonly<{
|
|
23
|
+
readonly codex: ".codex/auth.json";
|
|
24
|
+
readonly "claude-code": ".claude/.credentials.json";
|
|
25
|
+
}>;
|
|
26
|
+
/** Convert a native credential JSON bundle without reading host credentials. */
|
|
27
|
+
declare function materializeCliAuthBundle(backendType: string, rawBundle: string): LocalCliAuthFile[];
|
|
28
|
+
declare const CLI_AUTH_REFERENCE_ENV_VAR = "AGENT_INTERNAL_CLI_AUTH_REF";
|
|
29
|
+
type CliAuthMaterial = {
|
|
30
|
+
reference: CliAuthReference;
|
|
31
|
+
authFiles: LocalCliAuthFile[];
|
|
32
|
+
tokenEnvironment: Record<string, string>;
|
|
33
|
+
};
|
|
34
|
+
declare const cliAuthFilesSchema: z.ZodArray<z.ZodObject<{
|
|
35
|
+
path: z.ZodString;
|
|
36
|
+
content: z.ZodString;
|
|
37
|
+
mode: z.ZodOptional<z.ZodNumber>;
|
|
38
|
+
}, z.core.$strict>>;
|
|
39
|
+
declare function assertCliAuthReferenceSupported(backendType: string, model: {
|
|
40
|
+
cliAuth?: CliAuthReference;
|
|
41
|
+
authMode?: string;
|
|
42
|
+
apiKey?: string;
|
|
43
|
+
apiKeyEnv?: string;
|
|
44
|
+
baseUrl?: string;
|
|
45
|
+
authFiles?: LocalCliAuthFile[];
|
|
46
|
+
}): CliAuthReference | undefined;
|
|
47
|
+
/** Resolve only the selected injected secret, without copying it into a public config. */
|
|
48
|
+
declare function resolveCliAuthReference(backendType: string, model: Parameters<typeof assertCliAuthReferenceSupported>[1], environment: Readonly<Record<string, string | undefined>>): CliAuthMaterial | undefined;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { assertCliAuthReferenceSupported as a, resolveCliAuthReference as c, LocalCliAuthFile as i, CliAuthReference as l, CLI_AUTH_REFERENCE_ENV_VAR as n, cliAuthFilesSchema as o, CliAuthMaterial as r, materializeCliAuthBundle as s, AUTH_BUNDLE_PATHS as t, cliAuthReferenceSchema as u };
|
|
51
|
+
//# sourceMappingURL=cli-auth-bundle-CwAaH0Ap.d.mts.map
|
|
@@ -1,49 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
//#region src/cli-auth-bundle.d.ts
|
|
4
|
-
type LocalCliAuthFile = {
|
|
5
|
-
path: string;
|
|
6
|
-
content: string;
|
|
7
|
-
mode?: number;
|
|
8
|
-
};
|
|
9
|
-
declare const AUTH_BUNDLE_PATHS: Readonly<{
|
|
10
|
-
readonly codex: ".codex/auth.json";
|
|
11
|
-
readonly "claude-code": ".claude/.credentials.json";
|
|
12
|
-
}>;
|
|
13
|
-
/** Convert a native credential JSON bundle without reading host credentials. */
|
|
14
|
-
declare function materializeCliAuthBundle(backendType: string, rawBundle: string): LocalCliAuthFile[];
|
|
15
|
-
declare const CLI_AUTH_REFERENCE_ENV_VAR = "AGENT_INTERNAL_CLI_AUTH_REF";
|
|
16
|
-
declare const cliAuthReferenceSchema: z.ZodObject<{
|
|
17
|
-
account: z.ZodString;
|
|
18
|
-
secretEnv: z.ZodString;
|
|
19
|
-
format: z.ZodEnum<{
|
|
20
|
-
token: "token";
|
|
21
|
-
bundle: "bundle";
|
|
22
|
-
files: "files";
|
|
23
|
-
}>;
|
|
24
|
-
}, z.core.$strict>;
|
|
25
|
-
/** A supplied account binding label, not a verified native account principal. */
|
|
26
|
-
type CliAuthReference = z.infer<typeof cliAuthReferenceSchema>;
|
|
27
|
-
type CliAuthMaterial = {
|
|
28
|
-
reference: CliAuthReference;
|
|
29
|
-
authFiles: LocalCliAuthFile[];
|
|
30
|
-
tokenEnvironment: Record<string, string>;
|
|
31
|
-
};
|
|
32
|
-
declare const cliAuthFilesSchema: z.ZodArray<z.ZodObject<{
|
|
33
|
-
path: z.ZodString;
|
|
34
|
-
content: z.ZodString;
|
|
35
|
-
mode: z.ZodOptional<z.ZodNumber>;
|
|
36
|
-
}, z.core.$strict>>;
|
|
37
|
-
declare function assertCliAuthReferenceSupported(backendType: string, model: {
|
|
38
|
-
cliAuth?: CliAuthReference;
|
|
39
|
-
authMode?: string;
|
|
40
|
-
apiKey?: string;
|
|
41
|
-
apiKeyEnv?: string;
|
|
42
|
-
baseUrl?: string;
|
|
43
|
-
authFiles?: LocalCliAuthFile[];
|
|
44
|
-
}): CliAuthReference | undefined;
|
|
45
|
-
/** Resolve only the selected injected secret, without copying it into a public config. */
|
|
46
|
-
declare function resolveCliAuthReference(backendType: string, model: Parameters<typeof assertCliAuthReferenceSupported>[1], environment: Readonly<Record<string, string | undefined>>): CliAuthMaterial | undefined;
|
|
47
|
-
//#endregion
|
|
48
|
-
export { AUTH_BUNDLE_PATHS, CLI_AUTH_REFERENCE_ENV_VAR, CliAuthMaterial, CliAuthReference, LocalCliAuthFile, assertCliAuthReferenceSupported, cliAuthFilesSchema, cliAuthReferenceSchema, materializeCliAuthBundle, resolveCliAuthReference };
|
|
49
|
-
//# sourceMappingURL=cli-auth-bundle.d.mts.map
|
|
1
|
+
import { a as assertCliAuthReferenceSupported, c as resolveCliAuthReference, i as LocalCliAuthFile, l as CliAuthReference, n as CLI_AUTH_REFERENCE_ENV_VAR, o as cliAuthFilesSchema, r as CliAuthMaterial, s as materializeCliAuthBundle, t as AUTH_BUNDLE_PATHS, u as cliAuthReferenceSchema } from "./cli-auth-bundle-CwAaH0Ap.mjs";
|
|
2
|
+
export { AUTH_BUNDLE_PATHS, CLI_AUTH_REFERENCE_ENV_VAR, CliAuthMaterial, CliAuthReference, LocalCliAuthFile, assertCliAuthReferenceSupported, cliAuthFilesSchema, cliAuthReferenceSchema, materializeCliAuthBundle, resolveCliAuthReference };
|
package/dist/cli-auth-bundle.mjs
CHANGED
|
@@ -1,92 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
//#region src/cli-auth-bundle.ts
|
|
4
|
-
const DEFAULT_MODE = 384;
|
|
5
|
-
const AUTH_BUNDLE_PATHS = Object.freeze({
|
|
6
|
-
codex: ".codex/auth.json",
|
|
7
|
-
"claude-code": ".claude/.credentials.json"
|
|
8
|
-
});
|
|
9
|
-
/** Convert a native credential JSON bundle without reading host credentials. */
|
|
10
|
-
function materializeCliAuthBundle(backendType, rawBundle) {
|
|
11
|
-
if (backendType !== "codex" && backendType !== "claude-code") throw new Error("CLI auth bundle is not supported for the selected backend");
|
|
12
|
-
if (typeof rawBundle !== "string") throw new Error("CLI auth bundle must be a JSON object");
|
|
13
|
-
let value;
|
|
14
|
-
try {
|
|
15
|
-
value = JSON.parse(rawBundle);
|
|
16
|
-
} catch {
|
|
17
|
-
throw new Error("CLI auth bundle must be a JSON object");
|
|
18
|
-
}
|
|
19
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("CLI auth bundle must be a JSON object");
|
|
20
|
-
return [{
|
|
21
|
-
path: AUTH_BUNDLE_PATHS[backendType],
|
|
22
|
-
content: rawBundle,
|
|
23
|
-
mode: DEFAULT_MODE
|
|
24
|
-
}];
|
|
25
|
-
}
|
|
26
|
-
const CLI_AUTH_REFERENCE_ENV_VAR = "AGENT_INTERNAL_CLI_AUTH_REF";
|
|
27
|
-
const cliAuthReferenceSchema = z.object({
|
|
28
|
-
account: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9@._+-]{0,127}$/),
|
|
29
|
-
secretEnv: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,63}$/),
|
|
30
|
-
format: z.enum([
|
|
31
|
-
"token",
|
|
32
|
-
"bundle",
|
|
33
|
-
"files"
|
|
34
|
-
])
|
|
35
|
-
}).strict();
|
|
36
|
-
const cliAuthFilesSchema = z.array(z.object({
|
|
37
|
-
path: z.string().min(1).max(4096).refine((value) => !value.startsWith("/") && !/^[A-Za-z]:/.test(value) && !/[\\\0]/.test(value) && value.split("/").every((part) => part !== "" && part !== "." && part !== "..")),
|
|
38
|
-
content: z.string().max(1024 * 1024),
|
|
39
|
-
mode: z.number().int().min(0).max(448).refine((mode) => (mode & 63) === 0).optional()
|
|
40
|
-
}).strict()).min(1).max(128);
|
|
41
|
-
function assertCliAuthReferenceSupported(backendType, model) {
|
|
42
|
-
if (model.cliAuth === void 0) return void 0;
|
|
43
|
-
const parsedReference = cliAuthReferenceSchema.safeParse(model.cliAuth);
|
|
44
|
-
if (!parsedReference.success) throw new Error("Invalid native authentication reference");
|
|
45
|
-
const reference = parsedReference.data;
|
|
46
|
-
if (model.authMode === "api-key" || model.apiKey !== void 0 || model.apiKeyEnv !== void 0 || model.baseUrl !== void 0 || model.authFiles !== void 0) throw new Error("cliAuth cannot be combined with API credentials, baseUrl, or inline authFiles");
|
|
47
|
-
const spec = getSpec(backendType);
|
|
48
|
-
if (!spec?.hasCliAuth) throw new Error(`Native CLI authentication is unsupported by ${backendType}`);
|
|
49
|
-
if (reference.format === "token" && !spec.envVars.oauthToken) throw new Error(`Native subscription tokens are unsupported by ${backendType}`);
|
|
50
|
-
if (reference.format === "bundle" && backendType !== "codex" && backendType !== "claude-code") throw new Error(`Native credential bundles are unsupported by ${backendType}`);
|
|
51
|
-
return reference;
|
|
52
|
-
}
|
|
53
|
-
/** Resolve only the selected injected secret, without copying it into a public config. */
|
|
54
|
-
function resolveCliAuthReference(backendType, model, environment) {
|
|
55
|
-
const reference = assertCliAuthReferenceSupported(backendType, model);
|
|
56
|
-
if (!reference) return void 0;
|
|
57
|
-
const value = environment[reference.secretEnv];
|
|
58
|
-
if (typeof value !== "string" || value.trim().length === 0) throw new Error(`Missing native credential environment variable: ${reference.secretEnv}`);
|
|
59
|
-
if (reference.format === "token") {
|
|
60
|
-
const tokenEnv = getSpec(backendType)?.envVars.oauthToken;
|
|
61
|
-
if (!tokenEnv) throw new Error(`Native subscription tokens are unsupported by ${backendType}`);
|
|
62
|
-
if (/\s/.test(value) || value.startsWith("{") || value.startsWith("[")) throw new Error("Native token authentication requires a raw token, not a credential wrapper");
|
|
63
|
-
return {
|
|
64
|
-
reference,
|
|
65
|
-
authFiles: [],
|
|
66
|
-
tokenEnvironment: { [tokenEnv]: value }
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (reference.format === "bundle") return {
|
|
70
|
-
reference,
|
|
71
|
-
authFiles: materializeCliAuthBundle(backendType, value),
|
|
72
|
-
tokenEnvironment: {}
|
|
73
|
-
};
|
|
74
|
-
let parsed;
|
|
75
|
-
try {
|
|
76
|
-
parsed = JSON.parse(value);
|
|
77
|
-
} catch {
|
|
78
|
-
throw new Error("Native authFiles secret must contain a JSON array of auth files");
|
|
79
|
-
}
|
|
80
|
-
const files = cliAuthFilesSchema.safeParse(parsed);
|
|
81
|
-
if (!files.success) throw new Error("Native authFiles secret must contain a JSON array of auth files");
|
|
82
|
-
if (backendType === "codex" && (files.data.length !== 1 || files.data[0]?.path !== AUTH_BUNDLE_PATHS.codex || files.data[0]?.content.trim().length === 0)) throw new Error("Codex native auth files require only .codex/auth.json");
|
|
83
|
-
return {
|
|
84
|
-
reference,
|
|
85
|
-
authFiles: files.data,
|
|
86
|
-
tokenEnvironment: {}
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
//#endregion
|
|
1
|
+
import { a as materializeCliAuthBundle, i as cliAuthFilesSchema, n as CLI_AUTH_REFERENCE_ENV_VAR, o as resolveCliAuthReference, r as assertCliAuthReferenceSupported, s as cliAuthReferenceSchema, t as AUTH_BUNDLE_PATHS } from "./cli-auth-bundle-C6DtK7GX.mjs";
|
|
90
2
|
export { AUTH_BUNDLE_PATHS, CLI_AUTH_REFERENCE_ENV_VAR, assertCliAuthReferenceSupported, cliAuthFilesSchema, cliAuthReferenceSchema, materializeCliAuthBundle, resolveCliAuthReference };
|
|
91
|
-
|
|
92
|
-
//# sourceMappingURL=cli-auth-bundle.mjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { i as baseProxyToken, r as declaredSecretSlotTokens } from "./harness-
|
|
1
|
+
import { o as resolveCliAuthReference, r as assertCliAuthReferenceSupported, t as AUTH_BUNDLE_PATHS } from "./cli-auth-bundle-C6DtK7GX.mjs";
|
|
2
|
+
import { i as baseProxyToken, r as declaredSecretSlotTokens } from "./harness-D1fTxnDD.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/cli-auth-placeholder.ts
|
|
5
5
|
const identity = z.string().regex(/^[A-Za-z0-9_-]{1,256}$/);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { l as getSpec } from "./specs-
|
|
2
|
-
import {
|
|
3
|
-
import { n as isSafeEnvVarName, t as isForbiddenEnvVarName } from "./harness-
|
|
1
|
+
import { l as getSpec } from "./specs-BBF55TnM.mjs";
|
|
2
|
+
import { i as cliAuthFilesSchema, n as CLI_AUTH_REFERENCE_ENV_VAR, o as resolveCliAuthReference, s as cliAuthReferenceSchema } from "./cli-auth-bundle-C6DtK7GX.mjs";
|
|
3
|
+
import { n as isSafeEnvVarName, t as isForbiddenEnvVarName } from "./harness-D1fTxnDD.mjs";
|
|
4
4
|
//#region src/cli-backend-auth-env.ts
|
|
5
5
|
/** The narrow credential leg shared by the host and sidecar rebind boundary. */
|
|
6
6
|
function assertCliBackendAuthEnv(backendType, authEnv) {
|
package/dist/default-backend.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as isBackendType, t as ALL_BACKEND_TYPES } from "./backend-types-
|
|
2
|
-
import "./specs-
|
|
1
|
+
import { i as isBackendType, t as ALL_BACKEND_TYPES } from "./backend-types-CNo_Zj_K.mjs";
|
|
2
|
+
import "./specs-BBF55TnM.mjs";
|
|
3
3
|
//#region src/default-backend.ts
|
|
4
4
|
/**
|
|
5
5
|
* Platform-wide default agent backend, read from `DEFAULT_AGENT_BACKEND`.
|
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "
|
|
1
|
+
import { n as HARNESS_WARM_TRANSPORT_ENV } from "./harness-contracts-BZoECCMc.mjs";
|
|
2
|
+
import { ProxySecretBindingSchema, ProxySecretGrantSchema, ProxySecretReceiptSchema, ProxySecretUpdateControlsSchema, ProxySecretsSchema, isProxySecretScopeAttenuation, ownPropertyRecordSchema, proxySecretPresentationsEqual } from "@tangle-network/agent-interface";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
/**
|
|
5
|
-
* Strip the per-sandbox salt, returning the shared base token. The reverse
|
|
6
|
-
* lookup (token -> secret env var name) keys on the base, so a salted token must
|
|
7
|
-
* be reduced here before lookup. An unsalted token (no separator) is returned
|
|
8
|
-
* as-is.
|
|
9
|
-
*/
|
|
10
4
|
function baseProxyToken(token) {
|
|
11
5
|
const i = token.indexOf(".");
|
|
12
6
|
return i === -1 ? token : token.slice(0, i);
|
|
13
7
|
}
|
|
14
|
-
/**
|
|
15
|
-
* The dummy model credential the egress proxy swaps for each env var a box
|
|
16
|
-
* may carry. A box holds only these, salted per sandbox; the real keys stay
|
|
17
|
-
* with the egress proxy. Host-side proxy configuration adds the non-model
|
|
18
|
-
* tokens.
|
|
19
|
-
*/
|
|
20
8
|
const MODEL_PROXY_TOKENS = {
|
|
21
9
|
OPENCODE_MODEL_API_KEY: "proxy-model-token",
|
|
22
10
|
OPENAI_API_KEY: "proxy-openai-token",
|
|
@@ -33,15 +21,14 @@ new Set([
|
|
|
33
21
|
"GITHUB_TOKEN",
|
|
34
22
|
"GH_TOKEN"
|
|
35
23
|
]);
|
|
36
|
-
/**
|
|
37
|
-
* Fixed proxy slot names. The egress layer keys every secret it holds by an
|
|
38
|
-
* env-var-shaped name, and its persistence and recovery paths list those
|
|
39
|
-
* names; a declaration takes the slot at its index, so a sandbox with
|
|
40
|
-
* declarations needs no name the layer has not already listed.
|
|
41
|
-
*/
|
|
24
|
+
/** Proxy-private slot names shared by legacy and canonical bindings. */
|
|
42
25
|
function declaredSecretSlotEnvVar(index) {
|
|
43
26
|
return `TANGLE_DECLARED_SLOT_${index}`;
|
|
44
27
|
}
|
|
28
|
+
/** True for a slot name, which exists at the proxy and never in a box env. */
|
|
29
|
+
function isDeclaredSecretSlotEnvVar(name) {
|
|
30
|
+
return /^TANGLE_DECLARED_SLOT_\d+$/.test(name);
|
|
31
|
+
}
|
|
45
32
|
/** The base placeholder for the slot at `index`; the box holds it salted. */
|
|
46
33
|
function declaredSecretBaseToken(index) {
|
|
47
34
|
return `proxy-declared-${index}-token`;
|
|
@@ -53,6 +40,44 @@ function declaredSecretSlotTokens() {
|
|
|
53
40
|
return slots;
|
|
54
41
|
}
|
|
55
42
|
//#endregion
|
|
43
|
+
//#region ../runtime-contracts/dist/proxy-secret-materialization.js
|
|
44
|
+
const syntheticHeader = {
|
|
45
|
+
alg: "HS256",
|
|
46
|
+
typ: "JWT"
|
|
47
|
+
};
|
|
48
|
+
const encode = (value) => btoa(value instanceof Uint8Array ? String.fromCharCode(...value) : JSON.stringify(value)).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
|
|
49
|
+
function placeholderPrefix(slot, format, expiresAt) {
|
|
50
|
+
return format === "jwt" ? `${encode(syntheticHeader)}.${encode({
|
|
51
|
+
sub: "sandbox-placeholder",
|
|
52
|
+
aud: "proxy-secret-placeholder",
|
|
53
|
+
exp: Math.floor(Date.parse(expiresAt) / 1e3)
|
|
54
|
+
})}.` : `proxy-declared-${slot.slice(21)}-token-`;
|
|
55
|
+
}
|
|
56
|
+
function isSyntheticPlaceholder(material) {
|
|
57
|
+
const prefix = placeholderPrefix(material.slot, material.grant.placeholderFormat, material.issuerExpiresAt);
|
|
58
|
+
return material.placeholder.startsWith(prefix) && /^[A-Za-z0-9_-]{43}$/.test(material.placeholder.slice(prefix.length));
|
|
59
|
+
}
|
|
60
|
+
z.array(z.strictObject({
|
|
61
|
+
binding: ProxySecretBindingSchema,
|
|
62
|
+
grant: ProxySecretGrantSchema,
|
|
63
|
+
placeholder: z.string().min(1),
|
|
64
|
+
slot: z.string().refine(isDeclaredSecretSlotEnvVar),
|
|
65
|
+
issuerExpiresAt: z.iso.datetime(),
|
|
66
|
+
native: z.unknown().optional()
|
|
67
|
+
})).superRefine((materials, ctx) => {
|
|
68
|
+
const bindings = ProxySecretsSchema.safeParse(materials.map((m) => m.binding));
|
|
69
|
+
const unique = (values) => new Set(values).size === values.length;
|
|
70
|
+
if (!bindings.success || !unique(materials.map((m) => m.slot)) || !unique(materials.map((m) => m.placeholder)) || !unique(materials.map((m) => m.grant.grantId)) || new Set(materials.map((m) => m.grant.epoch)).size > 1 || new Set(materials.map((m) => m.grant.sandboxId)).size > 1 || materials.some((material) => !isSyntheticPlaceholder(material)) || materials.some(({ binding, grant, issuerExpiresAt }) => !isProxySecretScopeAttenuation(binding, grant.scope) || !proxySecretPresentationsEqual(binding.presentation, grant.presentation) || (binding.placeholderFormat ?? "opaque") !== grant.placeholderFormat || Date.parse(grant.expiresAt) > Date.parse(issuerExpiresAt))) ctx.addIssue({
|
|
71
|
+
code: "custom",
|
|
72
|
+
message: "Invalid proxy secret materialization"
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
ProxySecretUpdateControlsSchema.extend({
|
|
76
|
+
resolvedSecrets: ownPropertyRecordSchema(z.string().min(1), { maxEntries: Number.MAX_SAFE_INTEGER }).default({}),
|
|
77
|
+
proxySecretGrants: ProxySecretReceiptSchema.options[0].shape.bindings,
|
|
78
|
+
expectedProxySecretGeneration: ProxySecretUpdateControlsSchema.shape.expectedProxySecretGeneration.unwrap()
|
|
79
|
+
}).strict().refine((body) => new Set(body.proxySecretGrants.map((b) => b.envName)).size === body.proxySecretGrants.length);
|
|
80
|
+
//#endregion
|
|
56
81
|
//#region ../runtime-contracts/dist/runtime-environment.js
|
|
57
82
|
const SAFE_ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
58
83
|
function isSafeEnvVarName(name) {
|
|
@@ -60,6 +85,23 @@ function isSafeEnvVarName(name) {
|
|
|
60
85
|
if (name.length === 0 || name.length > 256) return false;
|
|
61
86
|
return SAFE_ENV_VAR_NAME_RE.test(name);
|
|
62
87
|
}
|
|
88
|
+
/** Client proxy URLs first, then bypass names. */
|
|
89
|
+
const EGRESS_PROXY_ENV_NAMES = [
|
|
90
|
+
"HTTPS_PROXY",
|
|
91
|
+
"https_proxy",
|
|
92
|
+
"HTTP_PROXY",
|
|
93
|
+
"http_proxy",
|
|
94
|
+
"NO_PROXY",
|
|
95
|
+
"no_proxy"
|
|
96
|
+
];
|
|
97
|
+
const CA_TRUST_ENV_NAMES = [
|
|
98
|
+
"NODE_EXTRA_CA_CERTS",
|
|
99
|
+
"SSL_CERT_FILE",
|
|
100
|
+
"CURL_CA_BUNDLE",
|
|
101
|
+
"GIT_SSL_CAINFO",
|
|
102
|
+
"NIX_SSL_CERT_FILE"
|
|
103
|
+
];
|
|
104
|
+
[...EGRESS_PROXY_ENV_NAMES, ...CA_TRUST_ENV_NAMES];
|
|
63
105
|
const FORBIDDEN_ENV_VAR_NAMES = new Set([
|
|
64
106
|
"LD_PRELOAD",
|
|
65
107
|
"LD_LIBRARY_PATH",
|
|
@@ -133,20 +175,10 @@ function isForbiddenEnvVarName(name) {
|
|
|
133
175
|
return false;
|
|
134
176
|
}
|
|
135
177
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* into a container the caller owns (user code), where names like
|
|
139
|
-
* `PATH`, `NODE_OPTIONS`, `LD_PRELOAD`, or `HTTPS_PROXY` are legitimate
|
|
140
|
-
* because the user controls the resulting process environment.
|
|
141
|
-
*
|
|
142
|
-
* Callers that merge env into the runtime's OWN process.env (sidecar
|
|
143
|
-
* `/config/env`, orchestrator `/sidecars/start`, project provisioning)
|
|
144
|
-
* MUST additionally reject the process-control blocklist via
|
|
145
|
-
* {@link isForbiddenEnvVarName} — see
|
|
146
|
-
* `apps/orchestrator/src/routes/sidecars.ts` and
|
|
147
|
-
* `apps/sidecar/src/routes/agents-config.ts` for the canonical shape.
|
|
178
|
+
* POSIX names for caller-owned container env. Runtime process.env merges must additionally enforce
|
|
179
|
+
* isForbiddenEnvVarName, including project provisioning and Sidecar config.
|
|
148
180
|
*/
|
|
149
|
-
const safeEnvRecordSchema =
|
|
181
|
+
const safeEnvRecordSchema = ownPropertyRecordSchema(z.string(), { maxEntries: Number.MAX_SAFE_INTEGER }).refine((value) => Object.keys(value).every(isSafeEnvVarName), { message: "invalid env var name" });
|
|
150
182
|
/** Names only: the caller must keep a separate source and pass values to resume({ env }). */
|
|
151
183
|
const sandboxEnvRecoverySchema = z.object({ callerResupplies: z.array(z.string().max(256).refine(isSafeEnvVarName, { message: "invalid env var name" })).max(128).refine((keys) => new Set(keys).size === keys.length, { message: "callerResupplies must contain unique keys" }) }).strict();
|
|
152
184
|
z.object({
|
|
@@ -164,4 +196,4 @@ safeEnvRecordSchema.refine((value) => Object.keys(value).every((key) => !isForbi
|
|
|
164
196
|
//#endregion
|
|
165
197
|
export { baseProxyToken as i, isSafeEnvVarName as n, declaredSecretSlotTokens as r, isForbiddenEnvVarName as t };
|
|
166
198
|
|
|
167
|
-
//# sourceMappingURL=harness-
|
|
199
|
+
//# sourceMappingURL=harness-D1fTxnDD.mjs.map
|