@labelbox/rl-sdk 0.0.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 (64) hide show
  1. package/README.md +90 -0
  2. package/dist/client-options.d.ts +39 -0
  3. package/dist/client-options.js +29 -0
  4. package/dist/generated/client/client.gen.d.ts +2 -0
  5. package/dist/generated/client/client.gen.js +216 -0
  6. package/dist/generated/client/index.d.ts +8 -0
  7. package/dist/generated/client/index.js +6 -0
  8. package/dist/generated/client/types.gen.d.ts +120 -0
  9. package/dist/generated/client/types.gen.js +2 -0
  10. package/dist/generated/client/utils.gen.d.ts +37 -0
  11. package/dist/generated/client/utils.gen.js +228 -0
  12. package/dist/generated/client.gen.d.ts +12 -0
  13. package/dist/generated/client.gen.js +3 -0
  14. package/dist/generated/core/auth.gen.d.ts +18 -0
  15. package/dist/generated/core/auth.gen.js +14 -0
  16. package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
  17. package/dist/generated/core/bodySerializer.gen.js +57 -0
  18. package/dist/generated/core/params.gen.d.ts +43 -0
  19. package/dist/generated/core/params.gen.js +100 -0
  20. package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
  21. package/dist/generated/core/pathSerializer.gen.js +106 -0
  22. package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
  23. package/dist/generated/core/queryKeySerializer.gen.js +92 -0
  24. package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
  25. package/dist/generated/core/serverSentEvents.gen.js +132 -0
  26. package/dist/generated/core/types.gen.d.ts +78 -0
  27. package/dist/generated/core/types.gen.js +2 -0
  28. package/dist/generated/core/utils.gen.d.ts +19 -0
  29. package/dist/generated/core/utils.gen.js +87 -0
  30. package/dist/generated/index.d.ts +2 -0
  31. package/dist/generated/index.js +2 -0
  32. package/dist/generated/sdk.gen.d.ts +3054 -0
  33. package/dist/generated/sdk.gen.js +5962 -0
  34. package/dist/generated/types.gen.d.ts +39711 -0
  35. package/dist/generated/types.gen.js +2 -0
  36. package/dist/index.d.ts +21 -0
  37. package/dist/index.js +39 -0
  38. package/dist/nesting.d.ts +18 -0
  39. package/dist/nesting.js +75 -0
  40. package/dist/reference/concepts-reference.generated.d.ts +9 -0
  41. package/dist/reference/concepts-reference.generated.js +356 -0
  42. package/dist/reference/concepts-schema.d.ts +16 -0
  43. package/dist/reference/concepts-schema.js +39 -0
  44. package/dist/reference/concepts.d.ts +15 -0
  45. package/dist/reference/concepts.js +354 -0
  46. package/dist/reference/domains.d.ts +65 -0
  47. package/dist/reference/domains.js +32 -0
  48. package/dist/reference/recipes-reference.generated.d.ts +11 -0
  49. package/dist/reference/recipes-reference.generated.js +11415 -0
  50. package/dist/reference/recipes-schema.d.ts +676 -0
  51. package/dist/reference/recipes-schema.js +406 -0
  52. package/dist/reference/resources-reference.generated.d.ts +11 -0
  53. package/dist/reference/resources-reference.generated.js +7174 -0
  54. package/dist/reference/resources-schema.d.ts +78 -0
  55. package/dist/reference/resources-schema.js +71 -0
  56. package/dist/reference/schema.d.ts +153 -0
  57. package/dist/reference/schema.js +151 -0
  58. package/dist/reference/sdk-reference.generated.d.ts +10 -0
  59. package/dist/reference/sdk-reference.generated.js +65703 -0
  60. package/dist/reference/tutorials.d.ts +76 -0
  61. package/dist/reference/tutorials.js +65 -0
  62. package/dist/session-events.d.ts +92 -0
  63. package/dist/session-events.js +213 -0
  64. package/package.json +126 -0
@@ -0,0 +1,406 @@
1
+ import { z } from 'zod';
2
+ // Types for declarative **recipes** — medium-grained user goals composed of an
3
+ // ordered sequence of SDK operations, with values threaded from one step's
4
+ // response into the next step's inputs. Authored under
5
+ // `tests/smoke/recipes/<category>/<id>/` (a `manifest.ts` + an `api.ts`),
6
+ // statically validated and composed into SDK/CLI/cURL examples by
7
+ // `yarn dx recipes:generate`, and rendered in the in-app "Recipes" docs.
8
+ //
9
+ // Two layers live here:
10
+ // 1. Authoring types (`RecipeManifest`, `RecipeApi`) — what an author writes.
11
+ // 2. The generated reference entry (`RecipeReferenceEntry`) — what the
12
+ // generator emits and the frontend renders.
13
+ // ---------------------------------------------------------------------------
14
+ // Authoring types — `manifest.ts` + `api.ts`
15
+ // ---------------------------------------------------------------------------
16
+ // Kebab-case (lowercase words joined by single hyphens). Shared by recipe ids
17
+ // and category slugs: the docs nav groups by category and renders it via a
18
+ // kebab→sentence-case transform, so a free-form category (trailing space,
19
+ // spaces vs hyphens) could collapse two distinct categories into one nav group.
20
+ const KEBAB_CASE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
21
+ /**
22
+ * How often a recipe is validated — an **internal CI cadence**, never surfaced
23
+ * in the docs (deliberately not on `RecipeReferenceEntry`):
24
+ * - `'per-merge'` — rides the post-deploy smoke on every merge.
25
+ * - `{ everyDays: N }` — pulled out of the per-merge smoke; validated by the
26
+ * daily workflow only on the days it's "due" (date-modulo schedule).
27
+ * A future weekly tier is just `{ everyDays: 7 }` — no schema change.
28
+ */
29
+ export const RecipeCadenceSchema = z.union([
30
+ z.literal('per-merge'),
31
+ z.object({ everyDays: z.number().int().positive() }).strict(),
32
+ ]);
33
+ // ---------------------------------------------------------------------------
34
+ // Related links — the relationship graph between recipes and doc elements
35
+ // ---------------------------------------------------------------------------
36
+ //
37
+ // A recipe is no longer a floating island: its optional `related` block names
38
+ // what it **requires** (a prerequisite recipe or a precondition state), the
39
+ // **canonical** recipe it's a `variationOf` (one knob changed), and the concept
40
+ // / tutorial / resource pages worth reading to **learn more**. These are pure
41
+ // *metadata*, never execution — no recipe runs another; each still provisions
42
+ // and tears down its own world. They are a map read by the CLI (`rl recipes
43
+ // <id>`), the in-app recipe page, the agent (the recursion skill traverses
44
+ // them), and — later — the course generator. `recipes:check` validates that
45
+ // every target resolves and that the `requires` graph is acyclic.
46
+ /** A link to another **recipe** (traversable — the agent can follow it). */
47
+ export const RecipeRecipeTargetSchema = z
48
+ .object({ type: z.literal('recipe'), id: z.string().regex(KEBAB_CASE, 'id must be kebab-case') })
49
+ .strict();
50
+ /** A link to a **concept** (Explanation) page declared in `CONCEPT_REFERENCE`. */
51
+ export const RecipeConceptTargetSchema = z
52
+ .object({ type: z.literal('concept'), id: z.string().min(1) })
53
+ .strict();
54
+ /** A link to a **tutorial** page. */
55
+ export const RecipeTutorialTargetSchema = z
56
+ .object({ type: z.literal('tutorial'), id: z.string().min(1) })
57
+ .strict();
58
+ /** A link to a **resource** page. */
59
+ export const RecipeResourceTargetSchema = z
60
+ .object({ type: z.literal('resource'), id: z.string().min(1) })
61
+ .strict();
62
+ /**
63
+ * Any typed link target (`recipe | concept | tutorial | resource`). One typed
64
+ * model lets a recipe reference *any* doc element — relationships aren't only
65
+ * between recipes — instead of a separate field per kind.
66
+ */
67
+ export const RecipeLinkTargetSchema = z.discriminatedUnion('type', [
68
+ RecipeRecipeTargetSchema,
69
+ RecipeConceptTargetSchema,
70
+ RecipeTutorialTargetSchema,
71
+ RecipeResourceTargetSchema,
72
+ ]);
73
+ /**
74
+ * A `learnMore` target — the "why" behind the how-to: a concept / tutorial /
75
+ * resource. NOT a recipe (a recipe demonstrates; a concept explains — pairing
76
+ * them is what teaches the reader). The concept page lists its recipes via the
77
+ * inverse, so there's no second "taught by" field.
78
+ */
79
+ export const RecipeLearnMoreTargetSchema = z.discriminatedUnion('type', [
80
+ RecipeConceptTargetSchema,
81
+ RecipeTutorialTargetSchema,
82
+ RecipeResourceTargetSchema,
83
+ ]);
84
+ /**
85
+ * A `requires` entry that is a **state precondition** rather than a recipe — the
86
+ * common "the version must be locked" case that has no recipe of its own. It
87
+ * carries a human `explanation`, an optional machine-checkable `predicate`
88
+ * (e.g. `version.locked === true` — in L0 only *stored* and required to be a
89
+ * non-empty string; *evaluated* in a later layer), and an optional `via` link to
90
+ * whatever reaches the state (a recipe / concept / tutorial / resource).
91
+ */
92
+ export const RecipeStateRequirementSchema = z
93
+ .object({
94
+ type: z.literal('state'),
95
+ explanation: z.string().min(1),
96
+ predicate: z.string().min(1).optional(),
97
+ via: RecipeLinkTargetSchema.optional(),
98
+ })
99
+ .strict();
100
+ /**
101
+ * A typed prerequisite: another **recipe** (a real, followable edge — "author a
102
+ * problem before grading it") or a **state** precondition (the explanation +
103
+ * optional predicate above). The backbone an agent traverses off the `now what?`
104
+ * cliff.
105
+ */
106
+ export const RecipeRequiresEntrySchema = z.discriminatedUnion('type', [
107
+ RecipeRecipeTargetSchema,
108
+ RecipeStateRequirementSchema,
109
+ ]);
110
+ /**
111
+ * The optional `related` block on a recipe — its place in the graph. All fields
112
+ * optional; an absent block means "no declared relationships" (an island, which
113
+ * `recipes:check` permits but the docs nudge away from).
114
+ */
115
+ export const RecipeRelatedSchema = z
116
+ .object({
117
+ // Typed prerequisites (recipes and/or states) to satisfy before this recipe.
118
+ requires: z.array(RecipeRequiresEntrySchema).min(1).optional(),
119
+ // The canonical recipe this is a one-knob variation of (its id).
120
+ variationOf: z
121
+ .string()
122
+ .regex(KEBAB_CASE, 'variationOf must be a kebab-case recipe id')
123
+ .optional(),
124
+ // Related reading — the "why" behind the how-to.
125
+ learnMore: z.array(RecipeLearnMoreTargetSchema).min(1).optional(),
126
+ })
127
+ .strict();
128
+ /** A recipe's identity + docs metadata (`manifest.ts`). */
129
+ export const RecipeManifestSchema = z
130
+ .object({
131
+ // Stable kebab-case id; must match the recipe's folder name.
132
+ id: z.string().regex(KEBAB_CASE, 'id must be kebab-case'),
133
+ title: z.string().min(1),
134
+ // One-sentence statement of the user goal this recipe accomplishes.
135
+ goal: z.string().min(1),
136
+ // The canonical product domain this recipe lives under in the docs How-to nav
137
+ // (one of the eight `DOMAINS`). Kebab here; membership in `DOMAINS` is enforced
138
+ // fail-fast by `recipes:generate` (it can't import the domains module — schema
139
+ // files are loaded as source at codegen time, so they may only import npm deps).
140
+ category: z.string().regex(KEBAB_CASE, 'category must be kebab-case'),
141
+ // Internal CI validation cadence (required, no default — every recipe makes
142
+ // a deliberate tier choice). Read only by dx for smoke selection; NOT
143
+ // projected into the generated reference, so it never reaches the frontend.
144
+ cadence: RecipeCadenceSchema,
145
+ // Optional editorial one-liners for the walkthrough steps, keyed by the
146
+ // step's caption. Authored here (not captured), so editing copy is a fast
147
+ // `recipes:generate` — never a staging re-capture. Merged into the
148
+ // reference's walkthrough by `recipes:generate`.
149
+ stepDescriptions: z.record(z.string(), z.string()).optional(),
150
+ // The documented opt-out from the terminal GET-or-poll gate (`recipes:check`):
151
+ // every recipe must end its `main` phase by observing the user-meaningful
152
+ // outcome (a read or a `poll`). The ONLY exception is a last-mile step that
153
+ // genuinely has no API — e.g. the Intelligence reviewer's approval in
154
+ // `submit-and-review` — whose outcome is instead proven in `ui.spec`. Set this
155
+ // (with a non-empty reason naming the step) to satisfy the gate in that case.
156
+ outcomeInUiOnly: z
157
+ .object({ reason: z.string().min(1) })
158
+ .strict()
159
+ .optional(),
160
+ // The recipe's place in the relationship graph (prerequisites / canonical /
161
+ // related reading). Optional + additive; projected verbatim into the
162
+ // generated reference and validated by `recipes:check`.
163
+ related: RecipeRelatedSchema.optional(),
164
+ })
165
+ .strict();
166
+ /** A reference to a value captured by an earlier step (threading). */
167
+ export const RecipeRefSchema = z.object({ $ref: z.string().min(1) }).strict();
168
+ /**
169
+ * An input supplied to one of a step's params:
170
+ * - `{ $ref: '<captureName>' }` — threaded from an earlier step's capture.
171
+ * - `{ value: <json> }` — a literal rendered verbatim in the examples.
172
+ * Params not listed in a step's `inputs` render as placeholders (user-supplied).
173
+ */
174
+ export const RecipeInputSchema = z.union([
175
+ RecipeRefSchema,
176
+ z.object({ value: z.unknown() }).strict(),
177
+ ]);
178
+ /**
179
+ * A response-field condition: the value at `path` is one of `in`, OR (with
180
+ * `present: true`) is simply non-null. `present` gates on a field that only
181
+ * appears once the real outcome lands — e.g. `gradedAt`/`finalScore`, where the
182
+ * `status` string alone is ambiguous (a graded run passes through `completed`
183
+ * transiently before grading finalizes). Exactly one of `in` / `present`.
184
+ */
185
+ // A union of two CLOSED variants rather than one flat object with an `.refine`
186
+ // exclusivity check, so every consumer reads `cond.in` / `cond.present` with no
187
+ // `?? []` defence. Note the static guarantee is partial: authoring NEITHER field
188
+ // (`{ path }`) is a `satisfies RecipeApiInput` compile error (both variants
189
+ // require their discriminating field), but authoring BOTH (`{ path, in, present }`)
190
+ // still compiles — TypeScript's excess-property check treats a property as
191
+ // "known" if it appears in ANY union constituent — and is only rejected at
192
+ // runtime by the `.strict()` variants inside `recipes:generate`/`recipes:check`.
193
+ // (Root CLAUDE.md: "Leverage discriminated unions" / "Encode as much invariant
194
+ // information in the type system as possible".)
195
+ const RecipePollConditionSchema = z.union([
196
+ z
197
+ .object({
198
+ // A field path on the operation's response, in the same grammar `captures`
199
+ // uses (e.g. `status`, `result.grade`). Read each poll iteration.
200
+ path: z.string().min(1),
201
+ // The values that satisfy the condition (≥1). For `until`, these are the
202
+ // terminal-success states; for `failOn`, the terminal-failure states.
203
+ in: z.array(z.string()).min(1),
204
+ })
205
+ .strict(),
206
+ z
207
+ .object({
208
+ path: z.string().min(1),
209
+ // Satisfied as soon as the field is present (non-null) — e.g. a numeric
210
+ // `finalScore` (including `0`), where a `status` string alone is ambiguous.
211
+ present: z.literal(true),
212
+ })
213
+ .strict(),
214
+ ]);
215
+ /**
216
+ * A **poll** modifier on an SDK step: re-invoke this operation on an interval
217
+ * until it reaches a terminal state, *then* read its captures off that terminal
218
+ * response. This makes "wait for the result, then read it" a first-class,
219
+ * **documented** part of the recipe (rendered as a real loop in the SDK/CLI/cURL
220
+ * examples) rather than hidden test scaffolding — a recipe teaches the reader how
221
+ * to wait, exactly as the UI walkthrough does. The executor (`executeApiPlan`):
222
+ * - fails RED when `failOn` is set and its condition holds — `failOn.path`'s
223
+ * value is in `failOn.in` (or, with `present`, is non-null). Checked FIRST,
224
+ * so a terminal failure is surfaced, never masked by a coincident `until`.
225
+ * - stops successfully when `until` holds — `until.path`'s value is in
226
+ * `until.in`, or (with `present`) is non-null (e.g. `finalScore` landing).
227
+ * - fails RED when `timeoutMs` elapses first.
228
+ * Poll is SDK-only (an Intelligence step has no `operationId` to re-invoke).
229
+ */
230
+ export const RecipePollSchema = z
231
+ .object({
232
+ until: RecipePollConditionSchema,
233
+ failOn: RecipePollConditionSchema.optional(),
234
+ timeoutMs: z.number().int().positive(),
235
+ intervalMs: z.number().int().positive(),
236
+ })
237
+ .strict();
238
+ /**
239
+ * An SDK step — today's `operationId`-based call. `setup` steps render as a
240
+ * marked preamble (each recipe provisions its own setup); `main` steps are the
241
+ * goal proper. `kind` defaults to `'sdk'` so existing (kind-less) recipes stay
242
+ * valid and the common case needs no `kind:` line.
243
+ */
244
+ export const RecipeSdkStepSchema = z
245
+ .object({
246
+ kind: z.literal('sdk').default('sdk'),
247
+ operationId: z.string().min(1),
248
+ // Human caption — mirrors the matching `ui.spec` `test.step()` caption and
249
+ // doubles as the step heading in docs.
250
+ caption: z.string().optional(),
251
+ phase: z.enum(['setup', 'main']).default('main'),
252
+ // Param name → input value (threaded ref or literal).
253
+ inputs: z.record(z.string(), RecipeInputSchema).default({}),
254
+ // Optional poll: when set, this step waits for a terminal state (see
255
+ // RecipePollSchema) before reading its captures — the documented "wait for
256
+ // the result" step that lets a recipe prove its outcome.
257
+ poll: RecipePollSchema.optional(),
258
+ // Capture name → a field path on this operation's response shape.
259
+ captures: z.record(z.string(), z.string()).default({}),
260
+ })
261
+ .strict();
262
+ /**
263
+ * An Intelligence (Labelbox) step — a raw GraphQL command POSTed to
264
+ * `${LBX_URL}/api/_gql` with the SAME `Authorization: Bearer <LABELBOX_API_KEY>`
265
+ * the rl SDK/CLI already use. This surfaces the parts of a real flow that have
266
+ * no rl-gym SDK route (create a project, add a labeler, submit/review) so an
267
+ * agent reading the recipe gets the *complete* journey, not just the SDK slice.
268
+ * `caption` is REQUIRED — it is the user-facing instruction ("Create a project
269
+ * in Intelligence") that the whole feature exists to surface. `{ $ref }` markers
270
+ * embedded in `gql.variables` thread in earlier captures; `captures` reads
271
+ * fields off the GraphQL response's `data` object (e.g. `createProject.id`).
272
+ */
273
+ export const RecipeIntelligenceStepSchema = z
274
+ .object({
275
+ kind: z.literal('intelligence'),
276
+ caption: z.string().min(1),
277
+ phase: z.enum(['setup', 'main']).default('main'),
278
+ gql: z
279
+ .object({
280
+ query: z.string().min(1),
281
+ // GraphQL variables; values may embed `{ $ref: '<capture>' }` markers,
282
+ // resolved against earlier captures at execution + render time.
283
+ variables: z.record(z.string(), z.unknown()).default({}),
284
+ })
285
+ .strict(),
286
+ // Capture name → a dot/`[]` path on the GraphQL `data` response.
287
+ captures: z.record(z.string(), z.string()).default({}),
288
+ })
289
+ .strict();
290
+ /**
291
+ * One step of a recipe's `api.ts`: an SDK call or an Intelligence GraphQL
292
+ * command. A plain `z.union` (not `discriminatedUnion`) is deliberate — Zod 4's
293
+ * `discriminatedUnion` reads the discriminator BEFORE applying defaults, so a
294
+ * `kind`-less step would fail to match; `z.union` tries the SDK variant first,
295
+ * whose defaulted `kind` absorbs the omitted discriminator. TypeScript still
296
+ * narrows on the `kind` literal at the consumer.
297
+ */
298
+ export const RecipeApiStepSchema = z.union([RecipeSdkStepSchema, RecipeIntelligenceStepSchema]);
299
+ /** The ordered API plan for a recipe (`api.ts`). */
300
+ export const RecipeApiSchema = z
301
+ .object({
302
+ steps: z.array(RecipeApiStepSchema).min(1),
303
+ })
304
+ .strict();
305
+ // ---------------------------------------------------------------------------
306
+ // Generated reference entry — `recipes-reference.generated.ts`
307
+ // ---------------------------------------------------------------------------
308
+ /** A validated SDK step in the generated reference (phase/inputs/captures normalized). */
309
+ export const RecipeSdkReferenceStepSchema = z
310
+ .object({
311
+ kind: z.literal('sdk'),
312
+ operationId: z.string(),
313
+ caption: z.string().optional(),
314
+ phase: z.enum(['setup', 'main']),
315
+ inputs: z.record(z.string(), RecipeInputSchema),
316
+ // Mirrors the authoring step's `poll` (carried verbatim into the reference so
317
+ // the renderer can emit the wait-loop in the SDK/CLI/cURL examples).
318
+ poll: RecipePollSchema.optional(),
319
+ captures: z.record(z.string(), z.string()),
320
+ })
321
+ .strict();
322
+ /** A validated Intelligence step in the generated reference (normalized). */
323
+ export const RecipeIntelligenceReferenceStepSchema = z
324
+ .object({
325
+ kind: z.literal('intelligence'),
326
+ caption: z.string().min(1),
327
+ phase: z.enum(['setup', 'main']),
328
+ gql: z
329
+ .object({
330
+ query: z.string().min(1),
331
+ variables: z.record(z.string(), z.unknown()),
332
+ })
333
+ .strict(),
334
+ captures: z.record(z.string(), z.string()),
335
+ })
336
+ .strict();
337
+ /**
338
+ * A validated step in the generated reference. The reference is the *normalized*
339
+ * form (defaults already applied, so `kind` is always present) — a
340
+ * `discriminatedUnion` is safe here and gives precise per-variant errors.
341
+ */
342
+ export const RecipeReferenceStepSchema = z.discriminatedUnion('kind', [
343
+ RecipeSdkReferenceStepSchema,
344
+ RecipeIntelligenceReferenceStepSchema,
345
+ ]);
346
+ /**
347
+ * One step of the UI **walkthrough** — a user-facing caption next to its
348
+ * screenshot. Captured from the `ui.spec` run by `recipes:capture-media`
349
+ * (`image` is a filename under `apps/recursion/web/public/docs/recipes/<id>/`) and
350
+ * rendered as the docs Walkthrough filmstrip. The caption is page text beside
351
+ * the image, never burned into it.
352
+ */
353
+ export const RecipeWalkthroughStepSchema = z
354
+ .object({
355
+ caption: z.string().min(1),
356
+ image: z.string().min(1),
357
+ // Optional editorial one-liner (from the manifest's `stepDescriptions`),
358
+ // rendered under the caption. Absent in the captured manifest.
359
+ description: z.string().optional(),
360
+ })
361
+ .strict();
362
+ /** The committed walkthrough manifest (`walkthrough.json`): an ordered step list. */
363
+ export const RecipeWalkthroughSchema = z.array(RecipeWalkthroughStepSchema);
364
+ /**
365
+ * A composed example for one surface, split by phase: the `setup` preamble
366
+ * (provisioning steps — `phase: 'setup'`) and the `main` goal steps. The docs
367
+ * render `setup` as a collapsed disclosure so the recipe's actual point leads;
368
+ * concatenating `setup` + `main` is the full runnable script. Either may be the
369
+ * empty string (a recipe with no setup steps, or none in main).
370
+ */
371
+ export const RecipeSnippetSchema = z.object({ setup: z.string(), main: z.string() }).strict();
372
+ /**
373
+ * One recipe in the generated reference, keyed by id. Carries the docs
374
+ * metadata, the validated step plan, and the composed SDK/CLI/cURL examples
375
+ * (full runnable snippets with captured values threaded between steps), each
376
+ * split into a folded `setup` preamble + the `main` goal steps.
377
+ */
378
+ export const RecipeReferenceEntrySchema = z
379
+ .object({
380
+ id: z.string(),
381
+ title: z.string(),
382
+ goal: z.string(),
383
+ // The canonical domain (carried verbatim from the manifest) — keeps the docs
384
+ // How-to nav grouping 1:1 with the domain taxonomy. Membership validated by
385
+ // `recipes:generate`.
386
+ category: z.string().regex(KEBAB_CASE, 'category must be kebab-case'),
387
+ // Docs video path, derived as `<id>.mp4` by the generator (never authored).
388
+ // Always present: the generator sets it unconditionally from `id` (it is a
389
+ // derived path string, not captured content), so every generated entry has
390
+ // one. The file's existence — and a non-empty walkthrough — are separately
391
+ // presence-checked by `recipes:check` before a recipe can land.
392
+ video: z.string().min(1),
393
+ // Ordered UI walkthrough (caption + screenshot per step), captured from the
394
+ // ui.spec run. Empty until `recipes:capture-media` has been run.
395
+ walkthrough: z.array(RecipeWalkthroughStepSchema).default([]),
396
+ steps: z.array(RecipeReferenceStepSchema).min(1),
397
+ // Composed, ready-to-render examples per representation (setup + main split).
398
+ sdk: RecipeSnippetSchema,
399
+ cli: RecipeSnippetSchema,
400
+ curl: RecipeSnippetSchema,
401
+ // The recipe's place in the graph, carried verbatim from the manifest so
402
+ // every surface (CLI / frontend / agent) reads one source. Absent when the
403
+ // recipe declares no relationships.
404
+ related: RecipeRelatedSchema.optional(),
405
+ })
406
+ .strict();
@@ -0,0 +1,11 @@
1
+ /**
2
+ * AUTO-GENERATED by 'yarn dx resources:generate'.
3
+ * Do not edit manually — changes will be overwritten.
4
+ *
5
+ * Explanation-layer resource hubs, keyed by resource id (= the OpenAPI tag
6
+ * name). One hub per domain-resource tag; the resource tree (`parent`),
7
+ * object shape, operations, and relationships are all derived from the
8
+ * backend OpenAPI spec.
9
+ */
10
+ import type { ResourceReferenceEntry } from './resources-schema.js';
11
+ export declare const RESOURCE_REFERENCE: Record<string, ResourceReferenceEntry>;