@mochabug/adapt-sdk 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anthropic/index.d.ts.map +1 -1
- package/dist/cjs/anthropic.cjs +1 -1
- package/dist/cjs/anthropic.cjs.map +2 -2
- package/dist/cjs/gemini.cjs +1 -1
- package/dist/cjs/gemini.cjs.map +2 -2
- package/dist/cjs/openai.cjs +1 -1
- package/dist/cjs/openai.cjs.map +2 -2
- package/dist/esm/anthropic.mjs +1 -1
- package/dist/esm/anthropic.mjs.map +2 -2
- package/dist/esm/gemini.mjs +1 -1
- package/dist/esm/gemini.mjs.map +2 -2
- package/dist/esm/openai.mjs +1 -1
- package/dist/esm/openai.mjs.map +3 -3
- package/dist/gemini/index.d.ts.map +1 -1
- package/dist/openai/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/anthropic/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/anthropic/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,CAAC;AAslBnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qBAAa,mBAAmB;IAC9B,gGAAgG;IAChG,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAI3C;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,GAAG,mBAAmB;IAmC7D;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,oBAAoB,GAAG,mBAAmB;IAKxE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB;IAe5E,OAAO;IAcP;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,OAAO,GAAI,MAAM,OAAO,KAAG,aAAa,CAQtC;IAIF;;;;;;;;;OASG;IACH,MAAM;;;;;;;;;;;CAcP;AA4KD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,aAAa,GACvB,mBAAmB,CAErB;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,oBAAoB,GAC/B,mBAAmB,CAErB"}
|
package/dist/cjs/anthropic.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var J=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(e,t)=>{for(var n in t)J(e,n,{get:t[n],enumerable:!0})},N=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of P(t))!x.call(e,r)&&r!==n&&J(e,r,{get:()=>t[r],enumerable:!(o=O(t,r))||o.enumerable});return e};var C=e=>N(J({},"__esModule",{value:!0}),e);var te={};E(te,{AnthropicConversion:()=>y,convertSignalToAnthropicSchema:()=>ee,convertToAnthropicSchema:()=>Q});module.exports=C(te);var S=require("jtd");var I=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function F(e){return e.length===0?"/":e.map(t=>/^\d+$/.test(t)?`[${t}]`:`.${t}`).join("")}function k(e,t){let n=e;for(let o=0;o<t.length-1&&(n&&typeof n=="object"&&t[o]in n);o++)n=n[t[o]];return n}function M(e,t){let n=e;for(let o of t)if(n&&typeof n=="object")n=n[o];else return;return n}function _(e,t,n){let{instancePath:o,schemaPath:r}=e,i=F(o),s=r[r.length-1];if(s==="type"){let c=k(t,r)?.type;return c==="boolean"?`${i}: expected boolean`:c==="string"?`${i}: expected string`:c==="timestamp"?`${i}: expected timestamp string`:I.has(c)?`${i}: expected integer`:`${i}: expected number`}if(s==="enum"){let c=k(t,r)?.enum;return`${i}: expected one of [${c.join(", ")}]`}if(r.length>=2&&r[r.length-2]==="properties"&&s)return`${i==="/"?"":i}.${s}: missing required property`;if(s==="elements")return`${i}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${i}: expected object`;if(s==="discriminator")return`${i}: expected string discriminator`;if(s==="mapping"){let a=M(n,o);return`${i}: unknown variant "${a}"`}return r.length===0?`${i}: unexpected property`:`${i}: validation error at /${r.join("/")}`}function D(e,t,n){let o=n??e.definitions,r=o?{...e,definitions:o}:e;return(0,S.isValidSchema)(r)?(0,S.validate)(r,t,{maxDepth:U,maxErrors:V}).map(s=>_(s,r,t)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}var U=32,V=100;var h=32,T=`Must be a valid JSON value encoded as a string. For objects: '{"key": "value"}', for arrays: '[1, 2]', for primitives: '"hello"' or '42' or 'true' or 'null'.`,q=`The variant data encoded as a valid JSON string (e.g. '{"key": "value"}').`,B="Array of key-value entries representing a map/dictionary. Each entry has a string 'key' (the property name) and a 'value' (the property value).",j={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}},A={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 K(e,t){let n=e,o=0;for(;n.ref&&o<h;){let r=t?.[n.ref];if(!r)return!1;n=r,o++}return o>=h?!1:b(n)}function g(e){let t=[];if(!e||typeof e!="object")return t;if(e.ref&&t.push(e.ref),e.properties)for(let n of Object.values(e.properties))t.push(...g(n));if(e.optionalProperties)for(let n of Object.values(e.optionalProperties))t.push(...g(n));if(e.elements&&t.push(...g(e.elements)),e.values&&t.push(...g(e.values)),e.mapping)for(let n of Object.values(e.mapping))t.push(...g(n));return t}function G(e){let r=new Map;for(let s of Object.keys(e))r.set(s,0);function i(s){r.set(s,1);let a=e[s];if(a){for(let c of g(a))if(r.has(c)){if(r.get(c)===1)return c;if(r.get(c)===0){let p=i(c);if(p)return p}}}return r.set(s,2),null}for(let s of Object.keys(e))if(r.get(s)===0){let a=i(s);if(a)return a}return null}function f(e,t){return t?[e,"null"]:e}function H(e,t){e.description=e.description?`${e.description} ${t}`:t}var Y=new Set(["title","label","name","description"]);function l(e,t){let n=t.metadata;if(!n)return;let o=[],r=typeof n.title=="string"&&n.title.trim()||typeof n.label=="string"&&n.label.trim()||typeof n.name=="string"&&n.name.trim(),i=typeof n.description=="string"?n.description.trim():"";r&&i?o.push(`${r}. ${i}`):r?o.push(r):i&&o.push(i);let s=[];for(let[a,c]of Object.entries(n))Y.has(a)||(typeof c=="string"&&c.trim()?s.push(`[${a}: ${c.trim()}]`):(typeof c=="number"||typeof c=="boolean")&&s.push(`[${a}: ${c}]`));if(s.length>0&&o.push(s.join(" ")),o.length>0){let a=o.join(" ");e.description=e.description?`${e.description} ${a}`:a}}function d(e,t,n){if(n>h)throw new Error(`Schema nesting exceeded ${h} levels`);if(!e||typeof e!="object")return{type:"string",description:T};if(b(e)){let r={type:f("string",e.nullable===!0),description:T};return l(r,e),r}let o=e.nullable===!0;if(e.ref){let r=e.ref;if(!t?.[r])throw new Error(`Unresolved ref "${r}"`);if(o){let i={anyOf:[{$ref:`#/$defs/${r}`},{type:"null"}]};return l(i,e),i}return{$ref:`#/$defs/${r}`}}if(e.type){let r={},i,s=j[e.type];if(s)r.type=f("integer",o),i=`Value range: [${s.minimum}, ${s.maximum}].`;else switch(e.type){case"boolean":r.type=f("boolean",o);break;case"string":r.type=f("string",o);break;case"timestamp":r.type=f("string",o),r.format="date-time";break;case"float32":r.type=f("number",o),i=`Value range: [${A.minimum}, ${A.maximum}].`;break;case"float64":r.type=f("number",o);break;default:throw new Error(`Unknown JTD type "${e.type}"`)}return l(r,e),i&&H(r,i),r}if(e.enum){let r={type:f("string",o),enum:o?[...e.enum,null]:e.enum};return l(r,e),r}if(e.elements){let r={type:f("array",o),items:d(e.elements,t,n+1)};return l(r,e),r}if(e.properties||e.optionalProperties){let r={},i=[];if(e.properties)for(let[a,c]of Object.entries(e.properties))r[a]=d(c,t,n+1),i.push(a);if(e.optionalProperties)for(let[a,c]of Object.entries(e.optionalProperties))r[a]=d(c,t,n+1);let s={type:f("object",o),properties:r,additionalProperties:!1};return i.length>0&&(s.required=i),l(s,e),s}if(e.values){let r=d(e.values,t,n+1),i={type:f("array",o),description:B,items:{type:"object",properties:{key:{type:"string",description:"The property name."},value:r},required:["key","value"],additionalProperties:!1}};return l(i,e),i}if(e.discriminator&&e.mapping){let r=e.discriminator,i=e.mapping,s=[];for(let[c,p]of Object.entries(i)){let u;b(p)?u={type:"object",properties:{[r]:{const:c},_data:{type:"string",description:q}},required:[r,"_data"],additionalProperties:!1}:(u=d(p,t,n+1),u.properties[r]={const:c},(u.required??=[]).unshift(r),u.additionalProperties=!1),l(u,p),s.push(u)}o&&s.push({type:"null"});let a={anyOf:s};return l(a,e),a}return{type:"string",description:T}}var L=new Set(Object.keys(j));function m(e,t,n,o){if(o>h||e==null)return e;if(t.ref){let r=n?.[t.ref];return r?m(e,r,n,o+1):e}if(b(t)){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}if(t.type&&L.has(t.type))return typeof e=="number"&&!Number.isInteger(e)?Math.round(e):e;if(t.elements&&Array.isArray(e)){let r=t.elements;return e.map(i=>m(i,r,n,o+1))}if((t.properties||t.optionalProperties)&&typeof e=="object"&&e!==null){let r={...e};if(t.properties)for(let[i,s]of Object.entries(t.properties))i in r&&(r[i]=m(r[i],s,n,o+1));if(t.optionalProperties)for(let[i,s]of Object.entries(t.optionalProperties))i in r&&(r[i]=m(r[i],s,n,o+1));return r}if(t.values&&Array.isArray(e)){let r={};for(let i of e)if(typeof i=="object"&&i!==null){let s=i,a=s.key;r[a]=m(s.value,t.values,n,o+1)}return r}if(t.discriminator&&t.mapping&&typeof e=="object"&&e!==null){let r=e,i=t.discriminator,s=r[i];if(typeof s!="string")return e;let a=t.mapping[s];if(!a)return e;if(b(a)){let p=r._data;if(typeof p=="string")try{let u=JSON.parse(p);if(typeof u=="object"&&u!==null)return{[i]:s,...u}}catch{}return{[i]:s}}let c={[i]:s};if(a.properties)for(let[p,u]of Object.entries(a.properties))p in r&&(c[p]=m(r[p],u,n,o+1));if(a.optionalProperties)for(let[p,u]of Object.entries(a.optionalProperties))p in r&&(c[p]=m(r[p],u,n,o+1));return c}return e}function W(e){return{type:"string",description:`Base64-encoded binary content (MIME type: ${e}).`}}var y=class e{schema;strict;jtdSchema;descriptor;static fromJTD(t){let n=t.definitions;if(n&&Object.keys(n).length>0){let i=G(n);if(i)throw new Error(`Anthropic structured output does not support recursive schemas. Definition "${i}" contains a circular reference.`)}let o=!K(t,n),r;return o?(r=d(t,n,0),n&&Object.keys(n).length>0&&(r.$defs=Object.fromEntries(Object.entries(n).map(([i,s])=>[i,d(s,n,0)])))):(r={},l(r,t)),new e(r,o,t,void 0)}static fromSignal(t){let{schema:n,strict:o}=Z(t);return new e(n,o,void 0,t)}static fromJSON(t){let n=typeof t=="string"?JSON.parse(t):t;if(n.descriptor)return e.fromSignal(n.descriptor);if(n.jtdSchema)return e.fromJTD(n.jtdSchema);throw new Error("Cannot deserialize: missing jtdSchema or descriptor")}constructor(t,n,o,r){this.schema=t,this.strict=n,this.jtdSchema=o,this.descriptor=r}convert=t=>this.jtdSchema?R(this.jtdSchema,t):this.descriptor?z(this.descriptor,t):{success:!1,errors:["No source schema available"]};toJSON(){return this.descriptor?{schema:this.schema,strict:this.strict,descriptor:this.descriptor}:{schema:this.schema,strict:this.strict,jtdSchema:this.jtdSchema}}};function R(e,t){let n=e.definitions,o=m(t,e,n,0),r=D(e,o,n);return r.length>0?{success:!1,errors:r}:{success:!0,kind:"json",data:o}}function X(e,t){return typeof t!="string"?{success:!1,errors:[`/: expected base64 string for MIME type ${e}, got ${typeof t}`]}:{success:!0,kind:"binary",mimeType:e,data:new Uint8Array(Buffer.from(t,"base64"))}}function w(e,t){return e.mimeType?X(e.mimeType,t):e.jtdSchema?R(e.jtdSchema,t):{success:!1,errors:["Signal format has neither jtdSchema nor mimeType"]}}function z(e,t){let n=e.formats;if(!n||n.length===0)return{success:!1,errors:["Signal descriptor has no formats"]};if(n.length===1)return w(n[0],t);if(typeof t!="object"||t===null)return{success:!1,errors:[`/: expected object with format properties, got ${typeof t}`]};let o=t;for(let i=0;i<n.length;i++){let s=`format_${i}`;if(o[s]!==void 0&&o[s]!==null)return w(n[i],o[s])}if(e.optional)return{success:!0,kind:"json",data:null};let r=n.map((i,s)=>`format_${s}`);return{success:!1,errors:[`Signal '${e.name??"unnamed"}' is required but no format was provided. Set exactly one of: ${r.join(", ")}.`]}}function Z(e){let t=e.formats;if(!t||t.length===0)throw new Error("Signal descriptor has no formats");if(t.length===1){let[a]=t,{schema:c,strict:p}=$(a);if(e.label||e.description){let u=[];e.label&&u.push(e.label),e.description&&u.push(e.description);let v=u.join(". ");c.description=c.description?`${v} ${c.description}`:v}return{schema:c,strict:p}}let n={};for(let[a,c]of t.entries()){let{schema:p}=$(c);c.jtdSchema&&(p.description=p.description?`Structured JSON data. ${p.description}`:"Structured JSON data."),n[`format_${a}`]=p}let o=Object.keys(n),r=e.description??"",i=e.optional?"Provide at most ONE of the following format properties. All are optional.":`You MUST provide exactly ONE of the following format properties: ${o.join(", ")}.`;return{schema:{type:"object",description:r?`${r} ${i}`:i,properties:n,additionalProperties:!1},strict:!0}}function $(e){if(e.jtdSchema){let t=y.fromJTD(e.jtdSchema);return{schema:t.schema,strict:t.strict}}if(e.mimeType)return{schema:W(e.mimeType),strict:!0};throw new Error("Signal format has neither jtdSchema nor mimeType")}function Q(e){return y.fromJTD(e)}function ee(e){return y.fromSignal(e)}0&&(module.exports={AnthropicConversion,convertSignalToAnthropicSchema,convertToAnthropicSchema});
|
|
1
|
+
"use strict";var J=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(e,t)=>{for(var n in t)J(e,n,{get:t[n],enumerable:!0})},N=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of P(t))!x.call(e,r)&&r!==n&&J(e,r,{get:()=>t[r],enumerable:!(o=O(t,r))||o.enumerable});return e};var C=e=>N(J({},"__esModule",{value:!0}),e);var te={};E(te,{AnthropicConversion:()=>y,convertSignalToAnthropicSchema:()=>ee,convertToAnthropicSchema:()=>Q});module.exports=C(te);var S=require("jtd");var I=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function M(e){return e.length===0?"/":e.map(t=>/^\d+$/.test(t)?`[${t}]`:`.${t}`).join("")}function k(e,t){let n=e;for(let o=0;o<t.length-1&&(n&&typeof n=="object"&&t[o]in n);o++)n=n[t[o]];return n}function F(e,t){let n=e;for(let o of t)if(n&&typeof n=="object")n=n[o];else return;return n}function _(e,t,n){let{instancePath:o,schemaPath:r}=e,i=M(o),s=r[r.length-1];if(s==="type"){let c=k(t,r)?.type;return c==="boolean"?`${i}: expected boolean`:c==="string"?`${i}: expected string`:c==="timestamp"?`${i}: expected timestamp string`:I.has(c)?`${i}: expected integer`:`${i}: expected number`}if(s==="enum"){let c=k(t,r)?.enum;return`${i}: expected one of [${c.join(", ")}]`}if(r.length>=2&&r[r.length-2]==="properties"&&s)return`${i==="/"?"":i}.${s}: missing required property`;if(s==="elements")return`${i}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${i}: expected object`;if(s==="discriminator")return`${i}: expected string discriminator`;if(s==="mapping"){let a=F(n,o);return`${i}: unknown variant "${a}"`}return r.length===0?`${i}: unexpected property`:`${i}: validation error at /${r.join("/")}`}function D(e,t,n){let o=n??e.definitions,r=o?{...e,definitions:o}:e;return(0,S.isValidSchema)(r)?(0,S.validate)(r,t,{maxDepth:U,maxErrors:q}).map(s=>_(s,r,t)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}var U=32,q=100;var h=32,T=`Must be a valid JSON value encoded as a string. For objects: '{"key": "value"}', for arrays: '[1, 2]', for primitives: '"hello"' or '42' or 'true' or 'null'.`,V=`The variant data encoded as a valid JSON string (e.g. '{"key": "value"}').`,B="Array of key-value entries representing a map/dictionary. Each entry has a string 'key' (the property name) and a 'value' (the property value).",j={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}},A={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 K(e,t){let n=e,o=0;for(;n.ref&&o<h;){let r=t?.[n.ref];if(!r)return!1;n=r,o++}return o>=h?!1:b(n)}function g(e){let t=[];if(!e||typeof e!="object")return t;if(e.ref&&t.push(e.ref),e.properties)for(let n of Object.values(e.properties))t.push(...g(n));if(e.optionalProperties)for(let n of Object.values(e.optionalProperties))t.push(...g(n));if(e.elements&&t.push(...g(e.elements)),e.values&&t.push(...g(e.values)),e.mapping)for(let n of Object.values(e.mapping))t.push(...g(n));return t}function G(e){let r=new Map;for(let s of Object.keys(e))r.set(s,0);function i(s){r.set(s,1);let a=e[s];if(a){for(let c of g(a))if(r.has(c)){if(r.get(c)===1)return c;if(r.get(c)===0){let p=i(c);if(p)return p}}}return r.set(s,2),null}for(let s of Object.keys(e))if(r.get(s)===0){let a=i(s);if(a)return a}return null}function f(e,t){return t?[e,"null"]:e}function H(e,t){e.description=e.description?`${e.description} ${t}`:t}var Y=new Set(["title","label","name","description"]);function l(e,t){let n=t.metadata;if(!n)return;let o=[],r=typeof n.title=="string"&&n.title.trim()||typeof n.label=="string"&&n.label.trim()||typeof n.name=="string"&&n.name.trim(),i=typeof n.description=="string"?n.description.trim():"";r&&i?o.push(`${r}. ${i}`):r?o.push(r):i&&o.push(i);let s=[];for(let[a,c]of Object.entries(n))Y.has(a)||(typeof c=="string"&&c.trim()?s.push(`[${a}: ${c.trim()}]`):(typeof c=="number"||typeof c=="boolean")&&s.push(`[${a}: ${c}]`));if(s.length>0&&o.push(s.join(" ")),o.length>0){let a=o.join(" ");e.description=e.description?`${e.description} ${a}`:a}}function m(e,t,n){if(n>h)throw new Error(`Schema nesting exceeded ${h} levels`);if(!e||typeof e!="object")return{type:"string",description:T};if(b(e)){let r={type:f("string",e.nullable===!0),description:T};return l(r,e),r}let o=e.nullable===!0;if(e.ref){let r=e.ref;if(!t?.[r])throw new Error(`Unresolved ref "${r}"`);if(o){let i={anyOf:[{$ref:`#/$defs/${r}`},{type:"null"}]};return l(i,e),i}return{$ref:`#/$defs/${r}`}}if(e.type){let r={},i,s=j[e.type];if(s)r.type=f("integer",o),i=`Value range: [${s.minimum}, ${s.maximum}].`;else switch(e.type){case"boolean":r.type=f("boolean",o);break;case"string":r.type=f("string",o);break;case"timestamp":r.type=f("string",o),r.format="date-time";break;case"float32":r.type=f("number",o),i=`Value range: [${A.minimum}, ${A.maximum}].`;break;case"float64":r.type=f("number",o);break;default:throw new Error(`Unknown JTD type "${e.type}"`)}return l(r,e),i&&H(r,i),r}if(e.enum){let r={type:f("string",o),enum:o?[...e.enum,null]:e.enum};return l(r,e),r}if(e.elements){let r={type:f("array",o),items:m(e.elements,t,n+1)};return l(r,e),r}if(e.properties||e.optionalProperties){let r={},i=[];if(e.properties)for(let[a,c]of Object.entries(e.properties))r[a]=m(c,t,n+1),i.push(a);if(e.optionalProperties)for(let[a,c]of Object.entries(e.optionalProperties))r[a]=m(c,t,n+1);let s={type:f("object",o),properties:r,additionalProperties:!1};return i.length>0&&(s.required=i),l(s,e),s}if(e.values){let r=m(e.values,t,n+1),i={type:f("array",o),description:B,items:{type:"object",properties:{key:{type:"string",description:"The property name."},value:r},required:["key","value"],additionalProperties:!1}};return l(i,e),i}if(e.discriminator&&e.mapping){let r=e.discriminator,i=e.mapping,s=[];for(let[c,p]of Object.entries(i)){let u;b(p)?u={type:"object",properties:{[r]:{const:c},_data:{type:"string",description:V}},required:[r,"_data"],additionalProperties:!1}:(u=m(p,t,n+1),u.properties[r]={const:c},(u.required??=[]).unshift(r),u.additionalProperties=!1),l(u,p),s.push(u)}o&&s.push({type:"null"});let a={anyOf:s};return l(a,e),a}return{type:"string",description:T}}var L=new Set(Object.keys(j));function d(e,t,n,o){if(o>h||e==null)return e;if(t.ref){let r=n?.[t.ref];return r?d(e,r,n,o+1):e}if(b(t)){if(typeof e=="string")try{return JSON.parse(e)}catch{return e}return e}if(t.type&&L.has(t.type))return typeof e=="number"&&!Number.isInteger(e)?Math.round(e):e;if(t.elements&&Array.isArray(e)){let r=t.elements;return e.map(i=>d(i,r,n,o+1))}if((t.properties||t.optionalProperties)&&typeof e=="object"&&e!==null){let r={...e};if(t.properties)for(let[i,s]of Object.entries(t.properties))i in r&&(r[i]=d(r[i],s,n,o+1));if(t.optionalProperties)for(let[i,s]of Object.entries(t.optionalProperties))i in r&&(r[i]=d(r[i],s,n,o+1));return r}if(t.values&&Array.isArray(e)){let r={};for(let i of e)if(typeof i=="object"&&i!==null){let s=i,a=s.key;r[a]=d(s.value,t.values,n,o+1)}return r}if(t.discriminator&&t.mapping&&typeof e=="object"&&e!==null){let r=e,i=t.discriminator,s=r[i];if(typeof s!="string")return e;let a=t.mapping[s];if(!a)return e;if(b(a)){let p=r._data;if(typeof p=="string")try{let u=JSON.parse(p);if(typeof u=="object"&&u!==null)return{[i]:s,...u}}catch{}return{[i]:s}}let c={[i]:s};if(a.properties)for(let[p,u]of Object.entries(a.properties))p in r&&(c[p]=d(r[p],u,n,o+1));if(a.optionalProperties)for(let[p,u]of Object.entries(a.optionalProperties))p in r&&(c[p]=d(r[p],u,n,o+1));return c}return e}function W(e){return{type:"object",description:`Binary content (MIME type: ${e}).`,properties:{data:{type:"string",description:`The base64-encoded binary content (MIME type: ${e}).`},filename:{type:"string",description:'Optional filename for the binary content (e.g. "report.pdf", "image.png").'}},required:["data"],additionalProperties:!1}}var y=class e{schema;strict;jtdSchema;descriptor;static fromJTD(t){let n=t.definitions;if(n&&Object.keys(n).length>0){let i=G(n);if(i)throw new Error(`Anthropic structured output does not support recursive schemas. Definition "${i}" contains a circular reference.`)}let o=!K(t,n),r;return o?(r=m(t,n,0),n&&Object.keys(n).length>0&&(r.$defs=Object.fromEntries(Object.entries(n).map(([i,s])=>[i,m(s,n,0)])))):(r={},l(r,t)),new e(r,o,t,void 0)}static fromSignal(t){let{schema:n,strict:o}=Z(t);return new e(n,o,void 0,t)}static fromJSON(t){let n=typeof t=="string"?JSON.parse(t):t;if(n.descriptor)return e.fromSignal(n.descriptor);if(n.jtdSchema)return e.fromJTD(n.jtdSchema);throw new Error("Cannot deserialize: missing jtdSchema or descriptor")}constructor(t,n,o,r){this.schema=t,this.strict=n,this.jtdSchema=o,this.descriptor=r}convert=t=>this.jtdSchema?R(this.jtdSchema,t):this.descriptor?z(this.descriptor,t):{success:!1,errors:["No source schema available"]};toJSON(){return this.descriptor?{schema:this.schema,strict:this.strict,descriptor:this.descriptor}:{schema:this.schema,strict:this.strict,jtdSchema:this.jtdSchema}}};function R(e,t){let n=e.definitions,o=d(t,e,n,0),r=D(e,o,n);return r.length>0?{success:!1,errors:r}:{success:!0,kind:"json",data:o}}function X(e,t){if(typeof t!="object"||t===null)return{success:!1,errors:[`/: expected object with 'data' field for MIME type ${e}, got ${typeof t}`]};let n=t;if(typeof n.data!="string")return{success:!1,errors:[`/data: expected base64 string for MIME type ${e}, got ${typeof n.data}`]};let o={success:!0,kind:"binary",mimeType:e,data:new Uint8Array(Buffer.from(n.data,"base64"))};return typeof n.filename=="string"&&n.filename&&(o.filename=n.filename),o}function $(e,t){return e.mimeType?X(e.mimeType,t):e.jtdSchema?R(e.jtdSchema,t):{success:!1,errors:["Signal format has neither jtdSchema nor mimeType"]}}function z(e,t){let n=e.formats;if(!n||n.length===0)return{success:!1,errors:["Signal descriptor has no formats"]};if(n.length===1)return $(n[0],t);if(typeof t!="object"||t===null)return{success:!1,errors:[`/: expected object with format properties, got ${typeof t}`]};let o=t;for(let i=0;i<n.length;i++){let s=`format_${i}`;if(o[s]!==void 0&&o[s]!==null)return $(n[i],o[s])}if(e.optional)return{success:!0,kind:"json",data:null};let r=n.map((i,s)=>`format_${s}`);return{success:!1,errors:[`Signal '${e.name??"unnamed"}' is required but no format was provided. Set exactly one of: ${r.join(", ")}.`]}}function Z(e){let t=e.formats;if(!t||t.length===0)throw new Error("Signal descriptor has no formats");if(t.length===1){let[a]=t,{schema:c,strict:p}=w(a);if(e.label||e.description){let u=[];e.label&&u.push(e.label),e.description&&u.push(e.description);let v=u.join(". ");c.description=c.description?`${v} ${c.description}`:v}return{schema:c,strict:p}}let n={};for(let[a,c]of t.entries()){let{schema:p}=w(c);c.jtdSchema&&(p.description=p.description?`Structured JSON data. ${p.description}`:"Structured JSON data."),n[`format_${a}`]=p}let o=Object.keys(n),r=e.description??"",i=e.optional?"Provide at most ONE of the following format properties. All are optional.":`You MUST provide exactly ONE of the following format properties: ${o.join(", ")}.`;return{schema:{type:"object",description:r?`${r} ${i}`:i,properties:n,additionalProperties:!1},strict:!0}}function w(e){if(e.jtdSchema){let t=y.fromJTD(e.jtdSchema);return{schema:t.schema,strict:t.strict}}if(e.mimeType)return{schema:W(e.mimeType),strict:!0};throw new Error("Signal format has neither jtdSchema nor mimeType")}function Q(e){return y.fromJTD(e)}function ee(e){return y.fromSignal(e)}0&&(module.exports={AnthropicConversion,convertSignalToAnthropicSchema,convertToAnthropicSchema});
|
|
2
2
|
//# sourceMappingURL=anthropic.cjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/anthropic/index.ts", "../../src/signals/index.ts"],
|
|
4
|
-
"sourcesContent": ["// 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/**\n * JSON Schema subset accepted by the Anthropic structured-output API.\n *\n * This is the provider-specific representation produced by\n * {@link AnthropicConversion}. It covers the keywords that Anthropic\n * inspects when constraining model output: `type`, `properties`, `required`,\n * `additionalProperties`, `enum`, `const`, `format`, `items`, `anyOf`,\n * `$defs`, `$ref`, and `description`.\n */\nexport interface AnthropicSchema {\n type?: string | string[];\n description?: string;\n properties?: Record<string, AnthropicSchema>;\n required?: string[];\n additionalProperties?: false;\n enum?: (string | number | boolean | null)[];\n const?: string | number | boolean | null;\n format?: string;\n items?: AnthropicSchema;\n anyOf?: AnthropicSchema[];\n $defs?: Record<string, AnthropicSchema>;\n $ref?: string;\n}\n\n/**\n * Successful conversion result for a JTD format.\n *\n * Returned when the raw LLM output has been coerced to match the JTD schema\n * and passes JTD validation. `data` contains the deserialized, coerced, and\n * JTD-validated JSON value.\n */\nexport interface ConvertSuccessJson {\n success: true;\n kind: 'json';\n /** The deserialized, coerced, and JTD-validated JSON value. */\n data: unknown;\n}\n\n/**\n * Successful conversion result for a MIME (binary) format.\n *\n * Returned when the raw LLM output matches a MIME format. The base64 string\n * produced by the model is decoded into raw binary bytes.\n */\nexport interface ConvertSuccessBinary {\n success: true;\n kind: 'binary';\n /** The concrete MIME type of the binary content (e.g. `\"image/png\"`). */\n mimeType: string;\n /** The raw binary data decoded from the base64 string returned by the LLM. */\n data: Uint8Array;\n /** Optional filename, provided by the caller if available. */\n filename?: string;\n}\n\n/**\n * Failed conversion result.\n *\n * `errors` contains one or more human-readable strings describing validation\n * or coercion failures. Each entry uses a JSON Pointer path prefix\n * (e.g. `\"/foo/bar: ...\"`) to locate the problem within the data.\n */\nexport interface ConvertFailure {\n success: false;\n /** Array of human-readable error messages with JSON Pointer path prefixes. */\n errors: string[];\n}\n\n/**\n * Discriminated union of conversion outcomes.\n *\n * Check `success` first, then narrow on `kind` (`'json'` or `'binary'`)\n * for successful results.\n */\nexport type ConvertResult =\n | ConvertSuccessJson\n | ConvertSuccessBinary\n | ConvertFailure;\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 UNSTRUCTURED_DESC =\n 'Must be a valid JSON value encoded as a string. ' +\n \"For objects: '{\\\"key\\\": \\\"value\\\"}', for arrays: '[1, 2]', for primitives: '\\\"hello\\\"' or '42' or 'true' or 'null'.\";\n\nconst UNSTRUCTURED_VARIANT_DESC =\n 'The variant data encoded as a valid JSON string ' +\n '(e.g. \\'{\"key\": \"value\"}\\').';\n\nconst VALUES_ARRAY_DESC =\n 'Array of key-value entries representing a map/dictionary. ' +\n \"Each entry has a string 'key' (the property name) and a 'value' (the property value).\";\n\nconst INTEGER_BOUNDS = {\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} satisfies Record<string, { minimum: number; maximum: number }>;\n\nconst FLOAT32_BOUNDS = {\n minimum: -3.4028235e38,\n maximum: 3.4028235e38\n} satisfies { minimum: number; maximum: number };\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 if (\n (schema.properties !== undefined ||\n schema.optionalProperties !== undefined) &&\n schema.additionalProperties === true\n ) {\n return true;\n }\n\n if (\n schema.properties !== undefined ||\n schema.optionalProperties !== undefined\n ) {\n return false;\n }\n\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];\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// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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// Circular ref detection (Anthropic does not support recursive 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\nfunction collectRefsInSchema(schema: JTDSchemaJson): string[] {\n const refs: string[] = [];\n if (!schema || typeof schema !== 'object') return refs;\n if (schema.ref) refs.push(schema.ref);\n if (schema.properties) {\n for (const v of Object.values(schema.properties)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n if (schema.optionalProperties) {\n for (const v of Object.values(schema.optionalProperties)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n if (schema.elements) refs.push(...collectRefsInSchema(schema.elements));\n if (schema.values) refs.push(...collectRefsInSchema(schema.values));\n if (schema.mapping) {\n for (const v of Object.values(schema.mapping)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n return refs;\n}\n\n/**\n * Detect circular references in JTD definitions.\n * Returns the name of a definition involved in a cycle, or null if acyclic.\n */\nfunction detectCircularRefs(\n defs: Record<string, JTDSchemaJson>\n): string | null {\n const WHITE = 0,\n GRAY = 1,\n BLACK = 2;\n const color = new Map<string, number>();\n for (const name of Object.keys(defs)) color.set(name, WHITE);\n\n function dfs(name: string): string | null {\n color.set(name, GRAY);\n const schema = defs[name];\n if (schema) {\n for (const ref of collectRefsInSchema(schema)) {\n if (!color.has(ref)) continue;\n if (color.get(ref) === GRAY) return ref;\n if (color.get(ref) === WHITE) {\n const result = dfs(ref);\n if (result) return result;\n }\n }\n }\n color.set(name, BLACK);\n return null;\n }\n\n for (const name of Object.keys(defs)) {\n if (color.get(name) === WHITE) {\n const cycle = dfs(name);\n if (cycle) return cycle;\n }\n }\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// 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\nfunction nullableType(baseType: string, nullable: boolean): string | string[] {\n return nullable ? [baseType, 'null'] : baseType;\n}\n\nfunction appendToDescription(result: AnthropicSchema, text: string): void {\n result.description = result.description\n ? `${result.description} ${text}`\n : text;\n}\n\nconst METADATA_KNOWN_KEYS = new Set(['title', 'label', 'name', 'description']);\n\nfunction applyMetadata(result: AnthropicSchema, schema: JTDSchemaJson): void {\n const meta = schema.metadata as Record<string, unknown> | undefined;\n if (!meta) return;\n\n const descParts: string[] = [];\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\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 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 Anthropic 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): AnthropicSchema {\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: UNSTRUCTURED_DESC };\n }\n\n // Unstructured \u2192 string\n if (isUnstructuredSchema(schema)) {\n const result: AnthropicSchema = {\n type: nullableType('string', schema.nullable === true),\n description: UNSTRUCTURED_DESC\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;\n if (!defs?.[refName]) {\n throw new Error(`Unresolved ref \"${refName}\"`);\n }\n if (isNullable) {\n const result: AnthropicSchema = {\n anyOf: [{ $ref: `#/$defs/${refName}` }, { type: 'null' }]\n };\n applyMetadata(result, schema);\n return result;\n }\n return { $ref: `#/$defs/${refName}` };\n }\n\n // Type form \u2014 Anthropic doesn't support min/max, so bounds go in description\n if (schema.type) {\n const result: AnthropicSchema = {};\n let boundsDesc: string | undefined;\n\n const intBounds =\n INTEGER_BOUNDS[schema.type as keyof typeof INTEGER_BOUNDS];\n if (intBounds) {\n result.type = nullableType('integer', isNullable);\n boundsDesc = `Value range: [${intBounds.minimum}, ${intBounds.maximum}].`;\n } else\n switch (schema.type) {\n case 'boolean':\n result.type = nullableType('boolean', isNullable);\n break;\n case 'string':\n result.type = nullableType('string', isNullable);\n break;\n case 'timestamp':\n result.type = nullableType('string', isNullable);\n result.format = 'date-time';\n break;\n case 'float32':\n result.type = nullableType('number', isNullable);\n boundsDesc = `Value range: [${FLOAT32_BOUNDS.minimum}, ${FLOAT32_BOUNDS.maximum}].`;\n break;\n case 'float64':\n result.type = nullableType('number', isNullable);\n break;\n default:\n throw new Error(`Unknown JTD type \"${schema.type}\"`);\n }\n\n applyMetadata(result, schema);\n if (boundsDesc) appendToDescription(result, boundsDesc);\n return result;\n }\n\n // Enum form\n if (schema.enum) {\n const result: AnthropicSchema = {\n type: nullableType('string', isNullable),\n enum: isNullable ? [...schema.enum, null] : schema.enum\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Elements form\n if (schema.elements) {\n const result: AnthropicSchema = {\n type: nullableType('array', isNullable),\n items: convertNode(schema.elements, defs, depth + 1)\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Properties form \u2014 optional properties stay optional (not in required)\n if (schema.properties || schema.optionalProperties) {\n const props: Record<string, AnthropicSchema> = {};\n const required: string[] = [];\n\n if (schema.properties) {\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n props[key] = convertNode(propSchema, defs, depth + 1);\n required.push(key);\n }\n }\n\n if (schema.optionalProperties) {\n for (const [key, propSchema] of Object.entries(\n schema.optionalProperties\n )) {\n props[key] = convertNode(propSchema, defs, depth + 1);\n // NOT added to required \u2014 genuinely optional\n }\n }\n\n const result: AnthropicSchema = {\n type: nullableType('object', isNullable),\n properties: props,\n additionalProperties: false\n };\n\n if (required.length > 0) {\n result.required = required;\n }\n\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(schema.values, defs, depth + 1);\n const result: AnthropicSchema = {\n type: nullableType('array', isNullable),\n description: VALUES_ARRAY_DESC,\n items: {\n type: 'object',\n properties: {\n key: { type: 'string', description: 'The property name.' },\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 const for discriminator\n if (schema.discriminator && schema.mapping) {\n const discKey = schema.discriminator;\n const mapping = schema.mapping;\n const variants: AnthropicSchema[] = [];\n\n for (const [tag, variantSchema] of Object.entries(mapping)) {\n let variantOut: AnthropicSchema;\n\n if (isUnstructuredSchema(variantSchema)) {\n variantOut = {\n type: 'object',\n properties: {\n [discKey]: { const: tag },\n _data: {\n type: 'string',\n description: UNSTRUCTURED_VARIANT_DESC\n }\n },\n required: [discKey, '_data'],\n additionalProperties: false\n };\n } else {\n variantOut = convertNode(variantSchema, defs, depth + 1);\n // Per RFC 8927, mapping values are always properties form,\n // and the discriminator tag never appears in variant properties.\n variantOut.properties![discKey] = { const: tag };\n (variantOut.required ??= []).unshift(discKey);\n variantOut.additionalProperties = false;\n }\n\n applyMetadata(variantOut, variantSchema);\n variants.push(variantOut);\n }\n\n if (isNullable) variants.push({ type: 'null' });\n const result: AnthropicSchema = { anyOf: variants };\n applyMetadata(result, schema);\n return result;\n }\n\n // Fallback\n return { type: 'string', description: UNSTRUCTURED_DESC };\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 (Anthropic 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\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 // Unstructured \u2014 parse JSON string\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)) {\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 const elemSchema = schema.elements;\n return value.map((item) => coerceToJTD(item, elemSchema, defs, depth + 1));\n }\n\n // Properties form \u2014 no null-stripping needed (optionals are genuinely optional)\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(obj[k], propSchema, defs, 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(obj[k], propSchema, defs, depth + 1);\n }\n }\n }\n\n return obj;\n }\n\n // Values form \u2014 array of {key, value} \u2192 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(rec.value, schema.values, defs, depth + 1);\n }\n }\n return result;\n }\n\n // Discriminator form \u2014 flat object, coerce variant fields\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;\n const tag = rec[discKey];\n if (typeof tag !== 'string') return value;\n const variantSchema = schema.mapping[tag];\n\n if (!variantSchema) return value;\n\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 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(rec[k], propSchema, defs, depth + 1);\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) {\n result[k] = coerceToJTD(rec[k], propSchema, defs, depth + 1);\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// MIME format 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\nfunction convertMimeFormat(mimeType: string): AnthropicSchema {\n return {\n type: 'string',\n description: `Base64-encoded binary content (MIME type: ${mimeType}).`\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// 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 * Converts JTD schemas or Adapt signal descriptors into Anthropic-compatible\n * JSON Schema, and converts raw LLM output back into validated data.\n *\n * ### JTD form mapping\n * - **type** -- mapped to the corresponding JSON Schema `type` (`string`,\n * `number`, `integer`, `boolean`). Integer sub-types (int8 .. uint32)\n * have their bounds described in `description` (Anthropic does not\n * support `minimum`/`maximum`). `timestamp` becomes `string` with\n * `format: \"date-time\"`.\n * - **enum** -- mapped to `type: \"string\"` with an `enum` array.\n * - **elements** -- mapped to `type: \"array\"` with `items`.\n * - **properties / optionalProperties** -- mapped to `type: \"object\"` with\n * `properties`, `required`, and `additionalProperties: false`. Unlike\n * OpenAI, **optional properties are kept genuinely optional** -- they are\n * not added to the `required` array. This avoids forced nullability.\n * - **values** -- mapped to an array of `{key, value}` objects because\n * Anthropic does not support `additionalProperties` with a schema value.\n * During {@link convert}, the array is coerced back into a plain `Record`.\n * - **discriminator** -- mapped to `anyOf` with one variant per mapping\n * entry. Each variant is a flat object containing the discriminator key\n * (with a `const` value) plus the variant's own properties.\n *\n * ### Unstructured schemas\n * Empty JTD schemas or schemas with only `additionalProperties: true` are\n * considered unstructured. They produce an empty `{}` JSON Schema with\n * `strict: false`, and during {@link convert} the raw string output is\n * parsed via `JSON.parse` back into an arbitrary value.\n *\n * ### MIME formats\n * MIME signal formats become `type: \"string\"` with a description requesting\n * base64-encoded content. On {@link convert}, the base64 string is decoded\n * into a {@link ConvertSuccessBinary} result.\n *\n * ### Circular references\n * Anthropic does not support recursive schemas. {@link fromJTD} will throw\n * if any circular reference is detected among the JTD definitions.\n *\n * ### Serialization\n * `JSON.stringify(conv)` produces a JSON-safe object via {@link toJSON}.\n * Use {@link fromJSON} to restore a fully functional instance from the\n * serialized form (string or parsed object).\n *\n * ```ts\n * const conv = AnthropicConversion.fromJTD(jtdSchema);\n * conv.schema; // Anthropic JSON Schema to pass to the LLM\n * conv.strict; // whether strict mode applies\n * conv.convert(output); // coerce + validate -> ConvertResult\n *\n * // Serialize & restore\n * const cached = JSON.stringify(conv);\n * const restored = AnthropicConversion.fromJSON(cached);\n * ```\n */\nexport class AnthropicConversion {\n /** The Anthropic-specific JSON Schema to pass to the Anthropic API as the tool input schema. */\n readonly schema: AnthropicSchema;\n /**\n * Whether the schema qualifies for Anthropic strict structured-output mode.\n *\n * This is `false` when the root JTD schema is empty or unstructured (e.g.\n * the empty schema `{}` or a properties form with no real properties and\n * `additionalProperties: true`). In that case `schema` is `{}` and the\n * model output is unconstrained.\n */\n readonly strict: boolean;\n /**\n * The original JTD schema used to build this conversion.\n * Set when created via {@link fromJTD}; `undefined` when created via {@link fromSignal}.\n */\n readonly jtdSchema?: JTDSchemaJson;\n /**\n * The original signal descriptor used to build this conversion.\n * Set when created via {@link fromSignal}; `undefined` when created via {@link fromJTD}.\n */\n readonly descriptor?: SignalDescriptorJson;\n\n // \u2500\u2500 Factories \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Build a conversion from a JTD schema.\n *\n * Recursively converts every JTD form into the equivalent Anthropic JSON\n * Schema node. Definitions (`jtdSchema.definitions`) are emitted as `$defs`\n * at the root level, and references become `$ref` pointers.\n *\n * If the root schema is unstructured, the result has an empty `schema` and\n * `strict: false`.\n *\n * @param jtdSchema - A valid JTD schema (RFC 8927).\n * @returns A new {@link AnthropicConversion} with `jtdSchema` set.\n * @throws If the schema contains an unknown JTD type, an unresolved `ref`,\n * nesting exceeding 32 levels, or **any circular reference** among\n * definitions (Anthropic does not support recursive schemas).\n */\n static fromJTD(jtdSchema: JTDSchemaJson): AnthropicConversion {\n const defs = jtdSchema.definitions;\n\n // Anthropic does not support recursive schemas \u2014 detect and throw\n if (defs && Object.keys(defs).length > 0) {\n const cycleNode = detectCircularRefs(defs);\n if (cycleNode) {\n throw new Error(\n `Anthropic structured output does not support recursive schemas. Definition \"${cycleNode}\" contains a circular reference.`\n );\n }\n }\n\n const strict = !isRootUnstructured(jtdSchema, defs);\n\n let schema: AnthropicSchema;\n if (strict) {\n schema = convertNode(jtdSchema, defs, 0);\n\n if (defs && Object.keys(defs).length > 0) {\n schema.$defs = Object.fromEntries(\n Object.entries(defs).map(([name, defSchema]) => [\n name,\n convertNode(defSchema, defs, 0)\n ])\n );\n }\n } else {\n schema = {};\n applyMetadata(schema, jtdSchema);\n }\n\n return new AnthropicConversion(schema, strict, jtdSchema, undefined);\n }\n\n /**\n * Build a conversion from an Adapt signal descriptor.\n *\n * If the descriptor has a single format, its schema is used directly\n * (unwrapped). If it has multiple formats, a wrapper object schema is\n * produced with `format_0`, `format_1`, ... properties. Unlike OpenAI,\n * the format properties are genuinely optional (not listed in `required`),\n * so the LLM only needs to provide the one it chooses.\n *\n * @param descriptor - An Adapt signal descriptor with one or more formats.\n * @returns A new {@link AnthropicConversion} with `descriptor` set.\n * @throws If the descriptor has no formats, or a format has neither\n * `jtdSchema` nor `mimeType`.\n */\n static fromSignal(descriptor: SignalDescriptorJson): AnthropicConversion {\n const { schema, strict } = buildSignalSchema(descriptor);\n return new AnthropicConversion(schema, strict, undefined, descriptor);\n }\n\n /**\n * Restore an {@link AnthropicConversion} from its serialized form.\n *\n * Accepts either the JSON string produced by `JSON.stringify(conv)` or the\n * already-parsed plain object. The original `jtdSchema` or `descriptor` is\n * re-processed through the corresponding factory, so the restored instance\n * is fully functional.\n *\n * @param data - A JSON string or parsed object previously produced by {@link toJSON}.\n * @returns A fully reconstructed {@link AnthropicConversion}.\n * @throws If the serialized data contains neither `jtdSchema` nor `descriptor`.\n */\n static fromJSON(data: string | Record<string, unknown>): AnthropicConversion {\n const parsed = typeof data === 'string' ? JSON.parse(data) : data;\n if (parsed.descriptor) {\n return AnthropicConversion.fromSignal(\n parsed.descriptor as SignalDescriptorJson\n );\n }\n if (parsed.jtdSchema) {\n return AnthropicConversion.fromJTD(parsed.jtdSchema as JTDSchemaJson);\n }\n throw new Error('Cannot deserialize: missing jtdSchema or descriptor');\n }\n\n // \u2500\u2500 Constructor (private) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private constructor(\n schema: AnthropicSchema,\n strict: boolean,\n jtdSchema: JTDSchemaJson | undefined,\n descriptor: SignalDescriptorJson | undefined\n ) {\n this.schema = schema;\n this.strict = strict;\n this.jtdSchema = jtdSchema;\n this.descriptor = descriptor;\n }\n\n // \u2500\u2500 Convert \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Convert raw LLM output into a validated result.\n *\n * For JTD-based conversions, the value is coerced to conform to the original\n * JTD schema:\n * - Non-integer numbers are rounded for integer types.\n * - `{key, value}` arrays from the values form are reassembled into Records.\n * - Unstructured/empty schemas parse the raw JSON string via `JSON.parse`.\n *\n * Unlike OpenAI, no null-stripping is needed for optional properties because\n * Anthropic keeps them genuinely optional (not in `required`).\n *\n * The coerced value is then validated against the JTD schema. Returns\n * {@link ConvertSuccessJson} on success.\n *\n * For MIME-based conversions, the value is expected to be a base64 string\n * which is decoded into raw bytes. Returns {@link ConvertSuccessBinary}.\n *\n * For multi-format signals, the first non-null `format_N` property is\n * selected and converted individually.\n *\n * @param json - The raw value returned by the Anthropic API (typically parsed JSON).\n * @returns A {@link ConvertResult} indicating success or failure with errors.\n */\n convert = (json: unknown): ConvertResult => {\n if (this.jtdSchema) {\n return convertJTDOutput(this.jtdSchema, json);\n }\n if (this.descriptor) {\n return convertSignalOutput(this.descriptor, json);\n }\n return { success: false, errors: ['No source schema available'] };\n };\n\n // \u2500\u2500 Serialization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Produce a JSON-serializable representation of this conversion.\n *\n * The output includes the Anthropic `schema`, `strict` flag, and either the\n * original `jtdSchema` or `descriptor` (whichever was used to create this\n * instance), which is sufficient to fully restore the conversion via\n * {@link fromJSON}.\n *\n * Called automatically by `JSON.stringify(conv)`.\n */\n toJSON() {\n if (this.descriptor) {\n return {\n schema: this.schema,\n strict: this.strict,\n descriptor: this.descriptor\n };\n }\n return {\n schema: this.schema,\n strict: this.strict,\n jtdSchema: this.jtdSchema\n };\n }\n}\n\n// \u2500\u2500 Convert helpers (stateless, used by the class) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction convertJTDOutput(\n jtdSchema: JTDSchemaJson,\n json: unknown\n): ConvertResult {\n const defs = jtdSchema.definitions;\n const coerced = coerceToJTD(json, jtdSchema, defs, 0);\n const errors = validateJsonAgainstJTD(jtdSchema, coerced, defs);\n if (errors.length > 0) return { success: false, errors };\n return { success: true, kind: 'json', data: coerced };\n}\n\nfunction convertMimeOutput(mimeType: string, json: unknown): ConvertResult {\n if (typeof json !== 'string') {\n return {\n success: false,\n errors: [\n `/: expected base64 string for MIME type ${mimeType}, got ${typeof json}`\n ]\n };\n }\n return {\n success: true,\n kind: 'binary',\n mimeType,\n data: new Uint8Array(Buffer.from(json, 'base64'))\n };\n}\n\nfunction convertSingleFormatOutput(\n fmt: SignalFormatJson,\n json: unknown\n): ConvertResult {\n if (fmt.mimeType) return convertMimeOutput(fmt.mimeType, json);\n if (fmt.jtdSchema) return convertJTDOutput(fmt.jtdSchema, json);\n return {\n success: false,\n errors: ['Signal format has neither jtdSchema nor mimeType']\n };\n}\n\nfunction convertSignalOutput(\n descriptor: SignalDescriptorJson,\n json: unknown\n): ConvertResult {\n const formats = descriptor.formats as SignalFormatJson[] | undefined;\n if (!formats || formats.length === 0) {\n return { success: false, errors: ['Signal descriptor has no formats'] };\n }\n\n // Single format\n if (formats.length === 1) {\n return convertSingleFormatOutput(formats[0], json);\n }\n\n // Multi-format\n if (typeof json !== 'object' || json === null) {\n return {\n success: false,\n errors: [`/: expected object with format properties, got ${typeof json}`]\n };\n }\n\n const rec = json as Record<string, unknown>;\n for (let i = 0; i < formats.length; i++) {\n const key = `format_${i}`;\n if (rec[key] !== undefined && rec[key] !== null) {\n return convertSingleFormatOutput(formats[i], rec[key]);\n }\n }\n\n if (descriptor.optional) {\n return { success: true, kind: 'json', data: null };\n }\n\n const keys = formats.map((_, i) => `format_${i}`);\n return {\n success: false,\n errors: [\n `Signal '${descriptor.name ?? 'unnamed'}' is required but no format was provided. Set exactly one of: ${keys.join(', ')}.`\n ]\n };\n}\n\n// \u2500\u2500 Signal schema builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction buildSignalSchema(descriptor: SignalDescriptorJson): {\n schema: AnthropicSchema;\n strict: boolean;\n} {\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 if (formats.length === 1) {\n const [fmt] = formats;\n const { schema, strict } = buildFormatSchema(fmt);\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 schema.description = schema.description\n ? `${newDesc} ${schema.description}`\n : newDesc;\n }\n return { schema, strict };\n }\n\n // Multi-format wrapper\n const wrapperProps: Record<string, AnthropicSchema> = {};\n for (const [i, fmt] of formats.entries()) {\n const { schema: fmtSchema } = buildFormatSchema(fmt);\n if (fmt.jtdSchema) {\n fmtSchema.description = fmtSchema.description\n ? `Structured JSON data. ${fmtSchema.description}`\n : 'Structured JSON data.';\n }\n // Anthropic: format_N schemas are NOT wrapped with makeNullable\n wrapperProps[`format_${i}`] = fmtSchema;\n }\n\n const keys = Object.keys(wrapperProps);\n const baseDesc = descriptor.description ?? '';\n const guidance = descriptor.optional\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: AnthropicSchema = {\n type: 'object',\n description: baseDesc ? `${baseDesc} ${guidance}` : guidance,\n properties: wrapperProps,\n additionalProperties: false\n // Anthropic: No required array \u2014 all format props are genuinely optional\n };\n\n return { schema, strict: true };\n}\n\nfunction buildFormatSchema(fmt: SignalFormatJson): {\n schema: AnthropicSchema;\n strict: boolean;\n} {\n if (fmt.jtdSchema) {\n const conv = AnthropicConversion.fromJTD(fmt.jtdSchema);\n return { schema: conv.schema, strict: conv.strict };\n }\n if (fmt.mimeType) {\n return { schema: convertMimeFormat(fmt.mimeType), strict: true };\n }\n throw new Error('Signal format has neither jtdSchema nor mimeType');\n}\n\n// \u2500\u2500 Convenience aliases \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Convenience alias for {@link AnthropicConversion.fromJTD}.\n *\n * @param jtdSchema - A valid JTD schema (RFC 8927).\n * @returns A new {@link AnthropicConversion}.\n */\nexport function convertToAnthropicSchema(\n jtdSchema: JTDSchemaJson\n): AnthropicConversion {\n return AnthropicConversion.fromJTD(jtdSchema);\n}\n\n/**\n * Convenience alias for {@link AnthropicConversion.fromSignal}.\n *\n * @param descriptor - An Adapt signal descriptor.\n * @returns A new {@link AnthropicConversion}.\n */\nexport function convertSignalToAnthropicSchema(\n descriptor: SignalDescriptorJson\n): AnthropicConversion {\n return AnthropicConversion.fromSignal(descriptor);\n}\n", "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"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// 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/**\n * JSON Schema subset accepted by the Anthropic structured-output API.\n *\n * This is the provider-specific representation produced by\n * {@link AnthropicConversion}. It covers the keywords that Anthropic\n * inspects when constraining model output: `type`, `properties`, `required`,\n * `additionalProperties`, `enum`, `const`, `format`, `items`, `anyOf`,\n * `$defs`, `$ref`, and `description`.\n */\nexport interface AnthropicSchema {\n type?: string | string[];\n description?: string;\n properties?: Record<string, AnthropicSchema>;\n required?: string[];\n additionalProperties?: false;\n enum?: (string | number | boolean | null)[];\n const?: string | number | boolean | null;\n format?: string;\n items?: AnthropicSchema;\n anyOf?: AnthropicSchema[];\n $defs?: Record<string, AnthropicSchema>;\n $ref?: string;\n}\n\n/**\n * Successful conversion result for a JTD format.\n *\n * Returned when the raw LLM output has been coerced to match the JTD schema\n * and passes JTD validation. `data` contains the deserialized, coerced, and\n * JTD-validated JSON value.\n */\nexport interface ConvertSuccessJson {\n success: true;\n kind: 'json';\n /** The deserialized, coerced, and JTD-validated JSON value. */\n data: unknown;\n}\n\n/**\n * Successful conversion result for a MIME (binary) format.\n *\n * Returned when the raw LLM output matches a MIME format. The base64 string\n * produced by the model is decoded into raw binary bytes.\n */\nexport interface ConvertSuccessBinary {\n success: true;\n kind: 'binary';\n /** The concrete MIME type of the binary content (e.g. `\"image/png\"`). */\n mimeType: string;\n /** The raw binary data decoded from the base64 string returned by the LLM. */\n data: Uint8Array;\n /** Optional filename, provided by the caller if available. */\n filename?: string;\n}\n\n/**\n * Failed conversion result.\n *\n * `errors` contains one or more human-readable strings describing validation\n * or coercion failures. Each entry uses a JSON Pointer path prefix\n * (e.g. `\"/foo/bar: ...\"`) to locate the problem within the data.\n */\nexport interface ConvertFailure {\n success: false;\n /** Array of human-readable error messages with JSON Pointer path prefixes. */\n errors: string[];\n}\n\n/**\n * Discriminated union of conversion outcomes.\n *\n * Check `success` first, then narrow on `kind` (`'json'` or `'binary'`)\n * for successful results.\n */\nexport type ConvertResult =\n | ConvertSuccessJson\n | ConvertSuccessBinary\n | ConvertFailure;\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 UNSTRUCTURED_DESC =\n 'Must be a valid JSON value encoded as a string. ' +\n \"For objects: '{\\\"key\\\": \\\"value\\\"}', for arrays: '[1, 2]', for primitives: '\\\"hello\\\"' or '42' or 'true' or 'null'.\";\n\nconst UNSTRUCTURED_VARIANT_DESC =\n 'The variant data encoded as a valid JSON string ' +\n '(e.g. \\'{\"key\": \"value\"}\\').';\n\nconst VALUES_ARRAY_DESC =\n 'Array of key-value entries representing a map/dictionary. ' +\n \"Each entry has a string 'key' (the property name) and a 'value' (the property value).\";\n\nconst INTEGER_BOUNDS = {\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} satisfies Record<string, { minimum: number; maximum: number }>;\n\nconst FLOAT32_BOUNDS = {\n minimum: -3.4028235e38,\n maximum: 3.4028235e38\n} satisfies { minimum: number; maximum: number };\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 if (\n (schema.properties !== undefined ||\n schema.optionalProperties !== undefined) &&\n schema.additionalProperties === true\n ) {\n return true;\n }\n\n if (\n schema.properties !== undefined ||\n schema.optionalProperties !== undefined\n ) {\n return false;\n }\n\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];\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// \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\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// Circular ref detection (Anthropic does not support recursive 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\nfunction collectRefsInSchema(schema: JTDSchemaJson): string[] {\n const refs: string[] = [];\n if (!schema || typeof schema !== 'object') return refs;\n if (schema.ref) refs.push(schema.ref);\n if (schema.properties) {\n for (const v of Object.values(schema.properties)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n if (schema.optionalProperties) {\n for (const v of Object.values(schema.optionalProperties)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n if (schema.elements) refs.push(...collectRefsInSchema(schema.elements));\n if (schema.values) refs.push(...collectRefsInSchema(schema.values));\n if (schema.mapping) {\n for (const v of Object.values(schema.mapping)) {\n refs.push(...collectRefsInSchema(v));\n }\n }\n return refs;\n}\n\n/**\n * Detect circular references in JTD definitions.\n * Returns the name of a definition involved in a cycle, or null if acyclic.\n */\nfunction detectCircularRefs(\n defs: Record<string, JTDSchemaJson>\n): string | null {\n const WHITE = 0,\n GRAY = 1,\n BLACK = 2;\n const color = new Map<string, number>();\n for (const name of Object.keys(defs)) color.set(name, WHITE);\n\n function dfs(name: string): string | null {\n color.set(name, GRAY);\n const schema = defs[name];\n if (schema) {\n for (const ref of collectRefsInSchema(schema)) {\n if (!color.has(ref)) continue;\n if (color.get(ref) === GRAY) return ref;\n if (color.get(ref) === WHITE) {\n const result = dfs(ref);\n if (result) return result;\n }\n }\n }\n color.set(name, BLACK);\n return null;\n }\n\n for (const name of Object.keys(defs)) {\n if (color.get(name) === WHITE) {\n const cycle = dfs(name);\n if (cycle) return cycle;\n }\n }\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// 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\nfunction nullableType(baseType: string, nullable: boolean): string | string[] {\n return nullable ? [baseType, 'null'] : baseType;\n}\n\nfunction appendToDescription(result: AnthropicSchema, text: string): void {\n result.description = result.description\n ? `${result.description} ${text}`\n : text;\n}\n\nconst METADATA_KNOWN_KEYS = new Set(['title', 'label', 'name', 'description']);\n\nfunction applyMetadata(result: AnthropicSchema, schema: JTDSchemaJson): void {\n const meta = schema.metadata as Record<string, unknown> | undefined;\n if (!meta) return;\n\n const descParts: string[] = [];\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\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 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 Anthropic 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): AnthropicSchema {\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: UNSTRUCTURED_DESC };\n }\n\n // Unstructured \u2192 string\n if (isUnstructuredSchema(schema)) {\n const result: AnthropicSchema = {\n type: nullableType('string', schema.nullable === true),\n description: UNSTRUCTURED_DESC\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;\n if (!defs?.[refName]) {\n throw new Error(`Unresolved ref \"${refName}\"`);\n }\n if (isNullable) {\n const result: AnthropicSchema = {\n anyOf: [{ $ref: `#/$defs/${refName}` }, { type: 'null' }]\n };\n applyMetadata(result, schema);\n return result;\n }\n return { $ref: `#/$defs/${refName}` };\n }\n\n // Type form \u2014 Anthropic doesn't support min/max, so bounds go in description\n if (schema.type) {\n const result: AnthropicSchema = {};\n let boundsDesc: string | undefined;\n\n const intBounds =\n INTEGER_BOUNDS[schema.type as keyof typeof INTEGER_BOUNDS];\n if (intBounds) {\n result.type = nullableType('integer', isNullable);\n boundsDesc = `Value range: [${intBounds.minimum}, ${intBounds.maximum}].`;\n } else\n switch (schema.type) {\n case 'boolean':\n result.type = nullableType('boolean', isNullable);\n break;\n case 'string':\n result.type = nullableType('string', isNullable);\n break;\n case 'timestamp':\n result.type = nullableType('string', isNullable);\n result.format = 'date-time';\n break;\n case 'float32':\n result.type = nullableType('number', isNullable);\n boundsDesc = `Value range: [${FLOAT32_BOUNDS.minimum}, ${FLOAT32_BOUNDS.maximum}].`;\n break;\n case 'float64':\n result.type = nullableType('number', isNullable);\n break;\n default:\n throw new Error(`Unknown JTD type \"${schema.type}\"`);\n }\n\n applyMetadata(result, schema);\n if (boundsDesc) appendToDescription(result, boundsDesc);\n return result;\n }\n\n // Enum form\n if (schema.enum) {\n const result: AnthropicSchema = {\n type: nullableType('string', isNullable),\n enum: isNullable ? [...schema.enum, null] : schema.enum\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Elements form\n if (schema.elements) {\n const result: AnthropicSchema = {\n type: nullableType('array', isNullable),\n items: convertNode(schema.elements, defs, depth + 1)\n };\n applyMetadata(result, schema);\n return result;\n }\n\n // Properties form \u2014 optional properties stay optional (not in required)\n if (schema.properties || schema.optionalProperties) {\n const props: Record<string, AnthropicSchema> = {};\n const required: string[] = [];\n\n if (schema.properties) {\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n props[key] = convertNode(propSchema, defs, depth + 1);\n required.push(key);\n }\n }\n\n if (schema.optionalProperties) {\n for (const [key, propSchema] of Object.entries(\n schema.optionalProperties\n )) {\n props[key] = convertNode(propSchema, defs, depth + 1);\n // NOT added to required \u2014 genuinely optional\n }\n }\n\n const result: AnthropicSchema = {\n type: nullableType('object', isNullable),\n properties: props,\n additionalProperties: false\n };\n\n if (required.length > 0) {\n result.required = required;\n }\n\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(schema.values, defs, depth + 1);\n const result: AnthropicSchema = {\n type: nullableType('array', isNullable),\n description: VALUES_ARRAY_DESC,\n items: {\n type: 'object',\n properties: {\n key: { type: 'string', description: 'The property name.' },\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 const for discriminator\n if (schema.discriminator && schema.mapping) {\n const discKey = schema.discriminator;\n const mapping = schema.mapping;\n const variants: AnthropicSchema[] = [];\n\n for (const [tag, variantSchema] of Object.entries(mapping)) {\n let variantOut: AnthropicSchema;\n\n if (isUnstructuredSchema(variantSchema)) {\n variantOut = {\n type: 'object',\n properties: {\n [discKey]: { const: tag },\n _data: {\n type: 'string',\n description: UNSTRUCTURED_VARIANT_DESC\n }\n },\n required: [discKey, '_data'],\n additionalProperties: false\n };\n } else {\n variantOut = convertNode(variantSchema, defs, depth + 1);\n // Per RFC 8927, mapping values are always properties form,\n // and the discriminator tag never appears in variant properties.\n variantOut.properties![discKey] = { const: tag };\n (variantOut.required ??= []).unshift(discKey);\n variantOut.additionalProperties = false;\n }\n\n applyMetadata(variantOut, variantSchema);\n variants.push(variantOut);\n }\n\n if (isNullable) variants.push({ type: 'null' });\n const result: AnthropicSchema = { anyOf: variants };\n applyMetadata(result, schema);\n return result;\n }\n\n // Fallback\n return { type: 'string', description: UNSTRUCTURED_DESC };\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 (Anthropic 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\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 // Unstructured \u2014 parse JSON string\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)) {\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 const elemSchema = schema.elements;\n return value.map((item) => coerceToJTD(item, elemSchema, defs, depth + 1));\n }\n\n // Properties form \u2014 no null-stripping needed (optionals are genuinely optional)\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(obj[k], propSchema, defs, 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(obj[k], propSchema, defs, depth + 1);\n }\n }\n }\n\n return obj;\n }\n\n // Values form \u2014 array of {key, value} \u2192 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(rec.value, schema.values, defs, depth + 1);\n }\n }\n return result;\n }\n\n // Discriminator form \u2014 flat object, coerce variant fields\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;\n const tag = rec[discKey];\n if (typeof tag !== 'string') return value;\n const variantSchema = schema.mapping[tag];\n\n if (!variantSchema) return value;\n\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 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(rec[k], propSchema, defs, depth + 1);\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) {\n result[k] = coerceToJTD(rec[k], propSchema, defs, depth + 1);\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// MIME format 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\nfunction convertMimeFormat(mimeType: string): AnthropicSchema {\n return {\n type: 'object',\n description: `Binary content (MIME type: ${mimeType}).`,\n properties: {\n data: {\n type: 'string',\n description: `The base64-encoded binary content (MIME type: ${mimeType}).`\n },\n filename: {\n type: 'string',\n description:\n 'Optional filename for the binary content (e.g. \"report.pdf\", \"image.png\").'\n }\n },\n required: ['data'],\n additionalProperties: false\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// 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 * Converts JTD schemas or Adapt signal descriptors into Anthropic-compatible\n * JSON Schema, and converts raw LLM output back into validated data.\n *\n * ### JTD form mapping\n * - **type** -- mapped to the corresponding JSON Schema `type` (`string`,\n * `number`, `integer`, `boolean`). Integer sub-types (int8 .. uint32)\n * have their bounds described in `description` (Anthropic does not\n * support `minimum`/`maximum`). `timestamp` becomes `string` with\n * `format: \"date-time\"`.\n * - **enum** -- mapped to `type: \"string\"` with an `enum` array.\n * - **elements** -- mapped to `type: \"array\"` with `items`.\n * - **properties / optionalProperties** -- mapped to `type: \"object\"` with\n * `properties`, `required`, and `additionalProperties: false`. Unlike\n * OpenAI, **optional properties are kept genuinely optional** -- they are\n * not added to the `required` array. This avoids forced nullability.\n * - **values** -- mapped to an array of `{key, value}` objects because\n * Anthropic does not support `additionalProperties` with a schema value.\n * During {@link convert}, the array is coerced back into a plain `Record`.\n * - **discriminator** -- mapped to `anyOf` with one variant per mapping\n * entry. Each variant is a flat object containing the discriminator key\n * (with a `const` value) plus the variant's own properties.\n *\n * ### Unstructured schemas\n * Empty JTD schemas or schemas with only `additionalProperties: true` are\n * considered unstructured. They produce an empty `{}` JSON Schema with\n * `strict: false`, and during {@link convert} the raw string output is\n * parsed via `JSON.parse` back into an arbitrary value.\n *\n * ### MIME formats\n * MIME signal formats become `type: \"string\"` with a description requesting\n * base64-encoded content. On {@link convert}, the base64 string is decoded\n * into a {@link ConvertSuccessBinary} result.\n *\n * ### Circular references\n * Anthropic does not support recursive schemas. {@link fromJTD} will throw\n * if any circular reference is detected among the JTD definitions.\n *\n * ### Serialization\n * `JSON.stringify(conv)` produces a JSON-safe object via {@link toJSON}.\n * Use {@link fromJSON} to restore a fully functional instance from the\n * serialized form (string or parsed object).\n *\n * ```ts\n * const conv = AnthropicConversion.fromJTD(jtdSchema);\n * conv.schema; // Anthropic JSON Schema to pass to the LLM\n * conv.strict; // whether strict mode applies\n * conv.convert(output); // coerce + validate -> ConvertResult\n *\n * // Serialize & restore\n * const cached = JSON.stringify(conv);\n * const restored = AnthropicConversion.fromJSON(cached);\n * ```\n */\nexport class AnthropicConversion {\n /** The Anthropic-specific JSON Schema to pass to the Anthropic API as the tool input schema. */\n readonly schema: AnthropicSchema;\n /**\n * Whether the schema qualifies for Anthropic strict structured-output mode.\n *\n * This is `false` when the root JTD schema is empty or unstructured (e.g.\n * the empty schema `{}` or a properties form with no real properties and\n * `additionalProperties: true`). In that case `schema` is `{}` and the\n * model output is unconstrained.\n */\n readonly strict: boolean;\n /**\n * The original JTD schema used to build this conversion.\n * Set when created via {@link fromJTD}; `undefined` when created via {@link fromSignal}.\n */\n readonly jtdSchema?: JTDSchemaJson;\n /**\n * The original signal descriptor used to build this conversion.\n * Set when created via {@link fromSignal}; `undefined` when created via {@link fromJTD}.\n */\n readonly descriptor?: SignalDescriptorJson;\n\n // \u2500\u2500 Factories \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Build a conversion from a JTD schema.\n *\n * Recursively converts every JTD form into the equivalent Anthropic JSON\n * Schema node. Definitions (`jtdSchema.definitions`) are emitted as `$defs`\n * at the root level, and references become `$ref` pointers.\n *\n * If the root schema is unstructured, the result has an empty `schema` and\n * `strict: false`.\n *\n * @param jtdSchema - A valid JTD schema (RFC 8927).\n * @returns A new {@link AnthropicConversion} with `jtdSchema` set.\n * @throws If the schema contains an unknown JTD type, an unresolved `ref`,\n * nesting exceeding 32 levels, or **any circular reference** among\n * definitions (Anthropic does not support recursive schemas).\n */\n static fromJTD(jtdSchema: JTDSchemaJson): AnthropicConversion {\n const defs = jtdSchema.definitions;\n\n // Anthropic does not support recursive schemas \u2014 detect and throw\n if (defs && Object.keys(defs).length > 0) {\n const cycleNode = detectCircularRefs(defs);\n if (cycleNode) {\n throw new Error(\n `Anthropic structured output does not support recursive schemas. Definition \"${cycleNode}\" contains a circular reference.`\n );\n }\n }\n\n const strict = !isRootUnstructured(jtdSchema, defs);\n\n let schema: AnthropicSchema;\n if (strict) {\n schema = convertNode(jtdSchema, defs, 0);\n\n if (defs && Object.keys(defs).length > 0) {\n schema.$defs = Object.fromEntries(\n Object.entries(defs).map(([name, defSchema]) => [\n name,\n convertNode(defSchema, defs, 0)\n ])\n );\n }\n } else {\n schema = {};\n applyMetadata(schema, jtdSchema);\n }\n\n return new AnthropicConversion(schema, strict, jtdSchema, undefined);\n }\n\n /**\n * Build a conversion from an Adapt signal descriptor.\n *\n * If the descriptor has a single format, its schema is used directly\n * (unwrapped). If it has multiple formats, a wrapper object schema is\n * produced with `format_0`, `format_1`, ... properties. Unlike OpenAI,\n * the format properties are genuinely optional (not listed in `required`),\n * so the LLM only needs to provide the one it chooses.\n *\n * @param descriptor - An Adapt signal descriptor with one or more formats.\n * @returns A new {@link AnthropicConversion} with `descriptor` set.\n * @throws If the descriptor has no formats, or a format has neither\n * `jtdSchema` nor `mimeType`.\n */\n static fromSignal(descriptor: SignalDescriptorJson): AnthropicConversion {\n const { schema, strict } = buildSignalSchema(descriptor);\n return new AnthropicConversion(schema, strict, undefined, descriptor);\n }\n\n /**\n * Restore an {@link AnthropicConversion} from its serialized form.\n *\n * Accepts either the JSON string produced by `JSON.stringify(conv)` or the\n * already-parsed plain object. The original `jtdSchema` or `descriptor` is\n * re-processed through the corresponding factory, so the restored instance\n * is fully functional.\n *\n * @param data - A JSON string or parsed object previously produced by {@link toJSON}.\n * @returns A fully reconstructed {@link AnthropicConversion}.\n * @throws If the serialized data contains neither `jtdSchema` nor `descriptor`.\n */\n static fromJSON(data: string | Record<string, unknown>): AnthropicConversion {\n const parsed = typeof data === 'string' ? JSON.parse(data) : data;\n if (parsed.descriptor) {\n return AnthropicConversion.fromSignal(\n parsed.descriptor as SignalDescriptorJson\n );\n }\n if (parsed.jtdSchema) {\n return AnthropicConversion.fromJTD(parsed.jtdSchema as JTDSchemaJson);\n }\n throw new Error('Cannot deserialize: missing jtdSchema or descriptor');\n }\n\n // \u2500\u2500 Constructor (private) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private constructor(\n schema: AnthropicSchema,\n strict: boolean,\n jtdSchema: JTDSchemaJson | undefined,\n descriptor: SignalDescriptorJson | undefined\n ) {\n this.schema = schema;\n this.strict = strict;\n this.jtdSchema = jtdSchema;\n this.descriptor = descriptor;\n }\n\n // \u2500\u2500 Convert \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Convert raw LLM output into a validated result.\n *\n * For JTD-based conversions, the value is coerced to conform to the original\n * JTD schema:\n * - Non-integer numbers are rounded for integer types.\n * - `{key, value}` arrays from the values form are reassembled into Records.\n * - Unstructured/empty schemas parse the raw JSON string via `JSON.parse`.\n *\n * Unlike OpenAI, no null-stripping is needed for optional properties because\n * Anthropic keeps them genuinely optional (not in `required`).\n *\n * The coerced value is then validated against the JTD schema. Returns\n * {@link ConvertSuccessJson} on success.\n *\n * For MIME-based conversions, the value is expected to be a base64 string\n * which is decoded into raw bytes. Returns {@link ConvertSuccessBinary}.\n *\n * For multi-format signals, the first non-null `format_N` property is\n * selected and converted individually.\n *\n * @param json - The raw value returned by the Anthropic API (typically parsed JSON).\n * @returns A {@link ConvertResult} indicating success or failure with errors.\n */\n convert = (json: unknown): ConvertResult => {\n if (this.jtdSchema) {\n return convertJTDOutput(this.jtdSchema, json);\n }\n if (this.descriptor) {\n return convertSignalOutput(this.descriptor, json);\n }\n return { success: false, errors: ['No source schema available'] };\n };\n\n // \u2500\u2500 Serialization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Produce a JSON-serializable representation of this conversion.\n *\n * The output includes the Anthropic `schema`, `strict` flag, and either the\n * original `jtdSchema` or `descriptor` (whichever was used to create this\n * instance), which is sufficient to fully restore the conversion via\n * {@link fromJSON}.\n *\n * Called automatically by `JSON.stringify(conv)`.\n */\n toJSON() {\n if (this.descriptor) {\n return {\n schema: this.schema,\n strict: this.strict,\n descriptor: this.descriptor\n };\n }\n return {\n schema: this.schema,\n strict: this.strict,\n jtdSchema: this.jtdSchema\n };\n }\n}\n\n// \u2500\u2500 Convert helpers (stateless, used by the class) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction convertJTDOutput(\n jtdSchema: JTDSchemaJson,\n json: unknown\n): ConvertResult {\n const defs = jtdSchema.definitions;\n const coerced = coerceToJTD(json, jtdSchema, defs, 0);\n const errors = validateJsonAgainstJTD(jtdSchema, coerced, defs);\n if (errors.length > 0) return { success: false, errors };\n return { success: true, kind: 'json', data: coerced };\n}\n\nfunction convertMimeOutput(mimeType: string, json: unknown): ConvertResult {\n if (typeof json !== 'object' || json === null) {\n return {\n success: false,\n errors: [\n `/: expected object with 'data' field for MIME type ${mimeType}, got ${typeof json}`\n ]\n };\n }\n const rec = json as Record<string, unknown>;\n if (typeof rec.data !== 'string') {\n return {\n success: false,\n errors: [\n `/data: expected base64 string for MIME type ${mimeType}, got ${typeof rec.data}`\n ]\n };\n }\n const result: ConvertSuccessBinary = {\n success: true,\n kind: 'binary',\n mimeType,\n data: new Uint8Array(Buffer.from(rec.data, 'base64'))\n };\n if (typeof rec.filename === 'string' && rec.filename) {\n result.filename = rec.filename;\n }\n return result;\n}\n\nfunction convertSingleFormatOutput(\n fmt: SignalFormatJson,\n json: unknown\n): ConvertResult {\n if (fmt.mimeType) return convertMimeOutput(fmt.mimeType, json);\n if (fmt.jtdSchema) return convertJTDOutput(fmt.jtdSchema, json);\n return {\n success: false,\n errors: ['Signal format has neither jtdSchema nor mimeType']\n };\n}\n\nfunction convertSignalOutput(\n descriptor: SignalDescriptorJson,\n json: unknown\n): ConvertResult {\n const formats = descriptor.formats as SignalFormatJson[] | undefined;\n if (!formats || formats.length === 0) {\n return { success: false, errors: ['Signal descriptor has no formats'] };\n }\n\n // Single format\n if (formats.length === 1) {\n return convertSingleFormatOutput(formats[0], json);\n }\n\n // Multi-format\n if (typeof json !== 'object' || json === null) {\n return {\n success: false,\n errors: [`/: expected object with format properties, got ${typeof json}`]\n };\n }\n\n const rec = json as Record<string, unknown>;\n for (let i = 0; i < formats.length; i++) {\n const key = `format_${i}`;\n if (rec[key] !== undefined && rec[key] !== null) {\n return convertSingleFormatOutput(formats[i], rec[key]);\n }\n }\n\n if (descriptor.optional) {\n return { success: true, kind: 'json', data: null };\n }\n\n const keys = formats.map((_, i) => `format_${i}`);\n return {\n success: false,\n errors: [\n `Signal '${descriptor.name ?? 'unnamed'}' is required but no format was provided. Set exactly one of: ${keys.join(', ')}.`\n ]\n };\n}\n\n// \u2500\u2500 Signal schema builder \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction buildSignalSchema(descriptor: SignalDescriptorJson): {\n schema: AnthropicSchema;\n strict: boolean;\n} {\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 if (formats.length === 1) {\n const [fmt] = formats;\n const { schema, strict } = buildFormatSchema(fmt);\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 schema.description = schema.description\n ? `${newDesc} ${schema.description}`\n : newDesc;\n }\n return { schema, strict };\n }\n\n // Multi-format wrapper\n const wrapperProps: Record<string, AnthropicSchema> = {};\n for (const [i, fmt] of formats.entries()) {\n const { schema: fmtSchema } = buildFormatSchema(fmt);\n if (fmt.jtdSchema) {\n fmtSchema.description = fmtSchema.description\n ? `Structured JSON data. ${fmtSchema.description}`\n : 'Structured JSON data.';\n }\n // Anthropic: format_N schemas are NOT wrapped with makeNullable\n wrapperProps[`format_${i}`] = fmtSchema;\n }\n\n const keys = Object.keys(wrapperProps);\n const baseDesc = descriptor.description ?? '';\n const guidance = descriptor.optional\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: AnthropicSchema = {\n type: 'object',\n description: baseDesc ? `${baseDesc} ${guidance}` : guidance,\n properties: wrapperProps,\n additionalProperties: false\n // Anthropic: No required array \u2014 all format props are genuinely optional\n };\n\n return { schema, strict: true };\n}\n\nfunction buildFormatSchema(fmt: SignalFormatJson): {\n schema: AnthropicSchema;\n strict: boolean;\n} {\n if (fmt.jtdSchema) {\n const conv = AnthropicConversion.fromJTD(fmt.jtdSchema);\n return { schema: conv.schema, strict: conv.strict };\n }\n if (fmt.mimeType) {\n return { schema: convertMimeFormat(fmt.mimeType), strict: true };\n }\n throw new Error('Signal format has neither jtdSchema nor mimeType');\n}\n\n// \u2500\u2500 Convenience aliases \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Convenience alias for {@link AnthropicConversion.fromJTD}.\n *\n * @param jtdSchema - A valid JTD schema (RFC 8927).\n * @returns A new {@link AnthropicConversion}.\n */\nexport function convertToAnthropicSchema(\n jtdSchema: JTDSchemaJson\n): AnthropicConversion {\n return AnthropicConversion.fromJTD(jtdSchema);\n}\n\n/**\n * Convenience alias for {@link AnthropicConversion.fromSignal}.\n *\n * @param descriptor - An Adapt signal descriptor.\n * @returns A new {@link AnthropicConversion}.\n */\nexport function convertSignalToAnthropicSchema(\n descriptor: SignalDescriptorJson\n): AnthropicConversion {\n return AnthropicConversion.fromSignal(descriptor);\n}\n", "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"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["anthropic_exports", "__export", "AnthropicConversion", "convertSignalToAnthropicSchema", "convertToAnthropicSchema", "__toCommonJS", "import_jtd", "INTEGER_TYPES", "formatInstancePath", "instancePath", "p", "resolveSchemaParent", "schema", "schemaPath", "current", "i", "resolveInstanceValue", "value", "key", "formatValidationError", "error", "path", "lastKey", "jtdType", "enumValues", "discValue", "validateJsonAgainstJTD", "definitions", "defs", "schemaForValidation", "jtdValidate", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "err", "MAX_VALIDATION_DEPTH", "MAX_VALIDATION_ERRORS", "MAX_REF_DEPTH", "UNSTRUCTURED_DESC", "UNSTRUCTURED_VARIANT_DESC", "VALUES_ARRAY_DESC", "INTEGER_BOUNDS", "FLOAT32_BOUNDS", "isUnstructuredSchema", "schema", "isRootUnstructured", "defs", "resolved", "depth", "target", "collectRefsInSchema", "refs", "v", "detectCircularRefs", "color", "name", "dfs", "ref", "result", "cycle", "nullableType", "baseType", "nullable", "appendToDescription", "text", "METADATA_KNOWN_KEYS", "applyMetadata", "meta", "descParts", "titleCandidate", "descText", "extras", "key", "value", "newDesc", "convertNode", "isNullable", "refName", "boundsDesc", "intBounds", "props", "required", "propSchema", "valueSchema", "discKey", "mapping", "variants", "tag", "variantSchema", "variantOut", "INTEGER_TYPE_SET", "coerceToJTD", "elemSchema", "item", "obj", "k", "entry", "rec", "dataStr", "parsed", "convertMimeFormat", "mimeType", "AnthropicConversion", "_AnthropicConversion", "jtdSchema", "cycleNode", "strict", "defSchema", "descriptor", "buildSignalSchema", "data", "json", "convertJTDOutput", "convertSignalOutput", "coerced", "errors", "validateJsonAgainstJTD", "convertMimeOutput", "convertSingleFormatOutput", "fmt", "formats", "keys", "_", "i", "buildFormatSchema", "parts", "wrapperProps", "fmtSchema", "baseDesc", "guidance", "conv", "convertToAnthropicSchema", "convertSignalToAnthropicSchema"]
|
|
7
7
|
}
|
package/dist/cjs/gemini.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var S=Object.defineProperty;var
|
|
1
|
+
"use strict";var S=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var O=(e,n)=>{for(var t in n)S(e,t,{get:n[t],enumerable:!0})},R=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of j(n))!x.call(e,r)&&r!==t&&S(e,r,{get:()=>n[r],enumerable:!(o=$(n,r))||o.enumerable});return e};var P=e=>R(S({},"__esModule",{value:!0}),e);var Y={};O(Y,{GeminiConversion:()=>y,convertSignalToGeminiSchema:()=>L,convertToGeminiSchema:()=>U});module.exports=P(Y);var d=require("jtd");var E=new Set(["int8","uint8","int16","uint16","int32","uint32"]);function A(e){return e.length===0?"/":e.map(n=>/^\d+$/.test(n)?`[${n}]`:`.${n}`).join("")}function J(e,n){let t=e;for(let o=0;o<n.length-1&&(t&&typeof t=="object"&&n[o]in t);o++)t=t[n[o]];return t}function N(e,n){let t=e;for(let o of n)if(t&&typeof t=="object")t=t[o];else return;return t}function G(e,n,t){let{instancePath:o,schemaPath:r}=e,i=A(o),s=r[r.length-1];if(s==="type"){let c=J(n,r)?.type;return c==="boolean"?`${i}: expected boolean`:c==="string"?`${i}: expected string`:c==="timestamp"?`${i}: expected timestamp string`:E.has(c)?`${i}: expected integer`:`${i}: expected number`}if(s==="enum"){let c=J(n,r)?.enum;return`${i}: expected one of [${c.join(", ")}]`}if(r.length>=2&&r[r.length-2]==="properties"&&s)return`${i==="/"?"":i}.${s}: missing required property`;if(s==="elements")return`${i}: expected array`;if(s==="properties"||s==="optionalProperties"||s==="values")return`${i}: expected object`;if(s==="discriminator")return`${i}: expected string discriminator`;if(s==="mapping"){let a=N(t,o);return`${i}: unknown variant "${a}"`}return r.length===0?`${i}: unexpected property`:`${i}: validation error at /${r.join("/")}`}function b(e,n,t){let o=t??e.definitions,r=o?{...e,definitions:o}:e;return(0,d.isValidSchema)(r)?(0,d.validate)(r,n,{maxDepth:C,maxErrors:M}).map(s=>G(s,r,n)):e.ref?[`/: unknown ref "${e.ref}"`]:["/: invalid schema"]}var C=32,M=100;var g=32,w={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}},T={minimum:-34028235e31,maximum:34028235e31};function u(e,n){return n?[e,"null"]:e}var F=new Set(["title","label","name","description"]);function p(e,n){let t=n.metadata;if(!t)return;typeof t.description=="string"&&t.description.trim()&&(e.description=t.description.trim());let o=typeof t.title=="string"&&t.title.trim()||typeof t.label=="string"&&t.label.trim()||typeof t.name=="string"&&t.name.trim();o&&(e.title=o);let r=[];for(let[i,s]of Object.entries(t))F.has(i)||(typeof s=="string"&&s.trim()?r.push(`[${i}: ${s.trim()}]`):(typeof s=="number"||typeof s=="boolean")&&r.push(`[${i}: ${s}]`));if(r.length>0){let i=r.join(" ");e.description=e.description?`${e.description} ${i}`:i}}function k(e,n,t){if(t>g)throw new Error(`Circular or excessively deep ref chain (exceeded ${g} levels)`);if(!e.ref)return e;let o=n?.[e.ref];if(!o)throw new Error(`Unresolved ref "${e.ref}"`);return k(o,n,t+1)}function f(e,n,t){if(t>g)throw new Error(`Schema nesting exceeded ${g} levels`);if(!e||typeof e!="object")return{description:"Any JSON value"};if(e.ref){let i=k(e,n,t),s=f(i,n,t+1);if(p(s,e),e.nullable){let a=s.type;s.type=Array.isArray(a)?[...a,"null"]:a?[a,"null"]:["null"]}return s}let o=e.nullable===!0,r={};if(e.type){let i=w[e.type];if(i)r.type=u("integer",o),r.minimum=i.minimum,r.maximum=i.maximum;else switch(e.type){case"boolean":r.type=u("boolean",o);break;case"string":r.type=u("string",o);break;case"timestamp":r.type=u("string",o),r.format="date-time";break;case"float32":r.type=u("number",o),r.minimum=T.minimum,r.maximum=T.maximum;break;case"float64":r.type=u("number",o);break;default:throw new Error(`Unknown JTD type "${e.type}"`)}return p(r,e),r}if(e.enum)return r.type=u("string",o),r.enum=o?[...e.enum,null]:e.enum,p(r,e),r;if(e.elements)return r.type=u("array",o),r.items=f(e.elements,n,t+1),p(r,e),r;if(e.properties||e.optionalProperties){r.type=u("object",o),r.properties={};let i=[];if(e.properties)for(let[s,a]of Object.entries(e.properties))r.properties[s]=f(a,n,t+1),i.push(s);if(e.optionalProperties)for(let[s,a]of Object.entries(e.optionalProperties))r.properties[s]=f(a,n,t+1);return i.length>0&&(r.required=i),e.additionalProperties!==!0&&(r.additionalProperties=!1),p(r,e),r}if(e.values)return r.type=u("object",o),r.additionalProperties=f(e.values,n,t+1),p(r,e),r;if(e.discriminator&&e.mapping){let i=Object.keys(e.mapping);r.type=u("object",o),r.description=`Tagged union: set '${e.discriminator}' to one of [${i.join(", ")}], then populate ONLY the property whose name matches the chosen '${e.discriminator}' value. Leave all other variant properties empty.`,r.properties={[e.discriminator]:{type:"string",enum:[...i],description:`Selects which variant to use. MUST match exactly one of: ${i.join(", ")}.`}},r.required=[e.discriminator],r.additionalProperties=!1;for(let[s,a]of Object.entries(e.mapping)){let c=f(a,n,t+1),l=`Populate ONLY when ${e.discriminator}='${s}'.`;c.description=c.description?`${c.description} \u2014 ${l}`:l,r.properties[s]=c}return p(r,e),r}return r.description="Any JSON value",p(r,e),r}var I=new Set(Object.keys(w));function m(e,n,t,o){if(o>g||e==null)return e;if(n.ref){let r=t?.[n.ref];return r?m(e,r,t,o+1):e}if(n.type&&I.has(n.type))return typeof e=="number"&&!Number.isInteger(e)?Math.round(e):e;if(n.elements&&Array.isArray(e)){let r=n.elements;return e.map(i=>m(i,r,t,o+1))}if((n.properties||n.optionalProperties)&&typeof e=="object"&&e!==null){let r={...e};if(n.properties)for(let[i,s]of Object.entries(n.properties))i in r&&(r[i]=m(r[i],s,t,o+1));if(n.optionalProperties)for(let[i,s]of Object.entries(n.optionalProperties))i in r&&(r[i]=m(r[i],s,t,o+1));return r}if(n.values&&typeof e=="object"&&e!==null){let r={};for(let[i,s]of Object.entries(e))r[i]=m(s,n.values,t,o+1);return r}if(n.discriminator&&n.mapping&&typeof e=="object"&&e!==null){let r=e,i=r[n.discriminator];if(typeof i!="string")return e;let s=n.mapping[i];if(!s||typeof r[i]!="object"||r[i]===null)return e;let a=m(r[i],s,t,o+1);return{[n.discriminator]:i,...a}}return e}var y=class e{schema;jtdSchema;descriptor;static fromJTD(n){let t=f(n,n.definitions,0);return new e(t,n,void 0)}static fromSignal(n){let t=_(n);return new e(t,void 0,n)}static fromJSON(n){let t=typeof n=="string"?JSON.parse(n):n;if(t.descriptor)return e.fromSignal(t.descriptor);if(t.jtdSchema)return e.fromJTD(t.jtdSchema);throw new Error("Cannot deserialize: missing jtdSchema or descriptor")}constructor(n,t,o){this.schema=n,this.jtdSchema=t,this.descriptor=o}convert=n=>this.jtdSchema?D(this.jtdSchema,n):this.descriptor?V(this.descriptor,n):{success:!1,errors:["No source schema available"]};toJSON(){return this.descriptor?{schema:this.schema,descriptor:this.descriptor}:{schema:this.schema,jtdSchema:this.jtdSchema}}};function D(e,n){let t=e.definitions,o=m(n,e,t,0),r=b(e,o,t);return r.length>0?{success:!1,errors:r}:{success:!0,kind:"json",data:o}}function q(e,n){if(typeof n!="object"||n===null)return{success:!1,errors:[`/: expected object with 'data' field for MIME type ${e}, got ${typeof n}`]};let t=n;if(typeof t.data!="string")return{success:!1,errors:[`/data: expected base64 string for MIME type ${e}, got ${typeof t.data}`]};let o={success:!0,kind:"binary",mimeType:e,data:new Uint8Array(Buffer.from(t.data,"base64"))};return typeof t.filename=="string"&&t.filename&&(o.filename=t.filename),o}function v(e,n){return e.mimeType?q(e.mimeType,n):e.jtdSchema?D(e.jtdSchema,n):{success:!1,errors:["Signal format has neither jtdSchema nor mimeType"]}}function V(e,n){let t=e.formats;if(!t||t.length===0)return{success:!1,errors:["Signal descriptor has no formats"]};if(t.length===1)return v(t[0],n);if(typeof n!="object"||n===null)return{success:!1,errors:[`/: expected object with format properties, got ${typeof n}`]};let o=n;for(let i=0;i<t.length;i++){let s=`format_${i}`;if(o[s]!==void 0&&o[s]!==null)return v(t[i],o[s])}if(e.optional)return{success:!0,kind:"json",data:null};let r=t.map((i,s)=>`format_${s}`);return{success:!1,errors:[`Signal '${e.name??"unnamed"}' is required but no format was provided. Set exactly one of: ${r.join(", ")}.`]}}function _(e){let n=e.formats;if(!n||n.length===0)throw new Error("Signal descriptor has no formats");if(n.length===1){let[a]=n,c=h(a);return e.label&&(c.title=e.label),e.description&&(c.description=e.description),c}let t={};for(let[a,c]of n.entries()){let l=h(c);c.jtdSchema&&(l.description=l.description?`Structured JSON data. ${l.description}`:"Structured JSON data."),t[`format_${a}`]=l}let o=Object.keys(t),r=e.description??"",i=e.optional?"Provide at most ONE of the following format properties. All are optional.":`You MUST provide exactly ONE of the following format properties: ${o.join(", ")}.`,s={type:"object",description:r?`${r} ${i}`:i,properties:t,additionalProperties:!1};return e.label&&(s.title=e.label),s}function h(e){if(e.jtdSchema)return f(e.jtdSchema,e.jtdSchema.definitions,0);if(e.mimeType)return B(e.mimeType);throw new Error("Signal format has neither jtdSchema nor mimeType")}function B(e){return{type:"object",description:`Binary content (MIME type: ${e}).`,properties:{data:{type:"string",description:`The base64-encoded binary content (MIME type: ${e}).`},filename:{type:"string",description:'Optional filename for the binary content (e.g. "report.pdf", "image.png").'}},required:["data"],additionalProperties:!1}}function U(e){return y.fromJTD(e)}function L(e){return y.fromSignal(e)}0&&(module.exports={GeminiConversion,convertSignalToGeminiSchema,convertToGeminiSchema});
|
|
2
2
|
//# sourceMappingURL=gemini.cjs.map
|