@crewhaus/spec 0.1.7 → 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 +2798 -187
- package/dist/index.js +255 -1
- 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,11 +343,146 @@ 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();
|
|
380
|
+
/**
|
|
381
|
+
* Response-feedback block — declares that a harness collects human ratings on
|
|
382
|
+
* agent responses (thumbs/stars/scale/comment) which `crewhaus distill` turns
|
|
383
|
+
* into eval datasets + graders. Cross-cutting like security: carried on the
|
|
384
|
+
* interactive shapes that consume it (cli, channel). `channelReactions` gates
|
|
385
|
+
* codegen of Slack 👍/👎 → feedback in the channel target; `modality`/`storage`
|
|
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.
|
|
391
|
+
*/
|
|
392
|
+
const feedbackBlock = z
|
|
393
|
+
.object({
|
|
394
|
+
enabled: z.boolean().optional(),
|
|
395
|
+
modality: z.enum(["binary", "stars", "scale", "comment"]).default("binary"),
|
|
396
|
+
scale: z.object({ min: z.number().int(), max: z.number().int() }).strict().optional(),
|
|
397
|
+
storage: z.object({ location: safeName }).strict().optional(),
|
|
398
|
+
autoDistill: z.boolean().optional(),
|
|
399
|
+
exitPrompt: z.boolean().optional(),
|
|
400
|
+
channelReactions: z.boolean().optional(),
|
|
401
|
+
})
|
|
402
|
+
.strict()
|
|
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();
|
|
273
486
|
/**
|
|
274
487
|
* Section 47 — blockchain subsystem blocks (cross-cutting). Any shape may
|
|
275
488
|
* declare any subset of `chains` / `wallets` / `contracts` /
|
|
@@ -402,6 +615,7 @@ const channelGatewayBlock = z
|
|
|
402
615
|
const cliSchema = z
|
|
403
616
|
.object({
|
|
404
617
|
name: safeName,
|
|
618
|
+
version: versionField,
|
|
405
619
|
target: z.literal("cli"),
|
|
406
620
|
agent: z
|
|
407
621
|
.object({
|
|
@@ -411,6 +625,11 @@ const cliSchema = z
|
|
|
411
625
|
// runtime default applies. Raise it for turns that emit large
|
|
412
626
|
// multi-file edits so the model isn't cut off mid-`tool_use`.
|
|
413
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,
|
|
414
633
|
sub_agents: subAgentsBlock,
|
|
415
634
|
})
|
|
416
635
|
.strict(),
|
|
@@ -421,6 +640,10 @@ const cliSchema = z
|
|
|
421
640
|
compaction: compactionBlock,
|
|
422
641
|
security: securityBlock,
|
|
423
642
|
failure_taxonomy: failureTaxonomyBlock,
|
|
643
|
+
budget: budgetBlock,
|
|
644
|
+
feedback: feedbackBlock,
|
|
645
|
+
memory: memoryBlock,
|
|
646
|
+
observability: observabilityBlock,
|
|
424
647
|
cli: cliOptionsBlock,
|
|
425
648
|
chains: chainsBlock,
|
|
426
649
|
wallets: walletsBlock,
|
|
@@ -440,6 +663,7 @@ const workflowStepSchema = z
|
|
|
440
663
|
const workflowSchema = z
|
|
441
664
|
.object({
|
|
442
665
|
name: safeName,
|
|
666
|
+
version: versionField,
|
|
443
667
|
target: z.literal("workflow"),
|
|
444
668
|
model: z.string().min(1),
|
|
445
669
|
steps: z.array(workflowStepSchema).min(1),
|
|
@@ -522,6 +746,11 @@ const channelAgentSchema = z
|
|
|
522
746
|
.object({
|
|
523
747
|
model: z.string().min(1),
|
|
524
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,
|
|
525
754
|
tools: z.array(z.string().min(1)).optional(),
|
|
526
755
|
tool_config: toolConfigBlock,
|
|
527
756
|
sub_agents: subAgentsBlock,
|
|
@@ -530,6 +759,7 @@ const channelAgentSchema = z
|
|
|
530
759
|
const channelSchema = z
|
|
531
760
|
.object({
|
|
532
761
|
name: safeName,
|
|
762
|
+
version: versionField,
|
|
533
763
|
target: z.literal("channel"),
|
|
534
764
|
agent: channelAgentSchema,
|
|
535
765
|
channels: channelsBlock,
|
|
@@ -538,6 +768,10 @@ const channelSchema = z
|
|
|
538
768
|
permissions: permissionsBlock,
|
|
539
769
|
compaction: compactionBlock,
|
|
540
770
|
failure_taxonomy: failureTaxonomyBlock,
|
|
771
|
+
budget: budgetBlock,
|
|
772
|
+
feedback: feedbackBlock,
|
|
773
|
+
memory: memoryBlock,
|
|
774
|
+
observability: observabilityBlock,
|
|
541
775
|
heartbeat: heartbeatBlock,
|
|
542
776
|
gateway: channelGatewayBlock,
|
|
543
777
|
chains: chainsBlock,
|
|
@@ -577,6 +811,7 @@ const graphEdgeSchema = z
|
|
|
577
811
|
const graphSchema = z
|
|
578
812
|
.object({
|
|
579
813
|
name: safeName,
|
|
814
|
+
version: versionField,
|
|
580
815
|
target: z.literal("graph"),
|
|
581
816
|
model: z.string().min(1),
|
|
582
817
|
entry: z.string().min(1),
|
|
@@ -610,17 +845,26 @@ const managedAgentSchema = z
|
|
|
610
845
|
.object({
|
|
611
846
|
model: z.string().min(1),
|
|
612
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,
|
|
613
853
|
})
|
|
614
854
|
.strict();
|
|
615
855
|
const managedSchema = z
|
|
616
856
|
.object({
|
|
617
857
|
name: safeName,
|
|
858
|
+
version: versionField,
|
|
618
859
|
target: z.literal("managed"),
|
|
619
860
|
agent: managedAgentSchema,
|
|
620
861
|
tenants: z.array(managedTenantSchema).min(1),
|
|
621
862
|
permissions: permissionsBlock,
|
|
622
863
|
compaction: compactionBlock,
|
|
623
864
|
failure_taxonomy: failureTaxonomyBlock,
|
|
865
|
+
budget: budgetBlock,
|
|
866
|
+
memory: memoryBlock,
|
|
867
|
+
observability: observabilityBlock,
|
|
624
868
|
})
|
|
625
869
|
.strict();
|
|
626
870
|
// Vector-store backend ids accepted in specs. Mirrors `VectorBackendId`
|
|
@@ -644,6 +888,7 @@ const pipelineDocumentSchema = z
|
|
|
644
888
|
const pipelineSchema = z
|
|
645
889
|
.object({
|
|
646
890
|
name: safeName,
|
|
891
|
+
version: versionField,
|
|
647
892
|
target: z.literal("pipeline"),
|
|
648
893
|
agent: z
|
|
649
894
|
.object({
|
|
@@ -709,6 +954,7 @@ const crewRoutingSchema = z
|
|
|
709
954
|
const crewSchema = z
|
|
710
955
|
.object({
|
|
711
956
|
name: safeName,
|
|
957
|
+
version: versionField,
|
|
712
958
|
target: z.literal("crew"),
|
|
713
959
|
/** Crew-wide model fallback used by any role that omits `role.model`. */
|
|
714
960
|
model: z.string().min(1),
|
|
@@ -743,6 +989,7 @@ const researchRetrieveSchema = z
|
|
|
743
989
|
const researchSchema = z
|
|
744
990
|
.object({
|
|
745
991
|
name: safeName,
|
|
992
|
+
version: versionField,
|
|
746
993
|
target: z.literal("research"),
|
|
747
994
|
agent: z
|
|
748
995
|
.object({
|
|
@@ -760,6 +1007,7 @@ const researchSchema = z
|
|
|
760
1007
|
permissions: permissionsBlock,
|
|
761
1008
|
compaction: compactionBlock,
|
|
762
1009
|
failure_taxonomy: failureTaxonomyBlock,
|
|
1010
|
+
memory: memoryBlock,
|
|
763
1011
|
chains: chainsBlock,
|
|
764
1012
|
wallets: walletsBlock,
|
|
765
1013
|
contracts: contractsBlock,
|
|
@@ -782,6 +1030,7 @@ const batchQueueSchema = z
|
|
|
782
1030
|
const batchSchema = z
|
|
783
1031
|
.object({
|
|
784
1032
|
name: safeName,
|
|
1033
|
+
version: versionField,
|
|
785
1034
|
target: z.literal("batch"),
|
|
786
1035
|
agent: z
|
|
787
1036
|
.object({
|
|
@@ -822,6 +1071,7 @@ const voiceTelephonySchema = z
|
|
|
822
1071
|
const voiceSchema = z
|
|
823
1072
|
.object({
|
|
824
1073
|
name: safeName,
|
|
1074
|
+
version: versionField,
|
|
825
1075
|
target: z.literal("voice"),
|
|
826
1076
|
agent: z
|
|
827
1077
|
.object({
|
|
@@ -856,6 +1106,7 @@ const browserDriverSchema = z
|
|
|
856
1106
|
const browserSchema = z
|
|
857
1107
|
.object({
|
|
858
1108
|
name: safeName,
|
|
1109
|
+
version: versionField,
|
|
859
1110
|
target: z.literal("browser"),
|
|
860
1111
|
agent: z
|
|
861
1112
|
.object({
|
|
@@ -885,6 +1136,7 @@ const browserSchema = z
|
|
|
885
1136
|
const evalSchema = z
|
|
886
1137
|
.object({
|
|
887
1138
|
name: safeName,
|
|
1139
|
+
version: versionField,
|
|
888
1140
|
target: z.literal("eval"),
|
|
889
1141
|
agent: z
|
|
890
1142
|
.object({
|
|
@@ -949,6 +1201,7 @@ const onchainTriggerSchema = z.discriminatedUnion("kind", [
|
|
|
949
1201
|
const onchainSchema = z
|
|
950
1202
|
.object({
|
|
951
1203
|
name: safeName,
|
|
1204
|
+
version: versionField,
|
|
952
1205
|
target: z.literal("onchain"),
|
|
953
1206
|
agent: z
|
|
954
1207
|
.object({
|
|
@@ -983,6 +1236,7 @@ const onchainSchema = z
|
|
|
983
1236
|
const onchainGameSchema = z
|
|
984
1237
|
.object({
|
|
985
1238
|
name: safeName,
|
|
1239
|
+
version: versionField,
|
|
986
1240
|
target: z.literal("onchain-game"),
|
|
987
1241
|
agent: z
|
|
988
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
|
},
|