@tangle-network/cli-agent-registry 0.0.0-stage → 0.15.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.
Files changed (37) hide show
  1. package/LICENSE +11 -0
  2. package/README.md +175 -2
  3. package/dist/backend-types-CNo_Zj_K.mjs +36 -0
  4. package/dist/backend-types-DRmLR1e0.d.mts +47 -0
  5. package/dist/backend-types.d.mts +2 -0
  6. package/dist/backend-types.mjs +2 -0
  7. package/dist/cli-auth-bundle-C6DtK7GX.mjs +95 -0
  8. package/dist/cli-auth-bundle-CwAaH0Ap.d.mts +51 -0
  9. package/dist/cli-auth-bundle.d.mts +2 -0
  10. package/dist/cli-auth-bundle.mjs +2 -0
  11. package/dist/cli-auth-placeholder.d.mts +54 -0
  12. package/dist/cli-auth-placeholder.mjs +200 -0
  13. package/dist/cli-backend-auth-env.d.mts +6 -0
  14. package/dist/cli-backend-auth-env.mjs +44 -0
  15. package/dist/default-backend.d.mts +24 -0
  16. package/dist/default-backend.mjs +31 -0
  17. package/dist/harness-D1fTxnDD.mjs +199 -0
  18. package/dist/harness-contracts-BZoECCMc.mjs +1076 -0
  19. package/dist/host-contracts.d.mts +30 -0
  20. package/dist/host-contracts.json +422 -0
  21. package/dist/host-contracts.mjs +63 -0
  22. package/dist/index.d.mts +1397 -0
  23. package/dist/index.mjs +151 -0
  24. package/dist/local-cli-auth.d.mts +14 -0
  25. package/dist/local-cli-auth.mjs +31 -0
  26. package/dist/native-session-contracts.d.mts +349 -0
  27. package/dist/native-session-contracts.mjs +40 -0
  28. package/dist/servable-models.d.mts +103 -0
  29. package/dist/servable-models.mjs +131 -0
  30. package/dist/session-contract-BhzcbPRW.d.mts +97 -0
  31. package/dist/session-contract.d.mts +2 -0
  32. package/dist/session-contract.mjs +142 -0
  33. package/dist/spec-CcvTM7-j.d.mts +346 -0
  34. package/dist/specs-BBF55TnM.mjs +735 -0
  35. package/dist/specs.d.mts +72 -0
  36. package/dist/specs.mjs +3 -0
  37. package/package.json +87 -3
@@ -0,0 +1,346 @@
1
+ import { t as HarnessSessionContract } from "./session-contract-BhzcbPRW.mjs";
2
+ import { SdkProviderAdapter, WellKnownInteractionKind } from "@tangle-network/agent-interface";
3
+ import { HarnessModelSupport, HarnessModelSupportOptions } from "@tangle-network/agent-interface/harness-capabilities";
4
+
5
+ //#region src/cli-dir-layout.d.ts
6
+ /**
7
+ * How a parked export reads a CLI's own directory (`.codex`, `.claude`, …)
8
+ * beyond the session stores its contract declares. Globs are relative to that
9
+ * directory except `homeSessionData`, in session-contract glob syntax (`*`, `**`).
10
+ *
11
+ * - `sessionData`: what holds a user's session, to be exported as a
12
+ * transcript is. Until the export carries it, it is missing, and the box is
13
+ * held.
14
+ * - `configAllow`: the CLI's own configuration and caches, withheld and named.
15
+ *
16
+ * - `credential`: what this CLI keeps in its directory that carries secrets
17
+ * but no shared credential name says so (a directory of shell environment
18
+ * snapshots, messaging keys): named, never sent, never missing. The names
19
+ * every CLI shares are runtime-contracts credential-paths.ts
20
+ * (`isNativeStoreCredentialPath`, `NATIVE_STORE_CREDENTIAL_NAMES`), checked
21
+ * first; a spec lists here only what its own pinned version writes.
22
+ *
23
+ * Anything else in the directory is undeclared: missing, so a layout a CLI
24
+ * version adds holds the box until it is classified here.
25
+ */
26
+ interface CliDirLayout {
27
+ /** Auxiliary session files relative to the owning runtime HOME, outside its CLI directory. */
28
+ homeSessionData: readonly string[];
29
+ sessionData: readonly string[];
30
+ configAllow: readonly (string | {
31
+ path: string;
32
+ kind: "symlink";
33
+ })[];
34
+ credential: readonly string[];
35
+ }
36
+ /** What every CLI's directory is read with; a spec adds its own entries. */
37
+ declare const DEFAULT_CLI_DIR_LAYOUT: CliDirLayout;
38
+ /** A spec's additions to the default layout. */
39
+ type CliDirLayoutAdditions = Partial<CliDirLayout>;
40
+ /** The default layout with a spec's additions. */
41
+ declare function mergeCliDirLayout(additions: CliDirLayoutAdditions | undefined): CliDirLayout;
42
+ //#endregion
43
+ //#region src/synthetic-router-model.d.mts
44
+ declare const SYNTHETIC_ROUTER_MODEL: "tangle/canary-echo";
45
+ //#endregion
46
+ //#region src/spec.d.ts
47
+ /**
48
+ * Capability descriptor surfaced via GET /backends.
49
+ * Mirrors `apps/orchestrator/src/routes/backends.ts` schema so the registry
50
+ * is the single source of truth for both the orchestrator UI surface and
51
+ * sidecar adapter selection.
52
+ */
53
+ interface HarnessSpecCapabilities {
54
+ streaming: boolean;
55
+ toolUse: boolean;
56
+ reasoning: boolean;
57
+ multimodal: boolean;
58
+ contextWindow: number;
59
+ mcp: boolean;
60
+ /** Runtime bindings lowered by the profile materializer, independently of dynamic MCP mutation. */
61
+ runtimeAttachments?: {
62
+ mcp: true;
63
+ };
64
+ sessions: boolean;
65
+ configurable: boolean;
66
+ /**
67
+ * Interaction kinds this harness is *capable* of originating
68
+ * (permission/question/plan). Static "can it, if asked" — NOT whether a
69
+ * given session enabled them (that's the per-session adapter
70
+ * getCapabilities() + toggle config). Empty = never asks the user.
71
+ */
72
+ interactions: WellKnownInteractionKind[];
73
+ /**
74
+ * Whether the harness forwards image input parts to the model natively
75
+ * (an argv flag or a stdin content block carrying the image itself)
76
+ * rather than a `[Image: <ref>]` text-marker reference. Distinct from
77
+ * `multimodal`, which is static "can the model reason over images, if
78
+ * asked" — `imageInput` is about the delivery mechanism this harness
79
+ * actually uses, not the model's capability.
80
+ *
81
+ * Like `interactions`, this is static "can it, if asked" — a specific
82
+ * config may still degrade: codex delivers natively on the exec path but
83
+ * marker-only on interactive (permission/question/plan) turns until the
84
+ * app-server protocol carries image elements (#3586). Per-config truth is
85
+ * the runtime adapter's getCapabilities().
86
+ */
87
+ imageInput: boolean;
88
+ }
89
+ type CliAgentEnvExtraParser = "string" | "int" | "json";
90
+ /**
91
+ * Model-tuple role an extra env var carries, for specs whose provider/mode
92
+ * ride the extras channel rather than a first-class {@link CliAgentEnvVars}
93
+ * field (opencode's OPENCODE_MODEL_PROVIDER / OPENCODE_MODEL_MODE). Lets
94
+ * spec-driven consumers (label codec, backend metadata) resolve the tuple
95
+ * without naming any backend's env vars. A spec that declares a `provider`
96
+ * role is authoritative for its provider value; specs without one leave
97
+ * provider resolution to the consumer (e.g. the router model slug's
98
+ * `provider/` prefix).
99
+ */
100
+ type CliAgentEnvExtraRole = "provider" | "mode";
101
+ interface CliAgentEnvExtra {
102
+ parser: CliAgentEnvExtraParser;
103
+ required?: boolean;
104
+ role?: CliAgentEnvExtraRole;
105
+ }
106
+ /**
107
+ * Env var name declared with `role` in this spec's extras, or undefined when
108
+ * the spec declares none. At most one extra may carry a given role (enforced
109
+ * by a registry test); the first declaration wins.
110
+ */
111
+ declare function cliAgentEnvRoleName(spec: CliAgentSpec, role: CliAgentEnvExtraRole): string | undefined;
112
+ interface CliAgentEnvVars {
113
+ apiKey?: string;
114
+ model?: string;
115
+ authMode?: string;
116
+ authFiles?: string;
117
+ /** Native subscription token; never delivered through a warm claim. */
118
+ oauthToken?: string;
119
+ baseUrl?: string;
120
+ /** Provider-specific extras keyed by env var name. */
121
+ extras?: Record<string, CliAgentEnvExtra>;
122
+ }
123
+ /**
124
+ * `inherit-home` means the spawned CLI reads $HOME from the sidecar process.
125
+ * `agent-home` means the adapter demotes to a fixed uid and forces $HOME to
126
+ * a fixed path (claude-code: uid=1000, /home/agent) when the sidecar runs as
127
+ * root. This is the only branch with a non-default home resolution.
128
+ */
129
+ type CliAuthHome = {
130
+ kind: "inherit-home";
131
+ } | {
132
+ kind: "agent-home";
133
+ uid: number;
134
+ home: string;
135
+ };
136
+ /**
137
+ * The wire protocol a harness speaks to the Tangle router.
138
+ *
139
+ * `openai-compat` (`/v1/chat/completions`) routes any provider's model — the
140
+ * router resolves a provider-prefixed slug verbatim. The other two are
141
+ * provider-native wires: the router passes that provider's own models through
142
+ * natively and translates every other model to chat completions (text, images
143
+ * and function tools, streamed or not; hosted tools such as web search are
144
+ * dropped), so each carries any router-served model. Measured 2026-10-15 with
145
+ * `zai/glm-5.3` on claude-code 2.1.300 (`/v1/messages`) and codex 0.162.1
146
+ * (`/v1/responses`): a plain turn and a tool turn completed on both.
147
+ */
148
+ type CliAgentModelWire = "openai-compat" | "openai-responses" | "anthropic-messages";
149
+ /** The wire a harness speaks; harnesses that declare none ride openai-compat. */
150
+ declare function harnessModelWire(spec: CliAgentSpec): CliAgentModelWire;
151
+ /**
152
+ * The model id a harness and model check reads: a `provider/model` slug as
153
+ * given, a bare id qualified by its tuple's vendor provider, and a bare id
154
+ * alone when the tuple names only the Router transport (agent-interface then
155
+ * resolves its provider from the id's family).
156
+ */
157
+ declare function canonicalModelSlug(model: string | {
158
+ provider?: string;
159
+ model?: string;
160
+ } | undefined): string | undefined;
161
+ /**
162
+ * Whether a harness can run a model, read from the one capability table in
163
+ * `@tangle-network/agent-interface`: pairs measured to fail on production
164
+ * (and any vendor lock it declares). A refused pair is refused
165
+ * where it is chosen (create, run, an authored workflow action) with the
166
+ * returned message, rather than provisioning a box whose first model call
167
+ * fails. An absent model is the harness's own default and is always supported.
168
+ */
169
+ declare function harnessModelSupportFor(harness: string, model: string | {
170
+ provider?: string;
171
+ model?: string;
172
+ } | undefined, options?: HarnessModelSupportOptions): HarnessModelSupport;
173
+ /**
174
+ * Env var names carrying this harness's claim-deliverable model tuple — the
175
+ * names a warm-claim rebind may deliver to a live sidecar: the model /
176
+ * base-URL / auth-mode roles plus declared extras. Deliberately EXCLUDES the
177
+ * credential-bearing roles: `apiKey` (a BYO key outside egress proxy-swap
178
+ * coverage would put a raw secret in the rebind body — the caller adds the
179
+ * name back only when its transport guarantees a dummy value) and `authFiles`
180
+ * (auth-file payloads are credential content and never ride a rebind).
181
+ */
182
+ declare function cliAgentClaimEnvVarNames(spec: CliAgentSpec): string[];
183
+ /**
184
+ * Sidecar lifecycle contract for a harness's adapter, declared as spec data
185
+ * so the backend manager, prewarm triggers, and execution guards key on
186
+ * capabilities instead of forking on a harness name. Omitted (or a field
187
+ * omitted) means the CLI default: a per-model-config adapter process with no
188
+ * shared server, no idle retention, no concurrency cap, and no prewarm.
189
+ */
190
+ interface CliAgentRuntimeSpec {
191
+ /**
192
+ * The adapter fronts one long-lived provider server per workspace and the
193
+ * model is a per-request override. Instance identity is therefore
194
+ * `type + workspace (+ profile/hub tools)`, never the model tuple, and
195
+ * config matching compares credentials + server address instead of the
196
+ * full model config. Non-server-based harnesses key every distinct model
197
+ * tuple to its own adapter instance — collapsing them would bleed one
198
+ * session's model config into another session's process.
199
+ */
200
+ serverBased?: boolean;
201
+ /**
202
+ * Keep an idle instance (refCount 0) alive for the next acquisition — the
203
+ * prewarm-then-claim first-token path depends on this. `envVar` names the
204
+ * deployed kill switch: unset means retain; "0"/"false"/"no"/"off"
205
+ * disables retention.
206
+ */
207
+ warmRetention?: {
208
+ envVar: string; /** Retained when `envVar` is unset. Defaults to true. */
209
+ enabledByDefault?: boolean;
210
+ };
211
+ /**
212
+ * Cap concurrent instances of this harness. The cap is read from `envVar`
213
+ * at acquisition time; unset means unlimited.
214
+ */
215
+ concurrencyLimit?: {
216
+ envVar: string;
217
+ };
218
+ /**
219
+ * Prewarm an instance from environment defaults at boot and after
220
+ * claim-time env injection so the first session skips the server spawn
221
+ * (~1.6s on the first-token path). Requires `serverBased`: prewarming a
222
+ * per-model CLI adapter would mint an instance keyed by a model tuple the
223
+ * claimed session may never match.
224
+ */
225
+ prewarmable?: boolean;
226
+ /**
227
+ * The adapter guarantees a tool-disabled visible-output continuation turn
228
+ * (`input.disableTools`). Execution fails loudly for harnesses without it.
229
+ */
230
+ supportsToolDisabledTurns?: boolean;
231
+ /** Adapter accepts host-env redaction; Sidecar must bind its sanitizer,
232
+ * admitting sandbox-public vars only and failing closed if this drifts off. */
233
+ redactsHostEnv?: boolean;
234
+ /** Native launch and MCP custody implement secret-profile UID/HOME isolation. */
235
+ secretProfileIsolation?: boolean;
236
+ }
237
+ /**
238
+ * A tool the harness ships built in, surfaced verbatim on the sidecar's
239
+ * tool-introspection routes. Declared as spec data so those routes serve
240
+ * whatever the registry says instead of forking on a harness name; a spec
241
+ * that declares none reports tool introspection as unsupported.
242
+ */
243
+ interface CliAgentBuiltinTool {
244
+ id: string;
245
+ name: string;
246
+ description: string;
247
+ }
248
+ interface CliAgentSpec {
249
+ name: string;
250
+ displayName: string;
251
+ description: string;
252
+ /** Durable message-store directory; omit when history requires a backend. */
253
+ messageStorageDir?: string;
254
+ /**
255
+ * What a parked export reads in this CLI's own directory beyond its session
256
+ * stores, added to DEFAULT_CLI_DIR_LAYOUT (cli-dir-layout.ts).
257
+ */
258
+ cliDirLayout?: CliDirLayoutAdditions;
259
+ envVars: CliAgentEnvVars;
260
+ runtime?: CliAgentRuntimeSpec;
261
+ /** Built-in tool inventory; omit when the harness declares none. */
262
+ builtinTools?: readonly CliAgentBuiltinTool[];
263
+ /**
264
+ * Operator-level tuning env names forwarded verbatim from a HOST process
265
+ * (orchestrator system env, host-agent process env) into every container —
266
+ * server log routing, retry/limit knobs, mock switches. NOT part of the
267
+ * claim-deliverable model tuple and never a credential channel: these names
268
+ * are excluded from the kernel-cmdline and rebind unions, and a secret-like
269
+ * name here would still be caught by the allowlist builders' secret-suffix
270
+ * guard. Omit for harnesses with no host-side tuning surface.
271
+ */
272
+ hostPassthroughEnvVars?: readonly string[];
273
+ /**
274
+ * Router wire this harness speaks. Omit for `openai-compat`, which every
275
+ * harness rides unless its CLI talks a provider-native protocol. Which models
276
+ * a harness can run is answered by {@link harnessModelSupportFor}; the model a
277
+ * managed session defaults to is `managedModelChain(name).chain[0]`.
278
+ */
279
+ modelWire?: CliAgentModelWire;
280
+ /**
281
+ * Hosts the vendor CLI must reach, allowed through egress only for a box
282
+ * running this harness. Declared beside {@link callerCredentialOnly} because
283
+ * a vendor-served harness cannot work without its vendor's API.
284
+ */
285
+ egressHosts?: readonly string[];
286
+ /**
287
+ * Whether this harness's native TUI can be launched PRE-SEEDED with an opening
288
+ * prompt (a launch arg the CLI submits once it is ready to read input).
289
+ *
290
+ * A caller that drives a TUI on the user's behalf — a workflow interactive run
291
+ * — always seeds one, so a harness without this can start a terminal but never
292
+ * receives the task. Declared here so the surface offering interactive runs and
293
+ * the sidecar that launches them cannot drift onto different sets; the actual
294
+ * argv shape stays with the launcher (`INTERACTIVE_INITIAL_PROMPT_ARGS`).
295
+ */
296
+ interactiveSeededPrompt?: boolean;
297
+ capabilities: HarnessSpecCapabilities;
298
+ /**
299
+ * The harness session contract (session-contract.ts): where the native
300
+ * session is stored, how its id is known, and which flags would disable
301
+ * it. Null only for a spec that runs no harness (`sessions: false`) or a
302
+ * harness listed in HARNESS_SESSION_UNSUPPORTED.
303
+ */
304
+ nativeSession: HarnessSessionContract | null;
305
+ /** Linux container caps. Defaults to ['SYS_PTRACE'] when omitted. */
306
+ securityCapabilities?: string[];
307
+ cliAuthHome: CliAuthHome;
308
+ hasCliAuth: boolean;
309
+ /**
310
+ * The harness completes a session on a caller-supplied OAuth bundle
311
+ * (`model.authFiles`) with no managed router key: its adapter scrubs the
312
+ * router pin under `authMode: "oauth"` and the CLI reaches the vendor's own
313
+ * subscription backend. A create for such a harness with auth files mints
314
+ * no router key.
315
+ */
316
+ byoOAuth?: boolean;
317
+ /**
318
+ * The Tangle Router cannot serve this harness: its CLI calls the vendor's own
319
+ * hosted service (amp: ampcode.com, cursor: api2.cursor.sh) and accepts no
320
+ * custom model endpoint. It runs only on the caller's credential (a key, a
321
+ * key reference, CLI auth, or login files through its `envVars.authFiles`
322
+ * channel), so it has no managed model chain: a create mints no Router key
323
+ * for it, is refused when it carries none, and its box gets no Router default
324
+ * model. The public backend catalog reports the flag. Every other harness
325
+ * starts on the Router when the caller brings no credential of its own.
326
+ */
327
+ callerCredentialOnly?: boolean;
328
+ /** A capability the harness needs and Tangle sandboxes lack: creates are refused. */
329
+ unavailable?: {
330
+ capability: "docker";
331
+ reason: string;
332
+ };
333
+ }
334
+ type AdapterFactory = (logger: ProviderLogger) => SdkProviderAdapter;
335
+ /** Bounded provider startup spans, timed by the operation's owner. */
336
+ type ProviderPhase = "profile_materialize" | "session_prepare" | "native_resume" | "native_session_new" | "history_replay" | "native_session_bind" | "config_build" | "config_write" | "session_turn_wait" | "session_view_bind" | "mcp_proxy_lease" | "native_home_wait" | "dependency_prep" | "cli_spawn" | "cli_boot" | "cli_initialize" | "cli_authenticate" | "server_listening" | "session_open" | "mcp_ready_wait" | "prompt_dispatch" | "cli_ready_wait" | "warm_server_hit" | "warm_server_miss";
337
+ type ProviderLogger = {
338
+ info: (msg: string, meta?: Record<string, unknown>) => void;
339
+ warn: (msg: string, meta?: Record<string, unknown>) => void;
340
+ error: (msg: string, meta?: Record<string, unknown>) => void;
341
+ debug: (msg: string, meta?: Record<string, unknown>) => void; /** Report one startup span; the host records it with the turn's phases. */
342
+ observePhase?: (phase: ProviderPhase, durationMs: number, scope?: "turn" | "prewarm") => void;
343
+ };
344
+ //#endregion
345
+ export { mergeCliDirLayout as C, DEFAULT_CLI_DIR_LAYOUT as S, harnessModelSupportFor as _, CliAgentEnvExtraRole as a, CliDirLayout as b, CliAgentRuntimeSpec as c, HarnessSpecCapabilities as d, ProviderLogger as f, cliAgentEnvRoleName as g, cliAgentClaimEnvVarNames as h, CliAgentEnvExtraParser as i, CliAgentSpec as l, canonicalModelSlug as m, CliAgentBuiltinTool as n, CliAgentEnvVars as o, ProviderPhase as p, CliAgentEnvExtra as r, CliAgentModelWire as s, AdapterFactory as t, CliAuthHome as u, harnessModelWire as v, CliDirLayoutAdditions as x, SYNTHETIC_ROUTER_MODEL as y };
346
+ //# sourceMappingURL=spec-CcvTM7-j.d.mts.map