@tangle-network/cli-agent-registry 0.0.0-stage → 0.14.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/LICENSE +11 -0
- package/README.md +145 -2
- package/dist/backend-types-CJH-wHS3.d.mts +56 -0
- package/dist/backend-types-CREj4iOY.mjs +45 -0
- package/dist/backend-types.d.mts +2 -0
- package/dist/backend-types.mjs +2 -0
- package/dist/cli-auth-bundle.d.mts +49 -0
- package/dist/cli-auth-bundle.mjs +92 -0
- package/dist/cli-auth-placeholder.d.mts +54 -0
- package/dist/cli-auth-placeholder.mjs +200 -0
- package/dist/cli-backend-auth-env.d.mts +6 -0
- package/dist/cli-backend-auth-env.mjs +44 -0
- package/dist/default-backend.d.mts +24 -0
- package/dist/default-backend.mjs +31 -0
- package/dist/harness-DIdVNSwl.mjs +167 -0
- package/dist/index.d.mts +1400 -0
- package/dist/index.mjs +146 -0
- package/dist/local-cli-auth.d.mts +14 -0
- package/dist/local-cli-auth.mjs +31 -0
- package/dist/native-session-contracts-DWFzgoye.mjs +1162 -0
- package/dist/native-session-contracts.d.mts +354 -0
- package/dist/native-session-contracts.mjs +2 -0
- package/dist/servable-models.d.mts +104 -0
- package/dist/servable-models.mjs +147 -0
- package/dist/session-contract-BC75JdnA.d.mts +131 -0
- package/dist/session-contract.d.mts +2 -0
- package/dist/session-contract.mjs +190 -0
- package/dist/specs-BSELpX1h.d.mts +415 -0
- package/dist/specs-Bbiay_8K.mjs +704 -0
- package/dist/specs.d.mts +3 -0
- package/dist/specs.mjs +3 -0
- package/package.json +81 -3
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { a as HARNESSES, r as NATIVE_SESSION_CONTRACTS } from "./native-session-contracts-DWFzgoye.mjs";
|
|
2
|
+
import { n as BACKEND_TYPE } from "./backend-types-CREj4iOY.mjs";
|
|
3
|
+
import { agentProfileJsonSchema, agentProfileSchema } from "@tangle-network/agent-interface";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { harnessModelSupport } from "@tangle-network/agent-interface/harness-capabilities";
|
|
6
|
+
//#region src/synthetic-router-model.mjs
|
|
7
|
+
/** Synthetic Router model shared with bare-Node release probes. */
|
|
8
|
+
const SYNTHETIC_ROUTER_MODEL = "tangle/canary-echo";
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/spec.ts
|
|
11
|
+
/**
|
|
12
|
+
* The Router's synthetic model: the Router answers it itself, with no provider
|
|
13
|
+
* call and no charge (tangle-router `lib/synthetic-models.ts`). It replies with
|
|
14
|
+
* the text of the last "Reply with exactly <text>" instruction it receives, on
|
|
15
|
+
* every wire a harness speaks (chat completions, Messages, Responses). The
|
|
16
|
+
* production canary and the production benchmark's harness legs run it, so a
|
|
17
|
+
* provider outage or a model-list change cannot page them and they cost $0.
|
|
18
|
+
* A key reaches it only when its model list names it.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Env var name declared with `role` in this spec's extras, or undefined when
|
|
22
|
+
* the spec declares none. At most one extra may carry a given role (enforced
|
|
23
|
+
* by a registry test); the first declaration wins.
|
|
24
|
+
*/
|
|
25
|
+
function cliAgentEnvRoleName(spec, role) {
|
|
26
|
+
const extras = spec.envVars.extras;
|
|
27
|
+
if (!extras) return void 0;
|
|
28
|
+
for (const [name, extra] of Object.entries(extras)) if (extra.role === role) return name;
|
|
29
|
+
}
|
|
30
|
+
/** The wire a harness speaks; harnesses that declare none ride openai-compat. */
|
|
31
|
+
function harnessModelWire(spec) {
|
|
32
|
+
return spec.modelWire ?? "openai-compat";
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Provider names that select the Router's OpenAI-compatible transport. They say
|
|
36
|
+
* how a request travels, not which vendor serves the model, so a model check
|
|
37
|
+
* never reads them as the model's provider.
|
|
38
|
+
*/
|
|
39
|
+
const ROUTER_TRANSPORT_PROVIDERS = new Set(["openai-compat", "tangle-router"]);
|
|
40
|
+
/**
|
|
41
|
+
* The model id a harness and model check reads: a `provider/model` slug as
|
|
42
|
+
* given, a bare id qualified by its tuple's vendor provider, and a bare id
|
|
43
|
+
* alone when the tuple names only the Router transport (agent-interface then
|
|
44
|
+
* resolves its provider from the id's family).
|
|
45
|
+
*/
|
|
46
|
+
function canonicalModelSlug(model) {
|
|
47
|
+
const tuple = typeof model === "string" ? { model } : model;
|
|
48
|
+
const id = tuple?.model?.trim();
|
|
49
|
+
if (!id) return void 0;
|
|
50
|
+
if (id.includes("/")) return id;
|
|
51
|
+
const provider = tuple?.provider?.trim();
|
|
52
|
+
return provider && !ROUTER_TRANSPORT_PROVIDERS.has(provider) ? `${provider}/${id}` : id;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether a harness can run a model, read from the one capability table in
|
|
56
|
+
* `@tangle-network/agent-interface`: vendor locks (kimi-code runs Moonshot
|
|
57
|
+
* models) and pairs measured to fail on production. A refused pair is refused
|
|
58
|
+
* where it is chosen (create, run, an authored workflow action) with the
|
|
59
|
+
* returned message, rather than provisioning a box whose first model call
|
|
60
|
+
* fails. An absent model is the harness's own default and is always supported.
|
|
61
|
+
*/
|
|
62
|
+
function harnessModelSupportFor(harness, model, options = {}) {
|
|
63
|
+
const slug = canonicalModelSlug(model);
|
|
64
|
+
if (slug === void 0) return {
|
|
65
|
+
supported: true,
|
|
66
|
+
model: "",
|
|
67
|
+
provider: null
|
|
68
|
+
};
|
|
69
|
+
if (slug === "tangle/canary-echo") return {
|
|
70
|
+
supported: true,
|
|
71
|
+
model: slug,
|
|
72
|
+
provider: null
|
|
73
|
+
};
|
|
74
|
+
return harnessModelSupport(harness, slug, options);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Env var names carrying this harness's claim-deliverable model tuple — the
|
|
78
|
+
* names a warm-claim rebind may deliver to a live sidecar: the model /
|
|
79
|
+
* base-URL / auth-mode roles plus declared extras. Deliberately EXCLUDES the
|
|
80
|
+
* credential-bearing roles: `apiKey` (a BYO key outside egress proxy-swap
|
|
81
|
+
* coverage would put a raw secret in the rebind body — the caller adds the
|
|
82
|
+
* name back only when its transport guarantees a dummy value) and `authFiles`
|
|
83
|
+
* (auth-file payloads are credential content and never ride a rebind).
|
|
84
|
+
*/
|
|
85
|
+
function cliAgentClaimEnvVarNames(spec) {
|
|
86
|
+
const names = [];
|
|
87
|
+
if (spec.envVars.model) names.push(spec.envVars.model);
|
|
88
|
+
if (spec.envVars.baseUrl) names.push(spec.envVars.baseUrl);
|
|
89
|
+
if (spec.envVars.authMode) names.push(spec.envVars.authMode);
|
|
90
|
+
if (spec.envVars.extras) names.push(...Object.keys(spec.envVars.extras));
|
|
91
|
+
return names;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/specs.ts
|
|
95
|
+
z.globalRegistry.add(agentProfileSchema, {
|
|
96
|
+
id: "AgentProfile",
|
|
97
|
+
...agentProfileJsonSchema
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* Env var naming a sandbox's selected backend. Stamped into every create env
|
|
101
|
+
* by the orchestrator (`buildSidecarContainerConfig`); read by the sidecar's
|
|
102
|
+
* backend resolution (`resolveConfiguredBackend`) and by the host-agent's
|
|
103
|
+
* warm-claim env selection to pick which spec's env vars the rebind delivers.
|
|
104
|
+
*/
|
|
105
|
+
const AGENT_BACKEND_ENV_VAR = "AGENT_BACKEND";
|
|
106
|
+
/**
|
|
107
|
+
* The managed-router model-key channel every backend shares: the box-side
|
|
108
|
+
* value is always the salted proxy dummy (`proxy-model-token.<salt>`), which
|
|
109
|
+
* the per-sandbox egress proxy swaps for the real budget-scoped key at the
|
|
110
|
+
* network boundary. The opencode-derived NAME is pinned naming debt: FC
|
|
111
|
+
* shared-snapshot salt recovery, resume re-key, and the egress proxy swap map
|
|
112
|
+
* all key on this literal, so renaming it bricks managed-model auth
|
|
113
|
+
* fleet-wide. Kept equal to the opencode spec's own apiKey declaration
|
|
114
|
+
* (enforced by a registry test).
|
|
115
|
+
*/
|
|
116
|
+
const MANAGED_MODEL_KEY_ENV_VAR = "OPENCODE_MODEL_API_KEY";
|
|
117
|
+
/**
|
|
118
|
+
* Caller-owned auth by reference: the NAME of the box env var (a stored
|
|
119
|
+
* secret) that holds the provider's key. The orchestrator sets it only when it
|
|
120
|
+
* injected no managed key; the sidecar composes the named provider on that
|
|
121
|
+
* credential. A variable name, never a secret, so it may ride every channel a
|
|
122
|
+
* create's env takes to the guest — the kernel cmdline and a warm-claim rebind.
|
|
123
|
+
*/
|
|
124
|
+
const MANAGED_MODEL_KEY_NAME_ENV_VAR = "OPENCODE_MODEL_API_KEY_ENV";
|
|
125
|
+
/**
|
|
126
|
+
* Env var names declared across ALL registered harness specs, grouped by
|
|
127
|
+
* their `CliAgentEnvVars` role. The ONE derivation every allowlist that must
|
|
128
|
+
* track "what env names can a backend legitimately use" builds from — the
|
|
129
|
+
* FC kernel-cmdline whitelist, the egress secret handling, the sidecar
|
|
130
|
+
* terminal scrub, the SSH env forward, and the rebind union below. Deriving
|
|
131
|
+
* from roles (not one flat set) lets each consumer apply its own security
|
|
132
|
+
* policy per role: apiKey and oauthToken names are secret channels.
|
|
133
|
+
* Native subscription tokens stay out of warm-claim delivery.
|
|
134
|
+
*/
|
|
135
|
+
function cliAgentEnvVarNamesByRole() {
|
|
136
|
+
const apiKey = /* @__PURE__ */ new Set();
|
|
137
|
+
const oauthToken = /* @__PURE__ */ new Set();
|
|
138
|
+
const model = /* @__PURE__ */ new Set();
|
|
139
|
+
const baseUrl = /* @__PURE__ */ new Set();
|
|
140
|
+
const authMode = /* @__PURE__ */ new Set();
|
|
141
|
+
const authFiles = /* @__PURE__ */ new Set();
|
|
142
|
+
const extras = /* @__PURE__ */ new Set();
|
|
143
|
+
for (const spec of CLI_AGENT_SPECS) {
|
|
144
|
+
if (spec.envVars.apiKey) apiKey.add(spec.envVars.apiKey);
|
|
145
|
+
if (spec.envVars.oauthToken) oauthToken.add(spec.envVars.oauthToken);
|
|
146
|
+
if (spec.envVars.model) model.add(spec.envVars.model);
|
|
147
|
+
if (spec.envVars.baseUrl) baseUrl.add(spec.envVars.baseUrl);
|
|
148
|
+
if (spec.envVars.authMode) authMode.add(spec.envVars.authMode);
|
|
149
|
+
if (spec.envVars.authFiles) authFiles.add(spec.envVars.authFiles);
|
|
150
|
+
for (const name of Object.keys(spec.envVars.extras ?? {})) extras.add(name);
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
apiKey,
|
|
154
|
+
oauthToken,
|
|
155
|
+
model,
|
|
156
|
+
baseUrl,
|
|
157
|
+
authMode,
|
|
158
|
+
authFiles,
|
|
159
|
+
extras
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Union of every spec's `hostPassthroughEnvVars` — the operator tuning names
|
|
164
|
+
* a host process (orchestrator system env, host-agent process env) may
|
|
165
|
+
* forward into containers. Request/caller env always keeps precedence at the
|
|
166
|
+
* host-agent boundary; the orchestrator system-env channel stays
|
|
167
|
+
* operator-authoritative. Replaces the old `OPENCODE_*` prefix forward,
|
|
168
|
+
* which leaked ANY stray host var with that prefix (model tuple and key
|
|
169
|
+
* included) into every tenant.
|
|
170
|
+
*/
|
|
171
|
+
function cliAgentHostPassthroughEnvVarNames() {
|
|
172
|
+
const names = /* @__PURE__ */ new Set();
|
|
173
|
+
for (const spec of CLI_AGENT_SPECS) for (const name of spec.hostPassthroughEnvVars ?? []) names.add(name);
|
|
174
|
+
return names;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Union of every env var name a warm-claim rebind may deliver, across all
|
|
178
|
+
* registered harnesses. The ONE source both sides of the rebind derive from:
|
|
179
|
+
* the host-agent selects its delivery from it and the sidecar rebind route
|
|
180
|
+
* carves it out of the loader-control rejection, so the two can never drift
|
|
181
|
+
* into "host delivers a name the sidecar 400s" — which silently cold-paths
|
|
182
|
+
* every warm claim of that backend. Includes each spec's apiKey name because
|
|
183
|
+
* acceptance is a superset of delivery: the HOST decides which key names are
|
|
184
|
+
* safe to send (egress proxy-swap-covered only), while the sidecar must not
|
|
185
|
+
* reject a name a valid host may deliver.
|
|
186
|
+
*/
|
|
187
|
+
function claimDeliverableEnvVarNames() {
|
|
188
|
+
const roles = cliAgentEnvVarNamesByRole();
|
|
189
|
+
return new Set([
|
|
190
|
+
AGENT_BACKEND_ENV_VAR,
|
|
191
|
+
MANAGED_MODEL_KEY_ENV_VAR,
|
|
192
|
+
MANAGED_MODEL_KEY_NAME_ENV_VAR,
|
|
193
|
+
...roles.model,
|
|
194
|
+
...roles.baseUrl,
|
|
195
|
+
...roles.authMode,
|
|
196
|
+
...roles.extras,
|
|
197
|
+
...roles.apiKey
|
|
198
|
+
]);
|
|
199
|
+
}
|
|
200
|
+
const CLI_AGENT_SPECS = [
|
|
201
|
+
{
|
|
202
|
+
name: BACKEND_TYPE.OPENCODE,
|
|
203
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.opencode,
|
|
204
|
+
messageStorageDir: ".opencode",
|
|
205
|
+
cliDirLayout: {
|
|
206
|
+
sessionData: ["snapshot/**"],
|
|
207
|
+
configAllow: ["bin/**"]
|
|
208
|
+
},
|
|
209
|
+
displayName: "OpenCode Agent",
|
|
210
|
+
description: "OpenCode CLI coding agent with native sessions, profiles, tools, and MCP.",
|
|
211
|
+
envVars: HARNESSES["opencode"].config.envVars,
|
|
212
|
+
capabilities: {
|
|
213
|
+
streaming: true,
|
|
214
|
+
toolUse: true,
|
|
215
|
+
reasoning: true,
|
|
216
|
+
multimodal: true,
|
|
217
|
+
contextWindow: 2e5,
|
|
218
|
+
mcp: true,
|
|
219
|
+
runtimeAttachments: { mcp: true },
|
|
220
|
+
sessions: true,
|
|
221
|
+
configurable: true,
|
|
222
|
+
interactions: [
|
|
223
|
+
"permission",
|
|
224
|
+
"question",
|
|
225
|
+
"plan"
|
|
226
|
+
],
|
|
227
|
+
imageInput: true
|
|
228
|
+
},
|
|
229
|
+
hostPassthroughEnvVars: [
|
|
230
|
+
"OPENCODE_MODEL_MODE",
|
|
231
|
+
"OPENCODE_CODEX_PLUGIN_VERSION",
|
|
232
|
+
"OPENCODE_EXPERIMENTAL_NATIVE_LLM"
|
|
233
|
+
],
|
|
234
|
+
interactiveSeededPrompt: true,
|
|
235
|
+
builtinTools: [
|
|
236
|
+
{
|
|
237
|
+
id: "apply_patch",
|
|
238
|
+
name: "Apply Patch",
|
|
239
|
+
description: "Apply a unified-diff patch to files"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: "bash",
|
|
243
|
+
name: "Bash",
|
|
244
|
+
description: "Execute bash commands"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: "codesearch",
|
|
248
|
+
name: "Code Search",
|
|
249
|
+
description: "Search code across the workspace"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
id: "edit",
|
|
253
|
+
name: "Edit",
|
|
254
|
+
description: "Edit a file with string replacement"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
id: "glob",
|
|
258
|
+
name: "Glob",
|
|
259
|
+
description: "Find files by glob pattern"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: "grep",
|
|
263
|
+
name: "Grep",
|
|
264
|
+
description: "Search file contents using regular expressions"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
id: "question",
|
|
268
|
+
name: "Question",
|
|
269
|
+
description: "Ask the user a question and wait for the answer"
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: "read",
|
|
273
|
+
name: "Read",
|
|
274
|
+
description: "Read file contents"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: "skill",
|
|
278
|
+
name: "Skill",
|
|
279
|
+
description: "Invoke an installed skill"
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: "task",
|
|
283
|
+
name: "Task",
|
|
284
|
+
description: "Delegate a task to a subagent"
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: "todowrite",
|
|
288
|
+
name: "Todo Write",
|
|
289
|
+
description: "Maintain the turn's todo list"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
id: "webfetch",
|
|
293
|
+
name: "Webfetch",
|
|
294
|
+
description: "Fetch and read web content"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: "websearch",
|
|
298
|
+
name: "Websearch",
|
|
299
|
+
description: "Search the web"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: "write",
|
|
303
|
+
name: "Write",
|
|
304
|
+
description: "Write content to a file"
|
|
305
|
+
}
|
|
306
|
+
],
|
|
307
|
+
runtime: HARNESSES["opencode"].lifecycle.runtime,
|
|
308
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
309
|
+
hasCliAuth: false
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
name: BACKEND_TYPE.CLAUDE_CODE,
|
|
313
|
+
nativeSession: NATIVE_SESSION_CONTRACTS["claude-code"],
|
|
314
|
+
runtime: HARNESSES["claude-code"].lifecycle.runtime,
|
|
315
|
+
messageStorageDir: ".claude-code",
|
|
316
|
+
cliDirLayout: {
|
|
317
|
+
sessionData: [
|
|
318
|
+
"plans/**",
|
|
319
|
+
"file-history/**",
|
|
320
|
+
"debug/**",
|
|
321
|
+
"projects/*/*/subagents/**/*.meta.json",
|
|
322
|
+
"projects/*/*/tool-results/**"
|
|
323
|
+
],
|
|
324
|
+
configAllow: [
|
|
325
|
+
".last-cleanup",
|
|
326
|
+
"policy-limits.json*",
|
|
327
|
+
"remote-settings.json",
|
|
328
|
+
"skills/**"
|
|
329
|
+
],
|
|
330
|
+
credential: [
|
|
331
|
+
"backups/**",
|
|
332
|
+
"session-env/**",
|
|
333
|
+
"shell-snapshots/**",
|
|
334
|
+
"sessions/**"
|
|
335
|
+
]
|
|
336
|
+
},
|
|
337
|
+
displayName: "Claude Code",
|
|
338
|
+
description: "Anthropic Claude Code CLI-based agent backend.",
|
|
339
|
+
envVars: HARNESSES["claude-code"].config.envVars,
|
|
340
|
+
modelWire: HARNESSES["claude-code"].config.modelWire,
|
|
341
|
+
capabilities: {
|
|
342
|
+
streaming: true,
|
|
343
|
+
toolUse: true,
|
|
344
|
+
reasoning: true,
|
|
345
|
+
multimodal: true,
|
|
346
|
+
contextWindow: 2e5,
|
|
347
|
+
mcp: true,
|
|
348
|
+
runtimeAttachments: { mcp: true },
|
|
349
|
+
sessions: true,
|
|
350
|
+
configurable: true,
|
|
351
|
+
interactions: [
|
|
352
|
+
"permission",
|
|
353
|
+
"question",
|
|
354
|
+
"plan"
|
|
355
|
+
],
|
|
356
|
+
imageInput: true
|
|
357
|
+
},
|
|
358
|
+
securityCapabilities: [
|
|
359
|
+
"SYS_PTRACE",
|
|
360
|
+
"SETUID",
|
|
361
|
+
"SETGID",
|
|
362
|
+
"DAC_OVERRIDE",
|
|
363
|
+
"CHOWN",
|
|
364
|
+
"FOWNER"
|
|
365
|
+
],
|
|
366
|
+
interactiveSeededPrompt: true,
|
|
367
|
+
cliAuthHome: {
|
|
368
|
+
kind: "agent-home",
|
|
369
|
+
uid: 1e3,
|
|
370
|
+
home: "/home/agent"
|
|
371
|
+
},
|
|
372
|
+
hasCliAuth: true,
|
|
373
|
+
byoOAuth: true
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
name: BACKEND_TYPE.KIMI_CODE,
|
|
377
|
+
nativeSession: NATIVE_SESSION_CONTRACTS["kimi-code"],
|
|
378
|
+
runtime: HARNESSES["kimi-code"].lifecycle.runtime,
|
|
379
|
+
messageStorageDir: ".kimi-code",
|
|
380
|
+
displayName: "Kimi Code",
|
|
381
|
+
description: "Moonshot AI Kimi Code CLI — headless non-interactive mode via `kimi --print --output-format stream-json --prompt ...`. Defaults to OAuth (Kimi Code subscription) with credentials materialized from the host-managed ~/.kimi/credentials/kimi-code.json; falls back to MOONSHOT_API_KEY when an apiKey is supplied.",
|
|
382
|
+
envVars: HARNESSES["kimi-code"].config.envVars,
|
|
383
|
+
capabilities: {
|
|
384
|
+
streaming: true,
|
|
385
|
+
toolUse: true,
|
|
386
|
+
reasoning: true,
|
|
387
|
+
multimodal: true,
|
|
388
|
+
contextWindow: 262144,
|
|
389
|
+
mcp: false,
|
|
390
|
+
runtimeAttachments: { mcp: true },
|
|
391
|
+
sessions: true,
|
|
392
|
+
configurable: true,
|
|
393
|
+
interactions: [],
|
|
394
|
+
imageInput: false
|
|
395
|
+
},
|
|
396
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
397
|
+
hasCliAuth: true
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
name: BACKEND_TYPE.CODEX,
|
|
401
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.codex,
|
|
402
|
+
messageStorageDir: ".codex",
|
|
403
|
+
cliDirLayout: { sessionData: [
|
|
404
|
+
"logs_*.sqlite*",
|
|
405
|
+
"goals_*.sqlite*",
|
|
406
|
+
"memories_*.sqlite*"
|
|
407
|
+
] },
|
|
408
|
+
displayName: "Codex",
|
|
409
|
+
description: "OpenAI Codex CLI-based agent backend.",
|
|
410
|
+
envVars: HARNESSES["codex"].config.envVars,
|
|
411
|
+
modelWire: HARNESSES["codex"].config.modelWire,
|
|
412
|
+
capabilities: {
|
|
413
|
+
streaming: true,
|
|
414
|
+
toolUse: true,
|
|
415
|
+
reasoning: false,
|
|
416
|
+
multimodal: true,
|
|
417
|
+
contextWindow: 128e3,
|
|
418
|
+
mcp: false,
|
|
419
|
+
sessions: true,
|
|
420
|
+
configurable: false,
|
|
421
|
+
runtimeAttachments: { mcp: true },
|
|
422
|
+
interactions: [
|
|
423
|
+
"permission",
|
|
424
|
+
"question",
|
|
425
|
+
"plan"
|
|
426
|
+
],
|
|
427
|
+
imageInput: true
|
|
428
|
+
},
|
|
429
|
+
interactiveSeededPrompt: true,
|
|
430
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
431
|
+
hasCliAuth: true,
|
|
432
|
+
byoOAuth: true
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: BACKEND_TYPE.AMP,
|
|
436
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.amp,
|
|
437
|
+
messageStorageDir: ".amp-sessions",
|
|
438
|
+
displayName: "AMP (Sourcegraph)",
|
|
439
|
+
description: "Sourcegraph AMP CLI-based agent backend.",
|
|
440
|
+
callerCredentialOnly: true,
|
|
441
|
+
envVars: HARNESSES["amp"].config.envVars,
|
|
442
|
+
capabilities: {
|
|
443
|
+
streaming: true,
|
|
444
|
+
toolUse: true,
|
|
445
|
+
reasoning: false,
|
|
446
|
+
multimodal: false,
|
|
447
|
+
contextWindow: 128e3,
|
|
448
|
+
mcp: false,
|
|
449
|
+
sessions: true,
|
|
450
|
+
configurable: false,
|
|
451
|
+
interactions: [],
|
|
452
|
+
imageInput: false
|
|
453
|
+
},
|
|
454
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
455
|
+
hasCliAuth: true
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: BACKEND_TYPE.FACTORY_DROIDS,
|
|
459
|
+
nativeSession: NATIVE_SESSION_CONTRACTS["factory-droids"],
|
|
460
|
+
messageStorageDir: ".factory-droids",
|
|
461
|
+
displayName: "Factory Droids",
|
|
462
|
+
description: "Factory Droids CLI-based agent backend. A managed box runs its Tangle Router model as a droid custom model; a caller's FACTORY_API_KEY runs on the caller's Factory account.",
|
|
463
|
+
envVars: HARNESSES["factory-droids"].config.envVars,
|
|
464
|
+
capabilities: {
|
|
465
|
+
streaming: true,
|
|
466
|
+
toolUse: true,
|
|
467
|
+
reasoning: false,
|
|
468
|
+
multimodal: false,
|
|
469
|
+
contextWindow: 128e3,
|
|
470
|
+
mcp: false,
|
|
471
|
+
sessions: true,
|
|
472
|
+
configurable: false,
|
|
473
|
+
interactions: ["question"],
|
|
474
|
+
imageInput: false
|
|
475
|
+
},
|
|
476
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
477
|
+
hasCliAuth: true
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
name: BACKEND_TYPE.PI,
|
|
481
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.pi,
|
|
482
|
+
runtime: HARNESSES["pi"].lifecycle.runtime,
|
|
483
|
+
messageStorageDir: ".pi/agent",
|
|
484
|
+
displayName: "Pi",
|
|
485
|
+
description: "Pi CLI backend. Managed OpenAI-compatible model tuples use one private runtime HOME models.json and the shared Pi model schema.",
|
|
486
|
+
envVars: HARNESSES["pi"].config.envVars,
|
|
487
|
+
capabilities: {
|
|
488
|
+
streaming: true,
|
|
489
|
+
toolUse: true,
|
|
490
|
+
reasoning: true,
|
|
491
|
+
multimodal: false,
|
|
492
|
+
contextWindow: 128e3,
|
|
493
|
+
mcp: true,
|
|
494
|
+
sessions: true,
|
|
495
|
+
configurable: true,
|
|
496
|
+
interactions: ["permission"],
|
|
497
|
+
runtimeAttachments: { mcp: true },
|
|
498
|
+
imageInput: false
|
|
499
|
+
},
|
|
500
|
+
interactiveSeededPrompt: true,
|
|
501
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
502
|
+
hasCliAuth: true
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
name: BACKEND_TYPE.PRIME,
|
|
506
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.prime,
|
|
507
|
+
messageStorageDir: ".prime-provider",
|
|
508
|
+
displayName: "Prime Agent (PrimeIntellect)",
|
|
509
|
+
description: "PrimeIntellect-ai/prime-agent — IPython-first coding agent (pi hard fork, fork line 0.7.x) driven over its native ACP mode. Model tuple travels via backend.model into a per-session materialized models.json, never env; the adapter pins PRIME_AGENT_CODING_AGENT_DIR to an isolated per-session agent dir (fail-closed harness-state isolation).",
|
|
510
|
+
envVars: HARNESSES["prime"].config.envVars,
|
|
511
|
+
hostPassthroughEnvVars: ["PRIME_AGENT_INSTALL_UV", "PRIME_AGENT_KERNEL_PYTHON"],
|
|
512
|
+
capabilities: {
|
|
513
|
+
streaming: true,
|
|
514
|
+
toolUse: true,
|
|
515
|
+
reasoning: true,
|
|
516
|
+
multimodal: true,
|
|
517
|
+
contextWindow: 128e3,
|
|
518
|
+
mcp: false,
|
|
519
|
+
sessions: true,
|
|
520
|
+
configurable: true,
|
|
521
|
+
interactions: [],
|
|
522
|
+
imageInput: true
|
|
523
|
+
},
|
|
524
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
525
|
+
hasCliAuth: false
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: BACKEND_TYPE.HERMES,
|
|
529
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.hermes,
|
|
530
|
+
messageStorageDir: ".hermes-agent",
|
|
531
|
+
cliDirLayout: {
|
|
532
|
+
sessionData: ["cache/spillover/**", "cache/delegation/**"],
|
|
533
|
+
configAllow: ["config.yaml"]
|
|
534
|
+
},
|
|
535
|
+
displayName: "Hermes Agent (Nous Research)",
|
|
536
|
+
description: "Open-source self-improving CLI agent. Persistent memory and skills live in $HERMES_HOME (pinned to the per-session workspace mount, not the read-only in-box $HOME) across same-tenant snapshot resumes — the learning loop is the differentiator. Provider-pluggable; defaults to OpenRouter via Tangle Router.",
|
|
537
|
+
envVars: HARNESSES["hermes"].config.envVars,
|
|
538
|
+
capabilities: {
|
|
539
|
+
streaming: false,
|
|
540
|
+
toolUse: true,
|
|
541
|
+
reasoning: false,
|
|
542
|
+
multimodal: false,
|
|
543
|
+
contextWindow: 2e5,
|
|
544
|
+
mcp: true,
|
|
545
|
+
sessions: true,
|
|
546
|
+
configurable: true,
|
|
547
|
+
interactions: [],
|
|
548
|
+
imageInput: true
|
|
549
|
+
},
|
|
550
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
551
|
+
hasCliAuth: true
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
name: BACKEND_TYPE.FORGE,
|
|
555
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.forge,
|
|
556
|
+
messageStorageDir: ".forge-agent",
|
|
557
|
+
displayName: "Forge (forgecode.dev)",
|
|
558
|
+
description: "Rust-built multi-provider coding agent from tailcallhq/forgecode. Speaks anthropic/openai/openrouter/gemini/deepseek/kimi + local providers (ollama, lm_studio, llama_cpp). Credentials live in ~/.forge/.credentials.json, materialized via the standard authFiles pipeline — no interactive `forge provider login` required.",
|
|
559
|
+
envVars: HARNESSES["forge"].config.envVars,
|
|
560
|
+
capabilities: {
|
|
561
|
+
streaming: false,
|
|
562
|
+
toolUse: true,
|
|
563
|
+
reasoning: true,
|
|
564
|
+
multimodal: false,
|
|
565
|
+
contextWindow: 2e5,
|
|
566
|
+
mcp: true,
|
|
567
|
+
sessions: true,
|
|
568
|
+
configurable: true,
|
|
569
|
+
interactions: [],
|
|
570
|
+
imageInput: false
|
|
571
|
+
},
|
|
572
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
573
|
+
hasCliAuth: true
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
name: BACKEND_TYPE.OPENCLAW,
|
|
577
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.openclaw,
|
|
578
|
+
messageStorageDir: ".openclaw-agent",
|
|
579
|
+
cliDirLayout: { configAllow: ["openclaw.json"] },
|
|
580
|
+
displayName: "OpenClaw (Orchestrator)",
|
|
581
|
+
description: "Orchestrator-tier CLI agent that dispatches to underlying coding-agent CLIs (claude-cli, codex-cli, gemini-cli) via its built-in cliBackends plugin model. Use this when you want one entry point that intelligently routes tasks to the right coding harness.",
|
|
582
|
+
envVars: HARNESSES["openclaw"].config.envVars,
|
|
583
|
+
capabilities: {
|
|
584
|
+
streaming: false,
|
|
585
|
+
toolUse: true,
|
|
586
|
+
reasoning: true,
|
|
587
|
+
multimodal: true,
|
|
588
|
+
contextWindow: 2e5,
|
|
589
|
+
mcp: true,
|
|
590
|
+
sessions: true,
|
|
591
|
+
configurable: true,
|
|
592
|
+
interactions: [],
|
|
593
|
+
imageInput: false
|
|
594
|
+
},
|
|
595
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
596
|
+
hasCliAuth: true
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
name: BACKEND_TYPE.NANOCLAW,
|
|
600
|
+
nativeSession: null,
|
|
601
|
+
messageStorageDir: ".nanoclaw-agent",
|
|
602
|
+
displayName: "NanoClaw",
|
|
603
|
+
description: "NanoClaw local socket bridge. Requires a running NanoClaw install and uses its `pnpm run chat` CLI channel; the adapter does not manage NanoClaw's Docker/service lifecycle.",
|
|
604
|
+
envVars: HARNESSES["nanoclaw"].config.envVars,
|
|
605
|
+
capabilities: {
|
|
606
|
+
streaming: false,
|
|
607
|
+
toolUse: true,
|
|
608
|
+
reasoning: true,
|
|
609
|
+
multimodal: false,
|
|
610
|
+
contextWindow: 2e5,
|
|
611
|
+
mcp: false,
|
|
612
|
+
sessions: true,
|
|
613
|
+
configurable: true,
|
|
614
|
+
interactions: [],
|
|
615
|
+
imageInput: false
|
|
616
|
+
},
|
|
617
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
618
|
+
hasCliAuth: false
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
name: BACKEND_TYPE.ACP,
|
|
622
|
+
nativeSession: NATIVE_SESSION_CONTRACTS.acp,
|
|
623
|
+
messageStorageDir: ".acp-agent",
|
|
624
|
+
displayName: "ACP Bridge (multi-agent)",
|
|
625
|
+
description: "Generic Agent Client Protocol bridge — fronts any ACP-compliant agent binary (claude-agent-acp, codex-acp, gemini, openclaw acp, hermes acp). Pick the backing agent via config.subAgent; hermes runs on the box's Router model when none is named. One TypeScript adapter, many supported coding harnesses.",
|
|
626
|
+
envVars: HARNESSES["acp"].config.envVars,
|
|
627
|
+
capabilities: {
|
|
628
|
+
streaming: true,
|
|
629
|
+
toolUse: true,
|
|
630
|
+
reasoning: true,
|
|
631
|
+
multimodal: false,
|
|
632
|
+
contextWindow: 2e5,
|
|
633
|
+
mcp: false,
|
|
634
|
+
sessions: true,
|
|
635
|
+
configurable: true,
|
|
636
|
+
interactions: ["permission"],
|
|
637
|
+
imageInput: false
|
|
638
|
+
},
|
|
639
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
640
|
+
hasCliAuth: true
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
name: BACKEND_TYPE.CURSOR,
|
|
644
|
+
nativeSession: null,
|
|
645
|
+
messageStorageDir: ".cursor-sdk-sessions",
|
|
646
|
+
displayName: "Cursor Agent SDK",
|
|
647
|
+
description: "Cursor Agent SDK backend. Runs Cursor's local agent against the sandbox workspace via @cursor/sdk, using CURSOR_API_KEY or backend.model.apiKey for authentication.",
|
|
648
|
+
callerCredentialOnly: true,
|
|
649
|
+
egressHosts: ["api2.cursor.sh", "api.cursor.com"],
|
|
650
|
+
envVars: HARNESSES["cursor"].config.envVars,
|
|
651
|
+
capabilities: {
|
|
652
|
+
streaming: true,
|
|
653
|
+
toolUse: true,
|
|
654
|
+
reasoning: true,
|
|
655
|
+
multimodal: true,
|
|
656
|
+
contextWindow: 2e5,
|
|
657
|
+
mcp: true,
|
|
658
|
+
sessions: true,
|
|
659
|
+
configurable: true,
|
|
660
|
+
interactions: [],
|
|
661
|
+
imageInput: true
|
|
662
|
+
},
|
|
663
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
664
|
+
hasCliAuth: false
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
name: BACKEND_TYPE.CLI_BASE,
|
|
668
|
+
nativeSession: null,
|
|
669
|
+
displayName: "CLI Base (no agent)",
|
|
670
|
+
description: "Bare sandbox without an AI agent backend. Use when you want the workspace, tools, and SSH access but no LLM dispatch.",
|
|
671
|
+
envVars: HARNESSES["cli-base"].config.envVars,
|
|
672
|
+
capabilities: {
|
|
673
|
+
streaming: false,
|
|
674
|
+
toolUse: false,
|
|
675
|
+
reasoning: false,
|
|
676
|
+
multimodal: false,
|
|
677
|
+
contextWindow: 0,
|
|
678
|
+
mcp: false,
|
|
679
|
+
sessions: false,
|
|
680
|
+
configurable: false,
|
|
681
|
+
interactions: [],
|
|
682
|
+
imageInput: false
|
|
683
|
+
},
|
|
684
|
+
cliAuthHome: { kind: "inherit-home" },
|
|
685
|
+
hasCliAuth: false
|
|
686
|
+
}
|
|
687
|
+
];
|
|
688
|
+
function getSpec(name) {
|
|
689
|
+
return CLI_AGENT_SPECS.find((spec) => spec.name === name);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* The directory, relative to a session's storage path, where a backend's
|
|
693
|
+
* message log lives: the one value adapters, the sidecar and the parked
|
|
694
|
+
* export read. Throws for a backend whose spec names none.
|
|
695
|
+
*/
|
|
696
|
+
function messageStorageDirOf(name) {
|
|
697
|
+
const dir = getSpec(name)?.messageStorageDir;
|
|
698
|
+
if (!dir) throw new Error(`No message storage directory for backend ${name}`);
|
|
699
|
+
return dir;
|
|
700
|
+
}
|
|
701
|
+
//#endregion
|
|
702
|
+
export { agentProfileSchema as a, cliAgentHostPassthroughEnvVarNames as c, canonicalModelSlug as d, cliAgentClaimEnvVarNames as f, SYNTHETIC_ROUTER_MODEL as g, harnessModelWire as h, MANAGED_MODEL_KEY_NAME_ENV_VAR as i, getSpec as l, harnessModelSupportFor as m, CLI_AGENT_SPECS as n, claimDeliverableEnvVarNames as o, cliAgentEnvRoleName as p, MANAGED_MODEL_KEY_ENV_VAR as r, cliAgentEnvVarNamesByRole as s, AGENT_BACKEND_ENV_VAR as t, messageStorageDirOf as u };
|
|
703
|
+
|
|
704
|
+
//# sourceMappingURL=specs-Bbiay_8K.mjs.map
|
package/dist/specs.d.mts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
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-CJH-wHS3.mjs";
|
|
2
|
+
import { D as harnessModelSupportFor, O as harnessModelWire, T as cliAgentClaimEnvVarNames, _ as CliAgentModelWire, a as agentProfileSchema, c as cliAgentHostPassthroughEnvVarNames, i as MANAGED_MODEL_KEY_NAME_ENV_VAR, l as getSpec, n as CLI_AGENT_SPECS, o as claimDeliverableEnvVarNames, r as MANAGED_MODEL_KEY_ENV_VAR, s as cliAgentEnvVarNamesByRole, t as AGENT_BACKEND_ENV_VAR, u as messageStorageDirOf, w as canonicalModelSlug, y as CliAgentSpec } from "./specs-BSELpX1h.mjs";
|
|
3
|
+
export { AGENT_BACKEND_ENV_VAR, ALL_BACKEND_TYPES, BACKEND_TYPE, BackendType, CLI_AGENT_SPECS, CliAgentModelWire, CliAgentSpec, MANAGED_MODEL_KEY_ENV_VAR, MANAGED_MODEL_KEY_NAME_ENV_VAR, agentProfileSchema, backendTypeSchema, canonicalModelSlug, claimDeliverableEnvVarNames, cliAgentClaimEnvVarNames, cliAgentEnvVarNamesByRole, cliAgentHostPassthroughEnvVarNames, getSpec, harnessModelSupportFor, harnessModelWire, isBackendType, messageStorageDirOf, parseBackendType };
|