@crewhaus/spec 0.1.8 → 0.2.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/dist/index.d.ts +2450 -188
- package/dist/index.js +235 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -26,6 +26,24 @@ const safeName = z
|
|
|
26
26
|
* Will grow into the full catalog spec (eval, deploy) — see
|
|
27
27
|
* docs/MODULE-CATALOG.md PART A Layer F1.
|
|
28
28
|
*/
|
|
29
|
+
/**
|
|
30
|
+
* Section 28 (#43) — OPTIONAL spec-schema version stamp. Every target schema is
|
|
31
|
+
* `.strict()`, so before this field a migration that stamped `version: 1` on a
|
|
32
|
+
* spec's YAML produced a document `parseSpec` REJECTED ("Unrecognized key(s)").
|
|
33
|
+
* This additive optional field gives migrations somewhere to stamp:
|
|
34
|
+
*
|
|
35
|
+
* - ABSENT → the spec is current/unversioned (the pre-#43 world). Fully
|
|
36
|
+
* back-compat: every existing spec keeps parsing unchanged.
|
|
37
|
+
* - PRESENT → a non-negative integer the migration-engine reads as the spec's
|
|
38
|
+
* schema version (`spec.version ?? 0` in migration-engine/migration-runner).
|
|
39
|
+
*
|
|
40
|
+
* It is a spec-schema knob, NOT the IR `version` (which stays `0` — the IR's
|
|
41
|
+
* own contract version). `lower()` does not thread this field into the IR; it
|
|
42
|
+
* exists purely so the versioned-migration chain has a home. Added to EVERY
|
|
43
|
+
* member of the discriminated union because the union is `.strict()` — a field
|
|
44
|
+
* absent from a member would still be rejected on that target.
|
|
45
|
+
*/
|
|
46
|
+
const versionField = z.number().int().nonnegative().optional();
|
|
29
47
|
// Permissions block (Section 7). SECURITY: `mode: "bypass"` is intentionally
|
|
30
48
|
// absent from the enum — bypass can only enter the system via the CLI flag.
|
|
31
49
|
// Defense in depth: parse-time and runtime checks both reject it.
|
|
@@ -163,6 +181,66 @@ const toolConfigBlock = z
|
|
|
163
181
|
}
|
|
164
182
|
})
|
|
165
183
|
.optional();
|
|
184
|
+
/**
|
|
185
|
+
* Item 22 — spec-declared provider failover chain, on the agent blocks of
|
|
186
|
+
* the shapes whose emitted runtime calls `runChatLoop` with a single
|
|
187
|
+
* primary model (cli, channel, managed today).
|
|
188
|
+
*
|
|
189
|
+
* `model_fallbacks` is an ordered list of model strings tried when the
|
|
190
|
+
* primary's circuit breaker is open — each entry follows the SAME
|
|
191
|
+
* model-string grammar as `agent.model` (`claude-*`, `openai/*`,
|
|
192
|
+
* `bedrock/*`, `groq/*`, …; validated like `agent.model` at parse time,
|
|
193
|
+
* with the full grammar enforced by the model-router when resolved).
|
|
194
|
+
* Cross-provider fallbacks resolve their own credentials lazily via the
|
|
195
|
+
* normal model-router path — a fallback with a missing key warns at boot
|
|
196
|
+
* and is skipped when tried, never hard-failing the run.
|
|
197
|
+
*
|
|
198
|
+
* `circuit_breaker` tunes the per-candidate breakers. Field names mirror
|
|
199
|
+
* `CircuitBreakerOptions` in `@crewhaus/circuit-breaker` exactly
|
|
200
|
+
* (failureThreshold / windowMs / cooldownMs); package defaults (5 failures
|
|
201
|
+
* / 60s window / 30s cooldown) apply per field when omitted. Declaring
|
|
202
|
+
* `circuit_breaker` WITHOUT `model_fallbacks` is valid: the primary
|
|
203
|
+
* adapter alone gets breaker-wrapped (fail-fast on a degraded provider
|
|
204
|
+
* instead of hammering it).
|
|
205
|
+
*/
|
|
206
|
+
const modelFallbacksBlock = z.array(z.string().min(1)).min(1).optional();
|
|
207
|
+
const circuitBreakerBlock = z
|
|
208
|
+
.object({
|
|
209
|
+
/** Consecutive failures inside windowMs that trip the breaker. */
|
|
210
|
+
failureThreshold: z.number().int().positive().optional(),
|
|
211
|
+
/** Window for counting consecutive failures (ms). */
|
|
212
|
+
windowMs: z.number().int().positive().optional(),
|
|
213
|
+
/** How long the breaker stays open before allowing a probe (ms). */
|
|
214
|
+
cooldownMs: z.number().int().positive().optional(),
|
|
215
|
+
})
|
|
216
|
+
.strict()
|
|
217
|
+
.optional();
|
|
218
|
+
/**
|
|
219
|
+
* Item 26 — opt-in two-tier turn-difficulty router. When present, the runtime
|
|
220
|
+
* picks a model tier PER TURN from deterministic signals (estimated context
|
|
221
|
+
* tokens, whether tools are in play, turn index, prior-turn tool_use density):
|
|
222
|
+
* the cheap `fast` model for easy turns, the `default` model for hard ones. A
|
|
223
|
+
* fast-tier turn that FAILS re-runs on `default` (misroute recovery). Both are
|
|
224
|
+
* full model-router grammar strings. `routing` tunes the escalation thresholds
|
|
225
|
+
* (all optional — sensible defaults apply). Omitted entirely → single-model
|
|
226
|
+
* behaviour, byte-identical bundles.
|
|
227
|
+
*/
|
|
228
|
+
const modelTiersBlock = z
|
|
229
|
+
.object({
|
|
230
|
+
fast: z.string().min(1),
|
|
231
|
+
default: z.string().min(1),
|
|
232
|
+
routing: z
|
|
233
|
+
.object({
|
|
234
|
+
contextTokenThreshold: z.number().int().positive().optional(),
|
|
235
|
+
toolsToDefault: z.boolean().optional(),
|
|
236
|
+
firstTurnToDefault: z.boolean().optional(),
|
|
237
|
+
priorToolDensityThreshold: z.number().int().positive().optional(),
|
|
238
|
+
})
|
|
239
|
+
.strict()
|
|
240
|
+
.optional(),
|
|
241
|
+
})
|
|
242
|
+
.strict()
|
|
243
|
+
.optional();
|
|
166
244
|
/**
|
|
167
245
|
* Section 17 — optional override for the model used by
|
|
168
246
|
* `compaction-autocompact` when summarising long conversations. Defaults
|
|
@@ -265,19 +343,51 @@ const failureTaxonomyEntrySchema = z
|
|
|
265
343
|
.object({
|
|
266
344
|
class: z.string().min(1),
|
|
267
345
|
pattern: z.string().min(1),
|
|
268
|
-
|
|
346
|
+
// Item 23 — `switch-model` routes the same turn onto the next provider
|
|
347
|
+
// failover candidate (pairs with `agent.model_fallbacks`; a no-op
|
|
348
|
+
// re-issue when no chain is declared). See recovery-engine +
|
|
349
|
+
// AUTOMATION-OPPORTUNITIES.md item 23.
|
|
350
|
+
recovery: z.enum(["retry", "compact", "continue", "tombstone", "switch-model", "fail"]),
|
|
269
351
|
hint: z.string().min(1).optional(),
|
|
270
352
|
})
|
|
271
353
|
.strict();
|
|
272
354
|
const failureTaxonomyBlock = z.array(failureTaxonomyEntrySchema).optional();
|
|
355
|
+
/**
|
|
356
|
+
* Item 27 — run-level spend cap with a degradation ladder. Generalizes the
|
|
357
|
+
* optimizer's `--budget-usd` to normal runs. `usd` is the dollar ceiling;
|
|
358
|
+
* when the run's accrued spend reaches it, `on_exceed` decides:
|
|
359
|
+
* - `{ action: "stop" }` — end the run cleanly before the next turn.
|
|
360
|
+
* - `{ action: "degrade", model }` — re-resolve the primary model to the
|
|
361
|
+
* cheaper `model` (one rung) and continue; a later breach on the
|
|
362
|
+
* degraded model stops the run.
|
|
363
|
+
* The check is PRE-TURN (beside compaction), so an in-flight turn always
|
|
364
|
+
* completes. Carried on the same interactive shapes as the failover chain
|
|
365
|
+
* (cli, channel, managed). `on_exceed.model` follows the agent.model
|
|
366
|
+
* grammar. Defaults to `{ action: "stop" }` when `on_exceed` is omitted.
|
|
367
|
+
*/
|
|
368
|
+
const budgetBlock = z
|
|
369
|
+
.object({
|
|
370
|
+
usd: z.number().positive(),
|
|
371
|
+
on_exceed: z
|
|
372
|
+
.discriminatedUnion("action", [
|
|
373
|
+
z.object({ action: z.literal("stop") }).strict(),
|
|
374
|
+
z.object({ action: z.literal("degrade"), model: z.string().min(1) }).strict(),
|
|
375
|
+
])
|
|
376
|
+
.default({ action: "stop" }),
|
|
377
|
+
})
|
|
378
|
+
.strict()
|
|
379
|
+
.optional();
|
|
273
380
|
/**
|
|
274
381
|
* Response-feedback block — declares that a harness collects human ratings on
|
|
275
382
|
* agent responses (thumbs/stars/scale/comment) which `crewhaus distill` turns
|
|
276
383
|
* into eval datasets + graders. Cross-cutting like security: carried on the
|
|
277
384
|
* interactive shapes that consume it (cli, channel). `channelReactions` gates
|
|
278
385
|
* codegen of Slack 👍/👎 → feedback in the channel target; `modality`/`storage`
|
|
279
|
-
* configure the capture surfaces; `autoDistill`
|
|
280
|
-
*
|
|
386
|
+
* configure the capture surfaces; `autoDistill` turns accumulated ratings into
|
|
387
|
+
* versioned `<name>-ratings` registry datasets at CLI run teardown (item 1);
|
|
388
|
+
* `exitPrompt` gates the one-keystroke REPL exit rating prompt (default on
|
|
389
|
+
* when the block is present; set `false` to keep capture surfaces without the
|
|
390
|
+
* prompt). `.strict()` so a typo'd sub-key fails the build.
|
|
281
391
|
*/
|
|
282
392
|
const feedbackBlock = z
|
|
283
393
|
.object({
|
|
@@ -286,10 +396,93 @@ const feedbackBlock = z
|
|
|
286
396
|
scale: z.object({ min: z.number().int(), max: z.number().int() }).strict().optional(),
|
|
287
397
|
storage: z.object({ location: safeName }).strict().optional(),
|
|
288
398
|
autoDistill: z.boolean().optional(),
|
|
399
|
+
exitPrompt: z.boolean().optional(),
|
|
289
400
|
channelReactions: z.boolean().optional(),
|
|
290
401
|
})
|
|
291
402
|
.strict()
|
|
292
403
|
.optional();
|
|
404
|
+
/**
|
|
405
|
+
* Feature #53 — cross-session memory block. Its mere presence wires the
|
|
406
|
+
* Remember/Recall tools into the harness (no hand-editing). The auto-*
|
|
407
|
+
* switches layer on top: `autoCapture` summarizes the session's durable
|
|
408
|
+
* outcomes into `.crewhaus/memories/<name>.jsonl` at run teardown;
|
|
409
|
+
* `autoRecall` injects the top-`recallK` relevant memories into the system
|
|
410
|
+
* prompt at session start (mirrors project-memory auto-load). Carried on the
|
|
411
|
+
* interactive shapes that run a chat loop (cli, channel, managed, research).
|
|
412
|
+
* `.strict()` so a typo'd sub-key fails the build.
|
|
413
|
+
*/
|
|
414
|
+
const memoryBlock = z
|
|
415
|
+
.object({
|
|
416
|
+
enabled: z.boolean().optional(),
|
|
417
|
+
autoCapture: z.boolean().optional(),
|
|
418
|
+
autoCaptureThreshold: z.number().int().positive().optional(),
|
|
419
|
+
autoRecall: z.boolean().optional(),
|
|
420
|
+
recallK: z.number().int().positive().max(50).optional(),
|
|
421
|
+
})
|
|
422
|
+
.strict()
|
|
423
|
+
.optional();
|
|
424
|
+
/**
|
|
425
|
+
* Ops item 37 — cross-cutting `observability` block. Today it carries one
|
|
426
|
+
* sub-block, `slo`, that declares production Service-Level Objectives + the
|
|
427
|
+
* mitigation ladder the runtime SLO monitor walks on a SUSTAINED breach.
|
|
428
|
+
*
|
|
429
|
+
* The monitor (runtime-core, env/spec-gated) folds bus events into rolling
|
|
430
|
+
* windows (reusing the alert-watchdog's accumulator + the metrics-collector's
|
|
431
|
+
* TTFT histogram) and, when a target is breached for `windowSeconds`, executes
|
|
432
|
+
* the ladder rungs in the declared order: `alert` (webhook/hook), `pause-intake`
|
|
433
|
+
* (gateway/managed 429 `budget_exceeded` path), `rollback` (auto-rollback the
|
|
434
|
+
* env pin via deployment-controller). Every rung is audit-logged.
|
|
435
|
+
*
|
|
436
|
+
* Targets are all OPTIONAL — declare only the SLOs you care about; an omitted
|
|
437
|
+
* target is never evaluated. `mitigation` defaults to `["alert"]` (observe-only
|
|
438
|
+
* is safe) so a spec that lists thresholds without a ladder still warns. Higher
|
|
439
|
+
* rungs are opt-in because they touch traffic/deploys — a spec must ask for them
|
|
440
|
+
* explicitly. `.strict()` so a typo'd sub-key fails the build.
|
|
441
|
+
*
|
|
442
|
+
* NOTE `egress_block_rate` derives from the `permission_decision` egress
|
|
443
|
+
* outcomes (no dedicated egress TraceEvent exists); `ttft_ms`/`p95_latency_ms`
|
|
444
|
+
* derive from the same per-turn/TTFT samples the alert-watchdog accumulates.
|
|
445
|
+
*/
|
|
446
|
+
const sloBlock = z
|
|
447
|
+
.object({
|
|
448
|
+
/** Fractional error rate ceiling (unrecovered errors / model calls), e.g. 0.05. */
|
|
449
|
+
error_rate: z.number().min(0).max(1).optional(),
|
|
450
|
+
/** p95 per-turn latency ceiling, milliseconds. */
|
|
451
|
+
p95_latency_ms: z.number().positive().optional(),
|
|
452
|
+
/** p95 time-to-first-token ceiling, milliseconds. */
|
|
453
|
+
ttft_ms: z.number().positive().optional(),
|
|
454
|
+
/** Cost burn ceiling, USD per hour of wall-clock. */
|
|
455
|
+
cost_per_hour_usd: z.number().positive().optional(),
|
|
456
|
+
/** Fractional egress-block rate ceiling (egress-blocked / external calls), e.g. 0.1. */
|
|
457
|
+
egress_block_rate: z.number().min(0).max(1).optional(),
|
|
458
|
+
/**
|
|
459
|
+
* Rolling window (seconds) a breach must persist before the ladder fires.
|
|
460
|
+
* A single blip never mitigates — the monitor only acts on a SUSTAINED
|
|
461
|
+
* breach across this window. Default 300s (5 min).
|
|
462
|
+
*/
|
|
463
|
+
window_seconds: z.number().int().positive().optional(),
|
|
464
|
+
/**
|
|
465
|
+
* Mitigation ladder, walked in declared order on a sustained breach. Each
|
|
466
|
+
* rung is executed at most once per session. `alert` is always safe;
|
|
467
|
+
* `pause-intake` / `rollback` touch traffic + deploys so they are opt-in.
|
|
468
|
+
*/
|
|
469
|
+
mitigation: z
|
|
470
|
+
.array(z.enum(["alert", "pause-intake", "rollback"]))
|
|
471
|
+
.nonempty()
|
|
472
|
+
.optional(),
|
|
473
|
+
})
|
|
474
|
+
.strict()
|
|
475
|
+
.refine((s) => s.error_rate !== undefined ||
|
|
476
|
+
s.p95_latency_ms !== undefined ||
|
|
477
|
+
s.ttft_ms !== undefined ||
|
|
478
|
+
s.cost_per_hour_usd !== undefined ||
|
|
479
|
+
s.egress_block_rate !== undefined, { message: "observability.slo must declare at least one target threshold" });
|
|
480
|
+
const observabilityBlock = z
|
|
481
|
+
.object({
|
|
482
|
+
slo: sloBlock.optional(),
|
|
483
|
+
})
|
|
484
|
+
.strict()
|
|
485
|
+
.optional();
|
|
293
486
|
/**
|
|
294
487
|
* Section 47 — blockchain subsystem blocks (cross-cutting). Any shape may
|
|
295
488
|
* declare any subset of `chains` / `wallets` / `contracts` /
|
|
@@ -422,6 +615,7 @@ const channelGatewayBlock = z
|
|
|
422
615
|
const cliSchema = z
|
|
423
616
|
.object({
|
|
424
617
|
name: safeName,
|
|
618
|
+
version: versionField,
|
|
425
619
|
target: z.literal("cli"),
|
|
426
620
|
agent: z
|
|
427
621
|
.object({
|
|
@@ -431,6 +625,11 @@ const cliSchema = z
|
|
|
431
625
|
// runtime default applies. Raise it for turns that emit large
|
|
432
626
|
// multi-file edits so the model isn't cut off mid-`tool_use`.
|
|
433
627
|
max_tokens: z.number().int().positive().optional(),
|
|
628
|
+
// Item 22 — provider failover chain (see modelFallbacksBlock docs).
|
|
629
|
+
model_fallbacks: modelFallbacksBlock,
|
|
630
|
+
circuit_breaker: circuitBreakerBlock,
|
|
631
|
+
// Item 26 — opt-in two-tier turn-difficulty router.
|
|
632
|
+
model_tiers: modelTiersBlock,
|
|
434
633
|
sub_agents: subAgentsBlock,
|
|
435
634
|
})
|
|
436
635
|
.strict(),
|
|
@@ -441,7 +640,10 @@ const cliSchema = z
|
|
|
441
640
|
compaction: compactionBlock,
|
|
442
641
|
security: securityBlock,
|
|
443
642
|
failure_taxonomy: failureTaxonomyBlock,
|
|
643
|
+
budget: budgetBlock,
|
|
444
644
|
feedback: feedbackBlock,
|
|
645
|
+
memory: memoryBlock,
|
|
646
|
+
observability: observabilityBlock,
|
|
445
647
|
cli: cliOptionsBlock,
|
|
446
648
|
chains: chainsBlock,
|
|
447
649
|
wallets: walletsBlock,
|
|
@@ -461,6 +663,7 @@ const workflowStepSchema = z
|
|
|
461
663
|
const workflowSchema = z
|
|
462
664
|
.object({
|
|
463
665
|
name: safeName,
|
|
666
|
+
version: versionField,
|
|
464
667
|
target: z.literal("workflow"),
|
|
465
668
|
model: z.string().min(1),
|
|
466
669
|
steps: z.array(workflowStepSchema).min(1),
|
|
@@ -543,6 +746,11 @@ const channelAgentSchema = z
|
|
|
543
746
|
.object({
|
|
544
747
|
model: z.string().min(1),
|
|
545
748
|
instructions: z.string().min(1),
|
|
749
|
+
// Item 22 — provider failover chain (see modelFallbacksBlock docs).
|
|
750
|
+
model_fallbacks: modelFallbacksBlock,
|
|
751
|
+
circuit_breaker: circuitBreakerBlock,
|
|
752
|
+
// Item 26 — opt-in two-tier turn-difficulty router.
|
|
753
|
+
model_tiers: modelTiersBlock,
|
|
546
754
|
tools: z.array(z.string().min(1)).optional(),
|
|
547
755
|
tool_config: toolConfigBlock,
|
|
548
756
|
sub_agents: subAgentsBlock,
|
|
@@ -551,6 +759,7 @@ const channelAgentSchema = z
|
|
|
551
759
|
const channelSchema = z
|
|
552
760
|
.object({
|
|
553
761
|
name: safeName,
|
|
762
|
+
version: versionField,
|
|
554
763
|
target: z.literal("channel"),
|
|
555
764
|
agent: channelAgentSchema,
|
|
556
765
|
channels: channelsBlock,
|
|
@@ -559,7 +768,10 @@ const channelSchema = z
|
|
|
559
768
|
permissions: permissionsBlock,
|
|
560
769
|
compaction: compactionBlock,
|
|
561
770
|
failure_taxonomy: failureTaxonomyBlock,
|
|
771
|
+
budget: budgetBlock,
|
|
562
772
|
feedback: feedbackBlock,
|
|
773
|
+
memory: memoryBlock,
|
|
774
|
+
observability: observabilityBlock,
|
|
563
775
|
heartbeat: heartbeatBlock,
|
|
564
776
|
gateway: channelGatewayBlock,
|
|
565
777
|
chains: chainsBlock,
|
|
@@ -599,6 +811,7 @@ const graphEdgeSchema = z
|
|
|
599
811
|
const graphSchema = z
|
|
600
812
|
.object({
|
|
601
813
|
name: safeName,
|
|
814
|
+
version: versionField,
|
|
602
815
|
target: z.literal("graph"),
|
|
603
816
|
model: z.string().min(1),
|
|
604
817
|
entry: z.string().min(1),
|
|
@@ -632,17 +845,26 @@ const managedAgentSchema = z
|
|
|
632
845
|
.object({
|
|
633
846
|
model: z.string().min(1),
|
|
634
847
|
instructions: z.string().min(1),
|
|
848
|
+
// Item 22 — provider failover chain (see modelFallbacksBlock docs).
|
|
849
|
+
model_fallbacks: modelFallbacksBlock,
|
|
850
|
+
circuit_breaker: circuitBreakerBlock,
|
|
851
|
+
// Item 26 — opt-in two-tier turn-difficulty router.
|
|
852
|
+
model_tiers: modelTiersBlock,
|
|
635
853
|
})
|
|
636
854
|
.strict();
|
|
637
855
|
const managedSchema = z
|
|
638
856
|
.object({
|
|
639
857
|
name: safeName,
|
|
858
|
+
version: versionField,
|
|
640
859
|
target: z.literal("managed"),
|
|
641
860
|
agent: managedAgentSchema,
|
|
642
861
|
tenants: z.array(managedTenantSchema).min(1),
|
|
643
862
|
permissions: permissionsBlock,
|
|
644
863
|
compaction: compactionBlock,
|
|
645
864
|
failure_taxonomy: failureTaxonomyBlock,
|
|
865
|
+
budget: budgetBlock,
|
|
866
|
+
memory: memoryBlock,
|
|
867
|
+
observability: observabilityBlock,
|
|
646
868
|
})
|
|
647
869
|
.strict();
|
|
648
870
|
// Vector-store backend ids accepted in specs. Mirrors `VectorBackendId`
|
|
@@ -666,6 +888,7 @@ const pipelineDocumentSchema = z
|
|
|
666
888
|
const pipelineSchema = z
|
|
667
889
|
.object({
|
|
668
890
|
name: safeName,
|
|
891
|
+
version: versionField,
|
|
669
892
|
target: z.literal("pipeline"),
|
|
670
893
|
agent: z
|
|
671
894
|
.object({
|
|
@@ -731,6 +954,7 @@ const crewRoutingSchema = z
|
|
|
731
954
|
const crewSchema = z
|
|
732
955
|
.object({
|
|
733
956
|
name: safeName,
|
|
957
|
+
version: versionField,
|
|
734
958
|
target: z.literal("crew"),
|
|
735
959
|
/** Crew-wide model fallback used by any role that omits `role.model`. */
|
|
736
960
|
model: z.string().min(1),
|
|
@@ -765,6 +989,7 @@ const researchRetrieveSchema = z
|
|
|
765
989
|
const researchSchema = z
|
|
766
990
|
.object({
|
|
767
991
|
name: safeName,
|
|
992
|
+
version: versionField,
|
|
768
993
|
target: z.literal("research"),
|
|
769
994
|
agent: z
|
|
770
995
|
.object({
|
|
@@ -782,6 +1007,7 @@ const researchSchema = z
|
|
|
782
1007
|
permissions: permissionsBlock,
|
|
783
1008
|
compaction: compactionBlock,
|
|
784
1009
|
failure_taxonomy: failureTaxonomyBlock,
|
|
1010
|
+
memory: memoryBlock,
|
|
785
1011
|
chains: chainsBlock,
|
|
786
1012
|
wallets: walletsBlock,
|
|
787
1013
|
contracts: contractsBlock,
|
|
@@ -804,6 +1030,7 @@ const batchQueueSchema = z
|
|
|
804
1030
|
const batchSchema = z
|
|
805
1031
|
.object({
|
|
806
1032
|
name: safeName,
|
|
1033
|
+
version: versionField,
|
|
807
1034
|
target: z.literal("batch"),
|
|
808
1035
|
agent: z
|
|
809
1036
|
.object({
|
|
@@ -844,6 +1071,7 @@ const voiceTelephonySchema = z
|
|
|
844
1071
|
const voiceSchema = z
|
|
845
1072
|
.object({
|
|
846
1073
|
name: safeName,
|
|
1074
|
+
version: versionField,
|
|
847
1075
|
target: z.literal("voice"),
|
|
848
1076
|
agent: z
|
|
849
1077
|
.object({
|
|
@@ -878,6 +1106,7 @@ const browserDriverSchema = z
|
|
|
878
1106
|
const browserSchema = z
|
|
879
1107
|
.object({
|
|
880
1108
|
name: safeName,
|
|
1109
|
+
version: versionField,
|
|
881
1110
|
target: z.literal("browser"),
|
|
882
1111
|
agent: z
|
|
883
1112
|
.object({
|
|
@@ -907,6 +1136,7 @@ const browserSchema = z
|
|
|
907
1136
|
const evalSchema = z
|
|
908
1137
|
.object({
|
|
909
1138
|
name: safeName,
|
|
1139
|
+
version: versionField,
|
|
910
1140
|
target: z.literal("eval"),
|
|
911
1141
|
agent: z
|
|
912
1142
|
.object({
|
|
@@ -971,6 +1201,7 @@ const onchainTriggerSchema = z.discriminatedUnion("kind", [
|
|
|
971
1201
|
const onchainSchema = z
|
|
972
1202
|
.object({
|
|
973
1203
|
name: safeName,
|
|
1204
|
+
version: versionField,
|
|
974
1205
|
target: z.literal("onchain"),
|
|
975
1206
|
agent: z
|
|
976
1207
|
.object({
|
|
@@ -1005,6 +1236,7 @@ const onchainSchema = z
|
|
|
1005
1236
|
const onchainGameSchema = z
|
|
1006
1237
|
.object({
|
|
1007
1238
|
name: safeName,
|
|
1239
|
+
version: versionField,
|
|
1008
1240
|
target: z.literal("onchain-game"),
|
|
1009
1241
|
agent: z
|
|
1010
1242
|
.object({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/spec",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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.
|
|
18
|
+
"@crewhaus/errors": "0.2.0",
|
|
19
19
|
"yaml": "^2.6.0",
|
|
20
20
|
"zod": "^3.23.8"
|
|
21
21
|
},
|