@crewhaus/spec 0.2.1 → 0.2.3

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 (3) hide show
  1. package/dist/index.d.ts +2770 -139
  2. package/dist/index.js +44 -24
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -195,6 +195,13 @@ const toolConfigBlock = z
195
195
  * normal model-router path — a fallback with a missing key warns at boot
196
196
  * and is skipped when tried, never hard-failing the run.
197
197
  *
198
+ * The declared ORDER is honoured verbatim — it is a TRUST ordering ("what do
199
+ * I run when my primary is down"), and the runtime never reorders it (a
200
+ * 2026-07 design review deliberately retired the cost-ranking idea; see the
201
+ * `rankFallbacks` docstring in model-router's failover.ts). Want cheaper
202
+ * models preferred? Order the list yourself — or use `agent.model_pool`,
203
+ * which is the cost/quality routing surface.
204
+ *
198
205
  * `circuit_breaker` tunes the per-candidate breakers. Field names mirror
199
206
  * `CircuitBreakerOptions` in `@crewhaus/circuit-breaker` exactly
200
207
  * (failureThreshold / windowMs / cooldownMs); package defaults (5 failures
@@ -302,6 +309,18 @@ const modelPoolBlock = z
302
309
  minSamplesPerArm: z.number().int().positive().optional(),
303
310
  costRefUsd: z.number().positive().optional(),
304
311
  latencyRefMs: z.number().int().positive().optional(),
312
+ // ε for ε-greedy online exploration once every arm clears the sample
313
+ // floor (fraction of exploit-phase turns that try a non-best model).
314
+ // Default 0 → deterministic explore-then-exploit, no RNG.
315
+ explorationRate: z.number().min(0).max(1).optional(),
316
+ // Fixed exploration seed for reproducible-across-runs behaviour (e.g.
317
+ // tests). Omitted → the runtime seeds from the sessionId, so each run
318
+ // explores differently while still replaying from its own transcript.
319
+ seed: z.string().min(1).optional(),
320
+ // Exploit-phase exploration strategy. "epsilon-greedy" (default) uses
321
+ // explorationRate; "thompson" draws each arm from its reward posterior
322
+ // and self-balances (explorationRate is then ignored).
323
+ bandit: z.enum(["epsilon-greedy", "thompson"]).optional(),
305
324
  })
306
325
  .strict()
307
326
  .optional(),
@@ -986,17 +1005,33 @@ const pipelineDocumentSchema = z
986
1005
  metadata: z.record(z.string(), z.unknown()).optional(),
987
1006
  })
988
1007
  .strict();
1008
+ /**
1009
+ * Adaptive model routing — the minimal single-agent block shared by the
1010
+ * pipeline/research/batch/browser shapes, now carrying the opt-in
1011
+ * `model_pool`. Their emitted runtimes each call `runChatLoop` with a single
1012
+ * primary (exactly the cli shape's execution model), so the pool routes there
1013
+ * with zero runtime changes. The superRefine is trivially satisfied today
1014
+ * (these shapes carry no `model_tiers`/`model_fallbacks`) but keeps the
1015
+ * mutual-exclusion rule uniform if they ever gain them. NOT used by
1016
+ * onchain/onchain-game: their emitted bundles are callable modules whose
1017
+ * agent-loop wiring is still deferred (see target-onchain slice-2 notes), so
1018
+ * a `model_pool` there would be an inert spec field.
1019
+ */
1020
+ const pooledSingleAgentSchema = z
1021
+ .object({
1022
+ model: z.string().min(1),
1023
+ instructions: z.string().min(1),
1024
+ // Adaptive model routing — N-candidate pool with a selection policy.
1025
+ model_pool: modelPoolBlock,
1026
+ })
1027
+ .strict()
1028
+ .superRefine(refineModelSelection);
989
1029
  const pipelineSchema = z
990
1030
  .object({
991
1031
  name: safeName,
992
1032
  version: versionField,
993
1033
  target: z.literal("pipeline"),
994
- agent: z
995
- .object({
996
- model: z.string().min(1),
997
- instructions: z.string().min(1),
998
- })
999
- .strict(),
1034
+ agent: pooledSingleAgentSchema,
1000
1035
  retrieve: z
1001
1036
  .object({
1002
1037
  embedderModel: z.string().min(1),
@@ -1092,12 +1127,7 @@ const researchSchema = z
1092
1127
  name: safeName,
1093
1128
  version: versionField,
1094
1129
  target: z.literal("research"),
1095
- agent: z
1096
- .object({
1097
- model: z.string().min(1),
1098
- instructions: z.string().min(1),
1099
- })
1100
- .strict(),
1130
+ agent: pooledSingleAgentSchema,
1101
1131
  goal: z.string().min(1),
1102
1132
  branchingFactor: z.number().int().min(1).max(8).default(3),
1103
1133
  maxDurationMs: z.number().int().positive().default(300_000),
@@ -1133,12 +1163,7 @@ const batchSchema = z
1133
1163
  name: safeName,
1134
1164
  version: versionField,
1135
1165
  target: z.literal("batch"),
1136
- agent: z
1137
- .object({
1138
- model: z.string().min(1),
1139
- instructions: z.string().min(1),
1140
- })
1141
- .strict(),
1166
+ agent: pooledSingleAgentSchema,
1142
1167
  queue: batchQueueSchema,
1143
1168
  concurrency: z.number().int().min(1).max(64).default(4),
1144
1169
  idempotencyWindowMs: z.number().int().positive().default(60_000),
@@ -1209,12 +1234,7 @@ const browserSchema = z
1209
1234
  name: safeName,
1210
1235
  version: versionField,
1211
1236
  target: z.literal("browser"),
1212
- agent: z
1213
- .object({
1214
- model: z.string().min(1),
1215
- instructions: z.string().min(1),
1216
- })
1217
- .strict(),
1237
+ agent: pooledSingleAgentSchema,
1218
1238
  driver: browserDriverSchema.default({}),
1219
1239
  /** Vision-grounding model. Defaults to the agent's primary model. */
1220
1240
  groundingModel: z.string().min(1).optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewhaus/spec",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "description": "User-facing spec schema (Zod) + YAML parser",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "test": "bun test src"
16
16
  },
17
17
  "dependencies": {
18
- "@crewhaus/errors": "0.2.1",
18
+ "@crewhaus/errors": "0.2.3",
19
19
  "yaml": "^2.6.0",
20
20
  "zod": "^3.23.8"
21
21
  },