@happyvertical/smrt-core 0.57.17 → 0.57.19
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/README.md +14 -0
- package/agents/build-knowledge.md +3 -0
- package/agents/cookbook-engine.md +2 -1
- package/dist/consumer-plugin/index.d.ts.map +1 -1
- package/dist/consumer-plugin/index.js +237 -10
- package/dist/consumer-plugin/index.js.map +1 -1
- package/dist/cookbook/engine/commands.d.ts.map +1 -1
- package/dist/cookbook/engine/commands.js +7 -2
- package/dist/cookbook/engine/commands.js.map +1 -1
- package/dist/cookbook/engine/document.d.ts.map +1 -1
- package/dist/cookbook/engine/document.js +2 -0
- package/dist/cookbook/engine/document.js.map +1 -1
- package/dist/cookbook/engine/engine.d.ts.map +1 -1
- package/dist/cookbook/engine/engine.js +1 -0
- package/dist/cookbook/engine/engine.js.map +1 -1
- package/dist/cookbook/engine/schemas.d.ts.map +1 -1
- package/dist/cookbook/engine/schemas.js +7 -1
- package/dist/cookbook/engine/schemas.js.map +1 -1
- package/dist/cookbook/engine/types.d.ts +3 -1
- package/dist/cookbook/engine/types.d.ts.map +1 -1
- package/dist/cookbook/engine/types.js.map +1 -1
- package/dist/cookbook/v1.schema.json +1 -0
- package/dist/cookbook/validate.d.ts.map +1 -1
- package/dist/cookbook/validate.js +6 -1
- package/dist/cookbook/validate.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/scripts/generate-manifest.js +1 -0
- package/dist/scripts/prepack.js +4 -0
- package/dist/scripts/verify-production-manifest.js +25 -0
- package/dist/smrt-knowledge.json +8 -7
- package/dist/utils/stack-frames.d.ts.map +1 -1
- package/dist/utils/stack-frames.js +10 -0
- package/dist/utils/stack-frames.js.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +15 -6
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/package.json +11 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","names":[],"sources":["../../../src/cookbook/engine/schemas.ts"],"sourcesContent":["import { DEFAULT_THEME_PRESETS, MAX_TERMS_LENGTH } from './defaults.js';\nimport type {\n CommandName,\n CommandTool,\n EngineCatalog,\n JsonSchema,\n} from './types.js';\n\nconst ids = (description: string, values?: readonly string[]): JsonSchema => ({\n type: 'array',\n description,\n minItems: 1,\n maxItems: 50,\n items: values?.length\n ? { type: 'string', enum: [...values] }\n : { type: 'string', minLength: 1 },\n});\n\nconst text = (description: string, extra: JsonSchema = {}): JsonSchema => ({\n type: 'string',\n description,\n minLength: 1,\n maxLength: 200,\n ...extra,\n});\n\nconst object = (\n properties: Record<string, JsonSchema>,\n required: string[] = [],\n): JsonSchema => ({\n type: 'object',\n properties,\n ...(required.length ? { required } : {}),\n additionalProperties: false,\n});\n\n/**\n * Every command as an MCP/LLM tool definition (`inputSchema` is JSON Schema\n * 2020-12). Recipe and cookbook ids become enums from the catalog, so\n * grammar-constrained decoding cannot name one that does not exist.\n */\nexport function buildCommandTools(catalog: EngineCatalog): CommandTool[] {\n const recipeIds = catalog.recipes.map((r) => r.id);\n const cookbookIds = (catalog.cookbooks ?? []).map((c) => c.id);\n const presets = catalog.themePresets ?? DEFAULT_THEME_PRESETS;\n const cookbookId = (description: string): JsonSchema => ({\n type: 'string',\n description,\n ...(cookbookIds.length ? { enum: [...cookbookIds] } : { minLength: 1 }),\n });\n const entryId = (what: string): JsonSchema =>\n text(`The id of ${what}, as the plan snapshot's \"sections\" lists it.`);\n const replace: JsonSchema = {\n type: 'boolean',\n description: 'Confirm replacing what is there.',\n };\n return [\n {\n name: 'add_recipes',\n description:\n 'Switch recipes on. Recipes they require come along. Returns what was added.',\n inputSchema: object({ ids: ids('Recipe ids to add.', recipeIds) }, [\n 'ids',\n ]),\n },\n {\n name: 'remove_recipes',\n description:\n 'Switch recipes off. A recipe another one needs is kept and reported.',\n inputSchema: object({ ids: ids('Recipe ids to remove.', recipeIds) }, [\n 'ids',\n ]),\n },\n {\n name: 'add_features',\n description:\n 'Add single models no recipe covers, by qualified name (`@scope/pkg:Class`).',\n inputSchema: object({ ids: ids('Qualified model names to add.') }, [\n 'ids',\n ]),\n },\n {\n name: 'remove_features',\n description: 'Remove single models added with add_features.',\n inputSchema: object({ ids: ids('Qualified model names to remove.') }, [\n 'ids',\n ]),\n },\n {\n name: 'add_cookbook',\n description:\n 'Add the recipes and features of a ready-made cookbook to the current app. Nothing is replaced.',\n inputSchema: object({ id: cookbookId('The cookbook to add.') }, ['id']),\n },\n {\n name: 'remove_cookbook',\n description:\n 'Remove the recipes and features a ready-made cookbook adds. Ones another recipe needs are kept.',\n inputSchema: object({ id: cookbookId('The cookbook to remove.') }, [\n 'id',\n ]),\n },\n {\n name: 'apply_cookbook',\n description:\n 'Select a ready-made cookbook: replace the whole app (recipes, options, menu, theme) with it. When the app has anything in it, replace must be true.',\n inputSchema: object(\n { id: cookbookId('The cookbook to set up.'), replace },\n ['id'],\n ),\n },\n {\n name: 'import_cookbook',\n description:\n 'Replace the whole app with a cookbook document (version 1). Checked strictly; nothing is applied if it is invalid. When the app has anything in it, replace must be true.',\n inputSchema: object(\n {\n document: {\n type: 'object',\n description: 'A cookbook document, version 1.',\n },\n replace,\n },\n ['document'],\n ),\n },\n {\n name: 'set_settings',\n description:\n 'Change app settings: currency, default tax rate (percent), default payment terms. Applies to new records only.',\n inputSchema: object({\n currency: catalog.currencies?.length\n ? {\n type: 'string',\n description: 'ISO 4217 code, e.g. CAD.',\n enum: [...catalog.currencies],\n }\n : {\n type: 'string',\n description: 'ISO 4217 code, e.g. CAD.',\n pattern: '^[A-Z]{3}$',\n },\n taxRate: {\n type: 'number',\n description: 'Default tax rate in percent, 0 to 100.',\n minimum: 0,\n maximum: 100,\n },\n paymentTerms: {\n type: 'string',\n description: 'Default payment terms, e.g. \"Net 30\".',\n minLength: 1,\n maxLength: MAX_TERMS_LENGTH,\n },\n pricesIncludeTax: {\n type: 'boolean',\n description: 'Whether new document prices include tax.',\n },\n taxRounding: {\n enum: ['line', 'document'],\n description: 'Whether tax rounds per line or per document.',\n },\n }),\n },\n {\n name: 'set_policy',\n description:\n \"Set one field's policy: default value, visibility, label or help. The model must be covered by a recipe or feature that is on. null clears a part.\",\n inputSchema: object(\n {\n model: text(\n 'Qualified model name, e.g. @happyvertical/smrt-commerce:Order.',\n ),\n field: text('The model field name.'),\n defaultValue: {\n description:\n 'The default as a JSON value (a string, number or boolean). null clears it.',\n },\n visibility: {\n enum: ['basic', 'advanced', 'hidden', null],\n description: 'Whether the field shows in forms and lists.',\n },\n label: {\n type: ['string', 'null'],\n description: 'A different label.',\n maxLength: 120,\n },\n help: {\n type: ['string', 'null'],\n description: 'Help text under the field.',\n maxLength: 400,\n },\n },\n ['model', 'field'],\n ),\n },\n {\n name: 'set_theme',\n description:\n 'Change the look: a preset, a brand colour, light or dark. A preset replaces a brand colour.',\n inputSchema: object({\n preset: { enum: [...presets], description: 'A built-in theme.' },\n primary: {\n type: 'string',\n description: 'Brand colour as #rrggbb.',\n pattern: '^#[0-9a-fA-F]{6}$',\n },\n colorScheme: {\n enum: ['light', 'dark', 'system'],\n description: 'Light, dark or follow the device.',\n },\n fontFamily: {\n type: ['string', 'null'],\n minLength: 1,\n description: 'Font key. Null restores the preset font.',\n },\n borderRadius: {\n enum: ['none', 'sm', 'md', 'lg', 'xl', 'full'],\n description: 'Corner roundness.',\n },\n density: {\n enum: ['comfortable', 'touch'],\n description: 'Control size: comfortable, or larger touch targets.',\n },\n contrast: {\n enum: ['auto', 'standard', 'more'],\n description:\n 'Contrast: auto follows the device, or force standard or more.',\n },\n }),\n },\n {\n name: 'reset_theme',\n description: 'Go back to the default look.',\n inputSchema: object({}),\n },\n {\n name: 'set_name',\n description: 'Name and describe the app. null clears a part.',\n inputSchema: object({\n name: { type: ['string', 'null'], minLength: 1, maxLength: 60 },\n description: {\n type: ['string', 'null'],\n minLength: 1,\n maxLength: 400,\n },\n }),\n },\n {\n name: 'rename_section',\n description: 'Rename a menu section.',\n inputSchema: object(\n {\n id: entryId('the section'),\n label: text('The new name.', { maxLength: 60 }),\n },\n ['id', 'label'],\n ),\n },\n {\n name: 'rename_item',\n description: 'Rename a menu entry. A null label restores its own name.',\n inputSchema: object(\n {\n id: entryId('the entry'),\n label: { type: ['string', 'null'], minLength: 1, maxLength: 60 },\n },\n ['id', 'label'],\n ),\n },\n {\n name: 'hide',\n description: 'Hide a menu section or entry. Nothing is deleted.',\n inputSchema: object({ id: entryId('the section or entry') }, ['id']),\n },\n {\n name: 'show',\n description: 'Show a hidden menu section or entry again.',\n inputSchema: object({ id: entryId('the section or entry') }, ['id']),\n },\n {\n name: 'validate',\n description:\n 'Check the current cookbook against the catalog and report typed diagnostics. Changes nothing.',\n inputSchema: object({}),\n },\n {\n name: 'export_cookbook',\n description:\n 'The cookbook as a <name>.cookbook.json file (text in the result). Changes nothing.',\n inputSchema: object({\n name: text('A name for the file.', { maxLength: 60 }),\n }),\n },\n {\n name: 'undo',\n description:\n 'Undo an earlier change by the undoId its receipt carried. Refused with a conflict when the plan changed since, unless force is true.',\n inputSchema: object(\n {\n undoId: text('The undoId from a receipt.'),\n force: {\n type: 'boolean',\n description: 'Undo even after later edits.',\n },\n },\n ['undoId'],\n ),\n },\n ];\n}\n\n/**\n * The batch envelope as a tool definition: several commands, applied\n * all-or-nothing. Commands inside are validated against their own schemas.\n */\nexport function buildBatchTool(catalog: EngineCatalog): {\n name: 'run_batch';\n description: string;\n inputSchema: JsonSchema;\n} {\n return {\n name: 'run_batch',\n description:\n 'Run several commands as one atomic batch: all apply or none does. A failure names the command and leaves the plan unchanged.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', minLength: 1, maxLength: 200 },\n expectedRevision: { type: 'integer', minimum: 0 },\n commands: {\n type: 'array',\n minItems: 1,\n maxItems: 50,\n items: {\n oneOf: buildCommandTools(catalog).map((tool) => ({\n type: 'object',\n properties: {\n name: { const: tool.name },\n input: tool.inputSchema,\n },\n required: ['name'],\n additionalProperties: false,\n })),\n },\n },\n },\n required: ['commands'],\n additionalProperties: false,\n },\n };\n}\n\nconst typeOf = (value: unknown): string =>\n value === null\n ? 'null'\n : Array.isArray(value)\n ? 'array'\n : Number.isInteger(value)\n ? 'integer'\n : typeof value;\n\nfunction typeMatches(wanted: string, value: unknown): boolean {\n const actual = typeOf(value);\n return actual === wanted || (wanted === 'number' && actual === 'integer');\n}\n\n/**\n * Check a value against a command schema (the subset the commands use). One\n * validator for runtime and exported schemas, so they cannot drift. Returns\n * the first problem as `{ path, message }`, or null.\n */\nexport function checkSchema(\n schema: JsonSchema,\n value: unknown,\n path = 'input',\n): { path: string; message: string } | null {\n const bad = (message: string) => ({ path, message: `${path} ${message}` });\n const type = schema.type as string | string[] | undefined;\n if (type) {\n const wanted = Array.isArray(type) ? type : [type];\n if (!wanted.some((t) => typeMatches(t, value))) {\n return bad(`must be ${wanted.join(' or ')}`);\n }\n }\n const choices = schema.enum as unknown[] | undefined;\n if (choices && !choices.includes(value)) {\n return bad(\n choices.length > 12\n ? 'is not a known value'\n : `must be one of ${choices.map((c) => JSON.stringify(c)).join(', ')}`,\n );\n }\n if (typeof value === 'string') {\n const { minLength, maxLength, pattern } = schema as {\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n };\n if (minLength !== undefined && value.length < minLength) {\n return bad('must not be empty');\n }\n if (maxLength !== undefined && value.length > maxLength) {\n return bad(`must be at most ${maxLength} characters`);\n }\n if (pattern && !new RegExp(pattern).test(value)) {\n return bad('has the wrong format');\n }\n }\n if (typeof value === 'number') {\n const { minimum, maximum } = schema as {\n minimum?: number;\n maximum?: number;\n };\n if (!Number.isFinite(value)) return bad('must be a finite number');\n if (minimum !== undefined && value < minimum) {\n return bad(`must be at least ${minimum}`);\n }\n if (maximum !== undefined && value > maximum) {\n return bad(`must be at most ${maximum}`);\n }\n }\n if (Array.isArray(value)) {\n const { minItems, maxItems, items } = schema as {\n minItems?: number;\n maxItems?: number;\n items?: JsonSchema;\n };\n if (minItems !== undefined && value.length < minItems) {\n return bad(`needs at least ${minItems} item${minItems === 1 ? '' : 's'}`);\n }\n if (maxItems !== undefined && value.length > maxItems) {\n return bad(`takes at most ${maxItems} items`);\n }\n if (items) {\n for (const [index, item] of value.entries()) {\n const problem = checkSchema(items, item, `${path}[${index}]`);\n if (problem) return problem;\n }\n }\n }\n if (typeOf(value) === 'object') {\n const object = value as Record<string, unknown>;\n const { properties, required, additionalProperties } = schema as {\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean;\n };\n for (const key of required ?? []) {\n if (object[key] === undefined) {\n return {\n path: `${path}.${key}`,\n message: `${path}.${key} is required`,\n };\n }\n }\n for (const [key, entry] of Object.entries(object)) {\n const child = properties?.[key];\n if (!child) {\n if (additionalProperties === false) {\n return {\n path: `${path}.${key}`,\n message: `${path}.${key} is not an option of this command`,\n };\n }\n continue;\n }\n if (entry === undefined) continue;\n const problem = checkSchema(child, entry, `${path}.${key}`);\n if (problem) return problem;\n }\n }\n return null;\n}\n\nexport type CommandSchemas = Readonly<Record<CommandName, JsonSchema>>;\n\n/** The input schemas by command name. */\nexport function commandSchemas(catalog: EngineCatalog): CommandSchemas {\n return Object.fromEntries(\n buildCommandTools(catalog).map((tool) => [tool.name, tool.inputSchema]),\n ) as CommandSchemas;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schemas.js","names":[],"sources":["../../../src/cookbook/engine/schemas.ts"],"sourcesContent":["import { DEFAULT_THEME_PRESETS, MAX_TERMS_LENGTH } from './defaults.js';\nimport type {\n CommandName,\n CommandTool,\n EngineCatalog,\n JsonSchema,\n} from './types.js';\n\nconst ids = (description: string, values?: readonly string[]): JsonSchema => ({\n type: 'array',\n description,\n minItems: 1,\n maxItems: 50,\n items: values?.length\n ? { type: 'string', enum: [...values] }\n : { type: 'string', minLength: 1 },\n});\n\nconst text = (description: string, extra: JsonSchema = {}): JsonSchema => ({\n type: 'string',\n description,\n minLength: 1,\n maxLength: 200,\n ...extra,\n});\n\nconst object = (\n properties: Record<string, JsonSchema>,\n required: string[] = [],\n): JsonSchema => ({\n type: 'object',\n properties,\n ...(required.length ? { required } : {}),\n additionalProperties: false,\n});\n\n/**\n * Every command as an MCP/LLM tool definition (`inputSchema` is JSON Schema\n * 2020-12). Recipe and cookbook ids become enums from the catalog, so\n * grammar-constrained decoding cannot name one that does not exist.\n */\nexport function buildCommandTools(catalog: EngineCatalog): CommandTool[] {\n const recipeIds = catalog.recipes.map((r) => r.id);\n const cookbookIds = (catalog.cookbooks ?? []).map((c) => c.id);\n const presets = catalog.themePresets ?? DEFAULT_THEME_PRESETS;\n const cookbookId = (description: string): JsonSchema => ({\n type: 'string',\n description,\n ...(cookbookIds.length ? { enum: [...cookbookIds] } : { minLength: 1 }),\n });\n const entryId = (what: string): JsonSchema =>\n text(`The id of ${what}, as the plan snapshot's \"sections\" lists it.`);\n const replace: JsonSchema = {\n type: 'boolean',\n description: 'Confirm replacing what is there.',\n };\n return [\n {\n name: 'add_recipes',\n description:\n 'Switch recipes on. Recipes they require come along. Returns what was added.',\n inputSchema: object({ ids: ids('Recipe ids to add.', recipeIds) }, [\n 'ids',\n ]),\n },\n {\n name: 'remove_recipes',\n description:\n 'Switch recipes off. A recipe another one needs is kept and reported.',\n inputSchema: object({ ids: ids('Recipe ids to remove.', recipeIds) }, [\n 'ids',\n ]),\n },\n {\n name: 'add_features',\n description:\n 'Add single models no recipe covers, by qualified name (`@scope/pkg:Class`).',\n inputSchema: object({ ids: ids('Qualified model names to add.') }, [\n 'ids',\n ]),\n },\n {\n name: 'remove_features',\n description: 'Remove single models added with add_features.',\n inputSchema: object({ ids: ids('Qualified model names to remove.') }, [\n 'ids',\n ]),\n },\n {\n name: 'add_cookbook',\n description:\n 'Add the recipes and features of a ready-made cookbook to the current app. Nothing is replaced.',\n inputSchema: object({ id: cookbookId('The cookbook to add.') }, ['id']),\n },\n {\n name: 'remove_cookbook',\n description:\n 'Remove the recipes and features a ready-made cookbook adds. Ones another recipe needs are kept.',\n inputSchema: object({ id: cookbookId('The cookbook to remove.') }, [\n 'id',\n ]),\n },\n {\n name: 'apply_cookbook',\n description:\n 'Select a ready-made cookbook: replace the whole app (recipes, options, menu, theme) with it. When the app has anything in it, replace must be true.',\n inputSchema: object(\n { id: cookbookId('The cookbook to set up.'), replace },\n ['id'],\n ),\n },\n {\n name: 'import_cookbook',\n description:\n 'Replace the whole app with a cookbook document (version 1). Checked strictly; nothing is applied if it is invalid. When the app has anything in it, replace must be true.',\n inputSchema: object(\n {\n document: {\n type: 'object',\n description: 'A cookbook document, version 1.',\n },\n replace,\n },\n ['document'],\n ),\n },\n {\n name: 'set_settings',\n description:\n 'Change app settings: currency, default tax rate (percent), default payment terms. Applies to new records only.',\n inputSchema: object({\n currency: catalog.currencies?.length\n ? {\n type: 'string',\n description: 'ISO 4217 code, e.g. CAD.',\n enum: [...catalog.currencies],\n }\n : {\n type: 'string',\n description: 'ISO 4217 code, e.g. CAD.',\n pattern: '^[A-Z]{3}$',\n },\n taxRate: {\n type: 'number',\n description: 'Default tax rate in percent, 0 to 100.',\n minimum: 0,\n maximum: 100,\n },\n paymentTerms: {\n type: 'string',\n description: 'Default payment terms, e.g. \"Net 30\".',\n minLength: 1,\n maxLength: MAX_TERMS_LENGTH,\n },\n pricesIncludeTax: {\n type: 'boolean',\n description: 'Whether new document prices include tax.',\n },\n taxRounding: {\n enum: ['line', 'document'],\n description: 'Whether tax rounds per line or per document.',\n },\n }),\n },\n {\n name: 'set_policy',\n description:\n \"Set one field's policy: default value, visibility, label or help. The model must be covered by a recipe or feature that is on. null clears a part.\",\n inputSchema: object(\n {\n model: text(\n 'Qualified model name, e.g. @happyvertical/smrt-commerce:Order.',\n ),\n field: text('The model field name.'),\n defaultValue: {\n description:\n 'The default as a JSON value (a string, number or boolean). null clears it.',\n },\n visibility: {\n enum: ['basic', 'advanced', 'hidden', null],\n description: 'Whether the field shows in forms and lists.',\n },\n label: {\n type: ['string', 'null'],\n description: 'A different label.',\n maxLength: 120,\n },\n help: {\n type: ['string', 'null'],\n description: 'Help text under the field.',\n maxLength: 400,\n },\n },\n ['model', 'field'],\n ),\n },\n {\n name: 'set_theme',\n description:\n 'Change the look: a preset, a brand colour, light or dark. A preset replaces a brand colour.',\n inputSchema: object({\n preset: { enum: [...presets], description: 'A built-in theme.' },\n primary: {\n type: 'string',\n description: 'Brand colour as #rrggbb.',\n pattern: '^#[0-9a-fA-F]{6}$',\n },\n colorScheme: {\n enum: ['light', 'dark', 'system'],\n description: 'Light, dark or follow the device.',\n },\n fontFamily: {\n type: ['string', 'null'],\n minLength: 1,\n description: 'Font key. Null restores the preset font.',\n },\n borderRadius: {\n enum: ['none', 'sm', 'md', 'lg', 'xl', 'full'],\n description: 'Corner roundness.',\n },\n density: {\n enum: ['comfortable', 'touch'],\n description: 'Control size: comfortable, or larger touch targets.',\n },\n contrast: {\n enum: ['auto', 'standard', 'more'],\n description:\n 'Contrast: auto follows the device, or force standard or more.',\n },\n }),\n },\n {\n name: 'reset_theme',\n description: 'Go back to the default look.',\n inputSchema: object({}),\n },\n {\n name: 'set_name',\n description: 'Name, describe and specify the app. null clears a part.',\n inputSchema: object({\n name: { type: ['string', 'null'], minLength: 1, maxLength: 60 },\n description: {\n type: ['string', 'null'],\n minLength: 1,\n maxLength: 400,\n },\n specs: {\n type: ['string', 'null'],\n minLength: 1,\n maxLength: 20000,\n description:\n 'Product requirements beyond recipes and features, as plain text or a short list.',\n },\n }),\n },\n {\n name: 'rename_section',\n description: 'Rename a menu section.',\n inputSchema: object(\n {\n id: entryId('the section'),\n label: text('The new name.', { maxLength: 60 }),\n },\n ['id', 'label'],\n ),\n },\n {\n name: 'rename_item',\n description: 'Rename a menu entry. A null label restores its own name.',\n inputSchema: object(\n {\n id: entryId('the entry'),\n label: { type: ['string', 'null'], minLength: 1, maxLength: 60 },\n },\n ['id', 'label'],\n ),\n },\n {\n name: 'hide',\n description: 'Hide a menu section or entry. Nothing is deleted.',\n inputSchema: object({ id: entryId('the section or entry') }, ['id']),\n },\n {\n name: 'show',\n description: 'Show a hidden menu section or entry again.',\n inputSchema: object({ id: entryId('the section or entry') }, ['id']),\n },\n {\n name: 'validate',\n description:\n 'Check the current cookbook against the catalog and report typed diagnostics. Changes nothing.',\n inputSchema: object({}),\n },\n {\n name: 'export_cookbook',\n description:\n 'The cookbook as a <name>.cookbook.json file (text in the result). Changes nothing.',\n inputSchema: object({\n name: text('A name for the file.', { maxLength: 60 }),\n }),\n },\n {\n name: 'undo',\n description:\n 'Undo an earlier change by the undoId its receipt carried. Refused with a conflict when the plan changed since, unless force is true.',\n inputSchema: object(\n {\n undoId: text('The undoId from a receipt.'),\n force: {\n type: 'boolean',\n description: 'Undo even after later edits.',\n },\n },\n ['undoId'],\n ),\n },\n ];\n}\n\n/**\n * The batch envelope as a tool definition: several commands, applied\n * all-or-nothing. Commands inside are validated against their own schemas.\n */\nexport function buildBatchTool(catalog: EngineCatalog): {\n name: 'run_batch';\n description: string;\n inputSchema: JsonSchema;\n} {\n return {\n name: 'run_batch',\n description:\n 'Run several commands as one atomic batch: all apply or none does. A failure names the command and leaves the plan unchanged.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', minLength: 1, maxLength: 200 },\n expectedRevision: { type: 'integer', minimum: 0 },\n commands: {\n type: 'array',\n minItems: 1,\n maxItems: 50,\n items: {\n oneOf: buildCommandTools(catalog).map((tool) => ({\n type: 'object',\n properties: {\n name: { const: tool.name },\n input: tool.inputSchema,\n },\n required: ['name'],\n additionalProperties: false,\n })),\n },\n },\n },\n required: ['commands'],\n additionalProperties: false,\n },\n };\n}\n\nconst typeOf = (value: unknown): string =>\n value === null\n ? 'null'\n : Array.isArray(value)\n ? 'array'\n : Number.isInteger(value)\n ? 'integer'\n : typeof value;\n\nfunction typeMatches(wanted: string, value: unknown): boolean {\n const actual = typeOf(value);\n return actual === wanted || (wanted === 'number' && actual === 'integer');\n}\n\n/**\n * Check a value against a command schema (the subset the commands use). One\n * validator for runtime and exported schemas, so they cannot drift. Returns\n * the first problem as `{ path, message }`, or null.\n */\nexport function checkSchema(\n schema: JsonSchema,\n value: unknown,\n path = 'input',\n): { path: string; message: string } | null {\n const bad = (message: string) => ({ path, message: `${path} ${message}` });\n const type = schema.type as string | string[] | undefined;\n if (type) {\n const wanted = Array.isArray(type) ? type : [type];\n if (!wanted.some((t) => typeMatches(t, value))) {\n return bad(`must be ${wanted.join(' or ')}`);\n }\n }\n const choices = schema.enum as unknown[] | undefined;\n if (choices && !choices.includes(value)) {\n return bad(\n choices.length > 12\n ? 'is not a known value'\n : `must be one of ${choices.map((c) => JSON.stringify(c)).join(', ')}`,\n );\n }\n if (typeof value === 'string') {\n const { minLength, maxLength, pattern } = schema as {\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n };\n if (minLength !== undefined && value.length < minLength) {\n return bad('must not be empty');\n }\n if (maxLength !== undefined && value.length > maxLength) {\n return bad(`must be at most ${maxLength} characters`);\n }\n if (pattern && !new RegExp(pattern).test(value)) {\n return bad('has the wrong format');\n }\n }\n if (typeof value === 'number') {\n const { minimum, maximum } = schema as {\n minimum?: number;\n maximum?: number;\n };\n if (!Number.isFinite(value)) return bad('must be a finite number');\n if (minimum !== undefined && value < minimum) {\n return bad(`must be at least ${minimum}`);\n }\n if (maximum !== undefined && value > maximum) {\n return bad(`must be at most ${maximum}`);\n }\n }\n if (Array.isArray(value)) {\n const { minItems, maxItems, items } = schema as {\n minItems?: number;\n maxItems?: number;\n items?: JsonSchema;\n };\n if (minItems !== undefined && value.length < minItems) {\n return bad(`needs at least ${minItems} item${minItems === 1 ? '' : 's'}`);\n }\n if (maxItems !== undefined && value.length > maxItems) {\n return bad(`takes at most ${maxItems} items`);\n }\n if (items) {\n for (const [index, item] of value.entries()) {\n const problem = checkSchema(items, item, `${path}[${index}]`);\n if (problem) return problem;\n }\n }\n }\n if (typeOf(value) === 'object') {\n const object = value as Record<string, unknown>;\n const { properties, required, additionalProperties } = schema as {\n properties?: Record<string, JsonSchema>;\n required?: string[];\n additionalProperties?: boolean;\n };\n for (const key of required ?? []) {\n if (object[key] === undefined) {\n return {\n path: `${path}.${key}`,\n message: `${path}.${key} is required`,\n };\n }\n }\n for (const [key, entry] of Object.entries(object)) {\n const child = properties?.[key];\n if (!child) {\n if (additionalProperties === false) {\n return {\n path: `${path}.${key}`,\n message: `${path}.${key} is not an option of this command`,\n };\n }\n continue;\n }\n if (entry === undefined) continue;\n const problem = checkSchema(child, entry, `${path}.${key}`);\n if (problem) return problem;\n }\n }\n return null;\n}\n\nexport type CommandSchemas = Readonly<Record<CommandName, JsonSchema>>;\n\n/** The input schemas by command name. */\nexport function commandSchemas(catalog: EngineCatalog): CommandSchemas {\n return Object.fromEntries(\n buildCommandTools(catalog).map((tool) => [tool.name, tool.inputSchema]),\n ) as CommandSchemas;\n}\n"],"mappings":"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"}
|
|
@@ -126,10 +126,11 @@ export interface CommandInputs {
|
|
|
126
126
|
contrast?: 'auto' | 'standard' | 'more';
|
|
127
127
|
};
|
|
128
128
|
reset_theme: Record<string, never>;
|
|
129
|
-
/** Name
|
|
129
|
+
/** Name, describe and specify the app; null clears a part. */
|
|
130
130
|
set_name: {
|
|
131
131
|
name?: string | null;
|
|
132
132
|
description?: string | null;
|
|
133
|
+
specs?: string | null;
|
|
133
134
|
};
|
|
134
135
|
rename_section: {
|
|
135
136
|
id: string;
|
|
@@ -201,6 +202,7 @@ export interface PlanSnapshot {
|
|
|
201
202
|
app: {
|
|
202
203
|
name: string;
|
|
203
204
|
description: string | null;
|
|
205
|
+
specs: string | null;
|
|
204
206
|
cookbook: string | null;
|
|
205
207
|
};
|
|
206
208
|
recipes: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cookbook/engine/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cookbook/engine/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../../src/cookbook/engine/types.ts"],"sourcesContent":["/**\n * Cookbook command engine, contract v1 (#3753).\n *\n * Plain data in, plain data out: no SvelteKit, browser storage, planner\n * singleton or inference dependency, and no Node imports, so the same engine\n * runs in a browser planner, a CLI, an MCP server or a website. Adapters own\n * navigation/focus, persistence and transport; the engine owns the document.\n */\nimport type { Cookbook, RecipeDefinition } from '@happyvertical/smrt-types';\n\n/**\n * The command set version. A change an older client could not send or read\n * bumps it; adding a command or an optional field does not.\n */\nexport const COOKBOOK_COMMANDS_VERSION = 1;\n\n/** The part of a manifest recipe the engine reads (a `RecipeDefinition` fits). */\nexport type EngineRecipe = Pick<\n RecipeDefinition,\n 'id' | 'label' | 'models' | 'nav' | 'requires'\n> &\n Partial<\n Pick<RecipeDefinition, 'requiresAny' | 'group' | 'section' | 'options'>\n >;\n\n/** One field of a catalog model, for `set_policy` and settings defaults. */\nexport interface EngineField {\n name: string;\n /** System fields (id, timestamps) cannot be given a policy. */\n system?: boolean;\n /** The field's own starting value, so a setting equal to it writes no row. */\n default?: unknown;\n}\n\n/** One catalog model. Same shape as smrt-svelte's `CookbookModelInfo`, plus fields. */\nexport interface EngineModel {\n /** Qualified name, `@scope/pkg:Class`. */\n id: string;\n name: string;\n /** Package id used in item ids: `commerce` for `@happyvertical/smrt-commerce`. */\n packageId: string;\n description?: string;\n /** Has an API, MCP or CLI surface; only exposed models can be added as features. */\n exposed?: boolean;\n /** When given, `set_policy` rejects a field not listed. */\n fields?: readonly EngineField[];\n}\n\n/** A ready-made cookbook the catalog offers (a library entry). */\nexport interface EngineLibraryCookbook {\n id: string;\n name: string;\n document: Cookbook;\n}\n\n/** Which model fields each app setting is the default of. */\nexport type SettingTargets = Record<\n 'currency' | 'taxRate' | 'paymentTerms' | 'pricesIncludeTax' | 'taxRounding',\n readonly { model: string; field: string }[]\n>;\n\n/**\n * Everything the engine resolves ids against, as data: recipes and models from\n * published manifests, optionally a library of cookbooks. Nothing here is\n * bundled with the engine.\n */\nexport interface EngineCatalog {\n recipes: readonly EngineRecipe[];\n models: readonly EngineModel[];\n cookbooks?: readonly EngineLibraryCookbook[];\n /** Movable shell item ids resolved by the host (`dock:`, `slot:`, recipe, or host ids). */\n placementItems?: readonly string[];\n /** Theme preset names; default {@link DEFAULT_THEME_PRESETS}. */\n themePresets?: readonly string[];\n /** ISO 4217 codes; default any three capital letters. */\n currencies?: readonly string[];\n /** Default {@link COMMERCE_SETTING_TARGETS}. */\n settingTargets?: SettingTargets;\n}\n\n/** Input of each command, keyed by the command's (tool) name. */\nexport interface CommandInputs {\n /** Switch recipes on, with everything they `require`. */\n add_recipes: { ids: string[] };\n /** Switch recipes off; ones another recipe needs are kept (and reported). */\n remove_recipes: { ids: string[] };\n /** Add models no recipe covers, by qualified name. */\n add_features: { ids: string[] };\n remove_features: { ids: string[] };\n /** Add the recipes and features of a library cookbook to what is there. */\n add_cookbook: { id: string };\n /** Remove what a library cookbook added (recipes others need are kept). */\n remove_cookbook: { id: string };\n /** Select a library cookbook, replacing the app (needs `replace` if non-empty). */\n apply_cookbook: { id: string; replace?: boolean };\n /** Import a cookbook document, replacing the app (needs `replace` if non-empty). */\n import_cookbook: { document: unknown; replace?: boolean };\n /** App settings; tax rate in percent, 0 to 100. */\n set_settings: {\n currency?: string;\n taxRate?: number;\n paymentTerms?: string;\n pricesIncludeTax?: boolean;\n taxRounding?: 'line' | 'document';\n };\n /** Set (or clear with null) one field's policy row. App scope. */\n set_policy: {\n model: string;\n field: string;\n defaultValue?: unknown;\n visibility?: 'basic' | 'advanced' | 'hidden' | null;\n label?: string | null;\n help?: string | null;\n };\n set_theme: {\n preset?: string;\n primary?: string;\n colorScheme?: 'light' | 'dark' | 'system';\n fontFamily?: string | null;\n borderRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';\n density?: 'comfortable' | 'touch';\n contrast?: 'auto' | 'standard' | 'more';\n };\n reset_theme: Record<string, never>;\n /** Name (and describe) the app; null clears. */\n set_name: { name?: string | null; description?: string | null };\n rename_section: { id: string; label: string };\n /** `null` restores the entry's own name. */\n rename_item: { id: string; label: string | null };\n hide: { id: string };\n show: { id: string };\n /** Check the current document and report typed diagnostics. Changes nothing. */\n validate: Record<string, never>;\n /** The cookbook as `<name>.cookbook.json` text. Changes nothing. */\n export_cookbook: { name?: string };\n /** Undo an earlier change by the `undoId` its receipt carried. */\n undo: { undoId: string; force?: boolean };\n}\n\nexport type CommandName = keyof CommandInputs;\n\n/** A command as a client sends it. */\nexport type CookbookCommand = {\n [N in CommandName]: {\n name: N;\n input: CommandInputs[N];\n /** Retry key: a repeated id returns the first receipt and applies nothing. */\n id?: string;\n /** Refuse with `conflict` unless the plan is still at this revision. */\n expectedRevision?: number;\n };\n}[CommandName];\n\n/** Stable strings a client can switch on. */\nexport type CommandErrorCode =\n | 'unknown_command'\n | 'invalid_input'\n | 'not_found'\n /** A destructive command needs `replace: true` (or `force: true`). */\n | 'confirmation_required'\n /** The plan moved on since the caller looked (`expectedRevision`, undo). */\n | 'conflict'\n /** A command id was reused with a different command. */\n | 'id_reuse'\n /** An atomic batch failed; `details.index` names the command, nothing applied. */\n | 'batch_failed'\n | 'failed';\n\nexport interface CommandError {\n code: CommandErrorCode;\n message: string;\n /** Where the problem is, as a path into the input (`input.ids[1]`). */\n path?: string;\n details?: Record<string, unknown>;\n}\n\n/** What a recipe/feature command did, after `requires` ran. */\nexport interface RecipeChanges {\n added: string[];\n removed: string[];\n /** Asked to remove, but another recipe still needs them. */\n kept: string[];\n}\n\nexport interface PlanSnapshot {\n version: typeof COOKBOOK_COMMANDS_VERSION;\n /** Counts applied changes; equal histories give equal revisions. */\n revision: number;\n app: { name: string; description: string | null; cookbook: string | null };\n recipes: { id: string; label: string }[];\n features: string[];\n /** Recipe and feature ids this catalog lacks; kept on export. */\n unavailable: string[];\n settings: {\n currency: string;\n taxRate: number;\n paymentTerms: string;\n pricesIncludeTax: boolean;\n taxRounding: 'line' | 'document';\n };\n theme: {\n text: string;\n preset: string | null;\n primary: string | null;\n colorScheme: string;\n borderRadius: string | null;\n density: string | null;\n contrast: string | null;\n };\n sections: {\n id: string;\n label: string;\n hidden: boolean;\n items: { id: string; label: string; hidden: boolean }[];\n }[];\n policies: number;\n /** Undo ids still available, newest last. */\n undo: string[];\n}\n\nexport interface CommandReceipt {\n name: CommandName;\n /** The command id, when one was sent. */\n id?: string;\n summary: string;\n changed: boolean;\n revisionBefore: number;\n revisionAfter: number;\n undoId?: string;\n changes?: RecipeChanges;\n /** Non-fatal notes (an import's legacy `$schema` migration). */\n warnings?: string[];\n}\n\nexport type CommandResult =\n | {\n ok: true;\n id?: string;\n /** True when this is the stored result of an earlier run of the same id. */\n replayed?: boolean;\n snapshot: PlanSnapshot;\n receipt: CommandReceipt;\n data?: unknown;\n }\n | { ok: false; id?: string; replayed?: boolean; error: CommandError };\n\nexport interface RunOptions {\n expectedRevision?: number;\n}\n\n/** Several commands applied all-or-nothing. */\nexport interface CommandBatch {\n id?: string;\n commands: readonly unknown[];\n expectedRevision?: number;\n}\n\nexport type BatchResult =\n | {\n ok: true;\n id?: string;\n replayed?: boolean;\n snapshot: PlanSnapshot;\n receipt: {\n id?: string;\n count: number;\n changed: boolean;\n revisionBefore: number;\n revisionAfter: number;\n undoId?: string;\n };\n /** One result per command, in order. */\n results: Extract<CommandResult, { ok: true }>[];\n }\n | {\n ok: false;\n id?: string;\n replayed?: boolean;\n error: CommandError;\n /** The state is exactly as before the batch. */\n snapshot: PlanSnapshot;\n };\n\n/** One diagnostic from `validate`. */\nexport interface Diagnostic {\n severity: 'error' | 'warning';\n code: string;\n path: string;\n message: string;\n}\n\nexport interface ValidateData {\n ok: boolean;\n diagnostics: Diagnostic[];\n}\n\nexport interface ExportData {\n fileName: string;\n text: string;\n cookbook: Cookbook;\n}\n\n/** A journal row: enough to answer a retry of `id` after a restart. */\nexport interface JournalEntry {\n id: string;\n fingerprint: string;\n result: CommandResult | BatchResult;\n}\n\n/** The engine's whole state as plain JSON, to persist and resume from. */\nexport interface EngineState {\n version: typeof COOKBOOK_COMMANDS_VERSION;\n revision: number;\n /** The library cookbook the plan was last set up from, if any. */\n applied: string | null;\n cookbook: Cookbook;\n journal: JournalEntry[];\n}\n\nexport interface JsonSchema {\n [key: string]: unknown;\n}\n\n/** One command as an LLM or MCP tool definition. */\nexport interface CommandTool {\n name: CommandName;\n description: string;\n inputSchema: JsonSchema;\n}\n"],"mappings":";;;;;AAcA,IAAa,4BAA4B"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../src/cookbook/engine/types.ts"],"sourcesContent":["/**\n * Cookbook command engine, contract v1 (#3753).\n *\n * Plain data in, plain data out: no SvelteKit, browser storage, planner\n * singleton or inference dependency, and no Node imports, so the same engine\n * runs in a browser planner, a CLI, an MCP server or a website. Adapters own\n * navigation/focus, persistence and transport; the engine owns the document.\n */\nimport type { Cookbook, RecipeDefinition } from '@happyvertical/smrt-types';\n\n/**\n * The command set version. A change an older client could not send or read\n * bumps it; adding a command or an optional field does not.\n */\nexport const COOKBOOK_COMMANDS_VERSION = 1;\n\n/** The part of a manifest recipe the engine reads (a `RecipeDefinition` fits). */\nexport type EngineRecipe = Pick<\n RecipeDefinition,\n 'id' | 'label' | 'models' | 'nav' | 'requires'\n> &\n Partial<\n Pick<RecipeDefinition, 'requiresAny' | 'group' | 'section' | 'options'>\n >;\n\n/** One field of a catalog model, for `set_policy` and settings defaults. */\nexport interface EngineField {\n name: string;\n /** System fields (id, timestamps) cannot be given a policy. */\n system?: boolean;\n /** The field's own starting value, so a setting equal to it writes no row. */\n default?: unknown;\n}\n\n/** One catalog model. Same shape as smrt-svelte's `CookbookModelInfo`, plus fields. */\nexport interface EngineModel {\n /** Qualified name, `@scope/pkg:Class`. */\n id: string;\n name: string;\n /** Package id used in item ids: `commerce` for `@happyvertical/smrt-commerce`. */\n packageId: string;\n description?: string;\n /** Has an API, MCP or CLI surface; only exposed models can be added as features. */\n exposed?: boolean;\n /** When given, `set_policy` rejects a field not listed. */\n fields?: readonly EngineField[];\n}\n\n/** A ready-made cookbook the catalog offers (a library entry). */\nexport interface EngineLibraryCookbook {\n id: string;\n name: string;\n document: Cookbook;\n}\n\n/** Which model fields each app setting is the default of. */\nexport type SettingTargets = Record<\n 'currency' | 'taxRate' | 'paymentTerms' | 'pricesIncludeTax' | 'taxRounding',\n readonly { model: string; field: string }[]\n>;\n\n/**\n * Everything the engine resolves ids against, as data: recipes and models from\n * published manifests, optionally a library of cookbooks. Nothing here is\n * bundled with the engine.\n */\nexport interface EngineCatalog {\n recipes: readonly EngineRecipe[];\n models: readonly EngineModel[];\n cookbooks?: readonly EngineLibraryCookbook[];\n /** Movable shell item ids resolved by the host (`dock:`, `slot:`, recipe, or host ids). */\n placementItems?: readonly string[];\n /** Theme preset names; default {@link DEFAULT_THEME_PRESETS}. */\n themePresets?: readonly string[];\n /** ISO 4217 codes; default any three capital letters. */\n currencies?: readonly string[];\n /** Default {@link COMMERCE_SETTING_TARGETS}. */\n settingTargets?: SettingTargets;\n}\n\n/** Input of each command, keyed by the command's (tool) name. */\nexport interface CommandInputs {\n /** Switch recipes on, with everything they `require`. */\n add_recipes: { ids: string[] };\n /** Switch recipes off; ones another recipe needs are kept (and reported). */\n remove_recipes: { ids: string[] };\n /** Add models no recipe covers, by qualified name. */\n add_features: { ids: string[] };\n remove_features: { ids: string[] };\n /** Add the recipes and features of a library cookbook to what is there. */\n add_cookbook: { id: string };\n /** Remove what a library cookbook added (recipes others need are kept). */\n remove_cookbook: { id: string };\n /** Select a library cookbook, replacing the app (needs `replace` if non-empty). */\n apply_cookbook: { id: string; replace?: boolean };\n /** Import a cookbook document, replacing the app (needs `replace` if non-empty). */\n import_cookbook: { document: unknown; replace?: boolean };\n /** App settings; tax rate in percent, 0 to 100. */\n set_settings: {\n currency?: string;\n taxRate?: number;\n paymentTerms?: string;\n pricesIncludeTax?: boolean;\n taxRounding?: 'line' | 'document';\n };\n /** Set (or clear with null) one field's policy row. App scope. */\n set_policy: {\n model: string;\n field: string;\n defaultValue?: unknown;\n visibility?: 'basic' | 'advanced' | 'hidden' | null;\n label?: string | null;\n help?: string | null;\n };\n set_theme: {\n preset?: string;\n primary?: string;\n colorScheme?: 'light' | 'dark' | 'system';\n fontFamily?: string | null;\n borderRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';\n density?: 'comfortable' | 'touch';\n contrast?: 'auto' | 'standard' | 'more';\n };\n reset_theme: Record<string, never>;\n /** Name, describe and specify the app; null clears a part. */\n set_name: {\n name?: string | null;\n description?: string | null;\n specs?: string | null;\n };\n rename_section: { id: string; label: string };\n /** `null` restores the entry's own name. */\n rename_item: { id: string; label: string | null };\n hide: { id: string };\n show: { id: string };\n /** Check the current document and report typed diagnostics. Changes nothing. */\n validate: Record<string, never>;\n /** The cookbook as `<name>.cookbook.json` text. Changes nothing. */\n export_cookbook: { name?: string };\n /** Undo an earlier change by the `undoId` its receipt carried. */\n undo: { undoId: string; force?: boolean };\n}\n\nexport type CommandName = keyof CommandInputs;\n\n/** A command as a client sends it. */\nexport type CookbookCommand = {\n [N in CommandName]: {\n name: N;\n input: CommandInputs[N];\n /** Retry key: a repeated id returns the first receipt and applies nothing. */\n id?: string;\n /** Refuse with `conflict` unless the plan is still at this revision. */\n expectedRevision?: number;\n };\n}[CommandName];\n\n/** Stable strings a client can switch on. */\nexport type CommandErrorCode =\n | 'unknown_command'\n | 'invalid_input'\n | 'not_found'\n /** A destructive command needs `replace: true` (or `force: true`). */\n | 'confirmation_required'\n /** The plan moved on since the caller looked (`expectedRevision`, undo). */\n | 'conflict'\n /** A command id was reused with a different command. */\n | 'id_reuse'\n /** An atomic batch failed; `details.index` names the command, nothing applied. */\n | 'batch_failed'\n | 'failed';\n\nexport interface CommandError {\n code: CommandErrorCode;\n message: string;\n /** Where the problem is, as a path into the input (`input.ids[1]`). */\n path?: string;\n details?: Record<string, unknown>;\n}\n\n/** What a recipe/feature command did, after `requires` ran. */\nexport interface RecipeChanges {\n added: string[];\n removed: string[];\n /** Asked to remove, but another recipe still needs them. */\n kept: string[];\n}\n\nexport interface PlanSnapshot {\n version: typeof COOKBOOK_COMMANDS_VERSION;\n /** Counts applied changes; equal histories give equal revisions. */\n revision: number;\n app: {\n name: string;\n description: string | null;\n specs: string | null;\n cookbook: string | null;\n };\n recipes: { id: string; label: string }[];\n features: string[];\n /** Recipe and feature ids this catalog lacks; kept on export. */\n unavailable: string[];\n settings: {\n currency: string;\n taxRate: number;\n paymentTerms: string;\n pricesIncludeTax: boolean;\n taxRounding: 'line' | 'document';\n };\n theme: {\n text: string;\n preset: string | null;\n primary: string | null;\n colorScheme: string;\n borderRadius: string | null;\n density: string | null;\n contrast: string | null;\n };\n sections: {\n id: string;\n label: string;\n hidden: boolean;\n items: { id: string; label: string; hidden: boolean }[];\n }[];\n policies: number;\n /** Undo ids still available, newest last. */\n undo: string[];\n}\n\nexport interface CommandReceipt {\n name: CommandName;\n /** The command id, when one was sent. */\n id?: string;\n summary: string;\n changed: boolean;\n revisionBefore: number;\n revisionAfter: number;\n undoId?: string;\n changes?: RecipeChanges;\n /** Non-fatal notes (an import's legacy `$schema` migration). */\n warnings?: string[];\n}\n\nexport type CommandResult =\n | {\n ok: true;\n id?: string;\n /** True when this is the stored result of an earlier run of the same id. */\n replayed?: boolean;\n snapshot: PlanSnapshot;\n receipt: CommandReceipt;\n data?: unknown;\n }\n | { ok: false; id?: string; replayed?: boolean; error: CommandError };\n\nexport interface RunOptions {\n expectedRevision?: number;\n}\n\n/** Several commands applied all-or-nothing. */\nexport interface CommandBatch {\n id?: string;\n commands: readonly unknown[];\n expectedRevision?: number;\n}\n\nexport type BatchResult =\n | {\n ok: true;\n id?: string;\n replayed?: boolean;\n snapshot: PlanSnapshot;\n receipt: {\n id?: string;\n count: number;\n changed: boolean;\n revisionBefore: number;\n revisionAfter: number;\n undoId?: string;\n };\n /** One result per command, in order. */\n results: Extract<CommandResult, { ok: true }>[];\n }\n | {\n ok: false;\n id?: string;\n replayed?: boolean;\n error: CommandError;\n /** The state is exactly as before the batch. */\n snapshot: PlanSnapshot;\n };\n\n/** One diagnostic from `validate`. */\nexport interface Diagnostic {\n severity: 'error' | 'warning';\n code: string;\n path: string;\n message: string;\n}\n\nexport interface ValidateData {\n ok: boolean;\n diagnostics: Diagnostic[];\n}\n\nexport interface ExportData {\n fileName: string;\n text: string;\n cookbook: Cookbook;\n}\n\n/** A journal row: enough to answer a retry of `id` after a restart. */\nexport interface JournalEntry {\n id: string;\n fingerprint: string;\n result: CommandResult | BatchResult;\n}\n\n/** The engine's whole state as plain JSON, to persist and resume from. */\nexport interface EngineState {\n version: typeof COOKBOOK_COMMANDS_VERSION;\n revision: number;\n /** The library cookbook the plan was last set up from, if any. */\n applied: string | null;\n cookbook: Cookbook;\n journal: JournalEntry[];\n}\n\nexport interface JsonSchema {\n [key: string]: unknown;\n}\n\n/** One command as an LLM or MCP tool definition. */\nexport interface CommandTool {\n name: CommandName;\n description: string;\n inputSchema: JsonSchema;\n}\n"],"mappings":";;;;;AAcA,IAAa,4BAA4B"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"version": { "const": 1 },
|
|
16
16
|
"name": { "type": "string" },
|
|
17
17
|
"description": { "type": "string" },
|
|
18
|
+
"specs": { "type": "string", "maxLength": 20000, "description": "Free-text product requirements beyond the recipes and features: what the app must also do. Agents treat it as requirements to build." },
|
|
18
19
|
"recipes": { "type": "array", "items": { "type": "string" } },
|
|
19
20
|
"features": { "type": "array", "items": { "type": "string" } },
|
|
20
21
|
"policies": { "type": "array", "items": { "$ref": "#/$defs/policyRow" } },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/cookbook/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EAGR,wBAAwB,EAKzB,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB,iDACgB,CAAC;AACjD,oFAAoF;AACpF,eAAO,MAAM,0BAA0B,kDACU,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,oDAAoD;IACpD,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,8DAA8D;IAC9D,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzB,mFAAmF;QACnF,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,2DAA2D;IAC3D,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CACjB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,wBAAwB,KAC/B,0BAA0B,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,0BAA0B,GAClC;IACE,EAAE,EAAE,IAAI,CAAC;IACT,0EAA0E;IAC1E,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC7C,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAC1B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAqdvE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,uBAA4B,GACpC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/cookbook/validate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EAGR,wBAAwB,EAKzB,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB,iDACgB,CAAC;AACjD,oFAAoF;AACpF,eAAO,MAAM,0BAA0B,kDACU,CAAC;AAClD,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,oDAAoD;IACpD,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChC,8DAA8D;IAC9D,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzB,mFAAmF;QACnF,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;KACnC,CAAC;IACF,2DAA2D;IAC3D,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CACjB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,wBAAwB,KAC/B,0BAA0B,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,0BAA0B,GAClC;IACE,EAAE,EAAE,IAAI,CAAC;IACT,0EAA0E;IAC1E,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC7C,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAE9D,MAAM,MAAM,kBAAkB,GAC1B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAAC;AAqdvE;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,uBAA4B,GACpC,kBAAkB,CAmVpB;AAED,yDAAyD;AACzD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,uBAA4B,GACpC,kBAAkB,CAmBpB"}
|
|
@@ -223,7 +223,12 @@ function validateCookbook(input, options = {}) {
|
|
|
223
223
|
else if (version > 1) error(diagnostics, "unsupported_version", "version", `version ${version} is newer than this reader understands (1)`);
|
|
224
224
|
else if (version !== 1) error(diagnostics, "unsupported_version", "version", `version ${version} is not supported`);
|
|
225
225
|
if ($schema === "https://s-m-r-t.dev/schemas/blueprint/v1.json") warning(diagnostics, "migrated_schema", "$schema", "$schema uses the legacy blueprint URL; migrated");
|
|
226
|
-
for (const key of [
|
|
226
|
+
for (const key of [
|
|
227
|
+
"name",
|
|
228
|
+
"description",
|
|
229
|
+
"specs"
|
|
230
|
+
]) if (input[key] !== void 0 && typeof input[key] !== "string") error(diagnostics, "invalid_type", key, `${key} must be a string`);
|
|
231
|
+
if (typeof input.specs === "string" && Array.from(input.specs).length > 2e4) error(diagnostics, "invalid_value", "specs", "specs must be at most 20,000 characters");
|
|
227
232
|
let recipes = [];
|
|
228
233
|
if (!isStrings(input.recipes)) error(diagnostics, "invalid_type", "recipes", "recipes must be a list of recipe ids");
|
|
229
234
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","names":[],"sources":["../../src/cookbook/validate.ts"],"sourcesContent":["import type {\n Cookbook,\n CookbookExposureSurface,\n CookbookLayout,\n CookbookOverviewOverride,\n CookbookOverviewWidget,\n CookbookPolicyRow,\n CookbookTheme,\n RecipeShellSlot,\n} from '@happyvertical/smrt-types';\n\nexport type { Cookbook } from '@happyvertical/smrt-types';\n\n/** What a v1 document carries in `$schema`. */\nexport const COOKBOOK_SCHEMA_URL =\n 'https://s-m-r-t.dev/schemas/cookbook/v1.json';\n/** Accepted on read (the document used to be called a blueprint); never written. */\nexport const COOKBOOK_LEGACY_SCHEMA_URL =\n 'https://s-m-r-t.dev/schemas/blueprint/v1.json';\nexport const COOKBOOK_VERSION = 1;\n\nexport interface CookbookValidateOptions {\n /**\n * The recipe ids that exist (from published manifests). When given, an id\n * outside it is an error. When absent no existence check runs: that is the\n * seam `smrt cookbook validate` fills.\n */\n recipes?: Iterable<string>;\n /** Built-in or host-registered theme preset ids. */\n themePresets?: Iterable<string>;\n /** Manifest-derived ids the cookbook layout may reference. */\n layout?: {\n sections?: Iterable<string>;\n items?: Iterable<string>;\n /** Movable shell item ids resolved by the host (`dock:`, `slot:`, or host ids). */\n placementItems?: Iterable<string>;\n };\n /** Overview page ids defined by the resolved app shell. */\n overviewIds?: Iterable<string>;\n /**\n * Validate and canonicalize one structurally valid override against its page\n * definition and widget registry. The callback is trusted host code; the\n * cookbook value remains plain data and is never executed.\n */\n validateOverview?: (\n id: string,\n override: CookbookOverviewOverride,\n ) => CookbookOverviewValidation;\n}\n\nexport interface CookbookDiagnostic {\n severity: 'error' | 'warning';\n /** Stable machine-readable category. Host validators may add their own. */\n code: string;\n /** Path into the cookbook, using the existing dotted/indexed notation. */\n path: string;\n message: string;\n}\n\nexport type CookbookOverviewValidation =\n | {\n ok: true;\n /** `null` means the canonical override is empty and should be omitted. */\n override: CookbookOverviewOverride | null;\n diagnostics?: readonly CookbookDiagnostic[];\n }\n | { ok: false; diagnostics: readonly CookbookDiagnostic[] };\n\nexport type CookbookValidation =\n | {\n ok: true;\n cookbook: Cookbook;\n warnings: string[];\n diagnostics: CookbookDiagnostic[];\n }\n | { ok: false; errors: string[]; diagnostics: CookbookDiagnostic[] };\n\nconst VISIBILITIES = new Set(['basic', 'advanced', 'hidden']);\nconst SURFACES = new Set(['api', 'mcp', 'cli']);\nconst SCHEMES = new Set(['light', 'dark', 'system']);\nconst THEME_ENUMS = {\n borderRadius: ['none', 'sm', 'md', 'lg', 'xl', 'full'],\n density: ['comfortable', 'touch'],\n contrast: ['auto', 'standard', 'more'],\n} as const;\nconst SHELL_SLOT_VALUES = [\n 'header.start',\n 'header.center',\n 'header.end',\n 'footer.start',\n 'footer.center',\n 'footer.end',\n 'leftSidebar.header',\n 'leftSidebar.footer',\n 'rightSidebar.header',\n 'rightSidebar.footer',\n] as const satisfies readonly RecipeShellSlot[];\nconst SHELL_SLOTS = new Set<string>(SHELL_SLOT_VALUES);\n\nconst isObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst isStrings = (v: unknown): v is string[] =>\n Array.isArray(v) && v.every((x) => typeof x === 'string');\nconst isStringRecord = (v: unknown, valid: (x: unknown) => boolean) =>\n isObject(v) &&\n !Object.hasOwn(v, '__proto__') &&\n Object.values(v).every(valid);\n\nconst add = (\n diagnostics: CookbookDiagnostic[],\n severity: CookbookDiagnostic['severity'],\n code: string,\n path: string,\n message: string,\n): void => {\n diagnostics.push({ severity, code, path, message });\n};\n\nconst error = (\n diagnostics: CookbookDiagnostic[],\n code: string,\n path: string,\n message: string,\n): void => add(diagnostics, 'error', code, path, message);\n\nconst warning = (\n diagnostics: CookbookDiagnostic[],\n code: string,\n path: string,\n message: string,\n): void => add(diagnostics, 'warning', code, path, message);\n\nfunction checkPolicy(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n) {\n if (!isObject(value))\n return error(diagnostics, 'invalid_type', at, `${at} must be an object`);\n for (const key of ['objectRef', 'fieldName'] as const) {\n if (typeof value[key] !== 'string' || !value[key]) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.${key}`,\n `${at}.${key} must be a non-empty string`,\n );\n }\n }\n if (value.scopeType !== 'app')\n error(\n diagnostics,\n 'invalid_value',\n `${at}.scopeType`,\n `${at}.scopeType must be \"app\"`,\n );\n for (const key of ['defaultValue', 'help', 'label'] as const) {\n const v = value[key];\n if (v !== undefined && v !== null && typeof v !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n `${at}.${key}`,\n `${at}.${key} must be a string or null`,\n );\n }\n }\n const vis = value.visibility;\n if (vis != null && !(typeof vis === 'string' && VISIBILITIES.has(vis))) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.visibility`,\n `${at}.visibility must be basic, advanced or hidden`,\n );\n }\n const order = value.displayOrder;\n if (order != null && !(typeof order === 'number' && Number.isFinite(order))) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.displayOrder`,\n `${at}.displayOrder must be a finite number`,\n );\n }\n if (value.locked != null && typeof value.locked !== 'boolean') {\n error(\n diagnostics,\n 'invalid_type',\n `${at}.locked`,\n `${at}.locked must be a boolean`,\n );\n }\n}\n\nfunction checkLayout(value: unknown, diagnostics: CookbookDiagnostic[]) {\n if (!isObject(value) || value.version !== 1) {\n return error(\n diagnostics,\n 'invalid_value',\n 'layout',\n 'layout must be an object with version 1',\n );\n }\n for (const key of ['sectionOrder', 'hidden'] as const) {\n if (value[key] !== undefined && !isStrings(value[key])) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n `layout.${key} must be a list of strings`,\n );\n }\n }\n for (const key of ['itemOrder', 'moved', 'placements'] as const) {\n const v = value[key];\n if (v === undefined) continue;\n const ok =\n key === 'itemOrder'\n ? isStringRecord(v, isStrings)\n : isStringRecord(v, (x) => typeof x === 'string');\n if (!ok) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n key === 'itemOrder'\n ? 'layout.itemOrder must map ids to lists of strings'\n : `layout.${key} must map ids to strings`,\n );\n }\n }\n if (isObject(value.placements)) {\n for (const [id, slot] of Object.entries(value.placements)) {\n if (typeof slot === 'string' && !SHELL_SLOTS.has(slot)) {\n error(\n diagnostics,\n 'unknown_layout_slot',\n `layout.placements.${id}`,\n `Unknown shell slot \"${slot}\".`,\n );\n }\n }\n }\n for (const key of ['sections', 'items', 'panels'] as const) {\n if (\n value[key] !== undefined &&\n !isStringRecord(value[key], (x) => isObject(x))\n ) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n `layout.${key} must map ids to objects`,\n );\n }\n }\n const custom = value.customSections;\n if (\n custom !== undefined &&\n !(\n Array.isArray(custom) &&\n custom.every(\n (c) =>\n isObject(c) &&\n typeof c.id === 'string' &&\n typeof c.label === 'string',\n )\n )\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'layout.customSections',\n 'layout.customSections must be a list of { id, label }',\n );\n }\n}\n\nfunction checkTheme(value: unknown, diagnostics: CookbookDiagnostic[]) {\n if (!isObject(value))\n return error(\n diagnostics,\n 'invalid_type',\n 'theme',\n 'theme must be an object',\n );\n if (value.preset !== undefined && typeof value.preset !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.preset',\n 'theme.preset must be a string',\n );\n }\n if (\n value.fontFamily !== undefined &&\n (typeof value.fontFamily !== 'string' || !value.fontFamily)\n ) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.fontFamily',\n 'theme.fontFamily must be a non-empty string',\n );\n }\n if (value.customCss !== undefined) {\n if (typeof value.customCss !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.customCss',\n 'theme.customCss must be a string',\n );\n } else if (Array.from(value.customCss).length > 65536) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.customCss',\n 'theme.customCss must be at most 65,536 characters',\n );\n }\n }\n if (\n value.colorScheme !== undefined &&\n !(typeof value.colorScheme === 'string' && SCHEMES.has(value.colorScheme))\n ) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.colorScheme',\n 'theme.colorScheme must be light, dark or system',\n );\n }\n for (const key of ['borderRadius', 'density', 'contrast'] as const) {\n const allowed: readonly string[] = THEME_ENUMS[key];\n const given = value[key];\n if (\n given !== undefined &&\n !(typeof given === 'string' && allowed.includes(given))\n ) {\n error(\n diagnostics,\n 'invalid_value',\n `theme.${key}`,\n `theme.${key} must be one of ${allowed.join(', ')}`,\n );\n }\n }\n const custom = value.custom;\n if (custom !== undefined) {\n if (!isObject(custom) || typeof custom.primary !== 'string') {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.custom',\n 'theme.custom must be an object with a string primary',\n );\n } else if (!/^#[0-9a-fA-F]{6}$/.test(custom.primary)) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.custom.primary',\n 'theme.custom.primary must be a hex colour like #c2410c',\n );\n } else if (\n custom.fontFamily !== undefined &&\n typeof custom.fontFamily !== 'string'\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.custom.fontFamily',\n 'theme.custom.fontFamily must be a string',\n );\n }\n }\n}\n\nconst OVERVIEW_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/;\nconst WIDGET_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\nconst WIDGET_TYPE = /^[a-z][a-z0-9-]{0,31}$/;\n\nconst isOptionValue = (value: unknown) =>\n value === null ||\n typeof value === 'string' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n typeof value === 'boolean';\n\nfunction normalizeOverviewWidget(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): CookbookOverviewWidget | null {\n if (!isObject(value)) {\n warning(diagnostics, 'malformed_overview_widget', at, `${at} was dropped`);\n return null;\n }\n const valid = [\n typeof value.id === 'string' && WIDGET_ID.test(value.id),\n typeof value.type === 'string' && WIDGET_TYPE.test(value.type),\n typeof value.span === 'number' &&\n Number.isInteger(value.span) &&\n value.span >= 1 &&\n value.span <= 4,\n isObject(value.options) &&\n Object.values(value.options).every(isOptionValue),\n value.version === undefined ||\n (typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 1),\n ];\n if (valid.every(Boolean)) return value as unknown as CookbookOverviewWidget;\n warning(\n diagnostics,\n 'malformed_overview_widget',\n at,\n `${at} was dropped because it is not a valid overview widget`,\n );\n return null;\n}\n\nfunction normalizeOverviewPatch(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): NonNullable<CookbookOverviewOverride['changed']>[string] | null {\n if (!isObject(value)) {\n warning(diagnostics, 'malformed_overview_change', at, `${at} was dropped`);\n return null;\n }\n const valid =\n (value.span === undefined ||\n (typeof value.span === 'number' &&\n Number.isInteger(value.span) &&\n value.span >= 1 &&\n value.span <= 4)) &&\n (value.options === undefined ||\n (isObject(value.options) &&\n Object.values(value.options).every(isOptionValue))) &&\n (value.version === undefined ||\n (typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 1));\n if (valid) {\n return value as NonNullable<CookbookOverviewOverride['changed']>[string];\n }\n warning(\n diagnostics,\n 'malformed_overview_change',\n at,\n `${at} was dropped because it is not a valid widget change`,\n );\n return null;\n}\n\nfunction normalizeOverview(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): CookbookOverviewOverride | null {\n if (!isObject(value) || value.version !== 1) {\n warning(\n diagnostics,\n 'malformed_overview',\n at,\n `${at} was dropped because it must be an object with version 1`,\n );\n return null;\n }\n const override = {\n ...value,\n version: 1,\n } as unknown as CookbookOverviewOverride;\n for (const key of ['order', 'removed'] as const) {\n if (value[key] !== undefined && !isStrings(value[key])) {\n warning(\n diagnostics,\n 'malformed_overview_list',\n `${at}.${key}`,\n `${at}.${key} was dropped because it must be a list of strings`,\n );\n delete override[key];\n } else if (value[key] !== undefined) {\n override[key] = [...new Set(value[key])];\n }\n }\n if (value.added !== undefined) {\n if (!Array.isArray(value.added)) {\n warning(\n diagnostics,\n 'malformed_overview_widgets',\n `${at}.added`,\n `${at}.added was dropped because it must be a list of widgets`,\n );\n delete override.added;\n } else {\n const added = value.added.flatMap((widget, index) => {\n const normalized = normalizeOverviewWidget(\n widget,\n `${at}.added[${index}]`,\n diagnostics,\n );\n return normalized ? [normalized] : [];\n });\n if (added.length) override.added = added;\n else delete override.added;\n }\n }\n if (value.changed !== undefined) {\n if (!isObject(value.changed) || Object.hasOwn(value.changed, '__proto__')) {\n warning(\n diagnostics,\n 'malformed_overview_changes',\n `${at}.changed`,\n `${at}.changed was dropped because it must map widget ids to objects`,\n );\n delete override.changed;\n } else {\n const changed: NonNullable<CookbookOverviewOverride['changed']> = {};\n for (const [id, patch] of Object.entries(value.changed)) {\n if (!WIDGET_ID.test(id)) {\n warning(\n diagnostics,\n 'malformed_overview_change',\n `${at}.changed.${id}`,\n `${at}.changed.${id} was dropped because its widget id is invalid`,\n );\n continue;\n }\n const normalized = normalizeOverviewPatch(\n patch,\n `${at}.changed.${id}`,\n diagnostics,\n );\n if (normalized) changed[id] = normalized;\n }\n if (Object.keys(changed).length) override.changed = changed;\n else delete override.changed;\n }\n }\n return override;\n}\n\n/**\n * Structural validation of an unknown value (parsed JSON). Returns the\n * normalised document (legacy `$schema` rewritten, `features` defaulted,\n * recipes sorted and unique) or every problem found, each a readable line\n * naming the path. Unknown top-level keys are kept (additive fields in v1).\n *\n * Deep checks use optional host-supplied catalogs. A structurally valid\n * cookbook remains portable when those catalogs are absent. Invalid overview\n * entries are dropped and reported, following the v1 overview contract.\n */\nexport function validateCookbook(\n input: unknown,\n options: CookbookValidateOptions = {},\n): CookbookValidation {\n const diagnostics: CookbookDiagnostic[] = [];\n if (!isObject(input)) {\n error(diagnostics, 'invalid_type', '', 'expected a JSON object');\n return { ok: false, errors: ['expected a JSON object'], diagnostics };\n }\n\n const { $schema, version } = input;\n if (\n $schema !== undefined &&\n $schema !== COOKBOOK_SCHEMA_URL &&\n $schema !== COOKBOOK_LEGACY_SCHEMA_URL\n ) {\n error(\n diagnostics,\n 'invalid_schema',\n '$schema',\n `$schema must be ${COOKBOOK_SCHEMA_URL}`,\n );\n }\n if (version === undefined) {\n error(diagnostics, 'missing_field', 'version', 'version is required');\n } else if (typeof version !== 'number' || !Number.isInteger(version)) {\n error(\n diagnostics,\n 'invalid_type',\n 'version',\n 'version must be a whole number',\n );\n } else if (version > COOKBOOK_VERSION) {\n error(\n diagnostics,\n 'unsupported_version',\n 'version',\n `version ${version} is newer than this reader understands (${COOKBOOK_VERSION})`,\n );\n } else if (version !== COOKBOOK_VERSION) {\n error(\n diagnostics,\n 'unsupported_version',\n 'version',\n `version ${version} is not supported`,\n );\n }\n if ($schema === COOKBOOK_LEGACY_SCHEMA_URL) {\n warning(\n diagnostics,\n 'migrated_schema',\n '$schema',\n '$schema uses the legacy blueprint URL; migrated',\n );\n }\n\n for (const key of ['name', 'description'] as const) {\n if (input[key] !== undefined && typeof input[key] !== 'string') {\n error(diagnostics, 'invalid_type', key, `${key} must be a string`);\n }\n }\n\n let recipes: string[] = [];\n if (!isStrings(input.recipes)) {\n error(\n diagnostics,\n 'invalid_type',\n 'recipes',\n 'recipes must be a list of recipe ids',\n );\n } else {\n recipes = [...new Set(input.recipes)].sort();\n if (options.recipes) {\n const known = new Set(options.recipes);\n for (const id of recipes) {\n if (!known.has(id))\n error(\n diagnostics,\n 'unknown_recipe',\n `recipes[${input.recipes.indexOf(id)}]`,\n `recipes: unknown recipe \"${id}\"`,\n );\n }\n }\n }\n\n let features: string[] = [];\n if (input.features !== undefined) {\n if (!isStrings(input.features)) {\n error(\n diagnostics,\n 'invalid_type',\n 'features',\n 'features must be a list of model names',\n );\n } else {\n features = [...new Set(input.features)].sort();\n if (features.length !== input.features.length) {\n warning(\n diagnostics,\n 'duplicate_value',\n 'features',\n 'features listed a model more than once; deduplicated',\n );\n }\n }\n }\n\n const policies: CookbookPolicyRow[] = [];\n if (!Array.isArray(input.policies)) {\n error(diagnostics, 'invalid_type', 'policies', 'policies must be a list');\n } else {\n for (const [i, row] of input.policies.entries()) {\n checkPolicy(row, `policies[${i}]`, diagnostics);\n policies.push(row as CookbookPolicyRow);\n }\n }\n\n if (input.exposure !== undefined) {\n const ok = isStringRecord(\n input.exposure,\n (s) => isStrings(s) && s.every((x) => SURFACES.has(x)),\n );\n if (!ok)\n error(\n diagnostics,\n 'invalid_value',\n 'exposure',\n 'exposure must map model names to lists of api, mcp or cli',\n );\n }\n if (input.layout !== undefined) checkLayout(input.layout, diagnostics);\n if (input.theme !== undefined) checkTheme(input.theme, diagnostics);\n\n if (isObject(input.theme) && typeof input.theme.preset === 'string') {\n const presets = options.themePresets\n ? new Set(options.themePresets)\n : undefined;\n if (presets && !presets.has(input.theme.preset)) {\n error(\n diagnostics,\n 'unknown_theme_preset',\n 'theme.preset',\n `Unknown theme preset \"${input.theme.preset}\".`,\n );\n }\n }\n\n if (isObject(input.layout) && input.layout.version === 1 && options.layout) {\n const sections = options.layout.sections\n ? new Set(options.layout.sections)\n : undefined;\n const items = options.layout.items\n ? new Set(options.layout.items)\n : undefined;\n const placementItems = options.layout.placementItems\n ? new Set(options.layout.placementItems)\n : undefined;\n if (sections && Array.isArray(input.layout.customSections)) {\n for (const section of input.layout.customSections) {\n if (isObject(section) && typeof section.id === 'string') {\n sections.add(section.id);\n }\n }\n }\n const known = (id: string, kind: 'section' | 'item' | 'either') =>\n kind === 'section'\n ? sections?.has(id) !== false\n : kind === 'item'\n ? items?.has(id) !== false\n : sections?.has(id) === true ||\n items?.has(id) === true ||\n (!sections && !items);\n const check = (\n id: unknown,\n path: string,\n kind: 'section' | 'item' | 'either',\n ) => {\n if (typeof id === 'string' && !known(id, kind)) {\n error(\n diagnostics,\n 'unknown_layout_id',\n path,\n `Unknown layout ${kind === 'either' ? 'section or item' : kind} \"${id}\".`,\n );\n }\n };\n if (isStrings(input.layout.sectionOrder)) {\n input.layout.sectionOrder.forEach((id, index) => {\n check(id, `layout.sectionOrder[${index}]`, 'section');\n });\n }\n if (isStrings(input.layout.hidden)) {\n input.layout.hidden.forEach((id, index) => {\n check(id, `layout.hidden[${index}]`, 'either');\n });\n }\n if (isObject(input.layout.itemOrder)) {\n for (const [section, order] of Object.entries(input.layout.itemOrder)) {\n check(section, `layout.itemOrder.${section}`, 'section');\n if (isStrings(order)) {\n order.forEach((id, index) => {\n check(id, `layout.itemOrder.${section}[${index}]`, 'item');\n });\n }\n }\n }\n if (isObject(input.layout.moved)) {\n for (const [id, section] of Object.entries(input.layout.moved)) {\n check(id, `layout.moved.${id}`, 'item');\n check(section, `layout.moved.${id}`, 'section');\n }\n }\n for (const key of ['sections', 'items'] as const) {\n if (!isObject(input.layout[key])) continue;\n for (const id of Object.keys(input.layout[key])) {\n check(\n id,\n `layout.${key}.${id}`,\n key === 'sections' ? 'section' : 'item',\n );\n }\n }\n if (isObject(input.layout.placements)) {\n for (const id of Object.keys(input.layout.placements)) {\n if (placementItems && !placementItems.has(id)) {\n error(\n diagnostics,\n 'unknown_layout_id',\n `layout.placements.${id}`,\n `Unknown layout placement item \"${id}\".`,\n );\n }\n }\n }\n }\n\n const overviews: Record<string, CookbookOverviewOverride> = {};\n if (input.overviews !== undefined) {\n if (\n !isObject(input.overviews) ||\n Object.hasOwn(input.overviews, '__proto__')\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'overviews',\n 'overviews must map overview ids to overrides',\n );\n } else {\n const overviewIds = options.overviewIds\n ? new Set(options.overviewIds)\n : undefined;\n for (const [id, value] of Object.entries(input.overviews)) {\n const at = `overviews.${id}`;\n if (!OVERVIEW_ID.test(id)) {\n warning(\n diagnostics,\n 'invalid_overview_id',\n at,\n `${at} was dropped because its overview id is invalid`,\n );\n continue;\n }\n if (overviewIds && !overviewIds.has(id)) {\n warning(\n diagnostics,\n 'unknown_overview',\n at,\n `Unknown overview \"${id}\" was dropped.`,\n );\n continue;\n }\n const override = normalizeOverview(value, at, diagnostics);\n if (!override) continue;\n if (!options.validateOverview) {\n overviews[id] = override;\n continue;\n }\n let checked: CookbookOverviewValidation;\n try {\n checked = options.validateOverview(id, override);\n } catch {\n warning(\n diagnostics,\n 'overview_validation_failed',\n at,\n `Overview \"${id}\" was dropped because its host validator failed.`,\n );\n continue;\n }\n for (const issue of checked.diagnostics ?? []) {\n warning(diagnostics, issue.code, issue.path || at, issue.message);\n }\n if (!checked.ok && checked.diagnostics.length === 0) {\n warning(\n diagnostics,\n 'overview_rejected',\n at,\n `Overview \"${id}\" was rejected by its host validator and dropped.`,\n );\n }\n if (checked.ok && checked.override) overviews[id] = checked.override;\n }\n }\n }\n\n const errors = diagnostics\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => diagnostic.message);\n if (errors.length) return { ok: false, errors, diagnostics };\n\n const cookbook = {\n ...input,\n $schema: COOKBOOK_SCHEMA_URL,\n version: COOKBOOK_VERSION,\n recipes,\n features,\n policies,\n } as unknown as Cookbook;\n if (input.exposure !== undefined) {\n cookbook.exposure = input.exposure as Record<\n string,\n CookbookExposureSurface[]\n >;\n }\n if (input.layout !== undefined)\n cookbook.layout = input.layout as CookbookLayout;\n if (input.theme !== undefined) cookbook.theme = input.theme as CookbookTheme;\n delete cookbook.overviews;\n if (Object.keys(overviews).length) cookbook.overviews = overviews;\n const warnings = diagnostics\n .filter((diagnostic) => diagnostic.severity === 'warning')\n .map((diagnostic) => diagnostic.message);\n return { ok: true, cookbook, warnings, diagnostics };\n}\n\n/** Parse JSON text, then {@link validateCookbook} it. */\nexport function parseCookbookText(\n text: string,\n options: CookbookValidateOptions = {},\n): CookbookValidation {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return {\n ok: false,\n errors: ['not valid JSON'],\n diagnostics: [\n {\n severity: 'error',\n code: 'invalid_json',\n path: '',\n message: 'not valid JSON',\n },\n ],\n };\n }\n return validateCookbook(value, options);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate.js","names":[],"sources":["../../src/cookbook/validate.ts"],"sourcesContent":["import type {\n Cookbook,\n CookbookExposureSurface,\n CookbookLayout,\n CookbookOverviewOverride,\n CookbookOverviewWidget,\n CookbookPolicyRow,\n CookbookTheme,\n RecipeShellSlot,\n} from '@happyvertical/smrt-types';\n\nexport type { Cookbook } from '@happyvertical/smrt-types';\n\n/** What a v1 document carries in `$schema`. */\nexport const COOKBOOK_SCHEMA_URL =\n 'https://s-m-r-t.dev/schemas/cookbook/v1.json';\n/** Accepted on read (the document used to be called a blueprint); never written. */\nexport const COOKBOOK_LEGACY_SCHEMA_URL =\n 'https://s-m-r-t.dev/schemas/blueprint/v1.json';\nexport const COOKBOOK_VERSION = 1;\n\nexport interface CookbookValidateOptions {\n /**\n * The recipe ids that exist (from published manifests). When given, an id\n * outside it is an error. When absent no existence check runs: that is the\n * seam `smrt cookbook validate` fills.\n */\n recipes?: Iterable<string>;\n /** Built-in or host-registered theme preset ids. */\n themePresets?: Iterable<string>;\n /** Manifest-derived ids the cookbook layout may reference. */\n layout?: {\n sections?: Iterable<string>;\n items?: Iterable<string>;\n /** Movable shell item ids resolved by the host (`dock:`, `slot:`, or host ids). */\n placementItems?: Iterable<string>;\n };\n /** Overview page ids defined by the resolved app shell. */\n overviewIds?: Iterable<string>;\n /**\n * Validate and canonicalize one structurally valid override against its page\n * definition and widget registry. The callback is trusted host code; the\n * cookbook value remains plain data and is never executed.\n */\n validateOverview?: (\n id: string,\n override: CookbookOverviewOverride,\n ) => CookbookOverviewValidation;\n}\n\nexport interface CookbookDiagnostic {\n severity: 'error' | 'warning';\n /** Stable machine-readable category. Host validators may add their own. */\n code: string;\n /** Path into the cookbook, using the existing dotted/indexed notation. */\n path: string;\n message: string;\n}\n\nexport type CookbookOverviewValidation =\n | {\n ok: true;\n /** `null` means the canonical override is empty and should be omitted. */\n override: CookbookOverviewOverride | null;\n diagnostics?: readonly CookbookDiagnostic[];\n }\n | { ok: false; diagnostics: readonly CookbookDiagnostic[] };\n\nexport type CookbookValidation =\n | {\n ok: true;\n cookbook: Cookbook;\n warnings: string[];\n diagnostics: CookbookDiagnostic[];\n }\n | { ok: false; errors: string[]; diagnostics: CookbookDiagnostic[] };\n\nconst VISIBILITIES = new Set(['basic', 'advanced', 'hidden']);\nconst SURFACES = new Set(['api', 'mcp', 'cli']);\nconst SCHEMES = new Set(['light', 'dark', 'system']);\nconst THEME_ENUMS = {\n borderRadius: ['none', 'sm', 'md', 'lg', 'xl', 'full'],\n density: ['comfortable', 'touch'],\n contrast: ['auto', 'standard', 'more'],\n} as const;\nconst SHELL_SLOT_VALUES = [\n 'header.start',\n 'header.center',\n 'header.end',\n 'footer.start',\n 'footer.center',\n 'footer.end',\n 'leftSidebar.header',\n 'leftSidebar.footer',\n 'rightSidebar.header',\n 'rightSidebar.footer',\n] as const satisfies readonly RecipeShellSlot[];\nconst SHELL_SLOTS = new Set<string>(SHELL_SLOT_VALUES);\n\nconst isObject = (v: unknown): v is Record<string, unknown> =>\n typeof v === 'object' && v !== null && !Array.isArray(v);\nconst isStrings = (v: unknown): v is string[] =>\n Array.isArray(v) && v.every((x) => typeof x === 'string');\nconst isStringRecord = (v: unknown, valid: (x: unknown) => boolean) =>\n isObject(v) &&\n !Object.hasOwn(v, '__proto__') &&\n Object.values(v).every(valid);\n\nconst add = (\n diagnostics: CookbookDiagnostic[],\n severity: CookbookDiagnostic['severity'],\n code: string,\n path: string,\n message: string,\n): void => {\n diagnostics.push({ severity, code, path, message });\n};\n\nconst error = (\n diagnostics: CookbookDiagnostic[],\n code: string,\n path: string,\n message: string,\n): void => add(diagnostics, 'error', code, path, message);\n\nconst warning = (\n diagnostics: CookbookDiagnostic[],\n code: string,\n path: string,\n message: string,\n): void => add(diagnostics, 'warning', code, path, message);\n\nfunction checkPolicy(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n) {\n if (!isObject(value))\n return error(diagnostics, 'invalid_type', at, `${at} must be an object`);\n for (const key of ['objectRef', 'fieldName'] as const) {\n if (typeof value[key] !== 'string' || !value[key]) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.${key}`,\n `${at}.${key} must be a non-empty string`,\n );\n }\n }\n if (value.scopeType !== 'app')\n error(\n diagnostics,\n 'invalid_value',\n `${at}.scopeType`,\n `${at}.scopeType must be \"app\"`,\n );\n for (const key of ['defaultValue', 'help', 'label'] as const) {\n const v = value[key];\n if (v !== undefined && v !== null && typeof v !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n `${at}.${key}`,\n `${at}.${key} must be a string or null`,\n );\n }\n }\n const vis = value.visibility;\n if (vis != null && !(typeof vis === 'string' && VISIBILITIES.has(vis))) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.visibility`,\n `${at}.visibility must be basic, advanced or hidden`,\n );\n }\n const order = value.displayOrder;\n if (order != null && !(typeof order === 'number' && Number.isFinite(order))) {\n error(\n diagnostics,\n 'invalid_value',\n `${at}.displayOrder`,\n `${at}.displayOrder must be a finite number`,\n );\n }\n if (value.locked != null && typeof value.locked !== 'boolean') {\n error(\n diagnostics,\n 'invalid_type',\n `${at}.locked`,\n `${at}.locked must be a boolean`,\n );\n }\n}\n\nfunction checkLayout(value: unknown, diagnostics: CookbookDiagnostic[]) {\n if (!isObject(value) || value.version !== 1) {\n return error(\n diagnostics,\n 'invalid_value',\n 'layout',\n 'layout must be an object with version 1',\n );\n }\n for (const key of ['sectionOrder', 'hidden'] as const) {\n if (value[key] !== undefined && !isStrings(value[key])) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n `layout.${key} must be a list of strings`,\n );\n }\n }\n for (const key of ['itemOrder', 'moved', 'placements'] as const) {\n const v = value[key];\n if (v === undefined) continue;\n const ok =\n key === 'itemOrder'\n ? isStringRecord(v, isStrings)\n : isStringRecord(v, (x) => typeof x === 'string');\n if (!ok) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n key === 'itemOrder'\n ? 'layout.itemOrder must map ids to lists of strings'\n : `layout.${key} must map ids to strings`,\n );\n }\n }\n if (isObject(value.placements)) {\n for (const [id, slot] of Object.entries(value.placements)) {\n if (typeof slot === 'string' && !SHELL_SLOTS.has(slot)) {\n error(\n diagnostics,\n 'unknown_layout_slot',\n `layout.placements.${id}`,\n `Unknown shell slot \"${slot}\".`,\n );\n }\n }\n }\n for (const key of ['sections', 'items', 'panels'] as const) {\n if (\n value[key] !== undefined &&\n !isStringRecord(value[key], (x) => isObject(x))\n ) {\n error(\n diagnostics,\n 'invalid_type',\n `layout.${key}`,\n `layout.${key} must map ids to objects`,\n );\n }\n }\n const custom = value.customSections;\n if (\n custom !== undefined &&\n !(\n Array.isArray(custom) &&\n custom.every(\n (c) =>\n isObject(c) &&\n typeof c.id === 'string' &&\n typeof c.label === 'string',\n )\n )\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'layout.customSections',\n 'layout.customSections must be a list of { id, label }',\n );\n }\n}\n\nfunction checkTheme(value: unknown, diagnostics: CookbookDiagnostic[]) {\n if (!isObject(value))\n return error(\n diagnostics,\n 'invalid_type',\n 'theme',\n 'theme must be an object',\n );\n if (value.preset !== undefined && typeof value.preset !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.preset',\n 'theme.preset must be a string',\n );\n }\n if (\n value.fontFamily !== undefined &&\n (typeof value.fontFamily !== 'string' || !value.fontFamily)\n ) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.fontFamily',\n 'theme.fontFamily must be a non-empty string',\n );\n }\n if (value.customCss !== undefined) {\n if (typeof value.customCss !== 'string') {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.customCss',\n 'theme.customCss must be a string',\n );\n } else if (Array.from(value.customCss).length > 65536) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.customCss',\n 'theme.customCss must be at most 65,536 characters',\n );\n }\n }\n if (\n value.colorScheme !== undefined &&\n !(typeof value.colorScheme === 'string' && SCHEMES.has(value.colorScheme))\n ) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.colorScheme',\n 'theme.colorScheme must be light, dark or system',\n );\n }\n for (const key of ['borderRadius', 'density', 'contrast'] as const) {\n const allowed: readonly string[] = THEME_ENUMS[key];\n const given = value[key];\n if (\n given !== undefined &&\n !(typeof given === 'string' && allowed.includes(given))\n ) {\n error(\n diagnostics,\n 'invalid_value',\n `theme.${key}`,\n `theme.${key} must be one of ${allowed.join(', ')}`,\n );\n }\n }\n const custom = value.custom;\n if (custom !== undefined) {\n if (!isObject(custom) || typeof custom.primary !== 'string') {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.custom',\n 'theme.custom must be an object with a string primary',\n );\n } else if (!/^#[0-9a-fA-F]{6}$/.test(custom.primary)) {\n error(\n diagnostics,\n 'invalid_value',\n 'theme.custom.primary',\n 'theme.custom.primary must be a hex colour like #c2410c',\n );\n } else if (\n custom.fontFamily !== undefined &&\n typeof custom.fontFamily !== 'string'\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'theme.custom.fontFamily',\n 'theme.custom.fontFamily must be a string',\n );\n }\n }\n}\n\nconst OVERVIEW_ID = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,95}$/;\nconst WIDGET_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;\nconst WIDGET_TYPE = /^[a-z][a-z0-9-]{0,31}$/;\n\nconst isOptionValue = (value: unknown) =>\n value === null ||\n typeof value === 'string' ||\n (typeof value === 'number' && Number.isFinite(value)) ||\n typeof value === 'boolean';\n\nfunction normalizeOverviewWidget(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): CookbookOverviewWidget | null {\n if (!isObject(value)) {\n warning(diagnostics, 'malformed_overview_widget', at, `${at} was dropped`);\n return null;\n }\n const valid = [\n typeof value.id === 'string' && WIDGET_ID.test(value.id),\n typeof value.type === 'string' && WIDGET_TYPE.test(value.type),\n typeof value.span === 'number' &&\n Number.isInteger(value.span) &&\n value.span >= 1 &&\n value.span <= 4,\n isObject(value.options) &&\n Object.values(value.options).every(isOptionValue),\n value.version === undefined ||\n (typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 1),\n ];\n if (valid.every(Boolean)) return value as unknown as CookbookOverviewWidget;\n warning(\n diagnostics,\n 'malformed_overview_widget',\n at,\n `${at} was dropped because it is not a valid overview widget`,\n );\n return null;\n}\n\nfunction normalizeOverviewPatch(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): NonNullable<CookbookOverviewOverride['changed']>[string] | null {\n if (!isObject(value)) {\n warning(diagnostics, 'malformed_overview_change', at, `${at} was dropped`);\n return null;\n }\n const valid =\n (value.span === undefined ||\n (typeof value.span === 'number' &&\n Number.isInteger(value.span) &&\n value.span >= 1 &&\n value.span <= 4)) &&\n (value.options === undefined ||\n (isObject(value.options) &&\n Object.values(value.options).every(isOptionValue))) &&\n (value.version === undefined ||\n (typeof value.version === 'number' &&\n Number.isInteger(value.version) &&\n value.version >= 1));\n if (valid) {\n return value as NonNullable<CookbookOverviewOverride['changed']>[string];\n }\n warning(\n diagnostics,\n 'malformed_overview_change',\n at,\n `${at} was dropped because it is not a valid widget change`,\n );\n return null;\n}\n\nfunction normalizeOverview(\n value: unknown,\n at: string,\n diagnostics: CookbookDiagnostic[],\n): CookbookOverviewOverride | null {\n if (!isObject(value) || value.version !== 1) {\n warning(\n diagnostics,\n 'malformed_overview',\n at,\n `${at} was dropped because it must be an object with version 1`,\n );\n return null;\n }\n const override = {\n ...value,\n version: 1,\n } as unknown as CookbookOverviewOverride;\n for (const key of ['order', 'removed'] as const) {\n if (value[key] !== undefined && !isStrings(value[key])) {\n warning(\n diagnostics,\n 'malformed_overview_list',\n `${at}.${key}`,\n `${at}.${key} was dropped because it must be a list of strings`,\n );\n delete override[key];\n } else if (value[key] !== undefined) {\n override[key] = [...new Set(value[key])];\n }\n }\n if (value.added !== undefined) {\n if (!Array.isArray(value.added)) {\n warning(\n diagnostics,\n 'malformed_overview_widgets',\n `${at}.added`,\n `${at}.added was dropped because it must be a list of widgets`,\n );\n delete override.added;\n } else {\n const added = value.added.flatMap((widget, index) => {\n const normalized = normalizeOverviewWidget(\n widget,\n `${at}.added[${index}]`,\n diagnostics,\n );\n return normalized ? [normalized] : [];\n });\n if (added.length) override.added = added;\n else delete override.added;\n }\n }\n if (value.changed !== undefined) {\n if (!isObject(value.changed) || Object.hasOwn(value.changed, '__proto__')) {\n warning(\n diagnostics,\n 'malformed_overview_changes',\n `${at}.changed`,\n `${at}.changed was dropped because it must map widget ids to objects`,\n );\n delete override.changed;\n } else {\n const changed: NonNullable<CookbookOverviewOverride['changed']> = {};\n for (const [id, patch] of Object.entries(value.changed)) {\n if (!WIDGET_ID.test(id)) {\n warning(\n diagnostics,\n 'malformed_overview_change',\n `${at}.changed.${id}`,\n `${at}.changed.${id} was dropped because its widget id is invalid`,\n );\n continue;\n }\n const normalized = normalizeOverviewPatch(\n patch,\n `${at}.changed.${id}`,\n diagnostics,\n );\n if (normalized) changed[id] = normalized;\n }\n if (Object.keys(changed).length) override.changed = changed;\n else delete override.changed;\n }\n }\n return override;\n}\n\n/**\n * Structural validation of an unknown value (parsed JSON). Returns the\n * normalised document (legacy `$schema` rewritten, `features` defaulted,\n * recipes sorted and unique) or every problem found, each a readable line\n * naming the path. Unknown top-level keys are kept (additive fields in v1).\n *\n * Deep checks use optional host-supplied catalogs. A structurally valid\n * cookbook remains portable when those catalogs are absent. Invalid overview\n * entries are dropped and reported, following the v1 overview contract.\n */\nexport function validateCookbook(\n input: unknown,\n options: CookbookValidateOptions = {},\n): CookbookValidation {\n const diagnostics: CookbookDiagnostic[] = [];\n if (!isObject(input)) {\n error(diagnostics, 'invalid_type', '', 'expected a JSON object');\n return { ok: false, errors: ['expected a JSON object'], diagnostics };\n }\n\n const { $schema, version } = input;\n if (\n $schema !== undefined &&\n $schema !== COOKBOOK_SCHEMA_URL &&\n $schema !== COOKBOOK_LEGACY_SCHEMA_URL\n ) {\n error(\n diagnostics,\n 'invalid_schema',\n '$schema',\n `$schema must be ${COOKBOOK_SCHEMA_URL}`,\n );\n }\n if (version === undefined) {\n error(diagnostics, 'missing_field', 'version', 'version is required');\n } else if (typeof version !== 'number' || !Number.isInteger(version)) {\n error(\n diagnostics,\n 'invalid_type',\n 'version',\n 'version must be a whole number',\n );\n } else if (version > COOKBOOK_VERSION) {\n error(\n diagnostics,\n 'unsupported_version',\n 'version',\n `version ${version} is newer than this reader understands (${COOKBOOK_VERSION})`,\n );\n } else if (version !== COOKBOOK_VERSION) {\n error(\n diagnostics,\n 'unsupported_version',\n 'version',\n `version ${version} is not supported`,\n );\n }\n if ($schema === COOKBOOK_LEGACY_SCHEMA_URL) {\n warning(\n diagnostics,\n 'migrated_schema',\n '$schema',\n '$schema uses the legacy blueprint URL; migrated',\n );\n }\n\n for (const key of ['name', 'description', 'specs'] as const) {\n if (input[key] !== undefined && typeof input[key] !== 'string') {\n error(diagnostics, 'invalid_type', key, `${key} must be a string`);\n }\n }\n if (typeof input.specs === 'string' && Array.from(input.specs).length > 20000)\n error(\n diagnostics,\n 'invalid_value',\n 'specs',\n 'specs must be at most 20,000 characters',\n );\n\n let recipes: string[] = [];\n if (!isStrings(input.recipes)) {\n error(\n diagnostics,\n 'invalid_type',\n 'recipes',\n 'recipes must be a list of recipe ids',\n );\n } else {\n recipes = [...new Set(input.recipes)].sort();\n if (options.recipes) {\n const known = new Set(options.recipes);\n for (const id of recipes) {\n if (!known.has(id))\n error(\n diagnostics,\n 'unknown_recipe',\n `recipes[${input.recipes.indexOf(id)}]`,\n `recipes: unknown recipe \"${id}\"`,\n );\n }\n }\n }\n\n let features: string[] = [];\n if (input.features !== undefined) {\n if (!isStrings(input.features)) {\n error(\n diagnostics,\n 'invalid_type',\n 'features',\n 'features must be a list of model names',\n );\n } else {\n features = [...new Set(input.features)].sort();\n if (features.length !== input.features.length) {\n warning(\n diagnostics,\n 'duplicate_value',\n 'features',\n 'features listed a model more than once; deduplicated',\n );\n }\n }\n }\n\n const policies: CookbookPolicyRow[] = [];\n if (!Array.isArray(input.policies)) {\n error(diagnostics, 'invalid_type', 'policies', 'policies must be a list');\n } else {\n for (const [i, row] of input.policies.entries()) {\n checkPolicy(row, `policies[${i}]`, diagnostics);\n policies.push(row as CookbookPolicyRow);\n }\n }\n\n if (input.exposure !== undefined) {\n const ok = isStringRecord(\n input.exposure,\n (s) => isStrings(s) && s.every((x) => SURFACES.has(x)),\n );\n if (!ok)\n error(\n diagnostics,\n 'invalid_value',\n 'exposure',\n 'exposure must map model names to lists of api, mcp or cli',\n );\n }\n if (input.layout !== undefined) checkLayout(input.layout, diagnostics);\n if (input.theme !== undefined) checkTheme(input.theme, diagnostics);\n\n if (isObject(input.theme) && typeof input.theme.preset === 'string') {\n const presets = options.themePresets\n ? new Set(options.themePresets)\n : undefined;\n if (presets && !presets.has(input.theme.preset)) {\n error(\n diagnostics,\n 'unknown_theme_preset',\n 'theme.preset',\n `Unknown theme preset \"${input.theme.preset}\".`,\n );\n }\n }\n\n if (isObject(input.layout) && input.layout.version === 1 && options.layout) {\n const sections = options.layout.sections\n ? new Set(options.layout.sections)\n : undefined;\n const items = options.layout.items\n ? new Set(options.layout.items)\n : undefined;\n const placementItems = options.layout.placementItems\n ? new Set(options.layout.placementItems)\n : undefined;\n if (sections && Array.isArray(input.layout.customSections)) {\n for (const section of input.layout.customSections) {\n if (isObject(section) && typeof section.id === 'string') {\n sections.add(section.id);\n }\n }\n }\n const known = (id: string, kind: 'section' | 'item' | 'either') =>\n kind === 'section'\n ? sections?.has(id) !== false\n : kind === 'item'\n ? items?.has(id) !== false\n : sections?.has(id) === true ||\n items?.has(id) === true ||\n (!sections && !items);\n const check = (\n id: unknown,\n path: string,\n kind: 'section' | 'item' | 'either',\n ) => {\n if (typeof id === 'string' && !known(id, kind)) {\n error(\n diagnostics,\n 'unknown_layout_id',\n path,\n `Unknown layout ${kind === 'either' ? 'section or item' : kind} \"${id}\".`,\n );\n }\n };\n if (isStrings(input.layout.sectionOrder)) {\n input.layout.sectionOrder.forEach((id, index) => {\n check(id, `layout.sectionOrder[${index}]`, 'section');\n });\n }\n if (isStrings(input.layout.hidden)) {\n input.layout.hidden.forEach((id, index) => {\n check(id, `layout.hidden[${index}]`, 'either');\n });\n }\n if (isObject(input.layout.itemOrder)) {\n for (const [section, order] of Object.entries(input.layout.itemOrder)) {\n check(section, `layout.itemOrder.${section}`, 'section');\n if (isStrings(order)) {\n order.forEach((id, index) => {\n check(id, `layout.itemOrder.${section}[${index}]`, 'item');\n });\n }\n }\n }\n if (isObject(input.layout.moved)) {\n for (const [id, section] of Object.entries(input.layout.moved)) {\n check(id, `layout.moved.${id}`, 'item');\n check(section, `layout.moved.${id}`, 'section');\n }\n }\n for (const key of ['sections', 'items'] as const) {\n if (!isObject(input.layout[key])) continue;\n for (const id of Object.keys(input.layout[key])) {\n check(\n id,\n `layout.${key}.${id}`,\n key === 'sections' ? 'section' : 'item',\n );\n }\n }\n if (isObject(input.layout.placements)) {\n for (const id of Object.keys(input.layout.placements)) {\n if (placementItems && !placementItems.has(id)) {\n error(\n diagnostics,\n 'unknown_layout_id',\n `layout.placements.${id}`,\n `Unknown layout placement item \"${id}\".`,\n );\n }\n }\n }\n }\n\n const overviews: Record<string, CookbookOverviewOverride> = {};\n if (input.overviews !== undefined) {\n if (\n !isObject(input.overviews) ||\n Object.hasOwn(input.overviews, '__proto__')\n ) {\n error(\n diagnostics,\n 'invalid_type',\n 'overviews',\n 'overviews must map overview ids to overrides',\n );\n } else {\n const overviewIds = options.overviewIds\n ? new Set(options.overviewIds)\n : undefined;\n for (const [id, value] of Object.entries(input.overviews)) {\n const at = `overviews.${id}`;\n if (!OVERVIEW_ID.test(id)) {\n warning(\n diagnostics,\n 'invalid_overview_id',\n at,\n `${at} was dropped because its overview id is invalid`,\n );\n continue;\n }\n if (overviewIds && !overviewIds.has(id)) {\n warning(\n diagnostics,\n 'unknown_overview',\n at,\n `Unknown overview \"${id}\" was dropped.`,\n );\n continue;\n }\n const override = normalizeOverview(value, at, diagnostics);\n if (!override) continue;\n if (!options.validateOverview) {\n overviews[id] = override;\n continue;\n }\n let checked: CookbookOverviewValidation;\n try {\n checked = options.validateOverview(id, override);\n } catch {\n warning(\n diagnostics,\n 'overview_validation_failed',\n at,\n `Overview \"${id}\" was dropped because its host validator failed.`,\n );\n continue;\n }\n for (const issue of checked.diagnostics ?? []) {\n warning(diagnostics, issue.code, issue.path || at, issue.message);\n }\n if (!checked.ok && checked.diagnostics.length === 0) {\n warning(\n diagnostics,\n 'overview_rejected',\n at,\n `Overview \"${id}\" was rejected by its host validator and dropped.`,\n );\n }\n if (checked.ok && checked.override) overviews[id] = checked.override;\n }\n }\n }\n\n const errors = diagnostics\n .filter((diagnostic) => diagnostic.severity === 'error')\n .map((diagnostic) => diagnostic.message);\n if (errors.length) return { ok: false, errors, diagnostics };\n\n const cookbook = {\n ...input,\n $schema: COOKBOOK_SCHEMA_URL,\n version: COOKBOOK_VERSION,\n recipes,\n features,\n policies,\n } as unknown as Cookbook;\n if (input.exposure !== undefined) {\n cookbook.exposure = input.exposure as Record<\n string,\n CookbookExposureSurface[]\n >;\n }\n if (input.layout !== undefined)\n cookbook.layout = input.layout as CookbookLayout;\n if (input.theme !== undefined) cookbook.theme = input.theme as CookbookTheme;\n delete cookbook.overviews;\n if (Object.keys(overviews).length) cookbook.overviews = overviews;\n const warnings = diagnostics\n .filter((diagnostic) => diagnostic.severity === 'warning')\n .map((diagnostic) => diagnostic.message);\n return { ok: true, cookbook, warnings, diagnostics };\n}\n\n/** Parse JSON text, then {@link validateCookbook} it. */\nexport function parseCookbookText(\n text: string,\n options: CookbookValidateOptions = {},\n): CookbookValidation {\n let value: unknown;\n try {\n value = JSON.parse(text);\n } catch {\n return {\n ok: false,\n errors: ['not valid JSON'],\n diagnostics: [\n {\n severity: 'error',\n code: 'invalid_json',\n path: '',\n message: 'not valid JSON',\n },\n ],\n };\n }\n return validateCookbook(value, options);\n}\n"],"mappings":"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"}
|