@datalayer/agent-runtimes 1.5.30 → 1.5.31

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.
@@ -38,6 +38,7 @@ import { getSkillSpec } from '../../specs/skills';
38
38
  import { getTeamSpec } from '../../specs/teams';
39
39
  import { getBackendToolSpec } from '../../specs/backendTools';
40
40
  import { getTrack } from '../../specs/tracks';
41
+ import { unservedHarnessProblem } from '../../runtimes/variants';
41
42
  import { pluginsOffSetupNotes } from '../plugins/canvas-blocks';
42
43
  import { APP_THEME_MODES, APP_THEME_VARIANTS, isAssistantCharacterId, PAGE_OUTPUT_SHOWS, parseAppspec, } from './appspec';
43
44
  import { classesOf, splitRef, toolBehaviours } from './rules';
@@ -397,6 +398,14 @@ function referenceProblems(app, organizationFrames) {
397
398
  if (app.agent && !getAgentspecs(idOf(app.agent)) && !getCog(app.agent)) {
398
399
  missing('agent or Cog', app.agent);
399
400
  }
401
+ // An agent on a catalogue harness is served by the runtime's ACP adapter
402
+ // (SHIELD SH-10); `custom` and a harness that is none are refused, not run
403
+ // on pydantic-ai in their place (SH-01).
404
+ const agent = app.agent ? getAgentspecs(idOf(app.agent)) : undefined;
405
+ const unserved = agent ? unservedHarnessProblem(agent) : undefined;
406
+ if (unserved) {
407
+ problems.push(unserved);
408
+ }
400
409
  if (app.team && !getTeamSpec(idOf(app.team))) {
401
410
  missing('team', app.team);
402
411
  }
@@ -1,31 +1,3 @@
1
- /**
2
- * Agent runtime variants: where an agent's loop runs, and what runs it.
3
- *
4
- * There have always been two ways to start an agent — a local agent-runtimes
5
- * server and a cloud one — and they were named after the service each talked
6
- * to (`local-agent-runtimes`, `backend-services`). That naming held while both
7
- * ran the same framework. A browser agent breaks it: it talks to no service at
8
- * all, and it runs a different framework.
9
- *
10
- * So a variant names the two things that actually vary, in that order:
11
- *
12
- * <location>-<harness> browser-vercelai
13
- * local-pydanticai
14
- * cloud-pydanticai
15
- *
16
- * The point of splitting them is that most code cares about exactly one half.
17
- * Anything about *reaching* a runtime — a URL, a lifecycle, a sandbox — is a
18
- * question of location. Anything about *turning the loop* — the SDK, the tool
19
- * protocol, the streaming format — is a question of harness. Code that branches
20
- * on the whole variant string has to be edited every time either axis gains a
21
- * value; code that asks {@link locationOf} or {@link harnessOf} does not.
22
- *
23
- * That is what makes the next ones cheap. `cloud-ax` is a new harness against
24
- * an existing location, so only harness-specific code changes; `browser-ax` is
25
- * a combination of two things that already exist.
26
- *
27
- * @module runtimes/variants
28
- */
29
1
  import type { Agentspec } from '../types/agentspecs';
30
2
  /** Where the agent's loop runs. */
31
3
  export type AgentLocation = 'browser' | 'local' | 'cloud';
@@ -58,6 +30,27 @@ export declare const DEFAULT_AGENT_RUNTIME_VARIANT: AgentRuntimeVariant;
58
30
  export declare const SPEC_HARNESS_BY_HARNESS: Record<AgentHarness, string>;
59
31
  /** The reverse, for reading an agentspec's declared harness. */
60
32
  export declare const HARNESS_BY_SPEC_HARNESS: Record<string, AgentHarness>;
33
+ /** The one catalogue harness whose command an organization's own spec supplies. */
34
+ export declare const CUSTOM_HARNESS = "custom";
35
+ /**
36
+ * Why no variant runs an agent on this harness, in a sentence, or undefined
37
+ * when one does.
38
+ *
39
+ * A harness of the catalogue (`agentspecs/harnesses`, SHIELD.md SH-01) — Claude
40
+ * Code, Codex, Gemini CLI, goose, OpenCode, OpenHands, fast-agent — is served
41
+ * by the Datalayer runtime through its ACP adapter (`ACPAgent`, SHIELD SH-10):
42
+ * the runtime launches the harness as its subprocess, so the runtime's
43
+ * locations run it and the browser, which has no process to launch, does not.
44
+ * Two are refused: `custom`, which names no command in the shared catalogue
45
+ * (an organization's own harness spec names it), and a harness neither built
46
+ * in nor of the catalogue. Nothing runs such an agent in its place.
47
+ */
48
+ export declare function unservedHarnessProblem(spec: Pick<Agentspec, 'id' | 'harness'>): string | undefined;
49
+ /**
50
+ * Whether a harness id names a harness the Datalayer runtime serves through
51
+ * its ACP adapter: one of the catalogue, launchable, so not `custom`.
52
+ */
53
+ export declare function isServedCatalogueHarness(harness: string): boolean;
61
54
  /**
62
55
  * The names the two original ways to start an agent went by.
63
56
  *
@@ -113,7 +106,7 @@ export declare function variantForLocation(location: AgentLocation): AgentRuntim
113
106
  * An agentspec says which framework it *prefers* — `harness:` is where the
114
107
  * agent normally runs, not a demand — and a variant says which framework a
115
108
  * location can actually provide. Where they disagree the location wins, which
116
- * is why the browser accepts any spec:
109
+ * is why the browser accepts any spec built for a framework:
117
110
  *
118
111
  * harness: pydantic-ai + browser → runs, with the Vercel AI SDK
119
112
  *
@@ -125,15 +118,22 @@ export declare function variantForLocation(location: AgentLocation): AgentRuntim
125
118
  * The remote locations are stricter: a spec built for the browser harness
126
119
  * assumes frontend tools and no server, so running it on a runtime would be
127
120
  * running something else.
121
+ *
122
+ * A harness of the catalogue (Claude Code, Codex, …) is a program, not a
123
+ * framework: the Datalayer runtime launches it as its subprocess and serves it
124
+ * through its ACP adapter (SHIELD SH-10), so the runtime's locations run it
125
+ * and the browser does not — the page has no process to launch, and nothing
126
+ * is run in the harness's place.
128
127
  */
129
128
  export declare function variantSupportsSpecHarness(variant: AgentRuntimeVariant, specHarness: string | undefined | null): boolean;
130
129
  /**
131
130
  * The variants that could run an agent with this declared harness.
132
131
  *
133
132
  * What a host offers a person choosing where to run something. The browser is
134
- * always among them — it can run anything, because it overrides the harness —
135
- * while an agent built for the browser is not offered a remote runtime that
136
- * would be running something else.
133
+ * among them for any framework — it can run those, because it overrides the
134
+ * harness — while an agent built for the browser is not offered a remote
135
+ * runtime that would be running something else, and an agent on a catalogue
136
+ * harness is offered the runtimes alone, which launch it.
137
137
  */
138
138
  export declare function variantsForSpecHarness(specHarness: string | undefined | null): AgentRuntimeVariant[];
139
139
  /**
@@ -147,19 +147,24 @@ export declare function variantsForSpecHarness(specHarness: string | undefined |
147
147
  */
148
148
  export declare function legacyTargetOf(variant: AgentRuntimeVariant): RuntimeCreationTarget;
149
149
  /**
150
- * The harness a spec asks for, in the variant spelling.
150
+ * The harness a spec asks for: a framework in the variant spelling
151
+ * (`pydanticai`, `vercelai`), or a catalogue harness by its id (`claude-code`).
151
152
  *
152
153
  * Defaulted rather than optional: every agent is run by something, and a spec
153
154
  * that says nothing is run by the framework that has always run it. That
154
- * default is what lets every spec written before this field stay correct.
155
+ * default is what lets every spec written before this field stay correct. A
156
+ * catalogue harness keeps its own id, because no variant spells it: the
157
+ * variant that serves it is the Datalayer runtime's, whose own loop is
158
+ * pydantic-ai's and whose ACP adapter turns the harness's.
155
159
  */
156
- export declare function specHarnessOf(spec: Pick<Agentspec, 'harness'>): AgentHarness;
160
+ export declare function specHarnessOf(spec: Pick<Agentspec, 'id' | 'harness'>): string;
157
161
  /**
158
162
  * The variants that could run this agent.
159
163
  *
160
164
  * What a host offers when someone picks where to run something: an agent built
161
165
  * for the browser harness should not be offered a cloud runtime that cannot
162
- * turn its loop, and a server-side agent should not be offered the page.
166
+ * turn its loop, a server-side agent should not be offered the page, and an
167
+ * agent on a catalogue harness is offered the runtimes that launch it.
163
168
  */
164
169
  export declare function variantsForSpec(spec: Pick<Agentspec, 'harness'>): AgentRuntimeVariant[];
165
170
  /**
@@ -169,4 +174,4 @@ export declare function variantsForSpec(spec: Pick<Agentspec, 'harness'>): Agent
169
174
  * variant that can run it at all — so a `harness: vercel-ai` agent lands in
170
175
  * the browser without every caller having to know that is where it belongs.
171
176
  */
172
- export declare function defaultVariantForSpec(spec: Pick<Agentspec, 'harness'>): AgentRuntimeVariant;
177
+ export declare function defaultVariantForSpec(spec: Pick<Agentspec, 'id' | 'harness'>): AgentRuntimeVariant;
@@ -2,6 +2,40 @@
2
2
  * Copyright (c) 2025-2026 Datalayer, Inc.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
+ /*
6
+ * Copyright (c) 2023-2026 Datalayer, Inc.
7
+ *
8
+ * MIT License
9
+ */
10
+ /**
11
+ * Agent runtime variants: where an agent's loop runs, and what runs it.
12
+ *
13
+ * There have always been two ways to start an agent — a local agent-runtimes
14
+ * server and a cloud one — and they were named after the service each talked
15
+ * to (`local-agent-runtimes`, `backend-services`). That naming held while both
16
+ * ran the same framework. A browser agent breaks it: it talks to no service at
17
+ * all, and it runs a different framework.
18
+ *
19
+ * So a variant names the two things that actually vary, in that order:
20
+ *
21
+ * <location>-<harness> browser-vercelai
22
+ * local-pydanticai
23
+ * cloud-pydanticai
24
+ *
25
+ * The point of splitting them is that most code cares about exactly one half.
26
+ * Anything about *reaching* a runtime — a URL, a lifecycle, a sandbox — is a
27
+ * question of location. Anything about *turning the loop* — the SDK, the tool
28
+ * protocol, the streaming format — is a question of harness. Code that branches
29
+ * on the whole variant string has to be edited every time either axis gains a
30
+ * value; code that asks {@link locationOf} or {@link harnessOf} does not.
31
+ *
32
+ * That is what makes the next ones cheap. `cloud-ax` is a new harness against
33
+ * an existing location, so only harness-specific code changes; `browser-ax` is
34
+ * a combination of two things that already exist.
35
+ *
36
+ * @module runtimes/variants
37
+ */
38
+ import { getHarness } from '../specs/harnesses';
5
39
  /**
6
40
  * The combinations that exist today.
7
41
  *
@@ -32,6 +66,44 @@ export const HARNESS_BY_SPEC_HARNESS = {
32
66
  'pydantic-ai': 'pydanticai',
33
67
  'vercel-ai': 'vercelai',
34
68
  };
69
+ /** The one catalogue harness whose command an organization's own spec supplies. */
70
+ export const CUSTOM_HARNESS = 'custom';
71
+ /**
72
+ * Why no variant runs an agent on this harness, in a sentence, or undefined
73
+ * when one does.
74
+ *
75
+ * A harness of the catalogue (`agentspecs/harnesses`, SHIELD.md SH-01) — Claude
76
+ * Code, Codex, Gemini CLI, goose, OpenCode, OpenHands, fast-agent — is served
77
+ * by the Datalayer runtime through its ACP adapter (`ACPAgent`, SHIELD SH-10):
78
+ * the runtime launches the harness as its subprocess, so the runtime's
79
+ * locations run it and the browser, which has no process to launch, does not.
80
+ * Two are refused: `custom`, which names no command in the shared catalogue
81
+ * (an organization's own harness spec names it), and a harness neither built
82
+ * in nor of the catalogue. Nothing runs such an agent in its place.
83
+ */
84
+ export function unservedHarnessProblem(spec) {
85
+ const harness = spec.harness ?? '';
86
+ if (!harness || harness in HARNESS_BY_SPEC_HARNESS) {
87
+ return undefined;
88
+ }
89
+ const catalogued = getHarness(harness);
90
+ if (!catalogued) {
91
+ return `The agent “${spec.id}” runs on “${harness}”, which is no harness.`;
92
+ }
93
+ if (harness === CUSTOM_HARNESS) {
94
+ return `The agent “${spec.id}” runs on the harness “custom”, which names no command: an organization's own harness spec names it, and is never typed into a form.`;
95
+ }
96
+ return undefined;
97
+ }
98
+ /**
99
+ * Whether a harness id names a harness the Datalayer runtime serves through
100
+ * its ACP adapter: one of the catalogue, launchable, so not `custom`.
101
+ */
102
+ export function isServedCatalogueHarness(harness) {
103
+ return (harness !== CUSTOM_HARNESS &&
104
+ !(harness in HARNESS_BY_SPEC_HARNESS) &&
105
+ getHarness(harness) !== undefined);
106
+ }
35
107
  const VARIANT_BY_LEGACY_TARGET = {
36
108
  'backend-services': 'cloud-pydanticai',
37
109
  'local-agent-runtimes': 'local-pydanticai',
@@ -104,7 +176,7 @@ export function variantForLocation(location) {
104
176
  * An agentspec says which framework it *prefers* — `harness:` is where the
105
177
  * agent normally runs, not a demand — and a variant says which framework a
106
178
  * location can actually provide. Where they disagree the location wins, which
107
- * is why the browser accepts any spec:
179
+ * is why the browser accepts any spec built for a framework:
108
180
  *
109
181
  * harness: pydantic-ai + browser → runs, with the Vercel AI SDK
110
182
  *
@@ -116,8 +188,19 @@ export function variantForLocation(location) {
116
188
  * The remote locations are stricter: a spec built for the browser harness
117
189
  * assumes frontend tools and no server, so running it on a runtime would be
118
190
  * running something else.
191
+ *
192
+ * A harness of the catalogue (Claude Code, Codex, …) is a program, not a
193
+ * framework: the Datalayer runtime launches it as its subprocess and serves it
194
+ * through its ACP adapter (SHIELD SH-10), so the runtime's locations run it
195
+ * and the browser does not — the page has no process to launch, and nothing
196
+ * is run in the harness's place.
119
197
  */
120
198
  export function variantSupportsSpecHarness(variant, specHarness) {
199
+ if (specHarness && !(specHarness in HARNESS_BY_SPEC_HARNESS)) {
200
+ // A catalogue harness runs where a runtime can launch it; `custom` and a
201
+ // harness that is none run nowhere.
202
+ return (isServedCatalogueHarness(specHarness) && needsRuntimeService(variant));
203
+ }
121
204
  if (runsInBrowser(variant)) {
122
205
  return true;
123
206
  }
@@ -131,9 +214,10 @@ export function variantSupportsSpecHarness(variant, specHarness) {
131
214
  * The variants that could run an agent with this declared harness.
132
215
  *
133
216
  * What a host offers a person choosing where to run something. The browser is
134
- * always among them — it can run anything, because it overrides the harness —
135
- * while an agent built for the browser is not offered a remote runtime that
136
- * would be running something else.
217
+ * among them for any framework — it can run those, because it overrides the
218
+ * harness — while an agent built for the browser is not offered a remote
219
+ * runtime that would be running something else, and an agent on a catalogue
220
+ * harness is offered the runtimes alone, which launch it.
137
221
  */
138
222
  export function variantsForSpecHarness(specHarness) {
139
223
  return AGENT_RUNTIME_VARIANTS.filter(variant => variantSupportsSpecHarness(variant, specHarness));
@@ -153,21 +237,32 @@ export function legacyTargetOf(variant) {
153
237
  : 'local-agent-runtimes';
154
238
  }
155
239
  /**
156
- * The harness a spec asks for, in the variant spelling.
240
+ * The harness a spec asks for: a framework in the variant spelling
241
+ * (`pydanticai`, `vercelai`), or a catalogue harness by its id (`claude-code`).
157
242
  *
158
243
  * Defaulted rather than optional: every agent is run by something, and a spec
159
244
  * that says nothing is run by the framework that has always run it. That
160
- * default is what lets every spec written before this field stay correct.
245
+ * default is what lets every spec written before this field stay correct. A
246
+ * catalogue harness keeps its own id, because no variant spells it: the
247
+ * variant that serves it is the Datalayer runtime's, whose own loop is
248
+ * pydantic-ai's and whose ACP adapter turns the harness's.
161
249
  */
162
250
  export function specHarnessOf(spec) {
163
- return HARNESS_BY_SPEC_HARNESS[spec.harness ?? ''] ?? 'pydanticai';
251
+ const problem = unservedHarnessProblem(spec);
252
+ if (problem) {
253
+ // Never pydantic-ai in its place: said, and refused (SHIELD SH-01).
254
+ throw new Error(problem);
255
+ }
256
+ const harness = spec.harness ?? '';
257
+ return HARNESS_BY_SPEC_HARNESS[harness] ?? (harness || 'pydanticai');
164
258
  }
165
259
  /**
166
260
  * The variants that could run this agent.
167
261
  *
168
262
  * What a host offers when someone picks where to run something: an agent built
169
263
  * for the browser harness should not be offered a cloud runtime that cannot
170
- * turn its loop, and a server-side agent should not be offered the page.
264
+ * turn its loop, a server-side agent should not be offered the page, and an
265
+ * agent on a catalogue harness is offered the runtimes that launch it.
171
266
  */
172
267
  export function variantsForSpec(spec) {
173
268
  return variantsForSpecHarness(spec.harness);
@@ -183,5 +278,10 @@ export function defaultVariantForSpec(spec) {
183
278
  if (variantSupportsSpecHarness(DEFAULT_AGENT_RUNTIME_VARIANT, spec.harness)) {
184
279
  return DEFAULT_AGENT_RUNTIME_VARIANT;
185
280
  }
186
- return variantsForSpec(spec)[0] ?? DEFAULT_AGENT_RUNTIME_VARIANT;
281
+ const [first] = variantsForSpec(spec);
282
+ if (!first) {
283
+ throw new Error(unservedHarnessProblem(spec) ??
284
+ `No variant runs the agent “${spec.id}” on “${spec.harness}”.`);
285
+ }
286
+ return first;
187
287
  }
@@ -8,13 +8,17 @@
8
8
  */
9
9
  import type { EnvvarSpec } from '../types';
10
10
  export declare const ALPHAVANTAGE_API_KEY_SPEC_0_0_1: EnvvarSpec;
11
+ export declare const ANTHROPIC_API_KEY_SPEC_0_0_1: EnvvarSpec;
11
12
  export declare const EARTHDATA_PASSWORD_SPEC_0_0_1: EnvvarSpec;
12
13
  export declare const EARTHDATA_USERNAME_SPEC_0_0_1: EnvvarSpec;
14
+ export declare const GEMINI_API_KEY_SPEC_0_0_1: EnvvarSpec;
13
15
  export declare const GITHUB_TOKEN_SPEC_0_0_1: EnvvarSpec;
14
16
  export declare const GOOGLE_OAUTH_CLIENT_ID_SPEC_0_0_1: EnvvarSpec;
15
17
  export declare const GOOGLE_OAUTH_CLIENT_SECRET_SPEC_0_0_1: EnvvarSpec;
16
18
  export declare const HF_TOKEN_SPEC_0_0_1: EnvvarSpec;
17
19
  export declare const KAGGLE_API_TOKEN_SPEC_0_0_1: EnvvarSpec;
20
+ export declare const LLM_API_KEY_SPEC_0_0_1: EnvvarSpec;
21
+ export declare const OPENAI_API_KEY_SPEC_0_0_1: EnvvarSpec;
18
22
  export declare const SLACK_BOT_TOKEN_SPEC_0_0_1: EnvvarSpec;
19
23
  export declare const SLACK_CHANNEL_IDS_SPEC_0_0_1: EnvvarSpec;
20
24
  export declare const SLACK_TEAM_ID_SPEC_0_0_1: EnvvarSpec;
@@ -15,6 +15,16 @@ export const ALPHAVANTAGE_API_KEY_SPEC_0_0_1 = {
15
15
  icon: 'key',
16
16
  emoji: '🔑',
17
17
  };
18
+ export const ANTHROPIC_API_KEY_SPEC_0_0_1 = {
19
+ id: 'ANTHROPIC_API_KEY',
20
+ version: '0.0.1',
21
+ name: 'Anthropic API Key',
22
+ description: "API key for Anthropic's Claude API. Required by the Claude Code harness, and by any harness configured with Anthropic as its model provider; the person's own, never a Claude.ai subscription login.",
23
+ registrationUrl: 'https://platform.claude.com/settings/keys',
24
+ tags: ['authentication', 'api-key', 'anthropic', 'harness'],
25
+ icon: 'key',
26
+ emoji: '🔑',
27
+ };
18
28
  export const EARTHDATA_PASSWORD_SPEC_0_0_1 = {
19
29
  id: 'EARTHDATA_PASSWORD',
20
30
  version: '0.0.1',
@@ -35,6 +45,16 @@ export const EARTHDATA_USERNAME_SPEC_0_0_1 = {
35
45
  icon: 'key',
36
46
  emoji: '🔑',
37
47
  };
48
+ export const GEMINI_API_KEY_SPEC_0_0_1 = {
49
+ id: 'GEMINI_API_KEY',
50
+ version: '0.0.1',
51
+ name: 'Gemini API Key',
52
+ description: "API key for Google's Gemini API. Required by the Gemini CLI harness in place of a Google login; the person's own.",
53
+ registrationUrl: 'https://aistudio.google.com/apikey',
54
+ tags: ['authentication', 'api-key', 'google', 'harness'],
55
+ icon: 'key',
56
+ emoji: '🔑',
57
+ };
38
58
  export const GITHUB_TOKEN_SPEC_0_0_1 = {
39
59
  id: 'GITHUB_TOKEN',
40
60
  version: '0.0.1',
@@ -92,6 +112,26 @@ export const KAGGLE_API_TOKEN_SPEC_0_0_1 = {
92
112
  icon: 'key',
93
113
  emoji: '🔑',
94
114
  };
115
+ export const LLM_API_KEY_SPEC_0_0_1 = {
116
+ id: 'LLM_API_KEY',
117
+ version: '0.0.1',
118
+ name: 'OpenHands LLM API Key',
119
+ description: "The model provider's key the OpenHands CLI reads, with LLM_MODEL, when started with --override-with-envs. Required by the OpenHands harness; the person's own key at their provider.",
120
+ registrationUrl: 'https://docs.openhands.dev/openhands/usage/cli/installation',
121
+ tags: ['authentication', 'api-key', 'openhands', 'harness'],
122
+ icon: 'key',
123
+ emoji: '🔑',
124
+ };
125
+ export const OPENAI_API_KEY_SPEC_0_0_1 = {
126
+ id: 'OPENAI_API_KEY',
127
+ version: '0.0.1',
128
+ name: 'OpenAI API Key',
129
+ description: "API key for OpenAI's API. Required by the Codex harness, which takes it in place of a ChatGPT login; the person's own.",
130
+ registrationUrl: 'https://platform.openai.com/api-keys',
131
+ tags: ['authentication', 'api-key', 'openai', 'harness'],
132
+ icon: 'key',
133
+ emoji: '🔑',
134
+ };
95
135
  export const SLACK_BOT_TOKEN_SPEC_0_0_1 = {
96
136
  id: 'SLACK_BOT_TOKEN',
97
137
  version: '0.0.1',
@@ -136,13 +176,17 @@ export const TAVILY_API_KEY_SPEC_0_0_1 = {
136
176
  // ============================================================================
137
177
  export const ENVVAR_CATALOG = {
138
178
  ALPHAVANTAGE_API_KEY: ALPHAVANTAGE_API_KEY_SPEC_0_0_1,
179
+ ANTHROPIC_API_KEY: ANTHROPIC_API_KEY_SPEC_0_0_1,
139
180
  EARTHDATA_PASSWORD: EARTHDATA_PASSWORD_SPEC_0_0_1,
140
181
  EARTHDATA_USERNAME: EARTHDATA_USERNAME_SPEC_0_0_1,
182
+ GEMINI_API_KEY: GEMINI_API_KEY_SPEC_0_0_1,
141
183
  GITHUB_TOKEN: GITHUB_TOKEN_SPEC_0_0_1,
142
184
  GOOGLE_OAUTH_CLIENT_ID: GOOGLE_OAUTH_CLIENT_ID_SPEC_0_0_1,
143
185
  GOOGLE_OAUTH_CLIENT_SECRET: GOOGLE_OAUTH_CLIENT_SECRET_SPEC_0_0_1,
144
186
  HF_TOKEN: HF_TOKEN_SPEC_0_0_1,
145
187
  KAGGLE_API_TOKEN: KAGGLE_API_TOKEN_SPEC_0_0_1,
188
+ LLM_API_KEY: LLM_API_KEY_SPEC_0_0_1,
189
+ OPENAI_API_KEY: OPENAI_API_KEY_SPEC_0_0_1,
146
190
  SLACK_BOT_TOKEN: SLACK_BOT_TOKEN_SPEC_0_0_1,
147
191
  SLACK_CHANNEL_IDS: SLACK_CHANNEL_IDS_SPEC_0_0_1,
148
192
  SLACK_TEAM_ID: SLACK_TEAM_ID_SPEC_0_0_1,
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Harness Catalog.
3
+ *
4
+ * An agent program driven over the Agent Client Protocol (SHIELD.md SH-01).
5
+ *
6
+ * This file is AUTO-GENERATED from YAML specifications.
7
+ * DO NOT EDIT MANUALLY - run 'make specs' to regenerate.
8
+ */
9
+ import type { HarnessSpec } from '../types/agentspecs';
10
+ export declare const CLAUDE_CODE_HARNESS_0_0_1: HarnessSpec;
11
+ export declare const CODEX_HARNESS_0_0_1: HarnessSpec;
12
+ export declare const CUSTOM_HARNESS_0_0_1: HarnessSpec;
13
+ export declare const FAST_AGENT_HARNESS_0_0_1: HarnessSpec;
14
+ export declare const GEMINI_CLI_HARNESS_0_0_1: HarnessSpec;
15
+ export declare const GOOSE_HARNESS_0_0_1: HarnessSpec;
16
+ export declare const OPENCODE_HARNESS_0_0_1: HarnessSpec;
17
+ export declare const OPENHANDS_HARNESS_0_0_1: HarnessSpec;
18
+ export declare const HARNESS_CATALOGUE: Record<string, HarnessSpec>;
19
+ /** A harness by id. */
20
+ export declare function getHarness(harnessId: string): HarnessSpec | undefined;
21
+ /** Every harness of the catalogue. */
22
+ export declare function listHarnesses(): HarnessSpec[];