@mochabug/adapt-sdk 0.3.12 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import{isSchema as I,isValidSchema as j,validate as x}from"jtd";var h=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function R(e){return e.length===0?"/":e.map(t=>/^\d+$/.test(t)?`[${t}]`:`.${t}`).join("")}function v(e,t){let o=e;for(let s=0;s<t.length-1&&(o&&typeof o=="object"&&t[s]in o);s++)o=o[t[s]];return o}function P(e,t){let o=e;for(let s of t)if(o&&typeof o=="object")o=o[s];else return;return o}function O(e,t,o){let{instancePath:s,schemaPath:n}=e,r=R(s),i=n[n.length-1];if(i==="type"){let u=v(t,n)?.type;return u==="boolean"?`${r}: expected boolean`:u==="string"?`${r}: expected string`:u==="timestamp"?`${r}: expected timestamp string`:h.has(u)?`${r}: expected integer`:`${r}: expected number`}if(i==="enum"){let u=v(t,n)?.enum;return`${r}: expected one of [${u.join(", ")}]`}if(n.length>=2&&n[n.length-2]==="properties"&&i)return`${r==="/"?"":r}.${i}: missing required property`;if(i==="elements")return`${r}: expected array`;if(i==="properties"||i==="optionalProperties"||i==="values")return`${r}: expected object`;if(i==="discriminator")return`${r}: expected string discriminator`;if(i==="mapping"){let a=P(o,s);return`${r}: unknown variant "${a}"`}return n.length===0?`${r}: unexpected property`:`${r}: validation error at /${n.join("/")}`}function T(e,t,o){let s=o??e.definitions,n=s?{...e,definitions:s}:e;return j(n)?x(n,t,{maxDepth:A,maxErrors:E}).map(i=>O(i,n,t)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}var A=32,E=100;var J=32,k={int8:{minimum:-128,maximum:127},uint8:{minimum:0,maximum:255},int16:{minimum:-32768,maximum:32767},uint16:{minimum:0,maximum:65535},int32:{minimum:-2147483648,maximum:2147483647},uint32:{minimum:0,maximum:4294967295}},w={minimum:-34028235e31,maximum:34028235e31},N=new Set(["title","label","name","description"]);function p(e,t){let o=t.metadata;if(!o)return;typeof o.description=="string"&&o.description.trim()&&(e.description=o.description.trim());let s=typeof o.title=="string"&&o.title.trim()||typeof o.label=="string"&&o.label.trim()||typeof o.name=="string"&&o.name.trim();s&&(e.title=s);let n=[];for(let[r,i]of Object.entries(o))N.has(r)||(typeof i=="string"&&i.trim()?n.push(`[${r}: ${i.trim()}]`):(typeof i=="number"||typeof i=="boolean")&&n.push(`[${r}: ${i}]`));if(n.length>0){let r=n.join(" ");e.description=e.description?`${e.description} ${r}`:r}}function $(e,t,o){if(o>J)throw new Error(`Circular or excessively deep ref chain (exceeded ${J} levels)`);if(!e.ref)return e;let s=t?.[e.ref];if(!s)throw new Error(`Unresolved ref "${e.ref}"`);return $(s,t,o+1)}function f(e,t,o){if(o>J)throw new Error(`Schema nesting exceeded ${J} levels`);if(!e||typeof e!="object")return{description:"Any JSON value"};if(e.ref){let r=$(e,t,o),i=f(r,t,o+1);if(p(i,e),e.nullable){let a=i.type;i.type=Array.isArray(a)?[...a,"null"]:a?[a,"null"]:["null"]}return i}let s=e.nullable===!0,n={};if(e.type){let r=e.type,i=k[r];if(i)return n.type=s?["integer","null"]:"integer",n.minimum=i.minimum,n.maximum=i.maximum,p(n,e),n;switch(r){case"boolean":n.type=s?["boolean","null"]:"boolean";break;case"string":n.type=s?["string","null"]:"string";break;case"timestamp":n.type=s?["string","null"]:"string",n.format="date-time";break;case"float32":n.type=s?["number","null"]:"number",n.minimum=w.minimum,n.maximum=w.maximum;break;case"float64":n.type=s?["number","null"]:"number";break;default:throw new Error(`Unknown JTD type "${r}"`)}return p(n,e),n}if(e.enum)return n.type=s?["string","null"]:"string",n.enum=s?[...e.enum,null]:[...e.enum],p(n,e),n;if(e.elements)return n.type=s?["array","null"]:"array",n.items=f(e.elements,t,o+1),p(n,e),n;if(e.properties||e.optionalProperties){n.type=s?["object","null"]:"object",n.properties={};let r=[];if(e.properties)for(let[i,a]of Object.entries(e.properties))n.properties[i]=f(a,t,o+1),r.push(i);if(e.optionalProperties)for(let[i,a]of Object.entries(e.optionalProperties))n.properties[i]=f(a,t,o+1);return r.length>0&&(n.required=r),e.additionalProperties!==!0&&(n.additionalProperties=!1),p(n,e),n}if(e.values)return n.type=s?["object","null"]:"object",n.additionalProperties=f(e.values,t,o+1),p(n,e),n;if(e.discriminator&&e.mapping){let r=e.discriminator,i=e.mapping,a=Object.keys(i);n.type=s?["object","null"]:"object",n.description=`Tagged union: set '${r}' to one of [${a.join(", ")}], then populate ONLY the property whose name matches the chosen '${r}' value. Leave all other variant properties empty.`,n.properties={[r]:{type:"string",enum:[...a],description:`Selects which variant to use. MUST match exactly one of: ${a.join(", ")}.`}},n.required=[r],n.additionalProperties=!1;for(let[u,d]of Object.entries(i)){let b=f(d,t,o+1),c=b.description;b.description=c?`${c} \u2014 Populate ONLY when ${r}='${u}'.`:`Populate ONLY when ${r}='${u}'.`,n.properties[u]=b}return p(n,e),n}return n.description="Any JSON value",p(n,e),n}var G=new Set(Object.keys(k));function m(e,t,o,s){if(s>J||e==null)return e;if(t.ref){let n=o?.[t.ref];return n?m(e,n,o,s+1):e}if(t.type&&G.has(t.type))return typeof e=="number"&&!Number.isInteger(e)?Math.round(e):e;if(t.elements&&Array.isArray(e))return e.map(n=>m(n,t.elements,o,s+1));if((t.properties||t.optionalProperties)&&typeof e=="object"&&e!==null){let n={...e};if(t.properties)for(let[r,i]of Object.entries(t.properties))r in n&&(n[r]=m(n[r],i,o,s+1));if(t.optionalProperties)for(let[r,i]of Object.entries(t.optionalProperties))r in n&&(n[r]=m(n[r],i,o,s+1));return n}if(t.values&&typeof e=="object"&&e!==null){let n={};for(let[r,i]of Object.entries(e))n[r]=m(i,t.values,o,s+1);return n}if(t.discriminator&&t.mapping&&typeof e=="object"&&e!==null){let n=e,r=t.discriminator,i=n[r],a=t.mapping[i];if(!a||typeof n[i]!="object"||n[i]===null)return e;let u=n[i],d=m(u,a,o,s+1);return{[r]:i,...d}}return e}function C(e){let t=e.definitions;return{schema:f(e,t,0),convert:n=>{let r=m(n,e,t,0),i=T(e,r,t);return i.length>0?{success:!1,errors:i}:{success:!0,data:r}}}}function F(e){return{type:"string",description:`Base64-encoded binary content (MIME type: ${e}).`}}function D(e){if(e.jtdSchema)return C(e.jtdSchema);if(e.mimeType)return{schema:F(e.mimeType),convert:s=>typeof s!="string"?{success:!1,errors:[`/: expected base64 string for MIME type ${e.mimeType}, got ${typeof s}`]}:{success:!0,data:s}};throw new Error("Signal format has neither jtdSchema nor mimeType")}function _(e){let t=e.formats;if(!t||t.length===0)throw new Error("Signal descriptor has no formats");let o=e.name??"unnamed",s=e.optional===!0;if(t.length===1){let c=D(t[0]);return e.label&&(c.schema.title=e.label),e.description&&(c.schema.description=e.description),c}let n=[],r={};for(let c=0;c<t.length;c++){let g=t[c],y=`format_${c}`,l=D(g);if(g.jtdSchema){let S=l.schema.description;l.schema.description=S?`Structured JSON data. ${S}`:"Structured JSON data."}r[y]=l.schema,n.push({key:y,converter:l})}let i=n.map(c=>c.key),a=e.description??"",u=s?"Provide at most ONE of the following format properties. All are optional.":`You MUST provide exactly ONE of the following format properties: ${i.join(", ")}.`,d={type:"object",description:a?`${a} ${u}`:u,properties:r,additionalProperties:!1};return e.label&&(d.title=e.label),{schema:d,convert:c=>{if(typeof c!="object"||c===null)return{success:!1,errors:[`/: expected object with format properties, got ${typeof c}`]};let g=c,y=n.find(({key:l})=>g[l]!==void 0&&g[l]!==null);return y?y.converter.convert(g[y.key]):s?{success:!0,data:null}:{success:!1,errors:[`Signal '${o}' is required but no format was provided. Set exactly one of: ${i.join(", ")}.`]}}}}export{_ as convertSignalToGeminiSchema,C as convertToGeminiSchema};
2
+ //# sourceMappingURL=gemini.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/signals/index.ts", "../../src/gemini/index.ts"],
4
+ "sourcesContent": ["import type {\n JTDSchemaJson,\n SignalDescriptorJson,\n SignalFormatJson\n} from '../api';\nimport { isSchema, isValidSchema, validate as jtdValidate } from 'jtd';\nimport type { Schema, ValidationError } from 'jtd';\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD FUZZER (generate sample values from JTD schemas)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Maximum recursion depth for fuzzJTD to prevent infinite loops on self-referencing schemas. */\nconst FUZZ_MAX_DEPTH = 10;\n\n/** Generate a fuzzed (sample) value from a JTD schema. */\nexport function fuzzJTD(\n schema: JTDSchemaJson,\n definitions?: Record<string, JTDSchemaJson>,\n _depth: number = 0\n): unknown {\n if (_depth > FUZZ_MAX_DEPTH) return null;\n\n if (schema.ref) {\n const def = definitions?.[schema.ref];\n if (def) return fuzzJTD(def, definitions, _depth + 1);\n return null;\n }\n\n if (schema.type) {\n switch (schema.type) {\n case 'string':\n return 'Lorem ipsum';\n case 'timestamp':\n return '2024-01-15T10:30:00Z';\n case 'float32':\n case 'float64':\n return 42.5;\n case 'int8':\n case 'uint8':\n case 'int16':\n case 'uint16':\n case 'int32':\n case 'uint32':\n return BigInt(42);\n case 'boolean':\n return true;\n default:\n return null;\n }\n }\n\n if (schema.enum) {\n return schema.enum[0] ?? null;\n }\n\n if (schema.elements) {\n return [\n fuzzJTD(schema.elements, definitions, _depth + 1),\n fuzzJTD(schema.elements, definitions, _depth + 1)\n ];\n }\n\n if (schema.values) {\n return { key1: fuzzJTD(schema.values, definitions, _depth + 1) };\n }\n\n if (schema.properties || schema.optionalProperties) {\n const obj: Record<string, unknown> = {};\n if (schema.properties) {\n for (const [k, v] of Object.entries(schema.properties)) {\n obj[k] = fuzzJTD(v, definitions, _depth + 1);\n }\n }\n if (schema.optionalProperties) {\n for (const [k, v] of Object.entries(schema.optionalProperties)) {\n obj[k] = fuzzJTD(v, definitions, _depth + 1);\n }\n }\n return obj;\n }\n\n if (schema.discriminator && schema.mapping) {\n const firstKey = Object.keys(schema.mapping)[0];\n if (firstKey) {\n const variant = schema.mapping[firstKey]!;\n const obj = fuzzJTD(variant, definitions, _depth + 1) as Record<\n string,\n unknown\n >;\n obj[schema.discriminator] = firstKey;\n return obj;\n }\n return null;\n }\n\n // Empty schema\n return null;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD VALUE VALIDATION (delegates to the `jtd` npm package)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst INTEGER_TYPES = new Set([\n 'int8',\n 'uint8',\n 'int16',\n 'uint16',\n 'int32',\n 'uint32'\n]);\n\nfunction formatInstancePath(instancePath: string[]): string {\n if (instancePath.length === 0) return '/';\n return instancePath\n .map((p) => (/^\\d+$/.test(p) ? `[${p}]` : `.${p}`))\n .join('');\n}\n\nfunction resolveSchemaParent(\n schema: Record<string, unknown>,\n schemaPath: string[]\n): Record<string, unknown> {\n let current: any = schema;\n for (let i = 0; i < schemaPath.length - 1; i++) {\n if (current && typeof current === 'object' && schemaPath[i]! in current) {\n current = current[schemaPath[i]!];\n } else {\n break;\n }\n }\n return current as Record<string, unknown>;\n}\n\nfunction resolveInstanceValue(value: unknown, instancePath: string[]): unknown {\n let current = value;\n for (const key of instancePath) {\n if (current && typeof current === 'object') {\n current = (current as Record<string, unknown>)[key];\n } else {\n return undefined;\n }\n }\n return current;\n}\n\nfunction formatValidationError(\n error: ValidationError,\n schema: Record<string, unknown>,\n value: unknown\n): string {\n const { instancePath, schemaPath } = error;\n const path = formatInstancePath(instancePath);\n const lastKey = schemaPath[schemaPath.length - 1];\n\n if (lastKey === 'type') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const jtdType = parent?.type as string;\n if (jtdType === 'boolean') return `${path}: expected boolean`;\n if (jtdType === 'string') return `${path}: expected string`;\n if (jtdType === 'timestamp') return `${path}: expected timestamp string`;\n if (INTEGER_TYPES.has(jtdType)) return `${path}: expected integer`;\n return `${path}: expected number`;\n }\n\n if (lastKey === 'enum') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const enumValues = parent?.enum as string[];\n return `${path}: expected one of [${enumValues.join(', ')}]`;\n }\n\n if (\n schemaPath.length >= 2 &&\n schemaPath[schemaPath.length - 2] === 'properties' &&\n lastKey\n ) {\n const prefix = path === '/' ? '' : path;\n return `${prefix}.${lastKey}: missing required property`;\n }\n\n if (lastKey === 'elements') return `${path}: expected array`;\n\n if (\n lastKey === 'properties' ||\n lastKey === 'optionalProperties' ||\n lastKey === 'values'\n ) {\n return `${path}: expected object`;\n }\n\n if (lastKey === 'discriminator')\n return `${path}: expected string discriminator`;\n\n if (lastKey === 'mapping') {\n const discValue = resolveInstanceValue(value, instancePath);\n return `${path}: unknown variant \"${discValue}\"`;\n }\n\n if (schemaPath.length === 0) return `${path}: unexpected property`;\n\n return `${path}: validation error at /${schemaPath.join('/')}`;\n}\n\n/**\n * Validate a value against a JTD schema, returning an array of error messages.\n * Delegates to the `jtd` npm package for spec-compliant validation.\n */\nexport function validateJsonAgainstJTD(\n schema: JTDSchemaJson,\n value: unknown,\n definitions?: Record<string, JTDSchemaJson>\n): string[] {\n const defs =\n definitions ??\n (schema.definitions as Record<string, JTDSchemaJson> | undefined);\n\n const schemaForValidation = defs\n ? ({ ...schema, definitions: defs } as Schema)\n : (schema as Schema);\n\n // The jtd lib throws on invalid schemas (e.g., unresolved refs).\n if (!isValidSchema(schemaForValidation)) {\n if (schema.ref) {\n return [`/: unknown ref \"${schema.ref}\"`];\n }\n return [`/: invalid schema`];\n }\n\n const errors = jtdValidate(schemaForValidation, value, {\n maxDepth: MAX_VALIDATION_DEPTH,\n maxErrors: MAX_VALIDATION_ERRORS\n });\n\n return errors.map((err) =>\n formatValidationError(\n err,\n schemaForValidation as Record<string, unknown>,\n value\n )\n );\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// SIGNAL-LEVEL VALIDATION (JSON values against JTD formats)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Validate a JSON value against a single SignalFormatJson. */\nexport function validateJsonAgainstSignal(\n format: SignalFormatJson,\n jsonValue: unknown\n): string[];\n/** Validate a JSON value against a SignalDescriptorJson (valid if value matches ANY JTD format). */\nexport function validateJsonAgainstSignal(\n descriptor: SignalDescriptorJson,\n jsonValue: unknown\n): string[];\nexport function validateJsonAgainstSignal(\n formatOrDescriptor: SignalFormatJson | SignalDescriptorJson,\n jsonValue: unknown\n): string[] {\n // Descriptor path \u2014 has `formats` array\n if (\n 'formats' in formatOrDescriptor &&\n Array.isArray(formatOrDescriptor.formats)\n ) {\n const jtdFormats = (\n formatOrDescriptor.formats as SignalFormatJson[]\n ).filter((f) => f.jtdSchema);\n if (jtdFormats.length === 0) {\n return ['/: no JTD formats in signal descriptor'];\n }\n // Valid if value matches ANY JTD format\n for (const format of jtdFormats) {\n const errors = validateJsonAgainstJTD(format.jtdSchema!, jsonValue);\n if (errors.length === 0) return [];\n }\n // None matched \u2014 return errors from last format attempt\n return validateJsonAgainstJTD(\n jtdFormats[jtdFormats.length - 1]!.jtdSchema!,\n jsonValue\n );\n }\n\n // Single format path\n const format = formatOrDescriptor as SignalFormatJson;\n if (!format.jtdSchema) {\n return ['/: signal format has no jtdSchema'];\n }\n return validateJsonAgainstJTD(format.jtdSchema, jsonValue);\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD \u2192 JSON SCHEMA CONVERTER\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/**\n * Convert JTD (JSON Type Definition) schema to JSON Schema for validation.\n *\n * Supports all 8 JTD schema forms per RFC 8927:\n * - Empty form: {}\n * - Ref form: { ref: \"...\" }\n * - Type form: { type: \"...\" }\n * - Enum form: { enum: [...] }\n * - Elements form: { elements: {...} }\n * - Properties form: { properties: {...}, optionalProperties: {...} }\n * - Values form: { values: {...} }\n * - Discriminator form: { discriminator: \"...\", mapping: {...} }\n */\nexport function jtdToJsonSchema(\n jtdSchema: JTDSchemaJson,\n definitions?: Record<string, JTDSchemaJson>,\n isRoot = true\n): any {\n if (!jtdSchema || typeof jtdSchema !== 'object') {\n return {};\n }\n\n const isNullable = jtdSchema['nullable'];\n const defs =\n definitions ||\n (jtdSchema['definitions'] as Record<string, JTDSchemaJson> | undefined);\n\n const result: any = {};\n\n if (isRoot) {\n result.$schema = 'http://json-schema.org/draft-07/schema#';\n }\n\n // Ref form\n if (jtdSchema['ref']) {\n const refName = jtdSchema['ref'] as string;\n if (defs && defs[refName]) {\n const resolvedSchema = jtdToJsonSchema(\n defs[refName] as JTDSchemaJson,\n defs,\n false\n );\n\n if (isNullable) {\n if (resolvedSchema.type) {\n resolvedSchema.type = Array.isArray(resolvedSchema.type)\n ? [...resolvedSchema.type, 'null']\n : [resolvedSchema.type, 'null'];\n } else {\n return {\n ...resolvedSchema,\n anyOf: [resolvedSchema, { type: 'null' }],\n ...(isRoot\n ? { $schema: 'http://json-schema.org/draft-07/schema#' }\n : {})\n };\n }\n }\n\n return isRoot\n ? {\n ...resolvedSchema,\n $schema: 'http://json-schema.org/draft-07/schema#'\n }\n : resolvedSchema;\n }\n return isRoot ? result : {};\n }\n\n // Type form\n if (jtdSchema['type']) {\n const typeMap: Record<string, string> = {\n boolean: 'boolean',\n string: 'string',\n timestamp: 'string',\n float32: 'number',\n float64: 'number',\n int8: 'integer',\n uint8: 'integer',\n int16: 'integer',\n uint16: 'integer',\n int32: 'integer',\n uint32: 'integer'\n };\n const jtdType = jtdSchema['type'] as string;\n const baseType = typeMap[jtdType] || 'string';\n\n result.type = isNullable ? [baseType, 'null'] : baseType;\n\n if (baseType === 'string' && jtdType === 'timestamp') {\n result.format = 'date-time';\n }\n return result;\n }\n\n // Enum form\n if (jtdSchema['enum']) {\n result.type = isNullable ? ['string', 'null'] : 'string';\n result.enum = isNullable\n ? [...(jtdSchema['enum'] as string[]), null]\n : jtdSchema['enum'];\n return result;\n }\n\n // Elements form\n if (jtdSchema['elements']) {\n result.type = isNullable ? ['array', 'null'] : 'array';\n result.items = jtdToJsonSchema(\n jtdSchema['elements'] as JTDSchemaJson,\n defs,\n false\n );\n return result;\n }\n\n // Properties form\n if (jtdSchema['properties'] || jtdSchema['optionalProperties']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.properties = {};\n result.required = [];\n\n if (jtdSchema['properties']) {\n for (const [key, value] of Object.entries(jtdSchema['properties'])) {\n result.properties[key] = jtdToJsonSchema(\n value as JTDSchemaJson,\n defs,\n false\n );\n result.required.push(key);\n }\n }\n\n if (jtdSchema['optionalProperties']) {\n for (const [key, value] of Object.entries(\n jtdSchema['optionalProperties']\n )) {\n result.properties[key] = jtdToJsonSchema(\n value as JTDSchemaJson,\n defs,\n false\n );\n }\n }\n\n // JTD is strict by default\n if (jtdSchema['additionalProperties'] !== true) {\n result.additionalProperties = false;\n }\n\n return result;\n }\n\n // Values form\n if (jtdSchema['values']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.additionalProperties = jtdToJsonSchema(\n jtdSchema['values'] as JTDSchemaJson,\n defs,\n false\n );\n return result;\n }\n\n // Discriminator form\n if (jtdSchema['discriminator'] && jtdSchema['mapping']) {\n const variants = [];\n const discriminatorKey = jtdSchema['discriminator'] as string;\n\n for (const [tag, schema] of Object.entries(jtdSchema['mapping'])) {\n const variantSchema = jtdToJsonSchema(\n schema as JTDSchemaJson,\n defs,\n false\n );\n\n if (!variantSchema.type) {\n variantSchema.type = 'object';\n } else if (\n variantSchema.type !== 'object' &&\n !Array.isArray(variantSchema.type)\n ) {\n variantSchema.type = 'object';\n }\n\n variantSchema.properties = variantSchema.properties || {};\n variantSchema.properties[discriminatorKey] = { const: tag };\n\n variantSchema.required = variantSchema.required || [];\n if (!variantSchema.required.includes(discriminatorKey)) {\n variantSchema.required.unshift(discriminatorKey);\n }\n\n // JTD discriminator variants are strict by default\n if (variantSchema.additionalProperties === undefined) {\n variantSchema.additionalProperties = false;\n }\n\n variants.push(variantSchema);\n }\n\n if (isNullable) {\n variants.push({ type: 'null' });\n }\n\n result.oneOf = variants;\n return result;\n }\n\n // Empty form\n return result;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD SCHEMA VALIDATION (using the `jtd` npm package)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nexport const MAX_VALIDATION_DEPTH = 32;\nexport const MAX_VALIDATION_ERRORS = 100;\n\n/** Validate that the input is a valid JTD schema. */\nexport function validateJTDSchema(\n schema: unknown\n): { valid: true; schema: JTDSchemaJson } | { valid: false; error: string } {\n if (!isSchema(schema)) {\n return {\n valid: false,\n error: 'Invalid JTD schema: Schema does not match JTD structure'\n };\n }\n\n if (!isValidSchema(schema)) {\n return {\n valid: false,\n error:\n 'Invalid JTD schema: Schema has semantic errors (e.g., circular references, conflicting forms)'\n };\n }\n\n return { valid: true, schema: schema as unknown as JTDSchemaJson };\n}\n\n/** Parse and validate a JSON string. */\nexport function validateJSON(jsonString: string): {\n valid: boolean;\n data?: unknown;\n error?: string;\n} {\n try {\n const data = JSON.parse(jsonString);\n return { valid: true, data };\n } catch (error) {\n return {\n valid: false,\n error: `Invalid JSON: ${error instanceof Error ? error.message : 'Parse error'}`\n };\n }\n}\n\n/** Parse a JSON string and validate it as a JTD schema. */\nexport function validateJTDSchemaString(\n schemaString: string\n): { valid: true; schema: JTDSchemaJson } | { valid: false; error: string } {\n const jsonResult = validateJSON(schemaString);\n if (!jsonResult.valid) return { valid: false, error: jsonResult.error! };\n\n return validateJTDSchema(jsonResult.data);\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// MONACO EDITOR CONFIG FOR JTD SCHEMA EDITING\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Monaco editor JSON schema configuration for JTD schema IntelliSense and validation. */\nexport const JTD_SCHEMA_CONFIG = {\n uri: 'https://jsontypedef.com/schemas/jtd-schema.json',\n fileMatch: ['inmemory://jtd-schema/*.json'],\n schema: {\n $schema: 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {\n type: {\n description: 'Type form - defines a primitive type',\n enum: [\n 'boolean',\n 'string',\n 'timestamp',\n 'float32',\n 'float64',\n 'int8',\n 'uint8',\n 'int16',\n 'uint16',\n 'int32',\n 'uint32'\n ]\n },\n enum: {\n description: 'Enum form - defines a set of string values',\n type: 'array',\n items: { type: 'string' }\n },\n elements: {\n description: 'Elements form - defines an array with typed elements',\n $ref: '#'\n },\n properties: {\n description:\n 'Properties form - defines an object with required properties',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n optionalProperties: {\n description: 'Optional properties - defines optional object properties',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n values: {\n description: 'Values form - defines a map/dictionary with typed values',\n $ref: '#'\n },\n discriminator: {\n description: 'Discriminator form - defines a tagged union',\n type: 'string'\n },\n mapping: {\n description: 'Mapping for discriminator form',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n ref: {\n description: 'Ref form - references a definition',\n type: 'string'\n },\n definitions: {\n description: 'Top-level definitions for reusable schemas',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n nullable: {\n description: 'Allow null values',\n type: 'boolean'\n },\n metadata: {\n description: 'Custom metadata for documentation',\n type: 'object'\n },\n additionalProperties: {\n description: 'Allow additional properties (properties form only)',\n type: 'boolean'\n }\n }\n }\n};\n", "// Copyright 2024-2025 Mochabug, LLC. All rights reserved.\n// Licensed under the Apache License, Version 2.0.\n\nimport type {\n JTDSchemaJson,\n SignalDescriptorJson,\n SignalFormatJson\n} from '../api';\nimport { validateJsonAgainstJTD } from '../signals';\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Types\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** JSON Schema subset supported by Gemini 3+ structured output. */\nexport interface GeminiSchema {\n type?: string | string[];\n title?: string;\n description?: string;\n properties?: Record<string, GeminiSchema>;\n required?: string[];\n additionalProperties?: boolean | GeminiSchema;\n enum?: (string | number | null)[];\n format?: string;\n items?: GeminiSchema;\n minimum?: number;\n maximum?: number;\n}\n\nexport interface ConvertSuccess {\n success: true;\n data: unknown;\n}\n\nexport interface ConvertFailure {\n success: false;\n errors: string[];\n}\n\nexport type ConvertResult = ConvertSuccess | ConvertFailure;\n\nexport interface GeminiConversionResult {\n /** Gemini 3+ compatible JSON Schema for structured output. */\n schema: GeminiSchema;\n /** Convert Gemini JSON output back to JTD-conforming JSON. */\n convert: (geminiJson: unknown) => ConvertResult;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Constants\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst MAX_REF_DEPTH = 32;\n\nconst INTEGER_BOUNDS: Record<string, { minimum: number; maximum: number }> = {\n int8: { minimum: -128, maximum: 127 },\n uint8: { minimum: 0, maximum: 255 },\n int16: { minimum: -32768, maximum: 32767 },\n uint16: { minimum: 0, maximum: 65535 },\n int32: { minimum: -2147483648, maximum: 2147483647 },\n uint32: { minimum: 0, maximum: 4294967295 }\n};\n\nconst FLOAT32_BOUNDS = {\n minimum: -3.4028235e38,\n maximum: 3.4028235e38\n};\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Metadata helper\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst METADATA_KNOWN_KEYS = new Set(['title', 'label', 'name', 'description']);\n\nfunction applyMetadata(result: GeminiSchema, schema: JTDSchemaJson): void {\n const meta = schema.metadata as Record<string, unknown> | undefined;\n if (!meta) return;\n\n if (typeof meta['description'] === 'string' && meta['description'].trim()) {\n result.description = meta['description'].trim();\n }\n\n const titleCandidate =\n (typeof meta['title'] === 'string' && meta['title'].trim()) ||\n (typeof meta['label'] === 'string' && meta['label'].trim()) ||\n (typeof meta['name'] === 'string' && meta['name'].trim());\n if (titleCandidate) {\n result.title = titleCandidate;\n }\n\n // Surface extra metadata keys as description hints\n const extras: string[] = [];\n for (const [key, value] of Object.entries(meta)) {\n if (METADATA_KNOWN_KEYS.has(key)) continue;\n if (typeof value === 'string' && value.trim()) {\n extras.push(`[${key}: ${value.trim()}]`);\n } else if (typeof value === 'number' || typeof value === 'boolean') {\n extras.push(`[${key}: ${value}]`);\n }\n }\n if (extras.length > 0) {\n const suffix = extras.join(' ');\n result.description = result.description\n ? `${result.description} ${suffix}`\n : suffix;\n }\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Schema conversion (JTD \u2192 Gemini JSON Schema)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nfunction resolveRef(\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): JTDSchemaJson {\n if (depth > MAX_REF_DEPTH) {\n throw new Error(\n `Circular or excessively deep ref chain (exceeded ${MAX_REF_DEPTH} levels)`\n );\n }\n if (!schema.ref) return schema;\n const resolved = defs?.[schema.ref];\n if (!resolved) {\n throw new Error(`Unresolved ref \"${schema.ref}\"`);\n }\n return resolveRef(resolved, defs, depth + 1);\n}\n\nfunction convertNode(\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): GeminiSchema {\n if (depth > MAX_REF_DEPTH) {\n throw new Error(`Schema nesting exceeded ${MAX_REF_DEPTH} levels`);\n }\n\n if (!schema || typeof schema !== 'object') {\n return { description: 'Any JSON value' };\n }\n\n // Ref form \u2014 inline resolve\n if (schema.ref) {\n const resolved = resolveRef(schema, defs, depth);\n const result = convertNode(resolved, defs, depth + 1);\n applyMetadata(result, schema);\n if (schema.nullable) {\n const existing = result.type;\n result.type = Array.isArray(existing)\n ? [...existing, 'null']\n : existing ? [existing, 'null'] : ['null'];\n }\n return result;\n }\n\n const isNullable = schema.nullable === true;\n const result: GeminiSchema = {};\n\n // Type form\n if (schema.type) {\n const jtdType = schema.type as string;\n\n const intBounds = INTEGER_BOUNDS[jtdType];\n if (intBounds) {\n result.type = isNullable ? ['integer', 'null'] : 'integer';\n result.minimum = intBounds.minimum;\n result.maximum = intBounds.maximum;\n applyMetadata(result, schema);\n return result;\n }\n\n switch (jtdType) {\n case 'boolean':\n result.type = isNullable ? ['boolean', 'null'] : 'boolean';\n break;\n case 'string':\n result.type = isNullable ? ['string', 'null'] : 'string';\n break;\n case 'timestamp':\n result.type = isNullable ? ['string', 'null'] : 'string';\n result.format = 'date-time';\n break;\n case 'float32':\n result.type = isNullable ? ['number', 'null'] : 'number';\n result.minimum = FLOAT32_BOUNDS.minimum;\n result.maximum = FLOAT32_BOUNDS.maximum;\n break;\n case 'float64':\n result.type = isNullable ? ['number', 'null'] : 'number';\n break;\n default:\n throw new Error(`Unknown JTD type \"${jtdType}\"`);\n }\n\n applyMetadata(result, schema);\n return result;\n }\n\n // Enum form\n if (schema.enum) {\n result.type = isNullable ? ['string', 'null'] : 'string';\n result.enum = isNullable\n ? [...(schema.enum as string[]), null]\n : [...(schema.enum as string[])];\n applyMetadata(result, schema);\n return result;\n }\n\n // Elements form\n if (schema.elements) {\n result.type = isNullable ? ['array', 'null'] : 'array';\n result.items = convertNode(\n schema.elements as JTDSchemaJson,\n defs,\n depth + 1\n );\n applyMetadata(result, schema);\n return result;\n }\n\n // Properties form\n if (schema.properties || schema.optionalProperties) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.properties = {};\n const required: string[] = [];\n\n if (schema.properties) {\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n result.properties[key] = convertNode(\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n required.push(key);\n }\n }\n\n if (schema.optionalProperties) {\n for (const [key, propSchema] of Object.entries(\n schema.optionalProperties\n )) {\n result.properties[key] = convertNode(\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n\n if (required.length > 0) {\n result.required = required;\n }\n\n if (schema.additionalProperties !== true) {\n result.additionalProperties = false;\n }\n\n applyMetadata(result, schema);\n return result;\n }\n\n // Values form\n if (schema.values) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.additionalProperties = convertNode(\n schema.values as JTDSchemaJson,\n defs,\n depth + 1\n );\n applyMetadata(result, schema);\n return result;\n }\n\n // Discriminator form\n if (schema.discriminator && schema.mapping) {\n const discKey = schema.discriminator as string;\n const mapping = schema.mapping as Record<string, JTDSchemaJson>;\n const tags = Object.keys(mapping);\n\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.description =\n `Tagged union: set '${discKey}' to one of [${tags.join(', ')}], ` +\n `then populate ONLY the property whose name matches the chosen '${discKey}' value. ` +\n `Leave all other variant properties empty.`;\n result.properties = {\n [discKey]: {\n type: 'string',\n enum: [...tags],\n description: `Selects which variant to use. MUST match exactly one of: ${tags.join(', ')}.`\n }\n };\n result.required = [discKey];\n result.additionalProperties = false;\n\n for (const [tag, variantSchema] of Object.entries(mapping)) {\n const variantGemini = convertNode(\n variantSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n const metaDesc = variantGemini.description;\n variantGemini.description = metaDesc\n ? `${metaDesc} \u2014 Populate ONLY when ${discKey}='${tag}'.`\n : `Populate ONLY when ${discKey}='${tag}'.`;\n result.properties[tag] = variantGemini;\n }\n\n applyMetadata(result, schema);\n return result;\n }\n\n // Empty form\n result.description = 'Any JSON value';\n applyMetadata(result, schema);\n return result;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Coercion (Gemini output \u2192 JTD-conforming JSON)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst INTEGER_TYPE_SET = new Set(Object.keys(INTEGER_BOUNDS));\n\nfunction coerceToJTD(\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): unknown {\n if (depth > MAX_REF_DEPTH) return value;\n if (value === null || value === undefined) return value;\n\n // Ref form \u2014 resolve and recurse\n if (schema.ref) {\n const resolved = defs?.[schema.ref];\n if (resolved) {\n return coerceToJTD(value, resolved, defs, depth + 1);\n }\n return value;\n }\n\n // Type form \u2014 integer coercion\n if (schema.type && INTEGER_TYPE_SET.has(schema.type as string)) {\n if (typeof value === 'number' && !Number.isInteger(value)) {\n return Math.round(value);\n }\n return value;\n }\n\n // Elements form\n if (schema.elements && Array.isArray(value)) {\n return value.map((item) =>\n coerceToJTD(item, schema.elements as JTDSchemaJson, defs, depth + 1)\n );\n }\n\n // Properties form\n if (\n (schema.properties || schema.optionalProperties) &&\n typeof value === 'object' &&\n value !== null\n ) {\n const obj = { ...(value as Record<string, unknown>) };\n if (schema.properties) {\n for (const [k, propSchema] of Object.entries(schema.properties)) {\n if (k in obj) {\n obj[k] = coerceToJTD(\n obj[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n if (schema.optionalProperties) {\n for (const [k, propSchema] of Object.entries(schema.optionalProperties)) {\n if (k in obj) {\n obj[k] = coerceToJTD(\n obj[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n return obj;\n }\n\n // Values form\n if (schema.values && typeof value === 'object' && value !== null) {\n const obj: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n obj[k] = coerceToJTD(v, schema.values as JTDSchemaJson, defs, depth + 1);\n }\n return obj;\n }\n\n // Discriminator form \u2014 extract matching variant and flatten\n if (\n schema.discriminator &&\n schema.mapping &&\n typeof value === 'object' &&\n value !== null\n ) {\n const rec = value as Record<string, unknown>;\n const discKey = schema.discriminator as string;\n const tag = rec[discKey] as string;\n const variantSchema = (schema.mapping as Record<string, JTDSchemaJson>)[\n tag\n ];\n\n if (!variantSchema || typeof rec[tag] !== 'object' || rec[tag] === null) {\n // Return as-is; validation will catch the error\n return value;\n }\n\n // Extract the variant data and merge with discriminator\n const variantData = rec[tag] as Record<string, unknown>;\n const coerced = coerceToJTD(variantData, variantSchema, defs, depth + 1);\n return { [discKey]: tag, ...(coerced as Record<string, unknown>) };\n }\n\n return value;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Public API\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/**\n * Convert a JTD schema to a Gemini 3+ compatible JSON Schema, with a\n * converter function that transforms and validates Gemini output against\n * the original JTD schema.\n *\n * @throws {Error} if the JTD schema contains forms that cannot be represented.\n */\nexport function convertToGeminiSchema(\n jtdSchema: JTDSchemaJson\n): GeminiConversionResult {\n const defs = jtdSchema.definitions as\n | Record<string, JTDSchemaJson>\n | undefined;\n\n const schema = convertNode(jtdSchema, defs, 0);\n\n const convert = (geminiJson: unknown): ConvertResult => {\n const coerced = coerceToJTD(geminiJson, jtdSchema, defs, 0);\n const errors = validateJsonAgainstJTD(jtdSchema, coerced, defs);\n if (errors.length > 0) {\n return { success: false, errors };\n }\n return { success: true, data: coerced };\n };\n\n return { schema, convert };\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Signal-level conversion (SignalDescriptorJson \u2192 Gemini schema)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nfunction convertMimeFormat(mimeType: string): GeminiSchema {\n return {\n type: 'string',\n description: `Base64-encoded binary content (MIME type: ${mimeType}).`\n };\n}\n\nfunction convertSingleFormat(format: SignalFormatJson): GeminiConversionResult {\n if (format.jtdSchema) {\n return convertToGeminiSchema(format.jtdSchema);\n }\n if (format.mimeType) {\n const schema = convertMimeFormat(format.mimeType);\n const convert = (geminiJson: unknown): ConvertResult => {\n if (typeof geminiJson !== 'string') {\n return {\n success: false,\n errors: [\n `/: expected base64 string for MIME type ${format.mimeType}, got ${typeof geminiJson}`\n ]\n };\n }\n return { success: true, data: geminiJson };\n };\n return { schema, convert };\n }\n throw new Error('Signal format has neither jtdSchema nor mimeType');\n}\n\n/**\n * Convert a SignalDescriptorJson to a Gemini 3+ compatible JSON Schema.\n *\n * Handles single and multi-format signals:\n * - Single format: schema is the converted format directly.\n * - Multiple formats: schema is a wrapper object with `format_0`, `format_1`, etc.\n * as optional properties. The convert function extracts the selected format.\n *\n * MIME type formats are mapped to base64 strings.\n *\n * @throws {Error} if the descriptor has no formats.\n */\nexport function convertSignalToGeminiSchema(\n descriptor: SignalDescriptorJson\n): GeminiConversionResult {\n const formats = descriptor.formats as SignalFormatJson[] | undefined;\n if (!formats || formats.length === 0) {\n throw new Error('Signal descriptor has no formats');\n }\n\n const signalName = descriptor.name ?? 'unnamed';\n const isOptional = descriptor.optional === true;\n\n // Single format \u2014 no wrapper\n if (formats.length === 1) {\n const result = convertSingleFormat(formats[0]!);\n if (descriptor.label) result.schema.title = descriptor.label;\n if (descriptor.description)\n result.schema.description = descriptor.description;\n return result;\n }\n\n // Multiple formats \u2014 wrapper object\n const formatConverters: Array<{\n key: string;\n converter: GeminiConversionResult;\n }> = [];\n\n const wrapperProps: Record<string, GeminiSchema> = {};\n\n for (let i = 0; i < formats.length; i++) {\n const fmt = formats[i]!;\n const key = `format_${i}`;\n const conv = convertSingleFormat(fmt);\n\n // Add format-specific description prefix\n if (fmt.jtdSchema) {\n const existing = conv.schema.description;\n conv.schema.description = existing\n ? `Structured JSON data. ${existing}`\n : 'Structured JSON data.';\n }\n\n wrapperProps[key] = conv.schema;\n formatConverters.push({ key, converter: conv });\n }\n\n const keys = formatConverters.map((f) => f.key);\n const baseDesc = descriptor.description ?? '';\n const guidance = isOptional\n ? 'Provide at most ONE of the following format properties. All are optional.'\n : `You MUST provide exactly ONE of the following format properties: ${keys.join(', ')}.`;\n\n const schema: GeminiSchema = {\n type: 'object',\n description: baseDesc ? `${baseDesc} ${guidance}` : guidance,\n properties: wrapperProps,\n additionalProperties: false\n };\n if (descriptor.label) schema.title = descriptor.label;\n\n const convert = (geminiJson: unknown): ConvertResult => {\n if (typeof geminiJson !== 'object' || geminiJson === null) {\n return {\n success: false,\n errors: [\n `/: expected object with format properties, got ${typeof geminiJson}`\n ]\n };\n }\n\n const rec = geminiJson as Record<string, unknown>;\n\n // Find which format property is set (non-null)\n const selected = formatConverters.find(\n ({ key }) => rec[key] !== undefined && rec[key] !== null\n );\n\n if (!selected) {\n if (isOptional) {\n return { success: true, data: null };\n }\n return {\n success: false,\n errors: [\n `Signal '${signalName}' is required but no format was provided. Set exactly one of: ${keys.join(', ')}.`\n ]\n };\n }\n\n return selected.converter.convert(rec[selected.key]);\n };\n\n return { schema, convert };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["isSchema", "isValidSchema", "jtdValidate", "INTEGER_TYPES", "formatInstancePath", "instancePath", "p", "resolveSchemaParent", "schema", "schemaPath", "current", "i", "resolveInstanceValue", "value", "key", "formatValidationError", "error", "path", "lastKey", "jtdType", "enumValues", "discValue", "validateJsonAgainstJTD", "definitions", "defs", "schemaForValidation", "isValidSchema", "jtdValidate", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "err", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "MAX_REF_DEPTH", "INTEGER_BOUNDS", "FLOAT32_BOUNDS", "METADATA_KNOWN_KEYS", "applyMetadata", "result", "schema", "meta", "titleCandidate", "extras", "key", "value", "suffix", "resolveRef", "defs", "depth", "resolved", "convertNode", "existing", "isNullable", "jtdType", "intBounds", "required", "propSchema", "discKey", "mapping", "tags", "tag", "variantSchema", "variantGemini", "metaDesc", "INTEGER_TYPE_SET", "coerceToJTD", "item", "obj", "k", "v", "rec", "variantData", "coerced", "convertToGeminiSchema", "jtdSchema", "geminiJson", "errors", "validateJsonAgainstJTD", "convertMimeFormat", "mimeType", "convertSingleFormat", "format", "convertSignalToGeminiSchema", "descriptor", "formats", "signalName", "isOptional", "formatConverters", "wrapperProps", "i", "fmt", "conv", "keys", "f", "baseDesc", "guidance", "selected"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{isSchema as U,isValidSchema as w,validate as h}from"jtd";var j=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function x(e){return e.length===0?"/":e.map(r=>/^\d+$/.test(r)?`[${r}]`:`.${r}`).join("")}function T(e,r){let o=e;for(let i=0;i<r.length-1&&(o&&typeof o=="object"&&r[i]in o);i++)o=o[r[i]];return o}function R(e,r){let o=e;for(let i of r)if(o&&typeof o=="object")o=o[i];else return;return o}function I(e,r,o){let{instancePath:i,schemaPath:n}=e,t=x(i),s=n[n.length-1];if(s==="type"){let u=T(r,n)?.type;return u==="boolean"?`${t}: expected boolean`:u==="string"?`${t}: expected string`:u==="timestamp"?`${t}: expected timestamp string`:j.has(u)?`${t}: expected integer`:`${t}: expected number`}if(s==="enum"){let u=T(r,n)?.enum;return`${t}: expected one of [${u.join(", ")}]`}if(n.length>=2&&n[n.length-2]==="properties"&&s)return`${t==="/"?"":t}.${s}: missing required property`;if(s==="elements")return`${t}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${t}: expected object`;if(s==="discriminator")return`${t}: expected string discriminator`;if(s==="mapping"){let a=R(o,i);return`${t}: unknown variant "${a}"`}return n.length===0?`${t}: unexpected property`:`${t}: validation error at /${n.join("/")}`}function O(e,r,o){let i=o??e.definitions,n=i?{...e,definitions:i}:e;return w(n)?h(n,r,{maxDepth:P,maxErrors:E}).map(s=>I(s,n,r)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}var P=32,E=100;var J=32,A={int8:{minimum:-128,maximum:127},uint8:{minimum:0,maximum:255},int16:{minimum:-32768,maximum:32767},uint16:{minimum:0,maximum:65535},int32:{minimum:-2147483648,maximum:2147483647},uint32:{minimum:0,maximum:4294967295}},D={minimum:-34028235e31,maximum:34028235e31};function b(e){return!e||typeof e!="object"?!0:e.type||e.enum||e.elements||e.values||e.discriminator||e.ref||e.properties&&Object.keys(e.properties).length>0||e.optionalProperties&&Object.keys(e.optionalProperties).length>0?!1:(e.properties!==void 0||e.optionalProperties!==void 0)&&e.additionalProperties===!0?!0:!(e.properties!==void 0||e.optionalProperties!==void 0)}function N(e,r){let o=e,i=0;for(;o.ref&&i<J;){let n=r?.[o.ref];if(!n)return!1;o=n,i++}return i>=J?!1:b(o)}function $(e){if(Array.isArray(e.type)&&e.type.includes("null")||e.type==="null")return e;if(e.$ref)return{anyOf:[e,{type:"null"}]};if(e.anyOf)return e.anyOf.some(o=>o.type==="null")?e:{...e,anyOf:[...e.anyOf,{type:"null"}]};let r={...e};return r.type&&(r.type=Array.isArray(r.type)?[...r.type,"null"]:[r.type,"null"]),r.enum&&!r.enum.includes(null)&&(r.enum=[...r.enum,null]),r}var M=new Set(["title","label","name","description"]);function f(e,r){let o=r.metadata;if(!o)return;let i=[],n=typeof o.title=="string"&&o.title.trim()||typeof o.label=="string"&&o.label.trim()||typeof o.name=="string"&&o.name.trim(),t=typeof o.description=="string"?o.description.trim():"";n&&t?i.push(`${n}. ${t}`):n?i.push(n):t&&i.push(t);let s=[];for(let[a,u]of Object.entries(o))M.has(a)||(typeof u=="string"&&u.trim()?s.push(`[${a}: ${u.trim()}]`):(typeof u=="number"||typeof u=="boolean")&&s.push(`[${a}: ${u}]`));if(s.length>0&&i.push(s.join(" ")),i.length>0){let a=i.join(" ");e.description=e.description?`${e.description} ${a}`:a}}function S(e,r,o){if(o>J)throw new Error(`Schema nesting exceeded ${J} levels`);if(!e||typeof e!="object")return{type:"string",description:"Must be a valid JSON value."};if(b(e)){let t={type:e.nullable===!0?["string","null"]:"string",description:"Must be a valid JSON value."};return f(t,e),t}let i=e.nullable===!0;if(e.ref){let n=e.ref;if(!r?.[n])throw new Error(`Unresolved ref "${n}"`);if(i){let t={anyOf:[{$ref:`#/$defs/${n}`},{type:"null"}]};return f(t,e),t}return{$ref:`#/$defs/${n}`}}if(e.type){let n=e.type,t={},s=A[n];if(s)return t.type=i?["integer","null"]:"integer",t.minimum=s.minimum,t.maximum=s.maximum,f(t,e),t;switch(n){case"boolean":t.type=i?["boolean","null"]:"boolean";break;case"string":t.type=i?["string","null"]:"string";break;case"timestamp":t.type=i?["string","null"]:"string",t.format="date-time";break;case"float32":t.type=i?["number","null"]:"number",t.minimum=D.minimum,t.maximum=D.maximum;break;case"float64":t.type=i?["number","null"]:"number";break;default:throw new Error(`Unknown JTD type "${n}"`)}return f(t,e),t}if(e.enum){let n={type:i?["string","null"]:"string",enum:i?[...e.enum,null]:[...e.enum]};return f(n,e),n}if(e.elements){let n={type:i?["array","null"]:"array",items:S(e.elements,r,o+1)};return f(n,e),n}if(e.properties||e.optionalProperties){let n={type:i?["object","null"]:"object",properties:{},additionalProperties:!1},t=[];if(e.properties)for(let[s,a]of Object.entries(e.properties))n.properties[s]=S(a,r,o+1),t.push(s);if(e.optionalProperties)for(let[s,a]of Object.entries(e.optionalProperties)){let u=S(a,r,o+1);n.properties[s]=$(u),t.push(s)}return n.required=t,f(n,e),n}if(e.values){let n=S(e.values,r,o+1),t={type:i?["array","null"]:"array",items:{type:"object",properties:{key:{type:"string"},value:n},required:["key","value"],additionalProperties:!1}};return f(t,e),t}if(e.discriminator&&e.mapping){let n=e.discriminator,t=e.mapping,s=[];for(let[u,p]of Object.entries(t)){let l;b(p)?l={type:"object",properties:{[n]:{type:"string",enum:[u]},_data:{type:"string",description:"Must be a valid JSON value representing the variant data."}},required:[n,"_data"],additionalProperties:!1}:(l=S(p,r,o+1),l.properties[n]={type:"string",enum:[u]},(l.required??=[]).unshift(n),l.additionalProperties=!1),f(l,p),s.push(l)}let a={anyOf:s};return i&&a.anyOf.push({type:"null"}),f(a,e),a}return{type:"string",description:"Must be a valid JSON value."}}var C=new Set(Object.keys(A));function g(e,r,o,i){if(i>J||e==null)return e;if(r.ref){let n=o?.[r.ref];return n?g(e,n,o,i+1):e}if(b(r)){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}if(r.type&&C.has(r.type))return typeof e=="number"&&!Number.isInteger(e)?Math.round(e):e;if(r.elements&&Array.isArray(e))return e.map(n=>g(n,r.elements,o,i+1));if((r.properties||r.optionalProperties)&&typeof e=="object"&&e!==null){let n={...e};if(r.properties)for(let[t,s]of Object.entries(r.properties))t in n&&(n[t]=g(n[t],s,o,i+1));if(r.optionalProperties)for(let[t,s]of Object.entries(r.optionalProperties))t in n&&(n[t]===null?delete n[t]:n[t]=g(n[t],s,o,i+1));return n}if(r.values&&Array.isArray(e)){let n={};for(let t of e)if(typeof t=="object"&&t!==null){let s=t,a=s.key;n[a]=g(s.value,r.values,o,i+1)}return n}if(r.discriminator&&r.mapping&&typeof e=="object"&&e!==null){let n=e,t=r.discriminator,s=n[t],a=r.mapping[s];if(!a)return e;if(b(a)){let p=n._data;if(typeof p=="string")try{let l=JSON.parse(p);if(typeof l=="object"&&l!==null)return{[t]:s,...l}}catch{}return{[t]:s}}let u={[t]:s};if(a.properties)for(let[p,l]of Object.entries(a.properties))p in n&&(u[p]=g(n[p],l,o,i+1));if(a.optionalProperties)for(let[p,l]of Object.entries(a.optionalProperties))p in n&&n[p]!==null&&(u[p]=g(n[p],l,o,i+1));return u}return e}function F(e){let r=e.definitions,o=!N(e,r),i;if(o){if(i=S(e,r,0),r&&Object.keys(r).length>0){let t={};for(let[s,a]of Object.entries(r))t[s]=S(a,r,0);i.$defs=t}}else i={},f(i,e);return{schema:i,strict:o,convert:t=>{let s=g(t,e,r,0),a=O(e,s,r);return a.length>0?{success:!1,errors:a}:{success:!0,data:s}}}}function q(e){return{type:"string",description:`Base64-encoded binary content (MIME type: ${e}).`}}function k(e){if(e.jtdSchema)return F(e.jtdSchema);if(e.mimeType)return{schema:q(e.mimeType),strict:!0,convert:i=>typeof i!="string"?{success:!1,errors:[`/: expected base64 string for MIME type ${e.mimeType}, got ${typeof i}`]}:{success:!0,data:i}};throw new Error("Signal format has neither jtdSchema nor mimeType")}function G(e){let r=e.formats;if(!r||r.length===0)throw new Error("Signal descriptor has no formats");let o=e.name??"unnamed",i=e.optional===!0;if(r.length===1){let c=k(r[0]);if(e.label||e.description){let m=[];e.label&&m.push(e.label),e.description&&m.push(e.description);let d=m.join(". ");c.schema.description=c.schema.description?`${d} ${c.schema.description}`:d}return c}let n=[],t={},s=[];for(let c=0;c<r.length;c++){let m=r[c],d=`format_${c}`,y=k(m);if(m.jtdSchema){let v=y.schema.description;y.schema.description=v?`Structured JSON data. ${v}`:"Structured JSON data."}t[d]=$(y.schema),s.push(d),n.push({key:d,converter:y})}let a=n.map(c=>c.key),u=e.description??"",p=i?"Provide at most ONE of the following format properties, set all others to null.":`You MUST provide exactly ONE of the following format properties: ${a.join(", ")}. Set all others to null.`;return{schema:{type:"object",description:u?`${u} ${p}`:p,properties:t,required:s,additionalProperties:!1},strict:!0,convert:c=>{if(typeof c!="object"||c===null)return{success:!1,errors:[`/: expected object with format properties, got ${typeof c}`]};let m=c,d=n.find(({key:y})=>m[y]!==void 0&&m[y]!==null);return d?d.converter.convert(m[d.key]):i?{success:!0,data:null}:{success:!1,errors:[`Signal '${o}' is required but no format was provided. Set exactly one of: ${a.join(", ")}.`]}}}}export{G as convertSignalToOpenAISchema,F as convertToOpenAISchema};
2
+ //# sourceMappingURL=openai.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/signals/index.ts", "../../src/openai/index.ts"],
4
+ "sourcesContent": ["import type {\n JTDSchemaJson,\n SignalDescriptorJson,\n SignalFormatJson\n} from '../api';\nimport { isSchema, isValidSchema, validate as jtdValidate } from 'jtd';\nimport type { Schema, ValidationError } from 'jtd';\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD FUZZER (generate sample values from JTD schemas)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Maximum recursion depth for fuzzJTD to prevent infinite loops on self-referencing schemas. */\nconst FUZZ_MAX_DEPTH = 10;\n\n/** Generate a fuzzed (sample) value from a JTD schema. */\nexport function fuzzJTD(\n schema: JTDSchemaJson,\n definitions?: Record<string, JTDSchemaJson>,\n _depth: number = 0\n): unknown {\n if (_depth > FUZZ_MAX_DEPTH) return null;\n\n if (schema.ref) {\n const def = definitions?.[schema.ref];\n if (def) return fuzzJTD(def, definitions, _depth + 1);\n return null;\n }\n\n if (schema.type) {\n switch (schema.type) {\n case 'string':\n return 'Lorem ipsum';\n case 'timestamp':\n return '2024-01-15T10:30:00Z';\n case 'float32':\n case 'float64':\n return 42.5;\n case 'int8':\n case 'uint8':\n case 'int16':\n case 'uint16':\n case 'int32':\n case 'uint32':\n return BigInt(42);\n case 'boolean':\n return true;\n default:\n return null;\n }\n }\n\n if (schema.enum) {\n return schema.enum[0] ?? null;\n }\n\n if (schema.elements) {\n return [\n fuzzJTD(schema.elements, definitions, _depth + 1),\n fuzzJTD(schema.elements, definitions, _depth + 1)\n ];\n }\n\n if (schema.values) {\n return { key1: fuzzJTD(schema.values, definitions, _depth + 1) };\n }\n\n if (schema.properties || schema.optionalProperties) {\n const obj: Record<string, unknown> = {};\n if (schema.properties) {\n for (const [k, v] of Object.entries(schema.properties)) {\n obj[k] = fuzzJTD(v, definitions, _depth + 1);\n }\n }\n if (schema.optionalProperties) {\n for (const [k, v] of Object.entries(schema.optionalProperties)) {\n obj[k] = fuzzJTD(v, definitions, _depth + 1);\n }\n }\n return obj;\n }\n\n if (schema.discriminator && schema.mapping) {\n const firstKey = Object.keys(schema.mapping)[0];\n if (firstKey) {\n const variant = schema.mapping[firstKey]!;\n const obj = fuzzJTD(variant, definitions, _depth + 1) as Record<\n string,\n unknown\n >;\n obj[schema.discriminator] = firstKey;\n return obj;\n }\n return null;\n }\n\n // Empty schema\n return null;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD VALUE VALIDATION (delegates to the `jtd` npm package)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst INTEGER_TYPES = new Set([\n 'int8',\n 'uint8',\n 'int16',\n 'uint16',\n 'int32',\n 'uint32'\n]);\n\nfunction formatInstancePath(instancePath: string[]): string {\n if (instancePath.length === 0) return '/';\n return instancePath\n .map((p) => (/^\\d+$/.test(p) ? `[${p}]` : `.${p}`))\n .join('');\n}\n\nfunction resolveSchemaParent(\n schema: Record<string, unknown>,\n schemaPath: string[]\n): Record<string, unknown> {\n let current: any = schema;\n for (let i = 0; i < schemaPath.length - 1; i++) {\n if (current && typeof current === 'object' && schemaPath[i]! in current) {\n current = current[schemaPath[i]!];\n } else {\n break;\n }\n }\n return current as Record<string, unknown>;\n}\n\nfunction resolveInstanceValue(value: unknown, instancePath: string[]): unknown {\n let current = value;\n for (const key of instancePath) {\n if (current && typeof current === 'object') {\n current = (current as Record<string, unknown>)[key];\n } else {\n return undefined;\n }\n }\n return current;\n}\n\nfunction formatValidationError(\n error: ValidationError,\n schema: Record<string, unknown>,\n value: unknown\n): string {\n const { instancePath, schemaPath } = error;\n const path = formatInstancePath(instancePath);\n const lastKey = schemaPath[schemaPath.length - 1];\n\n if (lastKey === 'type') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const jtdType = parent?.type as string;\n if (jtdType === 'boolean') return `${path}: expected boolean`;\n if (jtdType === 'string') return `${path}: expected string`;\n if (jtdType === 'timestamp') return `${path}: expected timestamp string`;\n if (INTEGER_TYPES.has(jtdType)) return `${path}: expected integer`;\n return `${path}: expected number`;\n }\n\n if (lastKey === 'enum') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const enumValues = parent?.enum as string[];\n return `${path}: expected one of [${enumValues.join(', ')}]`;\n }\n\n if (\n schemaPath.length >= 2 &&\n schemaPath[schemaPath.length - 2] === 'properties' &&\n lastKey\n ) {\n const prefix = path === '/' ? '' : path;\n return `${prefix}.${lastKey}: missing required property`;\n }\n\n if (lastKey === 'elements') return `${path}: expected array`;\n\n if (\n lastKey === 'properties' ||\n lastKey === 'optionalProperties' ||\n lastKey === 'values'\n ) {\n return `${path}: expected object`;\n }\n\n if (lastKey === 'discriminator')\n return `${path}: expected string discriminator`;\n\n if (lastKey === 'mapping') {\n const discValue = resolveInstanceValue(value, instancePath);\n return `${path}: unknown variant \"${discValue}\"`;\n }\n\n if (schemaPath.length === 0) return `${path}: unexpected property`;\n\n return `${path}: validation error at /${schemaPath.join('/')}`;\n}\n\n/**\n * Validate a value against a JTD schema, returning an array of error messages.\n * Delegates to the `jtd` npm package for spec-compliant validation.\n */\nexport function validateJsonAgainstJTD(\n schema: JTDSchemaJson,\n value: unknown,\n definitions?: Record<string, JTDSchemaJson>\n): string[] {\n const defs =\n definitions ??\n (schema.definitions as Record<string, JTDSchemaJson> | undefined);\n\n const schemaForValidation = defs\n ? ({ ...schema, definitions: defs } as Schema)\n : (schema as Schema);\n\n // The jtd lib throws on invalid schemas (e.g., unresolved refs).\n if (!isValidSchema(schemaForValidation)) {\n if (schema.ref) {\n return [`/: unknown ref \"${schema.ref}\"`];\n }\n return [`/: invalid schema`];\n }\n\n const errors = jtdValidate(schemaForValidation, value, {\n maxDepth: MAX_VALIDATION_DEPTH,\n maxErrors: MAX_VALIDATION_ERRORS\n });\n\n return errors.map((err) =>\n formatValidationError(\n err,\n schemaForValidation as Record<string, unknown>,\n value\n )\n );\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// SIGNAL-LEVEL VALIDATION (JSON values against JTD formats)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Validate a JSON value against a single SignalFormatJson. */\nexport function validateJsonAgainstSignal(\n format: SignalFormatJson,\n jsonValue: unknown\n): string[];\n/** Validate a JSON value against a SignalDescriptorJson (valid if value matches ANY JTD format). */\nexport function validateJsonAgainstSignal(\n descriptor: SignalDescriptorJson,\n jsonValue: unknown\n): string[];\nexport function validateJsonAgainstSignal(\n formatOrDescriptor: SignalFormatJson | SignalDescriptorJson,\n jsonValue: unknown\n): string[] {\n // Descriptor path \u2014 has `formats` array\n if (\n 'formats' in formatOrDescriptor &&\n Array.isArray(formatOrDescriptor.formats)\n ) {\n const jtdFormats = (\n formatOrDescriptor.formats as SignalFormatJson[]\n ).filter((f) => f.jtdSchema);\n if (jtdFormats.length === 0) {\n return ['/: no JTD formats in signal descriptor'];\n }\n // Valid if value matches ANY JTD format\n for (const format of jtdFormats) {\n const errors = validateJsonAgainstJTD(format.jtdSchema!, jsonValue);\n if (errors.length === 0) return [];\n }\n // None matched \u2014 return errors from last format attempt\n return validateJsonAgainstJTD(\n jtdFormats[jtdFormats.length - 1]!.jtdSchema!,\n jsonValue\n );\n }\n\n // Single format path\n const format = formatOrDescriptor as SignalFormatJson;\n if (!format.jtdSchema) {\n return ['/: signal format has no jtdSchema'];\n }\n return validateJsonAgainstJTD(format.jtdSchema, jsonValue);\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD \u2192 JSON SCHEMA CONVERTER\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/**\n * Convert JTD (JSON Type Definition) schema to JSON Schema for validation.\n *\n * Supports all 8 JTD schema forms per RFC 8927:\n * - Empty form: {}\n * - Ref form: { ref: \"...\" }\n * - Type form: { type: \"...\" }\n * - Enum form: { enum: [...] }\n * - Elements form: { elements: {...} }\n * - Properties form: { properties: {...}, optionalProperties: {...} }\n * - Values form: { values: {...} }\n * - Discriminator form: { discriminator: \"...\", mapping: {...} }\n */\nexport function jtdToJsonSchema(\n jtdSchema: JTDSchemaJson,\n definitions?: Record<string, JTDSchemaJson>,\n isRoot = true\n): any {\n if (!jtdSchema || typeof jtdSchema !== 'object') {\n return {};\n }\n\n const isNullable = jtdSchema['nullable'];\n const defs =\n definitions ||\n (jtdSchema['definitions'] as Record<string, JTDSchemaJson> | undefined);\n\n const result: any = {};\n\n if (isRoot) {\n result.$schema = 'http://json-schema.org/draft-07/schema#';\n }\n\n // Ref form\n if (jtdSchema['ref']) {\n const refName = jtdSchema['ref'] as string;\n if (defs && defs[refName]) {\n const resolvedSchema = jtdToJsonSchema(\n defs[refName] as JTDSchemaJson,\n defs,\n false\n );\n\n if (isNullable) {\n if (resolvedSchema.type) {\n resolvedSchema.type = Array.isArray(resolvedSchema.type)\n ? [...resolvedSchema.type, 'null']\n : [resolvedSchema.type, 'null'];\n } else {\n return {\n ...resolvedSchema,\n anyOf: [resolvedSchema, { type: 'null' }],\n ...(isRoot\n ? { $schema: 'http://json-schema.org/draft-07/schema#' }\n : {})\n };\n }\n }\n\n return isRoot\n ? {\n ...resolvedSchema,\n $schema: 'http://json-schema.org/draft-07/schema#'\n }\n : resolvedSchema;\n }\n return isRoot ? result : {};\n }\n\n // Type form\n if (jtdSchema['type']) {\n const typeMap: Record<string, string> = {\n boolean: 'boolean',\n string: 'string',\n timestamp: 'string',\n float32: 'number',\n float64: 'number',\n int8: 'integer',\n uint8: 'integer',\n int16: 'integer',\n uint16: 'integer',\n int32: 'integer',\n uint32: 'integer'\n };\n const jtdType = jtdSchema['type'] as string;\n const baseType = typeMap[jtdType] || 'string';\n\n result.type = isNullable ? [baseType, 'null'] : baseType;\n\n if (baseType === 'string' && jtdType === 'timestamp') {\n result.format = 'date-time';\n }\n return result;\n }\n\n // Enum form\n if (jtdSchema['enum']) {\n result.type = isNullable ? ['string', 'null'] : 'string';\n result.enum = isNullable\n ? [...(jtdSchema['enum'] as string[]), null]\n : jtdSchema['enum'];\n return result;\n }\n\n // Elements form\n if (jtdSchema['elements']) {\n result.type = isNullable ? ['array', 'null'] : 'array';\n result.items = jtdToJsonSchema(\n jtdSchema['elements'] as JTDSchemaJson,\n defs,\n false\n );\n return result;\n }\n\n // Properties form\n if (jtdSchema['properties'] || jtdSchema['optionalProperties']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.properties = {};\n result.required = [];\n\n if (jtdSchema['properties']) {\n for (const [key, value] of Object.entries(jtdSchema['properties'])) {\n result.properties[key] = jtdToJsonSchema(\n value as JTDSchemaJson,\n defs,\n false\n );\n result.required.push(key);\n }\n }\n\n if (jtdSchema['optionalProperties']) {\n for (const [key, value] of Object.entries(\n jtdSchema['optionalProperties']\n )) {\n result.properties[key] = jtdToJsonSchema(\n value as JTDSchemaJson,\n defs,\n false\n );\n }\n }\n\n // JTD is strict by default\n if (jtdSchema['additionalProperties'] !== true) {\n result.additionalProperties = false;\n }\n\n return result;\n }\n\n // Values form\n if (jtdSchema['values']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.additionalProperties = jtdToJsonSchema(\n jtdSchema['values'] as JTDSchemaJson,\n defs,\n false\n );\n return result;\n }\n\n // Discriminator form\n if (jtdSchema['discriminator'] && jtdSchema['mapping']) {\n const variants = [];\n const discriminatorKey = jtdSchema['discriminator'] as string;\n\n for (const [tag, schema] of Object.entries(jtdSchema['mapping'])) {\n const variantSchema = jtdToJsonSchema(\n schema as JTDSchemaJson,\n defs,\n false\n );\n\n if (!variantSchema.type) {\n variantSchema.type = 'object';\n } else if (\n variantSchema.type !== 'object' &&\n !Array.isArray(variantSchema.type)\n ) {\n variantSchema.type = 'object';\n }\n\n variantSchema.properties = variantSchema.properties || {};\n variantSchema.properties[discriminatorKey] = { const: tag };\n\n variantSchema.required = variantSchema.required || [];\n if (!variantSchema.required.includes(discriminatorKey)) {\n variantSchema.required.unshift(discriminatorKey);\n }\n\n // JTD discriminator variants are strict by default\n if (variantSchema.additionalProperties === undefined) {\n variantSchema.additionalProperties = false;\n }\n\n variants.push(variantSchema);\n }\n\n if (isNullable) {\n variants.push({ type: 'null' });\n }\n\n result.oneOf = variants;\n return result;\n }\n\n // Empty form\n return result;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// JTD SCHEMA VALIDATION (using the `jtd` npm package)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nexport const MAX_VALIDATION_DEPTH = 32;\nexport const MAX_VALIDATION_ERRORS = 100;\n\n/** Validate that the input is a valid JTD schema. */\nexport function validateJTDSchema(\n schema: unknown\n): { valid: true; schema: JTDSchemaJson } | { valid: false; error: string } {\n if (!isSchema(schema)) {\n return {\n valid: false,\n error: 'Invalid JTD schema: Schema does not match JTD structure'\n };\n }\n\n if (!isValidSchema(schema)) {\n return {\n valid: false,\n error:\n 'Invalid JTD schema: Schema has semantic errors (e.g., circular references, conflicting forms)'\n };\n }\n\n return { valid: true, schema: schema as unknown as JTDSchemaJson };\n}\n\n/** Parse and validate a JSON string. */\nexport function validateJSON(jsonString: string): {\n valid: boolean;\n data?: unknown;\n error?: string;\n} {\n try {\n const data = JSON.parse(jsonString);\n return { valid: true, data };\n } catch (error) {\n return {\n valid: false,\n error: `Invalid JSON: ${error instanceof Error ? error.message : 'Parse error'}`\n };\n }\n}\n\n/** Parse a JSON string and validate it as a JTD schema. */\nexport function validateJTDSchemaString(\n schemaString: string\n): { valid: true; schema: JTDSchemaJson } | { valid: false; error: string } {\n const jsonResult = validateJSON(schemaString);\n if (!jsonResult.valid) return { valid: false, error: jsonResult.error! };\n\n return validateJTDSchema(jsonResult.data);\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// MONACO EDITOR CONFIG FOR JTD SCHEMA EDITING\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Monaco editor JSON schema configuration for JTD schema IntelliSense and validation. */\nexport const JTD_SCHEMA_CONFIG = {\n uri: 'https://jsontypedef.com/schemas/jtd-schema.json',\n fileMatch: ['inmemory://jtd-schema/*.json'],\n schema: {\n $schema: 'http://json-schema.org/draft-07/schema#',\n type: 'object',\n properties: {\n type: {\n description: 'Type form - defines a primitive type',\n enum: [\n 'boolean',\n 'string',\n 'timestamp',\n 'float32',\n 'float64',\n 'int8',\n 'uint8',\n 'int16',\n 'uint16',\n 'int32',\n 'uint32'\n ]\n },\n enum: {\n description: 'Enum form - defines a set of string values',\n type: 'array',\n items: { type: 'string' }\n },\n elements: {\n description: 'Elements form - defines an array with typed elements',\n $ref: '#'\n },\n properties: {\n description:\n 'Properties form - defines an object with required properties',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n optionalProperties: {\n description: 'Optional properties - defines optional object properties',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n values: {\n description: 'Values form - defines a map/dictionary with typed values',\n $ref: '#'\n },\n discriminator: {\n description: 'Discriminator form - defines a tagged union',\n type: 'string'\n },\n mapping: {\n description: 'Mapping for discriminator form',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n ref: {\n description: 'Ref form - references a definition',\n type: 'string'\n },\n definitions: {\n description: 'Top-level definitions for reusable schemas',\n type: 'object',\n additionalProperties: { $ref: '#' }\n },\n nullable: {\n description: 'Allow null values',\n type: 'boolean'\n },\n metadata: {\n description: 'Custom metadata for documentation',\n type: 'object'\n },\n additionalProperties: {\n description: 'Allow additional properties (properties form only)',\n type: 'boolean'\n }\n }\n }\n};\n", "// Copyright 2024-2025 Mochabug, LLC. All rights reserved.\n// Licensed under the Apache License, Version 2.0.\n\nimport type {\n JTDSchemaJson,\n SignalDescriptorJson,\n SignalFormatJson\n} from '../api';\nimport { validateJsonAgainstJTD } from '../signals';\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Types\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** JSON Schema subset supported by OpenAI structured output (strict mode). */\nexport interface OpenAISchema {\n type?: string | string[];\n description?: string;\n properties?: Record<string, OpenAISchema>;\n required?: string[];\n additionalProperties?: false;\n enum?: (string | number | null)[];\n format?: string;\n items?: OpenAISchema;\n minimum?: number;\n maximum?: number;\n anyOf?: OpenAISchema[];\n $defs?: Record<string, OpenAISchema>;\n $ref?: string;\n}\n\nexport interface ConvertSuccess {\n success: true;\n data: unknown;\n}\n\nexport interface ConvertFailure {\n success: false;\n errors: string[];\n}\n\nexport type ConvertResult = ConvertSuccess | ConvertFailure;\n\nexport interface OpenAIConversionResult {\n /** OpenAI strict mode compatible JSON Schema. */\n schema: OpenAISchema;\n /** Whether the schema supports strict mode. False for unstructured (empty) schemas. */\n strict: boolean;\n /** Convert OpenAI JSON output back to JTD-conforming JSON. */\n convert: (openaiJson: unknown) => ConvertResult;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Constants\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst MAX_REF_DEPTH = 32;\n\nconst INTEGER_BOUNDS: Record<string, { minimum: number; maximum: number }> = {\n int8: { minimum: -128, maximum: 127 },\n uint8: { minimum: 0, maximum: 255 },\n int16: { minimum: -32768, maximum: 32767 },\n uint16: { minimum: 0, maximum: 65535 },\n int32: { minimum: -2147483648, maximum: 2147483647 },\n uint32: { minimum: 0, maximum: 4294967295 }\n};\n\nconst FLOAT32_BOUNDS = {\n minimum: -3.4028235e38,\n maximum: 3.4028235e38\n};\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Helpers\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/** Check if a JTD schema is unstructured (empty form or equivalent). */\nfunction isUnstructuredSchema(schema: JTDSchemaJson): boolean {\n if (!schema || typeof schema !== 'object') return true;\n\n if (\n schema.type ||\n schema.enum ||\n schema.elements ||\n schema.values ||\n schema.discriminator ||\n schema.ref\n ) {\n return false;\n }\n\n const hasRealProps =\n (schema.properties && Object.keys(schema.properties).length > 0) ||\n (schema.optionalProperties &&\n Object.keys(schema.optionalProperties).length > 0);\n\n if (hasRealProps) return false;\n\n // Properties form with empty props + additionalProperties: true \u2192 unstructured\n if (\n (schema.properties !== undefined ||\n schema.optionalProperties !== undefined) &&\n schema.additionalProperties === true\n ) {\n return true;\n }\n\n // Properties form with empty props, no AP:true \u2192 structured empty object\n if (\n schema.properties !== undefined ||\n schema.optionalProperties !== undefined\n ) {\n return false;\n }\n\n // Truly empty schema\n return true;\n}\n\n/** Resolve refs at root to determine if the root target is unstructured. */\nfunction isRootUnstructured(\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined\n): boolean {\n let resolved = schema;\n let depth = 0;\n while (resolved.ref && depth < MAX_REF_DEPTH) {\n const target = defs?.[resolved.ref as string];\n if (!target) return false;\n resolved = target;\n depth++;\n }\n if (depth >= MAX_REF_DEPTH) return false;\n return isUnstructuredSchema(resolved);\n}\n\n/** Make a schema nullable by adding \"null\" to the type. */\nfunction makeNullable(schema: OpenAISchema): OpenAISchema {\n if (Array.isArray(schema.type) && schema.type.includes('null')) return schema;\n if (schema.type === 'null') return schema;\n\n // $ref \u2192 wrap in anyOf with null\n if (schema.$ref) {\n return { anyOf: [schema, { type: 'null' }] };\n }\n\n // anyOf \u2192 add null variant\n if (schema.anyOf) {\n if (schema.anyOf.some((s) => s.type === 'null')) return schema;\n return { ...schema, anyOf: [...schema.anyOf, { type: 'null' }] };\n }\n\n // Standard: add null to type and enum\n const result = { ...schema };\n if (result.type) {\n result.type = Array.isArray(result.type)\n ? [...result.type, 'null']\n : [result.type, 'null'];\n }\n if (result.enum && !result.enum.includes(null)) {\n result.enum = [...result.enum, null];\n }\n return result;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Metadata helper\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst METADATA_KNOWN_KEYS = new Set(['title', 'label', 'name', 'description']);\n\nfunction applyMetadata(result: OpenAISchema, schema: JTDSchemaJson): void {\n const meta = schema.metadata as Record<string, unknown> | undefined;\n if (!meta) return;\n\n const descParts: string[] = [];\n\n // OAI doesn't support title \u2014 fold title/label/name into description\n const titleCandidate =\n (typeof meta['title'] === 'string' && meta['title'].trim()) ||\n (typeof meta['label'] === 'string' && meta['label'].trim()) ||\n (typeof meta['name'] === 'string' && meta['name'].trim());\n\n const descText =\n typeof meta['description'] === 'string' ? meta['description'].trim() : '';\n\n if (titleCandidate && descText) {\n descParts.push(`${titleCandidate}. ${descText}`);\n } else if (titleCandidate) {\n descParts.push(titleCandidate);\n } else if (descText) {\n descParts.push(descText);\n }\n\n // Extra metadata keys as description hints\n const extras: string[] = [];\n for (const [key, value] of Object.entries(meta)) {\n if (METADATA_KNOWN_KEYS.has(key)) continue;\n if (typeof value === 'string' && value.trim()) {\n extras.push(`[${key}: ${value.trim()}]`);\n } else if (typeof value === 'number' || typeof value === 'boolean') {\n extras.push(`[${key}: ${value}]`);\n }\n }\n if (extras.length > 0) {\n descParts.push(extras.join(' '));\n }\n\n if (descParts.length > 0) {\n const newDesc = descParts.join(' ');\n result.description = result.description\n ? `${result.description} ${newDesc}`\n : newDesc;\n }\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Schema conversion (JTD \u2192 OpenAI JSON Schema)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nfunction convertNode(\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): OpenAISchema {\n if (depth > MAX_REF_DEPTH) {\n throw new Error(`Schema nesting exceeded ${MAX_REF_DEPTH} levels`);\n }\n\n if (!schema || typeof schema !== 'object') {\n return { type: 'string', description: 'Must be a valid JSON value.' };\n }\n\n // Unstructured (empty form or AP:true with no real props) \u2192 string\n if (isUnstructuredSchema(schema)) {\n const isNullable = schema.nullable === true;\n const result: OpenAISchema = {\n type: isNullable ? ['string', 'null'] : 'string',\n description: 'Must be a valid JSON value.'\n };\n applyMetadata(result, schema);\n return result;\n }\n\n const isNullable = schema.nullable === true;\n\n // Ref form \u2192 $ref\n if (schema.ref) {\n const refName = schema.ref as string;\n if (!defs?.[refName]) {\n throw new Error(`Unresolved ref \"${refName}\"`);\n }\n if (isNullable) {\n const result: OpenAISchema = {\n anyOf: [{ $ref: `#/$defs/${refName}` }, { type: 'null' }]\n };\n applyMetadata(result, schema);\n return result;\n }\n // Bare $ref \u2014 skip metadata (JSON Schema $ref may ignore sibling keywords)\n return { $ref: `#/$defs/${refName}` };\n }\n\n // Type form\n if (schema.type) {\n const jtdType = schema.type as string;\n const result: OpenAISchema = {};\n\n const intBounds = INTEGER_BOUNDS[jtdType];\n if (intBounds) {\n result.type = isNullable ? ['integer', 'null'] : 'integer';\n result.minimum = intBounds.minimum;\n result.maximum = intBounds.maximum;\n applyMetadata(result, schema);\n return result;\n }\n\n switch (jtdType) {\n case 'boolean':\n result.type = isNullable ? ['boolean', 'null'] : 'boolean';\n break;\n case 'string':\n result.type = isNullable ? ['string', 'null'] : 'string';\n break;\n case 'timestamp':\n result.type = isNullable ? ['string', 'null'] : 'string';\n result.format = 'date-time';\n break;\n case 'float32':\n result.type = isNullable ? ['number', 'null'] : 'number';\n result.minimum = FLOAT32_BOUNDS.minimum;\n result.maximum = FLOAT32_BOUNDS.maximum;\n break;\n case 'float64':\n result.type = isNullable ? ['number', 'null'] : 'number';\n break;\n default:\n throw new Error(`Unknown JTD type \"${jtdType}\"`);\n }\n\n applyMetadata(result, schema);\n return result;\n }\n\n // Enum form\n if (schema.enum) {\n const result: OpenAISchema = {\n type: isNullable ? ['string', 'null'] : 'string',\n enum: isNullable\n ? [...(schema.enum as string[]), null]\n : [...(schema.enum as string[])]\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Elements form\n if (schema.elements) {\n const result: OpenAISchema = {\n type: isNullable ? ['array', 'null'] : 'array',\n items: convertNode(schema.elements as JTDSchemaJson, defs, depth + 1)\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Properties form (has real props \u2014 unstructured was caught above)\n if (schema.properties || schema.optionalProperties) {\n const result: OpenAISchema = {\n type: isNullable ? ['object', 'null'] : 'object',\n properties: {},\n additionalProperties: false\n };\n const required: string[] = [];\n\n if (schema.properties) {\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n result.properties![key] = convertNode(\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n required.push(key);\n }\n }\n\n // Optional properties \u2192 required + nullable\n if (schema.optionalProperties) {\n for (const [key, propSchema] of Object.entries(\n schema.optionalProperties\n )) {\n const converted = convertNode(\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n result.properties![key] = makeNullable(converted);\n required.push(key);\n }\n }\n\n result.required = required;\n applyMetadata(result, schema);\n return result;\n }\n\n // Values form \u2192 array of {key, value} objects\n if (schema.values) {\n const valueSchema = convertNode(\n schema.values as JTDSchemaJson,\n defs,\n depth + 1\n );\n const result: OpenAISchema = {\n type: isNullable ? ['array', 'null'] : 'array',\n items: {\n type: 'object',\n properties: {\n key: { type: 'string' },\n value: valueSchema\n },\n required: ['key', 'value'],\n additionalProperties: false\n }\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Discriminator form \u2192 anyOf with flat variants\n if (schema.discriminator && schema.mapping) {\n const discKey = schema.discriminator as string;\n const mapping = schema.mapping as Record<string, JTDSchemaJson>;\n const variants: OpenAISchema[] = [];\n\n for (const [tag, variantSchema] of Object.entries(mapping)) {\n let variantOAI: OpenAISchema;\n\n if (isUnstructuredSchema(variantSchema)) {\n // Unstructured variant: disc + _data string\n variantOAI = {\n type: 'object',\n properties: {\n [discKey]: { type: 'string', enum: [tag] },\n _data: {\n type: 'string',\n description:\n 'Must be a valid JSON value representing the variant data.'\n }\n },\n required: [discKey, '_data'],\n additionalProperties: false\n };\n } else {\n // Per RFC 8927, mapping values are always properties form,\n // and the discriminator tag never appears in variant properties.\n variantOAI = convertNode(variantSchema, defs, depth + 1);\n variantOAI.properties![discKey] = { type: 'string', enum: [tag] };\n (variantOAI.required ??= []).unshift(discKey);\n variantOAI.additionalProperties = false;\n }\n\n applyMetadata(variantOAI, variantSchema);\n variants.push(variantOAI);\n }\n\n const result: OpenAISchema = { anyOf: variants };\n if (isNullable) {\n result.anyOf!.push({ type: 'null' });\n }\n applyMetadata(result, schema);\n return result;\n }\n\n // Fallback\n return { type: 'string', description: 'Must be a valid JSON value.' };\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Coercion (OpenAI output \u2192 JTD-conforming JSON)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nconst INTEGER_TYPE_SET = new Set(Object.keys(INTEGER_BOUNDS));\n\nfunction coerceToJTD(\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): unknown {\n if (depth > MAX_REF_DEPTH) return value;\n if (value === null || value === undefined) return value;\n\n // Ref form \u2014 resolve in original JTD definitions and recurse\n if (schema.ref) {\n const resolved = defs?.[schema.ref as string];\n if (resolved) {\n return coerceToJTD(value, resolved, defs, depth + 1);\n }\n return value;\n }\n\n // Unstructured schema \u2014 parse JSON string back to value\n if (isUnstructuredSchema(schema)) {\n if (typeof value === 'string') {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n return value;\n }\n\n // Type form \u2014 integer coercion\n if (schema.type && INTEGER_TYPE_SET.has(schema.type as string)) {\n if (typeof value === 'number' && !Number.isInteger(value)) {\n return Math.round(value);\n }\n return value;\n }\n\n // Elements form\n if (schema.elements && Array.isArray(value)) {\n return value.map((item) =>\n coerceToJTD(item, schema.elements as JTDSchemaJson, defs, depth + 1)\n );\n }\n\n // Properties form \u2014 strip null optionals\n if (\n (schema.properties || schema.optionalProperties) &&\n typeof value === 'object' &&\n value !== null\n ) {\n const obj = { ...(value as Record<string, unknown>) };\n\n if (schema.properties) {\n for (const [k, propSchema] of Object.entries(schema.properties)) {\n if (k in obj) {\n obj[k] = coerceToJTD(\n obj[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n\n // Optional properties: null \u2192 omit\n if (schema.optionalProperties) {\n for (const [k, propSchema] of Object.entries(\n schema.optionalProperties\n )) {\n if (k in obj) {\n if (obj[k] === null) {\n delete obj[k];\n } else {\n obj[k] = coerceToJTD(\n obj[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n }\n\n return obj;\n }\n\n // Values form \u2014 convert array of {key, value} to Record\n if (schema.values && Array.isArray(value)) {\n const result: Record<string, unknown> = {};\n for (const entry of value) {\n if (typeof entry === 'object' && entry !== null) {\n const rec = entry as Record<string, unknown>;\n const key = rec.key as string;\n result[key] = coerceToJTD(\n rec.value,\n schema.values as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n return result;\n }\n\n // Discriminator form \u2014 flat object, coerce variant + strip null optionals\n if (\n schema.discriminator &&\n schema.mapping &&\n typeof value === 'object' &&\n value !== null\n ) {\n const rec = value as Record<string, unknown>;\n const discKey = schema.discriminator as string;\n const tag = rec[discKey] as string;\n const variantSchema = (schema.mapping as Record<string, JTDSchemaJson>)[\n tag\n ];\n\n if (!variantSchema) return value;\n\n // Unstructured variant: parse _data\n if (isUnstructuredSchema(variantSchema)) {\n const dataStr = rec._data;\n if (typeof dataStr === 'string') {\n try {\n const parsed = JSON.parse(dataStr);\n if (typeof parsed === 'object' && parsed !== null) {\n return { [discKey]: tag, ...parsed };\n }\n } catch {\n /* validation catches */\n }\n }\n return { [discKey]: tag };\n }\n\n // Build flat result: discriminator + variant properties\n const result: Record<string, unknown> = { [discKey]: tag };\n\n if (variantSchema.properties) {\n for (const [k, propSchema] of Object.entries(variantSchema.properties)) {\n if (k in rec) {\n result[k] = coerceToJTD(\n rec[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n\n if (variantSchema.optionalProperties) {\n for (const [k, propSchema] of Object.entries(\n variantSchema.optionalProperties\n )) {\n if (k in rec && rec[k] !== null) {\n result[k] = coerceToJTD(\n rec[k],\n propSchema as JTDSchemaJson,\n defs,\n depth + 1\n );\n }\n }\n }\n\n return result;\n }\n\n return value;\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Public API\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n/**\n * Convert a JTD schema to an OpenAI strict mode compatible JSON Schema, with a\n * converter function that transforms and validates OpenAI output against\n * the original JTD schema.\n *\n * @throws {Error} if the JTD schema contains forms that cannot be represented.\n */\nexport function convertToOpenAISchema(\n jtdSchema: JTDSchemaJson\n): OpenAIConversionResult {\n const defs = jtdSchema.definitions as\n | Record<string, JTDSchemaJson>\n | undefined;\n\n const strict = !isRootUnstructured(jtdSchema, defs);\n\n let schema: OpenAISchema;\n if (strict) {\n schema = convertNode(jtdSchema, defs, 0);\n\n // Attach $defs at root\n if (defs && Object.keys(defs).length > 0) {\n const oaiDefs: Record<string, OpenAISchema> = {};\n for (const [name, defSchema] of Object.entries(defs)) {\n oaiDefs[name] = convertNode(defSchema as JTDSchemaJson, defs, 0);\n }\n schema.$defs = oaiDefs;\n }\n } else {\n schema = {};\n applyMetadata(schema, jtdSchema);\n }\n\n const convert = (openaiJson: unknown): ConvertResult => {\n const coerced = coerceToJTD(openaiJson, jtdSchema, defs, 0);\n const errors = validateJsonAgainstJTD(jtdSchema, coerced, defs);\n if (errors.length > 0) {\n return { success: false, errors };\n }\n return { success: true, data: coerced };\n };\n\n return { schema, strict, convert };\n}\n\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n// Signal-level conversion (SignalDescriptorJson \u2192 OpenAI schema)\n// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nfunction convertMimeFormat(mimeType: string): OpenAISchema {\n return {\n type: 'string',\n description: `Base64-encoded binary content (MIME type: ${mimeType}).`\n };\n}\n\nfunction convertSingleFormat(\n format: SignalFormatJson\n): OpenAIConversionResult {\n if (format.jtdSchema) {\n return convertToOpenAISchema(format.jtdSchema);\n }\n if (format.mimeType) {\n const schema = convertMimeFormat(format.mimeType);\n const convert = (openaiJson: unknown): ConvertResult => {\n if (typeof openaiJson !== 'string') {\n return {\n success: false,\n errors: [\n `/: expected base64 string for MIME type ${format.mimeType}, got ${typeof openaiJson}`\n ]\n };\n }\n return { success: true, data: openaiJson };\n };\n return { schema, strict: true, convert };\n }\n throw new Error('Signal format has neither jtdSchema nor mimeType');\n}\n\n/**\n * Convert a SignalDescriptorJson to an OpenAI strict mode compatible JSON Schema.\n *\n * Handles single and multi-format signals:\n * - Single format: schema is the converted format directly.\n * - Multiple formats: wrapper object with `format_0`, `format_1`, etc.\n * All format properties are required and nullable (OAI strict mode).\n * The model sets exactly one to a value and the rest to null.\n *\n * @throws {Error} if the descriptor has no formats.\n */\nexport function convertSignalToOpenAISchema(\n descriptor: SignalDescriptorJson\n): OpenAIConversionResult {\n const formats = descriptor.formats as SignalFormatJson[] | undefined;\n if (!formats || formats.length === 0) {\n throw new Error('Signal descriptor has no formats');\n }\n\n const signalName = descriptor.name ?? 'unnamed';\n const isOptional = descriptor.optional === true;\n\n // Single format \u2014 no wrapper\n if (formats.length === 1) {\n const result = convertSingleFormat(formats[0]!);\n if (descriptor.label || descriptor.description) {\n const parts: string[] = [];\n if (descriptor.label) parts.push(descriptor.label);\n if (descriptor.description) parts.push(descriptor.description);\n const newDesc = parts.join('. ');\n result.schema.description = result.schema.description\n ? `${newDesc} ${result.schema.description}`\n : newDesc;\n }\n return result;\n }\n\n // Multiple formats \u2014 wrapper object, all format props required + nullable\n const formatConverters: Array<{\n key: string;\n converter: OpenAIConversionResult;\n }> = [];\n\n const wrapperProps: Record<string, OpenAISchema> = {};\n const required: string[] = [];\n\n for (let i = 0; i < formats.length; i++) {\n const fmt = formats[i]!;\n const key = `format_${i}`;\n const conv = convertSingleFormat(fmt);\n\n if (fmt.jtdSchema) {\n const existing = conv.schema.description;\n conv.schema.description = existing\n ? `Structured JSON data. ${existing}`\n : 'Structured JSON data.';\n }\n\n wrapperProps[key] = makeNullable(conv.schema);\n required.push(key);\n formatConverters.push({ key, converter: conv });\n }\n\n const keys = formatConverters.map((f) => f.key);\n const baseDesc = descriptor.description ?? '';\n const guidance = isOptional\n ? 'Provide at most ONE of the following format properties, set all others to null.'\n : `You MUST provide exactly ONE of the following format properties: ${keys.join(', ')}. Set all others to null.`;\n\n const schema: OpenAISchema = {\n type: 'object',\n description: baseDesc ? `${baseDesc} ${guidance}` : guidance,\n properties: wrapperProps,\n required,\n additionalProperties: false\n };\n\n const convert = (openaiJson: unknown): ConvertResult => {\n if (typeof openaiJson !== 'object' || openaiJson === null) {\n return {\n success: false,\n errors: [\n `/: expected object with format properties, got ${typeof openaiJson}`\n ]\n };\n }\n\n const rec = openaiJson as Record<string, unknown>;\n\n // Find which format is set (non-null)\n const selected = formatConverters.find(\n ({ key }) => rec[key] !== undefined && rec[key] !== null\n );\n\n if (!selected) {\n if (isOptional) {\n return { success: true, data: null };\n }\n return {\n success: false,\n errors: [\n `Signal '${signalName}' is required but no format was provided. Set exactly one of: ${keys.join(', ')}.`\n ]\n };\n }\n\n return selected.converter.convert(rec[selected.key]);\n };\n\n return { schema, strict: true, convert };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["isSchema", "isValidSchema", "jtdValidate", "INTEGER_TYPES", "formatInstancePath", "instancePath", "p", "resolveSchemaParent", "schema", "schemaPath", "current", "resolveInstanceValue", "value", "key", "formatValidationError", "error", "path", "lastKey", "jtdType", "enumValues", "discValue", "validateJsonAgainstJTD", "definitions", "defs", "schemaForValidation", "isValidSchema", "jtdValidate", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "err", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "MAX_REF_DEPTH", "INTEGER_BOUNDS", "FLOAT32_BOUNDS", "isUnstructuredSchema", "schema", "isRootUnstructured", "defs", "resolved", "depth", "target", "makeNullable", "s", "result", "METADATA_KNOWN_KEYS", "applyMetadata", "meta", "descParts", "titleCandidate", "descText", "extras", "key", "value", "newDesc", "convertNode", "isNullable", "refName", "jtdType", "intBounds", "required", "propSchema", "converted", "valueSchema", "discKey", "mapping", "variants", "tag", "variantSchema", "variantOAI", "INTEGER_TYPE_SET", "coerceToJTD", "item", "obj", "k", "entry", "rec", "dataStr", "parsed", "convertToOpenAISchema", "jtdSchema", "strict", "oaiDefs", "name", "defSchema", "openaiJson", "coerced", "errors", "validateJsonAgainstJTD", "convertMimeFormat", "mimeType", "convertSingleFormat", "format", "convertSignalToOpenAISchema", "descriptor", "formats", "signalName", "isOptional", "parts", "formatConverters", "wrapperProps", "i", "fmt", "conv", "existing", "keys", "f", "baseDesc", "guidance", "selected"]
7
+ }
@@ -1,2 +1,2 @@
1
- import{isSchema as T,isValidSchema as y,validate as D}from"jtd";var h=10;function u(e,r,t=0){if(t>h)return null;if(e.ref){let i=r?.[e.ref];return i?u(i,r,t+1):null}if(e.type)switch(e.type){case"string":return"Lorem ipsum";case"timestamp":return"2024-01-15T10:30:00Z";case"float32":case"float64":return 42.5;case"int8":case"uint8":case"int16":case"uint16":case"int32":case"uint32":return BigInt(42);case"boolean":return!0;default:return null}if(e.enum)return e.enum[0]??null;if(e.elements)return[u(e.elements,r,t+1),u(e.elements,r,t+1)];if(e.values)return{key1:u(e.values,r,t+1)};if(e.properties||e.optionalProperties){let i={};if(e.properties)for(let[o,n]of Object.entries(e.properties))i[o]=u(n,r,t+1);if(e.optionalProperties)for(let[o,n]of Object.entries(e.optionalProperties))i[o]=u(n,r,t+1);return i}if(e.discriminator&&e.mapping){let i=Object.keys(e.mapping)[0];if(i){let o=e.mapping[i],n=u(o,r,t+1);return n[e.discriminator]=i,n}return null}return null}var $=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function P(e){return e.length===0?"/":e.map(r=>/^\d+$/.test(r)?`[${r}]`:`.${r}`).join("")}function g(e,r){let t=e;for(let i=0;i<r.length-1&&(t&&typeof t=="object"&&r[i]in t);i++)t=t[r[i]];return t}function k(e,r){let t=e;for(let i of r)if(t&&typeof t=="object")t=t[i];else return;return t}function w(e,r,t){let{instancePath:i,schemaPath:o}=e,n=P(i),s=o[o.length-1];if(s==="type"){let p=g(r,o)?.type;return p==="boolean"?`${n}: expected boolean`:p==="string"?`${n}: expected string`:p==="timestamp"?`${n}: expected timestamp string`:$.has(p)?`${n}: expected integer`:`${n}: expected number`}if(s==="enum"){let p=g(r,o)?.enum;return`${n}: expected one of [${p.join(", ")}]`}if(o.length>=2&&o[o.length-2]==="properties"&&s)return`${n==="/"?"":n}.${s}: missing required property`;if(s==="elements")return`${n}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${n}: expected object`;if(s==="discriminator")return`${n}: expected string discriminator`;if(s==="mapping"){let a=k(t,i);return`${n}: unknown variant "${a}"`}return o.length===0?`${n}: unexpected property`:`${n}: validation error at /${o.join("/")}`}function d(e,r,t){let i=t??e.definitions,o=i?{...e,definitions:i}:e;return y(o)?D(o,r,{maxDepth:R,maxErrors:A}).map(s=>w(s,o,r)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}function U(e,r){if("formats"in e&&Array.isArray(e.formats)){let i=e.formats.filter(o=>o.jtdSchema);if(i.length===0)return["/: no JTD formats in signal descriptor"];for(let o of i)if(d(o.jtdSchema,r).length===0)return[];return d(i[i.length-1].jtdSchema,r)}let t=e;return t.jtdSchema?d(t.jtdSchema,r):["/: signal format has no jtdSchema"]}function c(e,r,t=!0){if(!e||typeof e!="object")return{};let i=e.nullable,o=r||e.definitions,n={};if(t&&(n.$schema="http://json-schema.org/draft-07/schema#"),e.ref){let s=e.ref;if(o&&o[s]){let a=c(o[s],o,!1);if(i)if(a.type)a.type=Array.isArray(a.type)?[...a.type,"null"]:[a.type,"null"];else return{...a,anyOf:[a,{type:"null"}],...t?{$schema:"http://json-schema.org/draft-07/schema#"}:{}};return t?{...a,$schema:"http://json-schema.org/draft-07/schema#"}:a}return t?n:{}}if(e.type){let s={boolean:"boolean",string:"string",timestamp:"string",float32:"number",float64:"number",int8:"integer",uint8:"integer",int16:"integer",uint16:"integer",int32:"integer",uint32:"integer"},a=e.type,p=s[a]||"string";return n.type=i?[p,"null"]:p,p==="string"&&a==="timestamp"&&(n.format="date-time"),n}if(e.enum)return n.type=i?["string","null"]:"string",n.enum=i?[...e.enum,null]:e.enum,n;if(e.elements)return n.type=i?["array","null"]:"array",n.items=c(e.elements,o,!1),n;if(e.properties||e.optionalProperties){if(n.type=i?["object","null"]:"object",n.properties={},n.required=[],e.properties)for(let[s,a]of Object.entries(e.properties))n.properties[s]=c(a,o,!1),n.required.push(s);if(e.optionalProperties)for(let[s,a]of Object.entries(e.optionalProperties))n.properties[s]=c(a,o,!1);return e.additionalProperties!==!0&&(n.additionalProperties=!1),n}if(e.values)return n.type=i?["object","null"]:"object",n.additionalProperties=c(e.values,o,!1),n;if(e.discriminator&&e.mapping){let s=[],a=e.discriminator;for(let[p,b]of Object.entries(e.mapping)){let l=c(b,o,!1);l.type?l.type!=="object"&&!Array.isArray(l.type)&&(l.type="object"):l.type="object",l.properties=l.properties||{},l.properties[a]={const:p},l.required=l.required||[],l.required.includes(a)||l.required.unshift(a),l.additionalProperties===void 0&&(l.additionalProperties=!1),s.push(l)}return i&&s.push({type:"null"}),n.oneOf=s,n}return n}function f(e,r=""){if(!e||typeof e!="object")return null;if("discriminator"in e||"mapping"in e)return`Discriminator unions are not supported${r?` (at ${r})`:""}. Use a simpler object structure instead.`;if("ref"in e)return`Schema references (ref) are not supported${r?` (at ${r})`:""}. Inline the schema definition instead.`;if("definitions"in e)return`Schema definitions are not supported${r?` (at ${r})`:""}. Inline the schema definition instead.`;if("values"in e)return`Dictionary/map schemas (values form) are not supported${r?` (at ${r})`:""}. OpenAI requires additionalProperties: false on all objects. Use explicit properties instead.`;if("elements"in e&&e.elements){let t=f(e.elements,`${r}/elements`);if(t)return t}if("properties"in e&&e.properties)for(let[t,i]of Object.entries(e.properties)){let o=f(i,`${r}/properties/${t}`);if(o)return o}if("optionalProperties"in e&&e.optionalProperties)for(let[t,i]of Object.entries(e.optionalProperties)){let o=f(i,`${r}/optionalProperties/${t}`);if(o)return o}return null}function m(e){if(!e||typeof e!="object")return{};let r="nullable"in e&&e.nullable===!0,t={},i=e.metadata;if(i&&(typeof i.title=="string"&&i.title.trim()&&(t.title=i.title.trim()),typeof i.description=="string"&&i.description.trim()&&(t.description=i.description.trim())),"type"in e&&e.type){let o={boolean:"boolean",string:"string",timestamp:"string",float32:"number",float64:"number",int8:"integer",uint8:"integer",int16:"integer",uint16:"integer",int32:"integer",uint32:"integer"},n=e.type,s=o[n]||"string";return t.type=r?[s,"null"]:s,n==="timestamp"&&(t.format="date-time"),t}if("enum"in e&&e.enum){let o=e.enum;return t.type=r?["string","null"]:"string",t.enum=r?[...o,null]:o,t}if("elements"in e&&e.elements)return t.type=r?["array","null"]:"array",t.items=m(e.elements),t;if("properties"in e||"optionalProperties"in e){if(t.type=r?["object","null"]:"object",t.properties={},t.required=[],t.additionalProperties=!1,"properties"in e&&e.properties)for(let[o,n]of Object.entries(e.properties))t.properties[o]=m(n),t.required.push(o);if("optionalProperties"in e&&e.optionalProperties)for(let[o,n]of Object.entries(e.optionalProperties))t.properties[o]=m(n);return t}return t}function O(e){let r=f(e);if(r)return{success:!1,error:r};try{return{success:!0,schema:m(e)}}catch(t){return{success:!1,error:t instanceof Error?t.message:"Unknown conversion error"}}}function x(e){let r=f(e);return r?{compatible:!1,error:r}:{compatible:!0}}var R=32,A=100;function v(e){return T(e)?y(e)?{valid:!0,schema:e}:{valid:!1,error:"Invalid JTD schema: Schema has semantic errors (e.g., circular references, conflicting forms)"}:{valid:!1,error:"Invalid JTD schema: Schema does not match JTD structure"}}function S(e){let r=v(e);if(!r.valid)return r;let t=r.schema;if(!("type"in t)&&!("enum"in t)&&!("elements"in t)&&!("properties"in t)&&!("optionalProperties"in t))return{valid:!1,error:"Schema must define structure (properties, type, enum, or elements). Empty schemas are not supported."};let i=x(r.schema);return i.compatible?{valid:!0,schema:r.schema}:{valid:!1,error:i.error}}function J(e){try{return{valid:!0,data:JSON.parse(e)}}catch(r){return{valid:!1,error:`Invalid JSON: ${r instanceof Error?r.message:"Parse error"}`}}}function C(e){let r=J(e);return r.valid?v(r.data):{valid:!1,error:r.error}}function I(e){let r=J(e);return r.valid?S(r.data):{valid:!1,error:r.error}}var V={uri:"https://mochabug.com/schemas/universal-jtd-schema.json",fileMatch:["inmemory://jtd-schema/*.json"],schema:{$schema:"http://json-schema.org/draft-07/schema#",title:"Universal JTD Schema",description:"JSON Type Definition schema compatible with Anthropic Claude, Google Gemini, and OpenAI structured outputs. Note: discriminator unions, refs, and dictionary/map schemas (values) are NOT supported.",type:"object",properties:{type:{description:"Type form - defines a primitive type",enum:["boolean","string","timestamp","float32","float64","int8","uint8","int16","uint16","int32","uint32"]},enum:{description:"Enum form - defines a set of string values for classification",type:"array",items:{type:"string"},minItems:1},elements:{description:"Elements form - defines an array with typed elements",$ref:"#"},properties:{description:"Properties form - defines an object with required properties",type:"object",additionalProperties:{$ref:"#"}},optionalProperties:{description:"Optional properties - defines optional object properties (can be omitted)",type:"object",additionalProperties:{$ref:"#"}},nullable:{description:"Allow null values in addition to the defined type",type:"boolean"},metadata:{description:'Custom metadata - use "title" and "description" to guide the AI model',type:"object",properties:{title:{type:"string",description:"Short title/label for this field"},description:{type:"string",description:"Detailed description of what this field should contain"}},additionalProperties:!1}}}},N={uri:"https://jsontypedef.com/schemas/jtd-schema.json",fileMatch:["inmemory://jtd-schema/*.json"],schema:{$schema:"http://json-schema.org/draft-07/schema#",type:"object",properties:{type:{description:"Type form - defines a primitive type",enum:["boolean","string","timestamp","float32","float64","int8","uint8","int16","uint16","int32","uint32"]},enum:{description:"Enum form - defines a set of string values",type:"array",items:{type:"string"}},elements:{description:"Elements form - defines an array with typed elements",$ref:"#"},properties:{description:"Properties form - defines an object with required properties",type:"object",additionalProperties:{$ref:"#"}},optionalProperties:{description:"Optional properties - defines optional object properties",type:"object",additionalProperties:{$ref:"#"}},values:{description:"Values form - defines a map/dictionary with typed values",$ref:"#"},discriminator:{description:"Discriminator form - defines a tagged union",type:"string"},mapping:{description:"Mapping for discriminator form",type:"object",additionalProperties:{$ref:"#"}},ref:{description:"Ref form - references a definition",type:"string"},definitions:{description:"Top-level definitions for reusable schemas",type:"object",additionalProperties:{$ref:"#"}},nullable:{description:"Allow null values",type:"boolean"},metadata:{description:"Custom metadata for documentation",type:"object"},additionalProperties:{description:"Allow additional properties (properties form only)",type:"boolean"}}}};export{N as JTD_SCHEMA_CONFIG,R as MAX_VALIDATION_DEPTH,A as MAX_VALIDATION_ERRORS,V as UNIVERSAL_JTD_SCHEMA_CONFIG,u as fuzzJTD,c as jtdToJsonSchema,O as jtdToUniversalJsonSchema,J as validateJSON,v as validateJTDSchema,C as validateJTDSchemaString,S as validateUniversalJTD,I as validateUniversalJTDSchemaString,d as validateValueAgainstJTD,U as validateValueAgainstSignal};
1
+ import{isSchema as y,isValidSchema as m,validate as J}from"jtd";var b=10;function u(e,n,i=0){if(i>b)return null;if(e.ref){let t=n?.[e.ref];return t?u(t,n,i+1):null}if(e.type)switch(e.type){case"string":return"Lorem ipsum";case"timestamp":return"2024-01-15T10:30:00Z";case"float32":case"float64":return 42.5;case"int8":case"uint8":case"int16":case"uint16":case"int32":case"uint32":return BigInt(42);case"boolean":return!0;default:return null}if(e.enum)return e.enum[0]??null;if(e.elements)return[u(e.elements,n,i+1),u(e.elements,n,i+1)];if(e.values)return{key1:u(e.values,n,i+1)};if(e.properties||e.optionalProperties){let t={};if(e.properties)for(let[o,r]of Object.entries(e.properties))t[o]=u(r,n,i+1);if(e.optionalProperties)for(let[o,r]of Object.entries(e.optionalProperties))t[o]=u(r,n,i+1);return t}if(e.discriminator&&e.mapping){let t=Object.keys(e.mapping)[0];if(t){let o=e.mapping[t],r=u(o,n,i+1);return r[e.discriminator]=t,r}return null}return null}var v=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function T(e){return e.length===0?"/":e.map(n=>/^\d+$/.test(n)?`[${n}]`:`.${n}`).join("")}function d(e,n){let i=e;for(let t=0;t<n.length-1&&(i&&typeof i=="object"&&n[t]in i);t++)i=i[n[t]];return i}function D(e,n){let i=e;for(let t of n)if(i&&typeof i=="object")i=i[t];else return;return i}function $(e,n,i){let{instancePath:t,schemaPath:o}=e,r=T(t),s=o[o.length-1];if(s==="type"){let l=d(n,o)?.type;return l==="boolean"?`${r}: expected boolean`:l==="string"?`${r}: expected string`:l==="timestamp"?`${r}: expected timestamp string`:v.has(l)?`${r}: expected integer`:`${r}: expected number`}if(s==="enum"){let l=d(n,o)?.enum;return`${r}: expected one of [${l.join(", ")}]`}if(o.length>=2&&o[o.length-2]==="properties"&&s)return`${r==="/"?"":r}.${s}: missing required property`;if(s==="elements")return`${r}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${r}: expected object`;if(s==="discriminator")return`${r}: expected string discriminator`;if(s==="mapping"){let a=D(i,t);return`${r}: unknown variant "${a}"`}return o.length===0?`${r}: unexpected property`:`${r}: validation error at /${o.join("/")}`}function c(e,n,i){let t=i??e.definitions,o=t?{...e,definitions:t}:e;return m(o)?J(o,n,{maxDepth:h,maxErrors:S}).map(s=>$(s,o,n)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}function x(e,n){if("formats"in e&&Array.isArray(e.formats)){let t=e.formats.filter(o=>o.jtdSchema);if(t.length===0)return["/: no JTD formats in signal descriptor"];for(let o of t)if(c(o.jtdSchema,n).length===0)return[];return c(t[t.length-1].jtdSchema,n)}let i=e;return i.jtdSchema?c(i.jtdSchema,n):["/: signal format has no jtdSchema"]}function f(e,n,i=!0){if(!e||typeof e!="object")return{};let t=e.nullable,o=n||e.definitions,r={};if(i&&(r.$schema="http://json-schema.org/draft-07/schema#"),e.ref){let s=e.ref;if(o&&o[s]){let a=f(o[s],o,!1);if(t)if(a.type)a.type=Array.isArray(a.type)?[...a.type,"null"]:[a.type,"null"];else return{...a,anyOf:[a,{type:"null"}],...i?{$schema:"http://json-schema.org/draft-07/schema#"}:{}};return i?{...a,$schema:"http://json-schema.org/draft-07/schema#"}:a}return i?r:{}}if(e.type){let s={boolean:"boolean",string:"string",timestamp:"string",float32:"number",float64:"number",int8:"integer",uint8:"integer",int16:"integer",uint16:"integer",int32:"integer",uint32:"integer"},a=e.type,l=s[a]||"string";return r.type=t?[l,"null"]:l,l==="string"&&a==="timestamp"&&(r.format="date-time"),r}if(e.enum)return r.type=t?["string","null"]:"string",r.enum=t?[...e.enum,null]:e.enum,r;if(e.elements)return r.type=t?["array","null"]:"array",r.items=f(e.elements,o,!1),r;if(e.properties||e.optionalProperties){if(r.type=t?["object","null"]:"object",r.properties={},r.required=[],e.properties)for(let[s,a]of Object.entries(e.properties))r.properties[s]=f(a,o,!1),r.required.push(s);if(e.optionalProperties)for(let[s,a]of Object.entries(e.optionalProperties))r.properties[s]=f(a,o,!1);return e.additionalProperties!==!0&&(r.additionalProperties=!1),r}if(e.values)return r.type=t?["object","null"]:"object",r.additionalProperties=f(e.values,o,!1),r;if(e.discriminator&&e.mapping){let s=[],a=e.discriminator;for(let[l,g]of Object.entries(e.mapping)){let p=f(g,o,!1);p.type?p.type!=="object"&&!Array.isArray(p.type)&&(p.type="object"):p.type="object",p.properties=p.properties||{},p.properties[a]={const:l},p.required=p.required||[],p.required.includes(a)||p.required.unshift(a),p.additionalProperties===void 0&&(p.additionalProperties=!1),s.push(p)}return t&&s.push({type:"null"}),r.oneOf=s,r}return r}var h=32,S=100;function k(e){return y(e)?m(e)?{valid:!0,schema:e}:{valid:!1,error:"Invalid JTD schema: Schema has semantic errors (e.g., circular references, conflicting forms)"}:{valid:!1,error:"Invalid JTD schema: Schema does not match JTD structure"}}function w(e){try{return{valid:!0,data:JSON.parse(e)}}catch(n){return{valid:!1,error:`Invalid JSON: ${n instanceof Error?n.message:"Parse error"}`}}}function P(e){let n=w(e);return n.valid?k(n.data):{valid:!1,error:n.error}}var A={uri:"https://jsontypedef.com/schemas/jtd-schema.json",fileMatch:["inmemory://jtd-schema/*.json"],schema:{$schema:"http://json-schema.org/draft-07/schema#",type:"object",properties:{type:{description:"Type form - defines a primitive type",enum:["boolean","string","timestamp","float32","float64","int8","uint8","int16","uint16","int32","uint32"]},enum:{description:"Enum form - defines a set of string values",type:"array",items:{type:"string"}},elements:{description:"Elements form - defines an array with typed elements",$ref:"#"},properties:{description:"Properties form - defines an object with required properties",type:"object",additionalProperties:{$ref:"#"}},optionalProperties:{description:"Optional properties - defines optional object properties",type:"object",additionalProperties:{$ref:"#"}},values:{description:"Values form - defines a map/dictionary with typed values",$ref:"#"},discriminator:{description:"Discriminator form - defines a tagged union",type:"string"},mapping:{description:"Mapping for discriminator form",type:"object",additionalProperties:{$ref:"#"}},ref:{description:"Ref form - references a definition",type:"string"},definitions:{description:"Top-level definitions for reusable schemas",type:"object",additionalProperties:{$ref:"#"}},nullable:{description:"Allow null values",type:"boolean"},metadata:{description:"Custom metadata for documentation",type:"object"},additionalProperties:{description:"Allow additional properties (properties form only)",type:"boolean"}}}};export{A as JTD_SCHEMA_CONFIG,h as MAX_VALIDATION_DEPTH,S as MAX_VALIDATION_ERRORS,u as fuzzJTD,f as jtdToJsonSchema,w as validateJSON,k as validateJTDSchema,P as validateJTDSchemaString,c as validateJsonAgainstJTD,x as validateJsonAgainstSignal};
2
2
  //# sourceMappingURL=signals.mjs.map