@zenera/neo 1.1.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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +178 -0
  3. package/dist/agent.d.ts +66 -0
  4. package/dist/agent.js +97 -0
  5. package/dist/architecture.d.ts +74 -0
  6. package/dist/architecture.js +105 -0
  7. package/dist/embedding.d.ts +60 -0
  8. package/dist/embedding.js +21 -0
  9. package/dist/embeddings/gemini.d.ts +24 -0
  10. package/dist/embeddings/gemini.js +71 -0
  11. package/dist/embeddings/index.d.ts +4 -0
  12. package/dist/embeddings/index.js +4 -0
  13. package/dist/embeddings/openai.d.ts +18 -0
  14. package/dist/embeddings/openai.js +27 -0
  15. package/dist/embeddings/openrouter.d.ts +21 -0
  16. package/dist/embeddings/openrouter.js +54 -0
  17. package/dist/events.d.ts +144 -0
  18. package/dist/events.js +110 -0
  19. package/dist/ids.d.ts +14 -0
  20. package/dist/ids.js +33 -0
  21. package/dist/index.d.ts +25 -0
  22. package/dist/index.js +25 -0
  23. package/dist/inspect/client.d.ts +2 -0
  24. package/dist/inspect/client.js +1326 -0
  25. package/dist/inspect/css.d.ts +2 -0
  26. package/dist/inspect/css.js +164 -0
  27. package/dist/inspect/index.d.ts +9 -0
  28. package/dist/inspect/index.js +12 -0
  29. package/dist/inspect/page.d.ts +3 -0
  30. package/dist/inspect/page.js +93 -0
  31. package/dist/inspect/report.d.ts +54 -0
  32. package/dist/inspect/report.js +62 -0
  33. package/dist/kernel.d.ts +178 -0
  34. package/dist/kernel.js +929 -0
  35. package/dist/memory-stores/factory.d.ts +15 -0
  36. package/dist/memory-stores/factory.js +29 -0
  37. package/dist/memory-stores/file.d.ts +37 -0
  38. package/dist/memory-stores/file.js +174 -0
  39. package/dist/memory-stores/in-memory.d.ts +17 -0
  40. package/dist/memory-stores/in-memory.js +80 -0
  41. package/dist/memory-stores/index.d.ts +4 -0
  42. package/dist/memory-stores/index.js +5 -0
  43. package/dist/memory.d.ts +115 -0
  44. package/dist/memory.js +213 -0
  45. package/dist/model.d.ts +25 -0
  46. package/dist/model.js +2 -0
  47. package/dist/models/anthropic.d.ts +36 -0
  48. package/dist/models/anthropic.js +293 -0
  49. package/dist/models/factory.d.ts +202 -0
  50. package/dist/models/factory.js +533 -0
  51. package/dist/models/gemini.d.ts +45 -0
  52. package/dist/models/gemini.js +368 -0
  53. package/dist/models/index.d.ts +7 -0
  54. package/dist/models/index.js +7 -0
  55. package/dist/models/openai-chat.d.ts +19 -0
  56. package/dist/models/openai-chat.js +203 -0
  57. package/dist/models/openai-responses.d.ts +31 -0
  58. package/dist/models/openai-responses.js +258 -0
  59. package/dist/models/openrouter.d.ts +44 -0
  60. package/dist/models/openrouter.js +230 -0
  61. package/dist/payload-stores/factory.d.ts +15 -0
  62. package/dist/payload-stores/factory.js +30 -0
  63. package/dist/payload-stores/file.d.ts +29 -0
  64. package/dist/payload-stores/file.js +112 -0
  65. package/dist/payload-stores/in-memory.d.ts +17 -0
  66. package/dist/payload-stores/in-memory.js +40 -0
  67. package/dist/payload-stores/index.d.ts +4 -0
  68. package/dist/payload-stores/index.js +5 -0
  69. package/dist/payload.d.ts +89 -0
  70. package/dist/payload.js +181 -0
  71. package/dist/project/config.d.ts +302 -0
  72. package/dist/project/config.js +290 -0
  73. package/dist/project/index.d.ts +4 -0
  74. package/dist/project/index.js +4 -0
  75. package/dist/project/load.d.ts +142 -0
  76. package/dist/project/load.js +430 -0
  77. package/dist/project/refs.d.ts +23 -0
  78. package/dist/project/refs.js +70 -0
  79. package/dist/prompt.d.ts +66 -0
  80. package/dist/prompt.js +62 -0
  81. package/dist/runner.d.ts +103 -0
  82. package/dist/runner.js +537 -0
  83. package/dist/services.d.ts +23 -0
  84. package/dist/services.js +44 -0
  85. package/dist/skill-providers/factory.d.ts +16 -0
  86. package/dist/skill-providers/factory.js +26 -0
  87. package/dist/skill-providers/file.d.ts +44 -0
  88. package/dist/skill-providers/file.js +209 -0
  89. package/dist/skill-providers/index.d.ts +4 -0
  90. package/dist/skill-providers/index.js +5 -0
  91. package/dist/skill-providers/static.d.ts +13 -0
  92. package/dist/skill-providers/static.js +47 -0
  93. package/dist/skills.d.ts +102 -0
  94. package/dist/skills.js +232 -0
  95. package/dist/state.d.ts +86 -0
  96. package/dist/state.js +49 -0
  97. package/dist/tools/exa.d.ts +23 -0
  98. package/dist/tools/exa.js +389 -0
  99. package/dist/tools/index.d.ts +4 -0
  100. package/dist/tools/index.js +6 -0
  101. package/dist/tools/sandbox.d.ts +172 -0
  102. package/dist/tools/sandbox.js +602 -0
  103. package/dist/tools/workspace.d.ts +53 -0
  104. package/dist/tools/workspace.js +1034 -0
  105. package/dist/trajectory.d.ts +213 -0
  106. package/dist/trajectory.js +232 -0
  107. package/dist/types.d.ts +195 -0
  108. package/dist/types.js +134 -0
  109. package/package.json +98 -0
@@ -0,0 +1,302 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * A named connection. Splitting this out of the model is what lets one project
4
+ * hold two keys for the same vendor: the key is declared once, under a name,
5
+ * and models point at the name.
6
+ */
7
+ declare const provider: z.ZodObject<{
8
+ kind: z.ZodOptional<z.ZodEnum<{
9
+ openai: "openai";
10
+ google: "google";
11
+ vertex: "vertex";
12
+ anthropic: "anthropic";
13
+ openrouter: "openrouter";
14
+ "openai-compatible": "openai-compatible";
15
+ }>>;
16
+ project: z.ZodOptional<z.ZodString>;
17
+ location: z.ZodOptional<z.ZodString>;
18
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
19
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
20
+ maxRetries: z.ZodOptional<z.ZodInt>;
21
+ apiKey: z.ZodOptional<z.ZodString>;
22
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
23
+ baseURL: z.ZodOptional<z.ZodString>;
24
+ baseURLEnv: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strict>;
26
+ /**
27
+ * `reasoningEffort` is a plain string rather than an enum on purpose: the
28
+ * vendor's accepted set changes faster than this file would, and the request
29
+ * that carries a bad value is the authority on rejecting it. An enum here would
30
+ * mean a config that the API accepts failing to load.
31
+ */
32
+ declare const modelSpec: z.ZodObject<{
33
+ provider: z.ZodOptional<z.ZodString>;
34
+ api: z.ZodOptional<z.ZodEnum<{
35
+ chat: "chat";
36
+ responses: "responses";
37
+ }>>;
38
+ model: z.ZodString;
39
+ reasoningEffort: z.ZodOptional<z.ZodString>;
40
+ reasoningSummary: z.ZodOptional<z.ZodEnum<{
41
+ auto: "auto";
42
+ concise: "concise";
43
+ detailed: "detailed";
44
+ }>>;
45
+ store: z.ZodOptional<z.ZodBoolean>;
46
+ maxTokens: z.ZodOptional<z.ZodInt>;
47
+ thinkingBudgetTokens: z.ZodOptional<z.ZodInt>;
48
+ thinkingBudget: z.ZodOptional<z.ZodInt>;
49
+ thinkingLevel: z.ZodOptional<z.ZodEnum<{
50
+ low: "low";
51
+ medium: "medium";
52
+ high: "high";
53
+ minimal: "minimal";
54
+ }>>;
55
+ includeThoughts: z.ZodOptional<z.ZodBoolean>;
56
+ routing: z.ZodOptional<z.ZodObject<{
57
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
58
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
59
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
+ sort: z.ZodOptional<z.ZodString>;
61
+ allowFallbacks: z.ZodOptional<z.ZodBoolean>;
62
+ requireParameters: z.ZodOptional<z.ZodBoolean>;
63
+ dataCollection: z.ZodOptional<z.ZodEnum<{
64
+ allow: "allow";
65
+ deny: "deny";
66
+ }>>;
67
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodString>>;
68
+ zdr: z.ZodOptional<z.ZodBoolean>;
69
+ }, z.core.$strict>>;
70
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
71
+ serviceTier: z.ZodOptional<z.ZodEnum<{
72
+ default: "default";
73
+ auto: "auto";
74
+ fast: "fast";
75
+ flex: "flex";
76
+ priority: "priority";
77
+ scale: "scale";
78
+ }>>;
79
+ apiKey: z.ZodOptional<z.ZodString>;
80
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
81
+ baseURL: z.ZodOptional<z.ZodString>;
82
+ baseURLEnv: z.ZodOptional<z.ZodString>;
83
+ }, z.core.$strict>;
84
+ /**
85
+ * A vectoriser. Deliberately much smaller than `modelSpec`: an embedding call
86
+ * has no conversation, no tools and no reasoning, so a connection, an id and a
87
+ * width is all there is to say. `taskType` is absent because it describes the
88
+ * *text*, not the model, and so belongs to the call.
89
+ */
90
+ declare const embeddingSpec: z.ZodObject<{
91
+ provider: z.ZodOptional<z.ZodString>;
92
+ model: z.ZodString;
93
+ dimensions: z.ZodOptional<z.ZodInt>;
94
+ title: z.ZodOptional<z.ZodString>;
95
+ maxBatch: z.ZodOptional<z.ZodInt>;
96
+ routing: z.ZodOptional<z.ZodObject<{
97
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
98
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
99
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
100
+ sort: z.ZodOptional<z.ZodString>;
101
+ allowFallbacks: z.ZodOptional<z.ZodBoolean>;
102
+ requireParameters: z.ZodOptional<z.ZodBoolean>;
103
+ dataCollection: z.ZodOptional<z.ZodEnum<{
104
+ allow: "allow";
105
+ deny: "deny";
106
+ }>>;
107
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodString>>;
108
+ zdr: z.ZodOptional<z.ZodBoolean>;
109
+ }, z.core.$strict>>;
110
+ apiKey: z.ZodOptional<z.ZodString>;
111
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
112
+ baseURL: z.ZodOptional<z.ZodString>;
113
+ baseURLEnv: z.ZodOptional<z.ZodString>;
114
+ }, z.core.$strict>;
115
+ declare const sandbox: z.ZodObject<{
116
+ image: z.ZodOptional<z.ZodString>;
117
+ cpus: z.ZodOptional<z.ZodNumber>;
118
+ memory: z.ZodOptional<z.ZodInt>;
119
+ network: z.ZodOptional<z.ZodEnum<{
120
+ none: "none";
121
+ host: "host";
122
+ bridge: "bridge";
123
+ }>>;
124
+ workdir: z.ZodOptional<z.ZodString>;
125
+ timeout: z.ZodOptional<z.ZodInt>;
126
+ user: z.ZodOptional<z.ZodString>;
127
+ persist: z.ZodOptional<z.ZodBoolean>;
128
+ env: z.ZodOptional<z.ZodArray<z.ZodString>>;
129
+ }, z.core.$strict>;
130
+ export declare const projectSchema: z.ZodObject<{
131
+ version: z.ZodDefault<z.ZodLiteral<1>>;
132
+ default: z.ZodOptional<z.ZodString>;
133
+ providers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
134
+ kind: z.ZodOptional<z.ZodEnum<{
135
+ openai: "openai";
136
+ google: "google";
137
+ vertex: "vertex";
138
+ anthropic: "anthropic";
139
+ openrouter: "openrouter";
140
+ "openai-compatible": "openai-compatible";
141
+ }>>;
142
+ project: z.ZodOptional<z.ZodString>;
143
+ location: z.ZodOptional<z.ZodString>;
144
+ headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
145
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
146
+ maxRetries: z.ZodOptional<z.ZodInt>;
147
+ apiKey: z.ZodOptional<z.ZodString>;
148
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
149
+ baseURL: z.ZodOptional<z.ZodString>;
150
+ baseURLEnv: z.ZodOptional<z.ZodString>;
151
+ }, z.core.$strict>>>;
152
+ provider: z.ZodOptional<z.ZodString>;
153
+ models: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
154
+ provider: z.ZodOptional<z.ZodString>;
155
+ api: z.ZodOptional<z.ZodEnum<{
156
+ chat: "chat";
157
+ responses: "responses";
158
+ }>>;
159
+ model: z.ZodString;
160
+ reasoningEffort: z.ZodOptional<z.ZodString>;
161
+ reasoningSummary: z.ZodOptional<z.ZodEnum<{
162
+ auto: "auto";
163
+ concise: "concise";
164
+ detailed: "detailed";
165
+ }>>;
166
+ store: z.ZodOptional<z.ZodBoolean>;
167
+ maxTokens: z.ZodOptional<z.ZodInt>;
168
+ thinkingBudgetTokens: z.ZodOptional<z.ZodInt>;
169
+ thinkingBudget: z.ZodOptional<z.ZodInt>;
170
+ thinkingLevel: z.ZodOptional<z.ZodEnum<{
171
+ low: "low";
172
+ medium: "medium";
173
+ high: "high";
174
+ minimal: "minimal";
175
+ }>>;
176
+ includeThoughts: z.ZodOptional<z.ZodBoolean>;
177
+ routing: z.ZodOptional<z.ZodObject<{
178
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
179
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
180
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
181
+ sort: z.ZodOptional<z.ZodString>;
182
+ allowFallbacks: z.ZodOptional<z.ZodBoolean>;
183
+ requireParameters: z.ZodOptional<z.ZodBoolean>;
184
+ dataCollection: z.ZodOptional<z.ZodEnum<{
185
+ allow: "allow";
186
+ deny: "deny";
187
+ }>>;
188
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodString>>;
189
+ zdr: z.ZodOptional<z.ZodBoolean>;
190
+ }, z.core.$strict>>;
191
+ fallbacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
192
+ serviceTier: z.ZodOptional<z.ZodEnum<{
193
+ default: "default";
194
+ auto: "auto";
195
+ fast: "fast";
196
+ flex: "flex";
197
+ priority: "priority";
198
+ scale: "scale";
199
+ }>>;
200
+ apiKey: z.ZodOptional<z.ZodString>;
201
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
202
+ baseURL: z.ZodOptional<z.ZodString>;
203
+ baseURLEnv: z.ZodOptional<z.ZodString>;
204
+ }, z.core.$strict>]>>>;
205
+ model: z.ZodOptional<z.ZodString>;
206
+ embeddings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
207
+ provider: z.ZodOptional<z.ZodString>;
208
+ model: z.ZodString;
209
+ dimensions: z.ZodOptional<z.ZodInt>;
210
+ title: z.ZodOptional<z.ZodString>;
211
+ maxBatch: z.ZodOptional<z.ZodInt>;
212
+ routing: z.ZodOptional<z.ZodObject<{
213
+ order: z.ZodOptional<z.ZodArray<z.ZodString>>;
214
+ only: z.ZodOptional<z.ZodArray<z.ZodString>>;
215
+ ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
216
+ sort: z.ZodOptional<z.ZodString>;
217
+ allowFallbacks: z.ZodOptional<z.ZodBoolean>;
218
+ requireParameters: z.ZodOptional<z.ZodBoolean>;
219
+ dataCollection: z.ZodOptional<z.ZodEnum<{
220
+ allow: "allow";
221
+ deny: "deny";
222
+ }>>;
223
+ quantizations: z.ZodOptional<z.ZodArray<z.ZodString>>;
224
+ zdr: z.ZodOptional<z.ZodBoolean>;
225
+ }, z.core.$strict>>;
226
+ apiKey: z.ZodOptional<z.ZodString>;
227
+ apiKeyEnv: z.ZodOptional<z.ZodString>;
228
+ baseURL: z.ZodOptional<z.ZodString>;
229
+ baseURLEnv: z.ZodOptional<z.ZodString>;
230
+ }, z.core.$strict>]>>>;
231
+ embedding: z.ZodOptional<z.ZodString>;
232
+ skills: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
233
+ sandbox: z.ZodOptional<z.ZodObject<{
234
+ image: z.ZodOptional<z.ZodString>;
235
+ cpus: z.ZodOptional<z.ZodNumber>;
236
+ memory: z.ZodOptional<z.ZodInt>;
237
+ network: z.ZodOptional<z.ZodEnum<{
238
+ none: "none";
239
+ host: "host";
240
+ bridge: "bridge";
241
+ }>>;
242
+ workdir: z.ZodOptional<z.ZodString>;
243
+ timeout: z.ZodOptional<z.ZodInt>;
244
+ user: z.ZodOptional<z.ZodString>;
245
+ persist: z.ZodOptional<z.ZodBoolean>;
246
+ env: z.ZodOptional<z.ZodArray<z.ZodString>>;
247
+ }, z.core.$strict>>;
248
+ agents: z.ZodArray<z.ZodObject<{
249
+ name: z.ZodString;
250
+ description: z.ZodOptional<z.ZodString>;
251
+ system: z.ZodOptional<z.ZodString>;
252
+ model: z.ZodOptional<z.ZodString>;
253
+ tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
254
+ handoffs: z.ZodOptional<z.ZodArray<z.ZodString>>;
255
+ skills: z.ZodOptional<z.ZodObject<{
256
+ provider: z.ZodOptional<z.ZodString>;
257
+ discovery: z.ZodDefault<z.ZodEnum<{
258
+ search: "search";
259
+ none: "none";
260
+ index: "index";
261
+ }>>;
262
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
263
+ preload: z.ZodOptional<z.ZodArray<z.ZodString>>;
264
+ maxIndexEntries: z.ZodOptional<z.ZodInt>;
265
+ }, z.core.$strict>>;
266
+ fork: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
267
+ agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
268
+ maxBranches: z.ZodOptional<z.ZodInt>;
269
+ }, z.core.$strict>]>>;
270
+ sandbox: z.ZodOptional<z.ZodObject<{
271
+ image: z.ZodOptional<z.ZodString>;
272
+ cpus: z.ZodOptional<z.ZodNumber>;
273
+ memory: z.ZodOptional<z.ZodInt>;
274
+ network: z.ZodOptional<z.ZodEnum<{
275
+ none: "none";
276
+ host: "host";
277
+ bridge: "bridge";
278
+ }>>;
279
+ workdir: z.ZodOptional<z.ZodString>;
280
+ timeout: z.ZodOptional<z.ZodInt>;
281
+ user: z.ZodOptional<z.ZodString>;
282
+ persist: z.ZodOptional<z.ZodBoolean>;
283
+ env: z.ZodOptional<z.ZodArray<z.ZodString>>;
284
+ }, z.core.$strict>>;
285
+ default: z.ZodOptional<z.ZodBoolean>;
286
+ }, z.core.$strict>>;
287
+ }, z.core.$strict>;
288
+ export type ProjectConfig = z.infer<typeof projectSchema>;
289
+ export type AgentConfig = ProjectConfig['agents'][number];
290
+ export type ProviderConfig = z.infer<typeof provider>;
291
+ export type ModelConfig = z.infer<typeof modelSpec>;
292
+ export type EmbeddingConfig = z.infer<typeof embeddingSpec>;
293
+ export type SandboxConfig = z.infer<typeof sandbox>;
294
+ /**
295
+ * Re-renders a zod failure as `agents.yaml: agents[1].skills.discovery — …`.
296
+ *
297
+ * The default message is a JSON blob with the path in a nested array, which
298
+ * tells an author everything except the one thing they need: which line to fix.
299
+ */
300
+ export declare function parseConfig(text: string, source: string): ProjectConfig;
301
+ export {};
302
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,290 @@
1
+ import { parse as parseYaml } from 'yaml';
2
+ import { z } from 'zod';
3
+ // ---------------------------------------------------------------------------
4
+ // agents.yaml
5
+ // ---------------------------------------------------------------------------
6
+ // Names reach the model as part of `transfer_to_<name>` and reach the file
7
+ // system as skill directory names, so they are restricted to a shape that is
8
+ // unambiguous in both.
9
+ const NAME = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/;
10
+ const name = z
11
+ .string()
12
+ .regex(NAME, 'must be lower-case words separated by "-" or "_", e.g. "order-triage"');
13
+ /**
14
+ * A model reference is either the shorthand `ModelRegistry.parse` understands
15
+ * (`gpt-4o`, `openai/responses:o3`, `openai-eu:o3`) or a key into the
16
+ * project's `models:` map. Which one it is cannot be decided here — the loader
17
+ * resolves aliases first and falls through to the shorthand — so the schema
18
+ * only asks for a non-empty string.
19
+ */
20
+ const modelRef = z.string().min(1);
21
+ /**
22
+ * Credentials, shared by providers and by the one-off model that overrides
23
+ * them. Values may embed `${VAR}` references; the substitution happens in the
24
+ * registry, not here, so a config that is never used never demands a key.
25
+ */
26
+ const credentials = {
27
+ apiKey: z.string().min(1).optional(),
28
+ apiKeyEnv: z.string().min(1).optional(),
29
+ baseURL: z.string().min(1).optional(),
30
+ baseURLEnv: z.string().min(1).optional(),
31
+ };
32
+ /**
33
+ * A named connection. Splitting this out of the model is what lets one project
34
+ * hold two keys for the same vendor: the key is declared once, under a name,
35
+ * and models point at the name.
36
+ */
37
+ const provider = z
38
+ .object({
39
+ ...credentials,
40
+ kind: z
41
+ .enum(['openai', 'google', 'vertex', 'anthropic', 'openrouter', 'openai-compatible'])
42
+ .optional(),
43
+ /** vertex only: the GCP project and region the endpoint is addressed by */
44
+ project: z.string().min(1).optional(),
45
+ location: z.string().min(1).optional(),
46
+ headers: z.record(z.string().min(1), z.string()).optional(),
47
+ timeoutMs: z.number().positive().optional(),
48
+ maxRetries: z.int().nonnegative().optional(),
49
+ })
50
+ .strict();
51
+ /**
52
+ * openrouter only: which upstream provider serves a request.
53
+ *
54
+ * Named `routing` because `provider:` in this file already means the
55
+ * connection. `sort` and the provider names are plain strings for the same
56
+ * reason `reasoningEffort` is — OpenRouter adds providers continuously, and a
57
+ * config the API would accept should not fail to load here first.
58
+ */
59
+ const routing = z
60
+ .object({
61
+ /** providers to try, in order */
62
+ order: z.array(z.string().min(1)).min(1).optional(),
63
+ /** restricts serving to these, rather than merely preferring them */
64
+ only: z.array(z.string().min(1)).min(1).optional(),
65
+ ignore: z.array(z.string().min(1)).min(1).optional(),
66
+ /** `price`, `throughput`, `latency`, `exacto` */
67
+ sort: z.string().min(1).optional(),
68
+ /** may OpenRouter go beyond `order`; on by default */
69
+ allowFallbacks: z.boolean().optional(),
70
+ /** skip providers that would silently drop parameters they do not support */
71
+ requireParameters: z.boolean().optional(),
72
+ dataCollection: z.enum(['allow', 'deny']).optional(),
73
+ quantizations: z.array(z.string().min(1)).min(1).optional(),
74
+ /** zero-data-retention endpoints only */
75
+ zdr: z.boolean().optional(),
76
+ })
77
+ .strict();
78
+ /**
79
+ * `reasoningEffort` is a plain string rather than an enum on purpose: the
80
+ * vendor's accepted set changes faster than this file would, and the request
81
+ * that carries a bad value is the authority on rejecting it. An enum here would
82
+ * mean a config that the API accepts failing to load.
83
+ */
84
+ const modelSpec = z
85
+ .object({
86
+ ...credentials,
87
+ /** a name from `providers:`, or a built-in kind */
88
+ provider: z.string().min(1).optional(),
89
+ api: z.enum(['chat', 'responses']).optional(),
90
+ model: z.string().min(1),
91
+ reasoningEffort: z.string().min(1).optional(),
92
+ reasoningSummary: z.enum(['auto', 'concise', 'detailed']).optional(),
93
+ store: z.boolean().optional(),
94
+ /** anthropic only: the output cap its API requires, and the thinking budget */
95
+ maxTokens: z.int().positive().optional(),
96
+ thinkingBudgetTokens: z.int().positive().optional(),
97
+ /** gemini only: 2.5 takes a token budget, 3 takes a level */
98
+ thinkingBudget: z.int().optional(),
99
+ thinkingLevel: z.enum(['minimal', 'low', 'medium', 'high']).optional(),
100
+ includeThoughts: z.boolean().optional(),
101
+ /** openrouter only: who serves the request, what to try when they cannot */
102
+ routing: routing.optional(),
103
+ fallbacks: z.array(z.string().min(1)).min(1).optional(),
104
+ serviceTier: z.enum(['auto', 'default', 'fast', 'flex', 'priority', 'scale']).optional(),
105
+ })
106
+ .strict();
107
+ /**
108
+ * A vectoriser. Deliberately much smaller than `modelSpec`: an embedding call
109
+ * has no conversation, no tools and no reasoning, so a connection, an id and a
110
+ * width is all there is to say. `taskType` is absent because it describes the
111
+ * *text*, not the model, and so belongs to the call.
112
+ */
113
+ const embeddingSpec = z
114
+ .object({
115
+ ...credentials,
116
+ /** a name from `providers:`, or a built-in kind */
117
+ provider: z.string().min(1).optional(),
118
+ model: z.string().min(1),
119
+ /** truncate to this width, where the model supports it */
120
+ dimensions: z.int().positive().optional(),
121
+ /** gemini only: a document title the retrieval task type takes into account */
122
+ title: z.string().min(1).optional(),
123
+ /** gemini only: texts per request; every `gemini-embedding-*` model takes one */
124
+ maxBatch: z.int().positive().optional(),
125
+ /** openrouter only: who serves the request */
126
+ routing: routing.optional(),
127
+ })
128
+ .strict();
129
+ const skillsBinding = z
130
+ .object({
131
+ /** provider id; defaults to the project's sole provider */
132
+ provider: z.string().min(1).optional(),
133
+ discovery: z.enum(['index', 'search', 'none']).default('index'),
134
+ /** restricts the catalog this agent sees; absent means all of it */
135
+ allow: z.array(name).optional(),
136
+ /** activated before the first call of every turn this agent owns */
137
+ preload: z.array(name).optional(),
138
+ maxIndexEntries: z.int().positive().optional(),
139
+ })
140
+ .strict();
141
+ /**
142
+ * Opt-in to parallel sub-agents. The kernel gates the `fork` tool on the
143
+ * binding *existing*, not on what it holds, so `true` and `{}` say the same
144
+ * thing and there is nothing here to default — an agent that does not mention
145
+ * `fork:` is never offered the tool.
146
+ *
147
+ * Both limits are stated as errors rather than as values that get clamped
148
+ * later: `maxBranches: 1` would make every call the model could write fail, and
149
+ * `agents: []` reads as "no agents" while actually meaning "only itself".
150
+ */
151
+ const forkBinding = z
152
+ .object({
153
+ /** agents a branch may run; absent means any registered agent */
154
+ agents: z.array(name).min(1).optional(),
155
+ /** a fork is never valid with one branch, so a cap below two is a contradiction */
156
+ maxBranches: z.int().min(2).optional(),
157
+ })
158
+ .strict();
159
+ /**
160
+ * The container command-line tools run in.
161
+ *
162
+ * Everything here is a *resource* decision — which image, how much of the
163
+ * machine, whether the network is reachable — because those are the decisions
164
+ * that differ between a laptop and CI and cannot be baked into an image.
165
+ *
166
+ * `env` names host variables to forward, and only names: values never appear
167
+ * in the config, so a repository never carries one. Names that read like a
168
+ * credential are refused outright. The CLI materialises the keyring into its
169
+ * own environment before loading a project, so an unguarded passthrough would
170
+ * hand every model key to whatever the agent decided to run.
171
+ */
172
+ const SECRETISH = /(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL)/i;
173
+ const sandbox = z
174
+ .object({
175
+ /** the base image, e.g. `docker.io/library/python:3.13-slim` */
176
+ image: z.string().min(1).optional(),
177
+ /** fractional cores the container may use */
178
+ cpus: z.number().positive().optional(),
179
+ /** MiB the container may use */
180
+ memory: z.int().positive().optional(),
181
+ network: z.enum(['bridge', 'none', 'host']).optional(),
182
+ /** where the workspace is mounted, and the default working directory */
183
+ workdir: z.string().min(1).optional(),
184
+ /** seconds one command may take before it is killed */
185
+ timeout: z.int().positive().optional(),
186
+ /** uid, name or `uid:gid`; unset means the image's own user */
187
+ user: z.string().min(1).optional(),
188
+ /** keep the container between sessions instead of removing it */
189
+ persist: z.boolean().optional(),
190
+ /** host variables to forward, by name */
191
+ env: z.array(z.string().min(1)).optional(),
192
+ })
193
+ .strict()
194
+ .superRefine((value, ctx) => {
195
+ for (const [i, name] of (value.env ?? []).entries()) {
196
+ if (SECRETISH.test(name)) {
197
+ ctx.addIssue({
198
+ code: 'custom',
199
+ path: ['env', i],
200
+ message: `refusing to forward ${name} into the sandbox — it reads like a ` +
201
+ 'credential, and the sandbox runs whatever the model writes',
202
+ });
203
+ }
204
+ }
205
+ });
206
+ const agent = z
207
+ .object({
208
+ name,
209
+ /** what a sibling agent's `transfer_to_` tool tells the model */
210
+ description: z.string().optional(),
211
+ /** path to a markdown file, relative to the project root */
212
+ system: z.string().min(1).optional(),
213
+ model: modelRef.optional(),
214
+ /** names resolved against `ProjectOptions.tools`; code cannot live in yaml */
215
+ tools: z.array(z.string().min(1)).optional(),
216
+ /**
217
+ * Plain agent names. Deliberately not objects: a hand-off carries no
218
+ * configuration in this version, so there is nothing for an object form
219
+ * to hold, and accepting one would mean accepting keys nothing honours.
220
+ */
221
+ handoffs: z.array(name).optional(),
222
+ skills: skillsBinding.optional(),
223
+ /** parallel sub-agents; `true` is the unrestricted form */
224
+ fork: z.union([z.boolean(), forkBinding]).optional(),
225
+ /**
226
+ * Overrides on the project's sandbox. An agent that overrides nothing
227
+ * shares the container with everyone else, which is what a hand-off
228
+ * usually wants; an agent that names its own image gets its own.
229
+ */
230
+ sandbox: sandbox.optional(),
231
+ /** entrypoint, when no top-level `default` is given */
232
+ default: z.boolean().optional(),
233
+ })
234
+ .strict();
235
+ export const projectSchema = z
236
+ .object({
237
+ version: z.literal(1).default(1),
238
+ /** entrypoint agent name; wins over any `default: true` */
239
+ default: name.optional(),
240
+ /** named connections; the built-in kinds work without being declared */
241
+ providers: z.record(name, provider).optional(),
242
+ /** the provider a bare model id belongs to */
243
+ provider: name.optional(),
244
+ /** named model configurations, referenced by `model:` anywhere below */
245
+ models: z.record(name, z.union([modelRef, modelSpec])).optional(),
246
+ /** fallback for agents that do not pin their own */
247
+ model: modelRef.optional(),
248
+ /**
249
+ * Named vectorisers. Not a per-agent key: nothing in the runtime
250
+ * consumes an embedder yet, and a key nothing honours is worse than a
251
+ * key that is not there.
252
+ */
253
+ embeddings: z.record(name, z.union([modelRef, embeddingSpec])).optional(),
254
+ /** the vectoriser `AgentProject.embedder()` hands back when asked for none */
255
+ embedding: modelRef.optional(),
256
+ /** one directory, or several merged into one catalog */
257
+ skills: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
258
+ /** the container `run_command` and friends execute in */
259
+ sandbox: sandbox.optional(),
260
+ agents: z.array(agent).min(1),
261
+ })
262
+ .strict();
263
+ /**
264
+ * Re-renders a zod failure as `agents.yaml: agents[1].skills.discovery — …`.
265
+ *
266
+ * The default message is a JSON blob with the path in a nested array, which
267
+ * tells an author everything except the one thing they need: which line to fix.
268
+ */
269
+ export function parseConfig(text, source) {
270
+ let raw;
271
+ try {
272
+ raw = parseYaml(text);
273
+ }
274
+ catch (e) {
275
+ throw new Error(`${source}: ${e.message}`);
276
+ }
277
+ const result = projectSchema.safeParse(raw);
278
+ if (!result.success) {
279
+ const lines = result.error.issues.map((i) => {
280
+ const path = i.path.length ? i.path.map(segment).join('').replace(/^\./, '') : '(root)';
281
+ return ` ${path} — ${i.message}`;
282
+ });
283
+ throw new Error(`${source}: invalid project configuration\n${lines.join('\n')}`);
284
+ }
285
+ return result.data;
286
+ }
287
+ function segment(p) {
288
+ return typeof p === 'number' ? `[${p}]` : `.${String(p)}`;
289
+ }
290
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,4 @@
1
+ export { parseConfig, projectSchema, type AgentConfig, type EmbeddingConfig, type ModelConfig, type ProjectConfig, type ProviderConfig, type SandboxConfig, } from './config.ts';
2
+ export { AgentProject, loadProject, projectRegistry, readProjectConfig, type ProjectOptions, type ProjectSource, } from './load.ts';
3
+ export { projectDir, projectFile, projectPath, projectRoot } from './refs.ts';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ export { parseConfig, projectSchema, } from "./config.js";
2
+ export { AgentProject, loadProject, projectRegistry, readProjectConfig, } from "./load.js";
3
+ export { projectDir, projectFile, projectPath, projectRoot } from "./refs.js";
4
+ //# sourceMappingURL=index.js.map