@mochabug/adapt-sdk 0.4.23 → 0.4.24
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/cel/index.d.ts +4 -0
- package/dist/cel/index.d.ts.map +1 -1
- package/dist/cjs/anthropic.cjs.map +1 -1
- package/dist/cjs/cel.cjs +3 -3
- package/dist/cjs/cel.cjs.map +4 -4
- package/dist/cjs/gemini.cjs.map +1 -1
- package/dist/cjs/openai.cjs.map +1 -1
- package/dist/cjs/signals.cjs +2 -2
- package/dist/cjs/signals.cjs.map +2 -2
- package/dist/esm/anthropic.mjs.map +1 -1
- package/dist/esm/cel.mjs +3 -3
- package/dist/esm/cel.mjs.map +4 -4
- package/dist/esm/gemini.mjs.map +1 -1
- package/dist/esm/openai.mjs.map +1 -1
- package/dist/esm/signals.mjs +1 -1
- package/dist/esm/signals.mjs.map +2 -2
- package/package.json +1 -1
package/dist/esm/cel.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/cel/index.ts", "../../src/signals/index.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n celFunc,\n celMethod,\n run as celRun,\n CelScalar,\n isCelError,\n isCelList,\n isCelMap,\n isCelUint,\n listType,\n objectType,\n type CelFunc as CelFuncType,\n type CelInput,\n type CelValue\n} from '@bufbuild/cel';\nimport { strings as stringsExt } from '@bufbuild/cel/ext';\nimport {\n timestampDate,\n timestampFromDate,\n timestampMs,\n timestampNow,\n TimestampSchema,\n type Timestamp\n} from '@bufbuild/protobuf/wkt';\nimport type { ReflectMessage } from '@bufbuild/protobuf/reflect';\nimport type { JTDSchemaJson, SignalBindingJson } from '../api';\nimport { fuzzJTD } 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// HELPERS (internal)\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 toNumber(val: unknown): number | null {\n if (typeof val === 'number') return val;\n if (typeof val === 'bigint') return Number(val);\n if (isCelUint(val)) return Number(val.value);\n return null;\n}\n\nfunction celEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n const aVal = isCelUint(a) ? a.value : a;\n const bVal = isCelUint(b) ? b.value : b;\n return aVal === bVal;\n}\n\nfunction isBytes(val: unknown): val is Uint8Array {\n return (\n val instanceof Uint8Array ||\n (ArrayBuffer.isView(val) && !(val instanceof DataView))\n );\n}\n\nfunction toUint8Array(val: unknown): Uint8Array {\n if (val instanceof Uint8Array) return val;\n if (ArrayBuffer.isView(val))\n return new Uint8Array(val.buffer, val.byteOffset, val.byteLength);\n return val as Uint8Array;\n}\n\n// The CEL runtime uses `instanceof Uint8Array` to recognize bytes values.\n// In jsdom environments (vitest), TextEncoder.encode() returns a Node-native\n// Uint8Array from a different realm, which fails `instanceof` against the\n// jsdom Uint8Array. Re-wrapping forces the current realm's constructor.\nfunction wrapBytes(data: Uint8Array): Uint8Array {\n return new Uint8Array(data);\n}\n\n// Platform capability \u2014 resolved once at module load\nconst _hasBuffer = typeof Buffer !== 'undefined';\n\n// Base64: Node Buffer > Uint8Array.fromBase64/toBase64 (TC39) > atob/btoa fallback\nconst base64Decode: (base64: string) => Uint8Array = (() => {\n if (_hasBuffer) {\n return (s: string) => Buffer.from(s, 'base64');\n }\n if (typeof (Uint8Array as any).fromBase64 === 'function') {\n return (s: string) => (Uint8Array as any).fromBase64(s);\n }\n return (s: string) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0));\n})();\n\nconst base64Encode: (bytes: Uint8Array) => string = (() => {\n if (_hasBuffer) {\n return (b: Uint8Array) =>\n Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString('base64');\n }\n if (typeof (Uint8Array.prototype as any).toBase64 === 'function') {\n return (b: Uint8Array) => (b as any).toBase64();\n }\n return (b: Uint8Array) =>\n btoa(Array.from(b, (byte) => String.fromCharCode(byte)).join(''));\n})();\n\nfunction encodeImpl(val: unknown, encoding = 'utf-8'): Uint8Array {\n if (isBytes(val)) return toUint8Array(val);\n const json = JSON.stringify(celToNative(val as CelValue));\n if (encoding === 'utf-8' || encoding === 'utf8') {\n return wrapBytes(new TextEncoder().encode(json));\n }\n // Node: Buffer handles all encodings natively\n if (_hasBuffer) {\n return new Uint8Array(Buffer.from(json, encoding as BufferEncoding));\n }\n // Browser fallback: charCodeAt only covers single-byte encodings (latin1, ascii)\n return Uint8Array.from(json, (c) => c.charCodeAt(0));\n}\n\nfunction decodeImpl(data: unknown, encoding = 'utf-8'): unknown {\n const bytes = toUint8Array(data);\n return JSON.parse(new TextDecoder(encoding).decode(bytes));\n}\n\nfunction htmlEscapeImpl(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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// CEL RUNTIME: Custom Functions\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 LIST_DYN = listType(CelScalar.DYN);\nconst { DYN, BOOL, INT } = CelScalar;\n\n/**\n * Format a timestamp using a pattern string.\n *\n * Supported patterns:\n * - YYYY - 4-digit year\n * - YY - 2-digit year\n * - MM - month (01-12)\n * - DD - day (01-31)\n * - HH - hours (00-23)\n * - mm - minutes (00-59)\n * - ss - seconds (00-59)\n */\nexport function formatDateWithPattern(\n timestamp: Date,\n pattern: string\n): string {\n const y = timestamp.getFullYear();\n const m = timestamp.getMonth() + 1;\n const d = timestamp.getDate();\n const H = timestamp.getHours();\n const min = timestamp.getMinutes();\n const s = timestamp.getSeconds();\n\n return pattern\n .replace(/YYYY/g, String(y))\n .replace(/YY/g, String(y).slice(-2))\n .replace(/MM/g, String(m).padStart(2, '0'))\n .replace(/DD/g, String(d).padStart(2, '0'))\n .replace(/HH/g, String(H).padStart(2, '0'))\n .replace(/mm/g, String(min).padStart(2, '0'))\n .replace(/ss/g, String(s).padStart(2, '0'));\n}\n\n/** Union of all custom CelFunc definitions across all plugins. */\nexport const CUSTOM_FUNCS: CelFuncType[] = [\n // \u2500\u2500 Aggregate: sum \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('sum', [LIST_DYN], DYN, (list) => {\n let total = 0;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null) total += n;\n }\n return total;\n }),\n celMethod('sum', LIST_DYN, [], DYN, function () {\n let total = 0;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null) total += n;\n }\n return total;\n }),\n\n // \u2500\u2500 Aggregate: min \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('min', [LIST_DYN], DYN, (list) => {\n let result: number | null = null;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null && (result === null || n < result)) result = n;\n }\n return result ?? 0;\n }),\n celMethod('min', LIST_DYN, [], DYN, function () {\n let result: number | null = null;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null && (result === null || n < result)) result = n;\n }\n return result ?? 0;\n }),\n\n // \u2500\u2500 Aggregate: max \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('max', [LIST_DYN], DYN, (list) => {\n let result: number | null = null;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null && (result === null || n > result)) result = n;\n }\n return result ?? 0;\n }),\n celMethod('max', LIST_DYN, [], DYN, function () {\n let result: number | null = null;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null && (result === null || n > result)) result = n;\n }\n return result ?? 0;\n }),\n\n // \u2500\u2500 Aggregate: avg \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('avg', [LIST_DYN], DYN, (list) => {\n let total = 0;\n let count = 0;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null) {\n total += n;\n count++;\n }\n }\n return count > 0 ? total / count : 0;\n }),\n celMethod('avg', LIST_DYN, [], DYN, function () {\n let total = 0;\n let count = 0;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null) {\n total += n;\n count++;\n }\n }\n return count > 0 ? total / count : 0;\n }),\n\n // \u2500\u2500 Search: includes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('includes', [LIST_DYN, DYN], BOOL, (list, element) => {\n for (const item of list) {\n if (celEqual(item, element)) return true;\n }\n return false;\n }),\n celMethod('includes', LIST_DYN, [DYN], BOOL, function (element) {\n for (const item of this) {\n if (celEqual(item, element)) return true;\n }\n return false;\n }),\n\n // \u2500\u2500 Search: findIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('findIndex', [LIST_DYN, DYN], INT, (list, element) => {\n let index = 0n;\n for (const item of list) {\n if (celEqual(item, element)) return index;\n index++;\n }\n return -1n;\n }),\n celMethod('findIndex', LIST_DYN, [DYN], INT, function (element) {\n let index = 0n;\n for (const item of this) {\n if (celEqual(item, element)) return index;\n index++;\n }\n return -1n;\n }),\n\n // \u2500\u2500 Search: findLastIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('findLastIndex', [LIST_DYN, DYN], INT, (list, element) => {\n const arr = [...list];\n for (let i = arr.length - 1; i >= 0; i--) {\n if (celEqual(arr[i], element)) return BigInt(i);\n }\n return -1n;\n }),\n celMethod('findLastIndex', LIST_DYN, [DYN], INT, function (element) {\n const arr = [...this];\n for (let i = arr.length - 1; i >= 0; i--) {\n if (celEqual(arr[i], element)) return BigInt(i);\n }\n return -1n;\n }),\n\n // \u2500\u2500 Utilities \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('now', [], objectType(TimestampSchema), () => timestampNow()),\n celFunc('lower', [CelScalar.STRING], CelScalar.STRING, (s) =>\n s.toLowerCase()\n ),\n celFunc('upper', [CelScalar.STRING], CelScalar.STRING, (s) =>\n s.toUpperCase()\n ),\n celMethod('lower', CelScalar.STRING, [], CelScalar.STRING, function () {\n return (this as unknown as string).toLowerCase();\n }),\n celMethod('upper', CelScalar.STRING, [], CelScalar.STRING, function () {\n return (this as unknown as string).toUpperCase();\n }),\n\n // \u2500\u2500 Encoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('base64decode', [CelScalar.STRING], DYN, (s) => base64Decode(s)),\n celFunc('base64encode', [DYN], CelScalar.STRING, (data) =>\n base64Encode(toUint8Array(data))\n ),\n celFunc('encode', [DYN], DYN, (val) => encodeImpl(val)),\n celFunc('encode', [DYN, CelScalar.STRING], DYN, (val, enc) =>\n encodeImpl(val, enc)\n ),\n celFunc('decode', [DYN], DYN, (data) => decodeImpl(data) as CelValue),\n celFunc(\n 'decode',\n [DYN, CelScalar.STRING],\n DYN,\n (data, enc) => decodeImpl(data, enc) as CelValue\n ),\n\n // \u2500\u2500 HTML escaping (native implementation, no `he` dependency) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n celFunc('htmlEscape', [CelScalar.STRING], CelScalar.STRING, (s) =>\n htmlEscapeImpl(s)\n ),\n celFunc('attrEscape', [CelScalar.STRING], CelScalar.STRING, (s) =>\n htmlEscapeImpl(s)\n ),\n\n // \u2500\u2500 Date formatting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celMethod(\n 'formatDate',\n objectType(TimestampSchema),\n [CelScalar.STRING],\n CelScalar.STRING,\n function (\n this: ReflectMessage & { message: Timestamp },\n pattern: string\n ): string {\n const timestamp = this.message;\n const ms =\n Number(timestamp.seconds) * 1000 +\n Math.floor(timestamp.nanos / 1000000);\n const date = new Date(ms);\n return formatDateWithPattern(date, pattern);\n }\n )\n];\n\n/** Ready-to-use options: strings extension + all custom funcs. */\nexport const celOptions = {\n funcs: [...stringsExt, ...CUSTOM_FUNCS]\n};\n\n/** Convert CEL types to native JS (CelList\u2192array, CelMap\u2192object, bigint\u2192number). */\nexport function celToNative(value: CelValue): unknown {\n if (isCelList(value)) {\n return [...value].map((item) => celToNative(item as CelValue));\n }\n if (isCelMap(value)) {\n const obj: Record<string, unknown> = {};\n for (const [k, v] of value) {\n obj[String(k)] = celToNative(v as CelValue);\n }\n return obj;\n }\n if (typeof value === 'bigint') {\n return Number(value);\n }\n return value;\n}\n\n// Re-export types from @bufbuild/cel that plugins commonly need\nexport type { CelFuncType, CelInput, CelValue };\nexport {\n celRun,\n isCelError,\n celFunc,\n celMethod,\n CelScalar,\n objectType,\n listType,\n isCelList,\n isCelMap,\n isCelUint\n};\nexport {\n stringsExt,\n timestampDate,\n timestampFromDate,\n timestampMs,\n timestampNow,\n TimestampSchema\n};\n\n// Re-export fuzzJTD from jtd module for convenience\nexport { fuzzJTD } 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// CEL EXPRESSION VALIDATION\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 allowed CEL expression length (characters). */\nconst MAX_EXPRESSION_LENGTH = 10_000;\n\nexport interface CelVariable {\n name: string;\n schema: JTDSchemaJson;\n optional?: boolean;\n}\n\nexport interface AccessPath {\n variableName: string;\n path: string[];\n fullPath: string;\n}\n\nexport interface OptionalityInfo {\n segmentIndex: number;\n propertyName: string;\n isSignalOptional: boolean;\n}\n\nexport interface ValidationError {\n message: string;\n path?: string;\n isOptionalAccess?: boolean;\n}\n\nexport type ValidationResult =\n | { valid: true }\n | { valid: false; errors: ValidationError[] };\n\n/**\n * Extract all access paths for known variables from a CEL expression.\n * Handles both dot notation (var.a.b) and bracket notation (var[\"a\"]).\n */\nexport function extractAccessPaths(\n expression: string,\n variableNames: string[]\n): AccessPath[] {\n // Filter out empty/whitespace-only variable names (would match every position in the regex)\n const validNames = variableNames.filter(\n (n) => n.length > 0 && /^\\w+$/.test(n)\n );\n if (validNames.length === 0) return [];\n\n const paths: AccessPath[] = [];\n const escapedNames = validNames.map((n) =>\n n.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const namesPattern = escapedNames.join('|');\n\n // Match variable with dot/bracket access, OR bare variable reference\n const regex = new RegExp(\n `\\\\b(${namesPattern})(?:(?:\\\\.([a-zA-Z_]\\\\w*)|\\\\[\"([^\"]+)\"\\\\]|\\\\['([^']+)'\\\\])|(?=$|[^a-zA-Z_0-9.\\\\[]))`,\n 'g'\n );\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(expression)) !== null) {\n const varName = match[1]!;\n const firstProp = match[2] || match[3] || match[4];\n\n if (!firstProp) {\n // Bare variable reference (e.g., just `filename`)\n paths.push({ variableName: varName, path: [], fullPath: varName });\n continue;\n }\n\n const pathParts = [firstProp];\n let pos = match.index + match[0].length;\n\n while (pos < expression.length) {\n const dotMatch = expression.slice(pos).match(/^\\.([a-zA-Z_]\\w*)/);\n if (dotMatch) {\n const nextPos = pos + dotMatch[0].length;\n if (expression[nextPos] === '(') break;\n pathParts.push(dotMatch[1]!);\n pos = nextPos;\n continue;\n }\n const bracketMatch = expression\n .slice(pos)\n .match(/^\\[\"([^\"]+)\"\\]|^\\['([^']+)'\\]/);\n if (bracketMatch) {\n pathParts.push(bracketMatch[1] || bracketMatch[2]!);\n pos += bracketMatch[0].length;\n continue;\n }\n break;\n }\n\n const fullPath = varName + '.' + pathParts.join('.');\n paths.push({ variableName: varName, path: pathParts, fullPath });\n }\n\n return deduplicateAccessPaths(paths);\n}\n\nfunction deduplicateAccessPaths(paths: AccessPath[]): AccessPath[] {\n const byVariable = new Map<string, AccessPath[]>();\n for (const path of paths) {\n const existing = byVariable.get(path.variableName) || [];\n existing.push(path);\n byVariable.set(path.variableName, existing);\n }\n\n const result: AccessPath[] = [];\n for (const [, variablePaths] of byVariable) {\n variablePaths.sort((a, b) => b.path.length - a.path.length);\n const kept: AccessPath[] = [];\n for (const candidate of variablePaths) {\n const isPrefix = kept.some((k) => isPathPrefix(candidate, k));\n if (!isPrefix) kept.push(candidate);\n }\n result.push(...kept);\n }\n return result;\n}\n\nfunction isPathPrefix(pathA: AccessPath, pathB: AccessPath): boolean {\n if (pathA.variableName !== pathB.variableName) return false;\n if (pathA.path.length > pathB.path.length) return false;\n for (let i = 0; i < pathA.path.length; i++) {\n if (pathA.path[i] !== pathB.path[i]) return false;\n }\n return true;\n}\n\n/** Find which segments in the path are optional according to the schema. */\nexport function findOptionalSegments(\n path: string[],\n schema: JTDSchemaJson | undefined,\n isSignalOptional: boolean\n): OptionalityInfo[] {\n const optionals: OptionalityInfo[] = [];\n if (isSignalOptional) {\n optionals.push({\n segmentIndex: -1,\n propertyName: '',\n isSignalOptional: true\n });\n }\n if (!schema || path.length === 0) return optionals;\n\n let currentSchema: JTDSchemaJson | undefined = schema;\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]!;\n if (!currentSchema) break;\n\n const optProps: Record<string, JTDSchemaJson> | undefined =\n currentSchema.optionalProperties;\n const reqProps: Record<string, JTDSchemaJson> | undefined =\n currentSchema.properties;\n\n if (optProps && segment in optProps) {\n optionals.push({\n segmentIndex: i,\n propertyName: segment,\n isSignalOptional: false\n });\n currentSchema = optProps[segment];\n } else if (reqProps && segment in reqProps) {\n currentSchema = reqProps[segment];\n } else {\n break;\n }\n }\n return optionals;\n}\n\n/** Generate test permutations for validating optional property access. */\nexport function generateTestPermutations(\n variables: CelVariable[],\n accessedPaths: AccessPath[]\n): {\n bindings: Record<string, unknown>;\n description: string;\n unsetPath?: string;\n}[] {\n const permutations: {\n bindings: Record<string, unknown>;\n description: string;\n unsetPath?: string;\n }[] = [];\n\n const allBindings: Record<string, unknown> = {};\n for (const v of variables) {\n allBindings[v.name] = fuzzJTD(v.schema, v.schema.definitions);\n }\n permutations.push({\n bindings: allBindings,\n description: 'All properties present'\n });\n\n for (const accessPath of accessedPaths) {\n const variable = variables.find((v) => v.name === accessPath.variableName);\n if (!variable) continue;\n\n const optionalSegments = findOptionalSegments(\n accessPath.path,\n variable.schema,\n variable.optional ?? false\n );\n\n for (const opt of optionalSegments) {\n const testBindings: Record<string, unknown> =\n structuredClone(allBindings);\n\n if (opt.isSignalOptional && opt.segmentIndex === -1) {\n delete testBindings[accessPath.variableName];\n permutations.push({\n bindings: testBindings,\n description: `Variable '${accessPath.variableName}' not bound`,\n unsetPath: accessPath.variableName\n });\n } else {\n const pathToUnset = accessPath.path.slice(0, opt.segmentIndex + 1);\n unsetNestedProperty(testBindings[accessPath.variableName], pathToUnset);\n const unsetPathStr = `${accessPath.variableName}.${pathToUnset.join('.')}`;\n permutations.push({\n bindings: testBindings,\n description: `Optional property '${opt.propertyName}' unset`,\n unsetPath: unsetPathStr\n });\n }\n }\n }\n\n return permutations;\n}\n\nfunction unsetNestedProperty(obj: unknown, path: string[]): void {\n if (path.length === 0 || obj === null || typeof obj !== 'object') return;\n let current: unknown = obj;\n for (let i = 0; i < path.length - 1; i++) {\n if (current === null || typeof current !== 'object') return;\n current = (current as Record<string, unknown>)[path[i]!];\n }\n if (current !== null && typeof current === 'object') {\n delete (current as Record<string, unknown>)[path[path.length - 1]!];\n }\n}\n\n/**\n * Evaluate a CEL expression with given bindings and return the result.\n * Generic version \u2014 callers provide their own binding context.\n */\nexport function evaluateExpression(\n expression: string,\n bindings: Record<string, unknown>\n): { result: unknown; error?: never } | { result?: never; error: string } {\n if (expression.length > MAX_EXPRESSION_LENGTH) {\n return {\n error: `Expression exceeds maximum length of ${MAX_EXPRESSION_LENGTH} characters`\n };\n }\n try {\n const celBindings: Record<string, CelInput> = {};\n for (const [k, v] of Object.entries(bindings)) {\n celBindings[k] = v as CelInput;\n }\n const result = celRun(expression, celBindings, celOptions);\n if (isCelError(result)) {\n return { error: result.message };\n }\n return { result: celToNative(result as CelValue) };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { error: message };\n }\n}\n\n/**\n * Validate a CEL expression with exhaustive testing of optional properties.\n * Each CelVariable becomes a top-level binding in the CEL environment.\n */\nexport function validateCelExpression(\n expression: string,\n variables: CelVariable[]\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (!expression.trim()) return { valid: true };\n\n // Step 1: Build bindings and syntax-check\n const bindings: Record<string, unknown> = {};\n for (const v of variables) {\n bindings[v.name] = fuzzJTD(v.schema, v.schema.definitions);\n }\n\n const syntaxCheck = evaluateExpression(expression, bindings);\n if (syntaxCheck.error) {\n return {\n valid: false,\n errors: [{ message: `Syntax error: ${syntaxCheck.error}` }]\n };\n }\n\n // Step 2: Extract accessed paths\n const variableNames = variables.map((v) => v.name);\n const accessedPaths = extractAccessPaths(expression, variableNames);\n if (accessedPaths.length === 0) return { valid: true };\n\n // Step 3: Generate test permutations\n const permutations = generateTestPermutations(variables, accessedPaths);\n\n // Step 4: Test each permutation (skip base case)\n for (let i = 1; i < permutations.length; i++) {\n const perm = permutations[i]!;\n const testResult = evaluateExpression(expression, perm.bindings);\n\n if (testResult.error) {\n errors.push({\n message: `Expression fails when ${perm.description}: ${testResult.error}`,\n path: perm.unsetPath,\n isOptionalAccess: true\n });\n }\n }\n\n return errors.length > 0 ? { valid: false, errors } : { valid: true };\n}\n\n/** Quick validation that only checks syntax, without optional property testing. */\nexport function validateCelExpressionSyntax(\n expression: string,\n variables: CelVariable[]\n): ValidationResult {\n if (!expression.trim()) return { valid: true };\n\n const bindings: Record<string, unknown> = {};\n for (const v of variables) {\n bindings[v.name] = fuzzJTD(v.schema, v.schema.definitions);\n }\n\n const result = evaluateExpression(expression, bindings);\n if (result.error) {\n return { valid: false, errors: [{ message: result.error }] };\n }\n return { valid: true };\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 LANGUAGE DEFINITION\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 CEL_LANGUAGE_ID = 'cel';\n\nexport interface FuncDescriptor {\n name: string;\n detail: string;\n documentation: string;\n params: string[];\n}\n\nexport interface MethodDescriptor extends FuncDescriptor {\n receiverType: string;\n}\n\n/** All global function descriptors (union of all plugins). */\nexport const GLOBAL_FUNCTIONS: FuncDescriptor[] = [\n // Type conversions (std/cast)\n {\n name: 'string',\n detail: 'string(x) \u2192 string',\n documentation:\n 'Convert value to string. Works on bool, int, uint, double, bytes, timestamp, duration.',\n params: ['x']\n },\n {\n name: 'int',\n detail: 'int(x) \u2192 int',\n documentation:\n 'Convert value to integer. Works on uint, double, string, timestamp, duration.',\n params: ['x']\n },\n {\n name: 'uint',\n detail: 'uint(x) \u2192 uint',\n documentation:\n 'Convert value to unsigned integer. Works on int, double, string.',\n params: ['x']\n },\n {\n name: 'double',\n detail: 'double(x) \u2192 double',\n documentation: 'Convert value to double. Works on int, uint, string.',\n params: ['x']\n },\n {\n name: 'bool',\n detail: 'bool(x) \u2192 bool',\n documentation:\n 'Convert value to boolean. String values: \"true\", \"false\", \"t\", \"f\", \"1\", \"0\".',\n params: ['x']\n },\n {\n name: 'bytes',\n detail: 'bytes(x) \u2192 bytes',\n documentation: 'Convert value to bytes. String is UTF-8 encoded.',\n params: ['x']\n },\n {\n name: 'timestamp',\n detail: 'timestamp(x) \u2192 timestamp',\n documentation: 'Convert value to timestamp. String must be RFC3339 format.',\n params: ['x']\n },\n {\n name: 'duration',\n detail: 'duration(x) \u2192 duration',\n documentation:\n 'Convert value to duration. String format: \"300s\", \"1.5h\", \"2m30s\".',\n params: ['x']\n },\n {\n name: 'type',\n detail: 'type(x) \u2192 type',\n documentation: 'Returns the type of the value.',\n params: ['x']\n },\n {\n name: 'dyn',\n detail: 'dyn(x) \u2192 dyn',\n documentation: 'Identity function, returns the value unchanged.',\n params: ['x']\n },\n\n // Collection/logic (std)\n {\n name: 'size',\n detail: 'size(x) \u2192 int',\n documentation: 'Returns size of string (codepoints), list, bytes, or map.',\n params: ['x']\n },\n {\n name: 'has',\n detail: 'has(x.field) \u2192 bool',\n documentation:\n 'Check if field exists and is not null. Use to guard optional values.',\n params: ['x.field']\n },\n\n // Date/time\n {\n name: 'now',\n detail: 'now() \u2192 timestamp',\n documentation: 'Returns the current timestamp.',\n params: []\n },\n\n // String functions (ext/strings)\n {\n name: 'strings.quote',\n detail: 'strings.quote(s) \u2192 string',\n documentation: 'Returns a quoted string with escape sequences.',\n params: ['s']\n },\n\n // Aggregate functions\n {\n name: 'sum',\n detail: 'sum(list) \u2192 number',\n documentation: 'Sum of numeric list elements.',\n params: ['list']\n },\n {\n name: 'min',\n detail: 'min(list) \u2192 number',\n documentation: 'Minimum value in a numeric list.',\n params: ['list']\n },\n {\n name: 'max',\n detail: 'max(list) \u2192 number',\n documentation: 'Maximum value in a numeric list.',\n params: ['list']\n },\n {\n name: 'avg',\n detail: 'avg(list) \u2192 number',\n documentation: 'Average of numeric list elements.',\n params: ['list']\n },\n {\n name: 'includes',\n detail: 'includes(list, element) \u2192 bool',\n documentation: 'True if list contains element.',\n params: ['list', 'element']\n },\n {\n name: 'findIndex',\n detail: 'findIndex(list, element) \u2192 int',\n documentation: 'Index of first occurrence, or -1.',\n params: ['list', 'element']\n },\n {\n name: 'findLastIndex',\n detail: 'findLastIndex(list, element) \u2192 int',\n documentation: 'Index of last occurrence, or -1.',\n params: ['list', 'element']\n },\n\n // String transformation\n {\n name: 'lower',\n detail: 'lower(s) \u2192 string',\n documentation: 'Full Unicode lowercase.',\n params: ['s']\n },\n {\n name: 'upper',\n detail: 'upper(s) \u2192 string',\n documentation: 'Full Unicode uppercase.',\n params: ['s']\n },\n\n // Encoding\n {\n name: 'base64decode',\n detail: 'base64decode(s) \u2192 bytes',\n documentation: 'Decode base64 string to bytes.',\n params: ['s']\n },\n {\n name: 'base64encode',\n detail: 'base64encode(data) \u2192 string',\n documentation: 'Encode bytes to base64 string.',\n params: ['data']\n },\n {\n name: 'encode',\n detail: 'encode(value, encoding?) \u2192 bytes',\n documentation:\n 'JSON-serialize any value to bytes. Default encoding: utf-8. If value is already bytes, passes through.',\n params: ['value', 'encoding']\n },\n {\n name: 'decode',\n detail: 'decode(data, encoding?) \u2192 dyn',\n documentation: 'Parse JSON bytes to a value. Default encoding: utf-8.',\n params: ['data', 'encoding']\n },\n\n // HTML escaping\n {\n name: 'htmlEscape',\n detail: 'htmlEscape(s) \u2192 string',\n documentation:\n 'HTML-encode a string for safe insertion into HTML text content.',\n params: ['s']\n },\n {\n name: 'attrEscape',\n detail: 'attrEscape(s) \u2192 string',\n documentation:\n 'HTML-encode a string for safe insertion into an HTML attribute value.',\n params: ['s']\n }\n];\n\n/** All method descriptors (deduplicated union of all plugins). */\nexport const CEL_METHODS: MethodDescriptor[] = [\n // \u2500\u2500\u2500 String methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'contains',\n detail: '.contains(substr) \u2192 bool',\n documentation: 'True if string contains substr.',\n params: ['substr'],\n receiverType: 'string'\n },\n {\n name: 'startsWith',\n detail: '.startsWith(prefix) \u2192 bool',\n documentation: 'True if string starts with prefix.',\n params: ['prefix'],\n receiverType: 'string'\n },\n {\n name: 'endsWith',\n detail: '.endsWith(suffix) \u2192 bool',\n documentation: 'True if string ends with suffix.',\n params: ['suffix'],\n receiverType: 'string'\n },\n {\n name: 'matches',\n detail: '.matches(regex) \u2192 bool',\n documentation: 'True if string matches RE2 regex pattern.',\n params: ['regex'],\n receiverType: 'string'\n },\n {\n name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Returns number of Unicode codepoints in string.',\n params: [],\n receiverType: 'string'\n },\n\n // \u2500\u2500\u2500 String methods (ext/strings) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'charAt',\n detail: '.charAt(index) \u2192 string',\n documentation: 'Returns character at index.',\n params: ['index'],\n receiverType: 'string'\n },\n {\n name: 'indexOf',\n detail: '.indexOf(substr, start?) \u2192 int',\n documentation: 'Index of first occurrence of substr, or -1 if not found.',\n params: ['substr', 'start'],\n receiverType: 'string'\n },\n {\n name: 'lastIndexOf',\n detail: '.lastIndexOf(substr, start?) \u2192 int',\n documentation: 'Index of last occurrence of substr, or -1 if not found.',\n params: ['substr', 'start'],\n receiverType: 'string'\n },\n {\n name: 'lowerAscii',\n detail: '.lowerAscii() \u2192 string',\n documentation: 'Convert ASCII letters to lowercase (A-Z only).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'upperAscii',\n detail: '.upperAscii() \u2192 string',\n documentation: 'Convert ASCII letters to uppercase (a-z only).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'replace',\n detail: '.replace(old, new, count?) \u2192 string',\n documentation:\n 'Replace occurrences of old with new. If count specified, replaces at most count times.',\n params: ['old', 'new', 'count'],\n receiverType: 'string'\n },\n {\n name: 'split',\n detail: '.split(sep, count?) \u2192 list',\n documentation:\n 'Split string by separator. If count specified, splits into at most count parts.',\n params: ['sep', 'count'],\n receiverType: 'string'\n },\n {\n name: 'substring',\n detail: '.substring(start, end?) \u2192 string',\n documentation:\n 'Extract substring from start index to end index (exclusive).',\n params: ['start', 'end'],\n receiverType: 'string'\n },\n {\n name: 'trim',\n detail: '.trim() \u2192 string',\n documentation: 'Remove leading and trailing Unicode whitespace.',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'format',\n detail: '.format(args) \u2192 string',\n documentation:\n 'Format string with arguments. Placeholders: %s (string), %d (decimal), %f (float), %e (exponent), %x (hex), %o (octal), %b (binary).',\n params: ['args'],\n receiverType: 'string'\n },\n {\n name: 'lower',\n detail: '.lower() \u2192 string',\n documentation: 'Lowercase string (full Unicode).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'upper',\n detail: '.upper() \u2192 string',\n documentation: 'Uppercase string (full Unicode).',\n params: [],\n receiverType: 'string'\n },\n\n // \u2500\u2500\u2500 List methods (ext/strings) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'join',\n detail: '.join(sep?) \u2192 string',\n documentation: 'Join list elements into string with optional separator.',\n params: ['sep'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Number of elements in list.',\n params: [],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List macros (built-in) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'map',\n detail: '.map(x, expr) \u2192 list',\n documentation: 'Transform each element using expression.',\n params: ['x', 'expr'],\n receiverType: 'list'\n },\n {\n name: 'filter',\n detail: '.filter(x, predicate) \u2192 list',\n documentation: 'Filter elements by predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'all',\n detail: '.all(x, predicate) \u2192 bool',\n documentation: 'True if all elements match predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'exists',\n detail: '.exists(x, predicate) \u2192 bool',\n documentation: 'True if any element matches predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'exists_one',\n detail: '.exists_one(x, predicate) \u2192 bool',\n documentation: 'True if exactly one element matches predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List aggregate methods (custom) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'sum',\n detail: '.sum() \u2192 number',\n documentation: 'Sum of numeric list elements.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'min',\n detail: '.min() \u2192 number',\n documentation: 'Minimum value in list.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'max',\n detail: '.max() \u2192 number',\n documentation: 'Maximum value in list.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'avg',\n detail: '.avg() \u2192 number',\n documentation: 'Average of list elements.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'includes',\n detail: '.includes(element) \u2192 bool',\n documentation: 'True if list contains element.',\n params: ['element'],\n receiverType: 'list'\n },\n {\n name: 'findIndex',\n detail: '.findIndex(element) \u2192 int',\n documentation: 'First index of element, or -1.',\n params: ['element'],\n receiverType: 'list'\n },\n {\n name: 'findLastIndex',\n detail: '.findLastIndex(element) \u2192 int',\n documentation: 'Last index of element, or -1.',\n params: ['element'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 Timestamp methods (std/time) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'getFullYear',\n detail: '.getFullYear(tz?) \u2192 int',\n documentation: '4-digit year. Optional timezone (IANA or fixed offset).',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMonth',\n detail: '.getMonth(tz?) \u2192 int',\n documentation: 'Month (0-11). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDate',\n detail: '.getDate(tz?) \u2192 int',\n documentation: 'Day of month (1-31). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfMonth',\n detail: '.getDayOfMonth(tz?) \u2192 int',\n documentation: 'Day of month (0-30). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfWeek',\n detail: '.getDayOfWeek(tz?) \u2192 int',\n documentation: 'Day of week (0=Sunday). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfYear',\n detail: '.getDayOfYear(tz?) \u2192 int',\n documentation: 'Day of year (0-365). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getHours',\n detail: '.getHours(tz?) \u2192 int',\n documentation: 'Hours (0-23). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMinutes',\n detail: '.getMinutes(tz?) \u2192 int',\n documentation: 'Minutes (0-59). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getSeconds',\n detail: '.getSeconds(tz?) \u2192 int',\n documentation: 'Seconds (0-59). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMilliseconds',\n detail: '.getMilliseconds(tz?) \u2192 int',\n documentation: 'Milliseconds (0-999). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'formatDate',\n detail: '.formatDate(pattern) \u2192 string',\n documentation: 'Format timestamp. Patterns: YYYY, YY, MM, DD, HH, mm, ss.',\n params: ['pattern'],\n receiverType: 'timestamp'\n },\n\n // \u2500\u2500\u2500 Duration methods (std/time) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'getSeconds',\n detail: '.getSeconds() \u2192 int',\n documentation: 'Total seconds in duration.',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getMinutes',\n detail: '.getMinutes() \u2192 int',\n documentation: 'Total minutes in duration (seconds / 60).',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getHours',\n detail: '.getHours() \u2192 int',\n documentation: 'Total hours in duration (seconds / 3600).',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getMilliseconds',\n detail: '.getMilliseconds() \u2192 int',\n documentation: 'Milliseconds portion of duration.',\n params: [],\n receiverType: 'duration'\n },\n\n // \u2500\u2500\u2500 Map/bytes methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Number of entries in map or bytes in buffer.',\n params: [],\n receiverType: 'map'\n }\n];\n\n/** Lookup table: function name \u2192 descriptors (for hover/signature help). */\nexport const CEL_DESCRIPTORS: Map<string, FuncDescriptor[]> = (() => {\n const map = new Map<string, FuncDescriptor[]>();\n for (const f of GLOBAL_FUNCTIONS) {\n const baseName = f.name.includes('.') ? f.name.split('.')[1]! : f.name;\n map.set(baseName, [f]);\n }\n for (const m of CEL_METHODS) {\n const existing = map.get(m.name);\n if (existing) {\n if (!existing.some((e) => e.detail === m.detail)) existing.push(m);\n } else {\n map.set(m.name, [m]);\n }\n }\n return map;\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// DYNAMIC INPUT VARIABLES (for Monaco autocompletion)\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 interface InputVariable {\n name: string;\n label?: string;\n schema?: JTDSchemaJson;\n}\n\nlet currentInputVariables: InputVariable[] = [];\n\n/** Update the available input variables for Monaco autocompletion. */\nexport function setInputVariables(inputs: InputVariable[]): void {\n currentInputVariables = inputs;\n}\n\n/** Resolve ref to its definition, passthrough otherwise. */\nfunction resolveInputSchema(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson {\n return schema.ref && defs?.[schema.ref]\n ? resolveInputSchema(defs[schema.ref]!, defs)\n : schema;\n}\n\n/** Get the root definitions from a schema (only present on root-level schemas). */\nfunction getRootDefs(\n schema: JTDSchemaJson | undefined\n): Record<string, JTDSchemaJson> | undefined {\n return schema?.definitions;\n}\n\nfunction getSchemaAtPath(\n schema: JTDSchemaJson | undefined,\n path: string[],\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson | undefined {\n if (!schema || path.length === 0) return schema;\n const resolved = resolveInputSchema(schema, defs);\n const [first, ...rest] = path;\n\n // Properties form\n const props = { ...resolved.properties, ...resolved.optionalProperties };\n if (first && props[first]) {\n return getSchemaAtPath(props[first]!, rest, defs);\n }\n\n // Discriminator form \u2014 expose union of all variant properties + discriminator tag\n if (resolved.discriminator && resolved.mapping && first) {\n if (first === resolved.discriminator) {\n // The tag itself \u2014 it's a string enum of mapping keys\n return rest.length === 0\n ? { enum: Object.keys(resolved.mapping) }\n : undefined;\n }\n // Search all variants for the property\n for (const variant of Object.values(resolved.mapping)) {\n const variantProps = {\n ...variant.properties,\n ...variant.optionalProperties\n };\n if (variantProps[first]) {\n return getSchemaAtPath(variantProps[first]!, rest, defs);\n }\n }\n }\n\n return undefined;\n}\n\nfunction describeSchemaType(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): string {\n const resolved = resolveInputSchema(schema, defs);\n if (resolved.type) return resolved.type;\n if (resolved.enum) {\n return `enum(${resolved.enum.slice(0, 3).join(', ')}${resolved.enum.length > 3 ? '...' : ''})`;\n }\n if (resolved.properties || resolved.optionalProperties) return 'object';\n if (resolved.elements) return 'list';\n if (resolved.values) return 'map';\n if (resolved.discriminator) return `union(${resolved.discriminator})`;\n return 'any';\n}\n\nfunction getSchemaProperties(\n schema: JTDSchemaJson | undefined,\n defs?: Record<string, JTDSchemaJson>\n): { name: string; type: string }[] {\n if (!schema) return [];\n const resolved = resolveInputSchema(schema, defs);\n const result: { name: string; type: string }[] = [];\n\n // Properties form\n const props = { ...resolved.properties, ...resolved.optionalProperties };\n for (const [name, propSchema] of Object.entries(props)) {\n result.push({ name, type: describeSchemaType(propSchema, defs) });\n }\n\n // Discriminator form \u2014 expose tag + union of all variant properties\n if (resolved.discriminator && resolved.mapping) {\n const tags = Object.keys(resolved.mapping);\n result.push({ name: resolved.discriminator, type: tags.join(' | ') });\n const seen = new Set<string>([resolved.discriminator]);\n for (const variant of Object.values(resolved.mapping)) {\n const variantProps = {\n ...variant.properties,\n ...variant.optionalProperties\n };\n for (const [name, propSchema] of Object.entries(variantProps)) {\n if (!seen.has(name)) {\n seen.add(name);\n result.push({ name, type: describeSchemaType(propSchema, defs) });\n }\n }\n }\n }\n\n return result;\n}\n\n/** Check if a schema has navigable child properties for autocomplete. */\nfunction hasChildProperties(\n schema: JTDSchemaJson | undefined,\n defs?: Record<string, JTDSchemaJson>\n): boolean {\n if (!schema) return false;\n const resolved = resolveInputSchema(schema, defs);\n return !!(\n resolved.properties ||\n resolved.optionalProperties ||\n (resolved.discriminator && resolved.mapping)\n );\n}\n\n// Deduplicate methods for completion\nfunction deduplicatedMethods(): MethodDescriptor[] {\n const seen = new Set<string>();\n const result: MethodDescriptor[] = [];\n for (const m of CEL_METHODS) {\n const key = `${m.name}|${m.detail}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(m);\n }\n }\n return result;\n}\n\n/**\n * Register CEL language with Monaco editor.\n * Takes a monaco instance as parameter \u2014 no monaco import needed.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function registerCelLanguage(monaco: any): void {\n if (\n monaco.languages\n .getLanguages()\n .some((l: { id: string }) => l.id === CEL_LANGUAGE_ID)\n )\n return;\n\n monaco.languages.register({ id: CEL_LANGUAGE_ID });\n\n // \u2500\u2500 Language configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.setLanguageConfiguration(CEL_LANGUAGE_ID, {\n brackets: [\n ['(', ')'],\n ['[', ']'],\n ['{', '}']\n ],\n autoClosingPairs: [\n { open: '(', close: ')' },\n { open: '[', close: ']' },\n { open: '{', close: '}' }\n ],\n surroundingPairs: [\n { open: '(', close: ')' },\n { open: '[', close: ']' },\n { open: '{', close: '}' },\n { open: '\"', close: '\"' },\n { open: \"'\", close: \"'\" }\n ]\n });\n\n // \u2500\u2500 Monarch tokenizer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.setMonarchTokensProvider(CEL_LANGUAGE_ID, {\n keywords: ['true', 'false', 'null', 'in'],\n builtins: GLOBAL_FUNCTIONS.map((f) => f.name.split('.')[0]!),\n operators: [\n '&&',\n '||',\n '!',\n '==',\n '!=',\n '<=',\n '>=',\n '<',\n '>',\n '+',\n '-',\n '*',\n '/',\n '%',\n '?',\n ':'\n ],\n tokenizer: {\n root: [\n [/\"(?:[^\"\\\\]|\\\\.)*\"/, 'string'],\n [/'(?:[^'\\\\]|\\\\.)*'/, 'string'],\n [/\\d+\\.\\d*([eE][-+]?\\d+)?/, 'number.float'],\n [/\\d*\\.\\d+([eE][-+]?\\d+)?/, 'number.float'],\n [/\\d+[eE][-+]?\\d+/, 'number.float'],\n [/0[xX][0-9a-fA-F]+[uU]?/, 'number.hex'],\n [/\\d+[uU]?/, 'number'],\n [/\\./, 'delimiter', '@afterDot'],\n [\n /[a-zA-Z_]\\w*/,\n {\n cases: {\n '@keywords': 'keyword',\n '@builtins': 'predefined',\n '@default': 'identifier'\n }\n }\n ],\n [/&&|\\|\\||[!=]=|[<>]=?/, 'operator'],\n [/[+\\-*/%?:!]/, 'operator'],\n [/[[\\](){}]/, '@brackets'],\n [/,/, 'delimiter'],\n [/\\s+/, 'white']\n ],\n afterDot: [\n [/[a-zA-Z_]\\w*/, 'variable.property', '@pop'],\n [/\\s+/, 'white'],\n [/./, '@rematch', '@pop']\n ]\n }\n } as never);\n\n // \u2500\u2500 Completion provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerCompletionItemProvider(CEL_LANGUAGE_ID, {\n triggerCharacters: ['.'],\n provideCompletionItems: (model: any, position: any) => {\n const textUntilPosition = model.getValueInRange({\n startLineNumber: position.lineNumber,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column\n });\n\n // Suppress completions inside string literals\n let inDouble = false;\n let inSingle = false;\n for (let i = 0; i < textUntilPosition.length; i++) {\n const ch = textUntilPosition[i];\n if (ch === '\\\\') {\n i++;\n continue;\n }\n if (ch === '\"' && !inSingle) inDouble = !inDouble;\n if (ch === \"'\" && !inDouble) inSingle = !inSingle;\n }\n if (inDouble || inSingle) return { suggestions: [] };\n\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n };\n\n // After \"inputs.X.Y.\" - offer nested JTD properties + methods\n const inputsNestedMatch = textUntilPosition\n .slice(0, textUntilPosition.length - word.word.length)\n .match(/inputs\\.(\\w+(?:\\.\\w+)*)\\.\\s*$/);\n if (inputsNestedMatch) {\n const pathParts = inputsNestedMatch[1]!.split('.');\n const varName = pathParts[0]!;\n const nestedPath = pathParts.slice(1);\n const inputVar = currentInputVariables.find((v) => v.name === varName);\n if (inputVar?.schema) {\n const defs = getRootDefs(inputVar.schema);\n const schemaAtPath = getSchemaAtPath(\n inputVar.schema,\n nestedPath,\n defs\n );\n const properties = getSchemaProperties(schemaAtPath, defs);\n const suggestions: any[] = properties.map((prop, i) => {\n const childSchema = getSchemaAtPath(\n schemaAtPath!,\n [prop.name],\n defs\n );\n const isNavigable = hasChildProperties(childSchema, defs);\n return {\n label: prop.name,\n kind: isNavigable\n ? monaco.languages.CompletionItemKind.Module\n : monaco.languages.CompletionItemKind.Property,\n detail: prop.type,\n documentation: `Property of inputs.${pathParts.join('.')}`,\n insertText: prop.name,\n range,\n sortText: String(i).padStart(3, '0')\n };\n });\n\n // Always include methods (they apply to any value after a dot)\n const methods = deduplicatedMethods();\n for (let mi = 0; mi < methods.length; mi++) {\n const m = methods[mi]!;\n suggestions.push({\n label: m.name,\n kind: monaco.languages.CompletionItemKind.Method,\n detail: `${m.detail} (${m.receiverType})`,\n documentation: m.documentation,\n insertText: m.params.length > 0 ? `${m.name}($0)` : `${m.name}()`,\n insertTextRules:\n m.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule\n .InsertAsSnippet\n : undefined,\n range,\n sortText: String(properties.length + mi).padStart(3, '0')\n });\n }\n\n return { suggestions };\n }\n return { suggestions: [] };\n }\n\n // After just \"inputs.\" - offer top-level input variable names\n if (\n /inputs\\.\\s*$/.test(\n textUntilPosition.slice(\n 0,\n textUntilPosition.length - word.word.length\n )\n )\n ) {\n return {\n suggestions: currentInputVariables.map((v, i) => {\n const hasNestedProps = hasChildProperties(\n v.schema,\n getRootDefs(v.schema)\n );\n return {\n label: v.name,\n kind: hasNestedProps\n ? monaco.languages.CompletionItemKind.Module\n : monaco.languages.CompletionItemKind.Variable,\n detail: v.label || (hasNestedProps ? 'object' : 'Input variable'),\n documentation: `Access as inputs.${v.name}${hasNestedProps ? ' (has nested properties)' : ''}`,\n insertText: v.name,\n range,\n sortText: String(i).padStart(3, '0')\n };\n })\n };\n }\n\n // After any other dot - offer methods\n if (\n /\\.\\s*$/.test(\n textUntilPosition.slice(\n 0,\n textUntilPosition.length - word.word.length\n )\n )\n ) {\n const methods = deduplicatedMethods();\n return {\n suggestions: methods.map((m, i) => ({\n label: m.name,\n kind: monaco.languages.CompletionItemKind.Method,\n detail: `${m.detail} (${m.receiverType})`,\n documentation: m.documentation,\n insertText: m.params.length > 0 ? `${m.name}($0)` : `${m.name}()`,\n insertTextRules:\n m.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet\n : undefined,\n range,\n sortText: String(i).padStart(3, '0')\n }))\n };\n }\n\n // Root level - offer global functions and input variables\n const suggestions: any[] = [];\n let sortIndex = 0;\n\n // inputs variable\n suggestions.push({\n label: 'inputs',\n kind: monaco.languages.CompletionItemKind.Variable,\n detail: 'object',\n documentation: 'Access input signals (e.g., inputs.customerName)',\n insertText: 'inputs.',\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n\n // Dynamic input variables with full path\n for (const v of currentInputVariables) {\n suggestions.push({\n label: `inputs.${v.name}`,\n kind: monaco.languages.CompletionItemKind.Variable,\n detail: v.label || 'Input variable',\n documentation: `Access the \"${v.name}\" input signal`,\n insertText: `inputs.${v.name}`,\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n }\n\n // Global functions\n for (const f of GLOBAL_FUNCTIONS) {\n suggestions.push({\n label: f.name,\n kind: monaco.languages.CompletionItemKind.Function,\n detail: f.detail,\n documentation: f.documentation,\n insertText: f.params.length > 0 ? `${f.name}($0)` : `${f.name}()`,\n insertTextRules:\n f.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet\n : undefined,\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n }\n\n return { suggestions };\n }\n });\n\n // \u2500\u2500 Hover provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerHoverProvider(CEL_LANGUAGE_ID, {\n provideHover: (model: any, position: any) => {\n const word = model.getWordAtPosition(position);\n if (!word) return null;\n\n // Check for input variable\n const inputVar = currentInputVariables.find((v) => v.name === word.word);\n if (inputVar) {\n return {\n range: {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n },\n contents: [\n {\n value: `**inputs.${inputVar.name}**${inputVar.label ? `\\n\\n${inputVar.label}` : ''}`\n }\n ]\n };\n }\n\n // Check functions/methods\n const descriptors = CEL_DESCRIPTORS.get(word.word);\n if (descriptors && descriptors.length > 0) {\n return {\n range: {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n },\n contents: descriptors.map((d) => ({\n value: `**${d.detail}**\\n\\n${d.documentation}`\n }))\n };\n }\n\n return null;\n }\n });\n\n // \u2500\u2500 Signature help provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerSignatureHelpProvider(CEL_LANGUAGE_ID, {\n signatureHelpTriggerCharacters: ['(', ','],\n provideSignatureHelp: (model: any, position: any) => {\n const textUntilPosition = model.getValueInRange({\n startLineNumber: position.lineNumber,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column\n });\n\n let depth = 0;\n let commaCount = 0;\n let parenIdx = -1;\n for (let i = textUntilPosition.length - 1; i >= 0; i--) {\n const ch = textUntilPosition[i];\n if (ch === ')') depth++;\n else if (ch === '(') {\n if (depth === 0) {\n parenIdx = i;\n break;\n }\n depth--;\n } else if (ch === ',' && depth === 0) {\n commaCount++;\n }\n }\n if (parenIdx < 0) return null;\n\n const before = textUntilPosition.slice(0, parenIdx);\n const nameMatch = before.match(/([a-zA-Z_]\\w*)\\s*$/);\n if (!nameMatch) return null;\n const funcName = nameMatch[1]!;\n\n const descriptors = CEL_DESCRIPTORS.get(funcName);\n if (!descriptors || descriptors.length === 0) return null;\n\n const signatures = descriptors\n .filter((d) => d.params.length > 0)\n .map((d) => ({\n label: d.detail,\n documentation: d.documentation,\n parameters: d.params.map((p) => ({ label: p }))\n }));\n\n if (signatures.length === 0) return null;\n\n return {\n value: {\n signatures,\n activeSignature: 0,\n activeParameter: Math.min(\n commaCount,\n signatures[0]!.parameters.length - 1\n )\n },\n dispose() {}\n };\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// CEL SYMBOL TREE (for advanced autocomplete with 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\nexport interface CelPropertyNode {\n detail: string;\n children: Record<string, CelPropertyNode>;\n}\n\nexport type CelSymbolTree = Record<string, CelPropertyNode>;\n\nconst ELEMENT_KEY = '[*]';\n\nfunction resolveSchema(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson {\n return schema.ref && defs?.[schema.ref]\n ? resolveSchema(defs[schema.ref]!, defs)\n : schema;\n}\n\nfunction buildNode(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): CelPropertyNode {\n const r = resolveSchema(schema, defs);\n const children: Record<string, CelPropertyNode> = {};\n let detail: string;\n\n if (r.type) {\n detail = r.type;\n } else if (r.enum) {\n detail = r.enum.map((v) => JSON.stringify(v)).join(' | ');\n } else if (r.elements) {\n const el = buildNode(r.elements, defs);\n children[ELEMENT_KEY] = el;\n detail = `${el.detail}[]`;\n } else if (r.values) {\n const val = buildNode(r.values, defs);\n children[ELEMENT_KEY] = val;\n detail = `map<${val.detail}>`;\n } else if (r.properties || r.optionalProperties) {\n const parts: string[] = [];\n if (r.properties) {\n for (const [k, v] of Object.entries(r.properties)) {\n const child = buildNode(v, defs);\n children[k] = child;\n parts.push(`${k}: ${child.detail}`);\n }\n }\n if (r.optionalProperties) {\n for (const [k, v] of Object.entries(r.optionalProperties)) {\n const child = buildNode(v, defs);\n children[k] = child;\n parts.push(`${k}?: ${child.detail}`);\n }\n }\n detail = `{ ${parts.join(', ')} }`;\n } else if (r.discriminator && r.mapping) {\n const tags = Object.keys(r.mapping);\n children[r.discriminator] = {\n detail: tags.map((t) => JSON.stringify(t)).join(' | '),\n children: {}\n };\n for (const variant of Object.values(r.mapping)) {\n const vNode = buildNode(variant, defs);\n for (const [k, v] of Object.entries(vNode.children)) {\n if (!(k in children)) children[k] = v;\n }\n }\n detail = `union(${r.discriminator}: ${tags.join(' | ')})`;\n } else {\n detail = 'any';\n }\n\n if (schema.nullable) detail += '?';\n if (schema.ref) detail = `ref(${schema.ref})`;\n\n return { detail, children };\n}\n\n/** Build symbol tree from signal bindings (JTD schemas \u2192 property tree). */\nexport function generateCelSymbolTree(\n bindings: SignalBindingJson[]\n): CelSymbolTree {\n const tree: CelSymbolTree = {};\n for (const binding of bindings) {\n if (!binding.name) continue;\n const format = binding.accepts?.[0];\n let node: CelPropertyNode;\n if (format?.jtdSchema) {\n node = buildNode(format.jtdSchema, format.jtdSchema.definitions);\n } else if (format?.mimeType) {\n node = { detail: format.mimeType, children: {} };\n } else {\n node = { detail: 'any', children: {} };\n }\n if (binding.optional) node = { ...node, detail: node.detail + ' | null' };\n tree[binding.name] = node;\n }\n return tree;\n}\n\nfunction buildTranslationNode(obj: Record<string, unknown>): CelPropertyNode {\n const children: Record<string, CelPropertyNode> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (typeof v === 'string') {\n children[k] = { detail: 'string', children: {} };\n } else if (typeof v === 'object' && v !== null) {\n children[k] = buildTranslationNode(v as Record<string, unknown>);\n }\n }\n const parts = Object.entries(children).map(([k, c]) => `${k}: ${c.detail}`);\n return { detail: `{ ${parts.join(', ')} }`, children };\n}\n\nfunction deepMergeForTree(\n target: Record<string, unknown>,\n source: Record<string, unknown>\n): void {\n for (const [k, v] of Object.entries(source)) {\n if (\n typeof v === 'object' &&\n v !== null &&\n typeof target[k] === 'object' &&\n target[k] !== null\n ) {\n deepMergeForTree(\n target[k] as Record<string, unknown>,\n v as Record<string, unknown>\n );\n } else {\n target[k] = v;\n }\n }\n}\n\n/** Build symbol tree from translation dictionaries. */\nexport function generateTranslationsSymbolTree(\n translations: Record<string, Record<string, unknown>>\n): CelPropertyNode {\n const merged: Record<string, unknown> = {};\n for (const dict of Object.values(translations)) {\n deepMergeForTree(merged, dict);\n }\n return buildTranslationNode(merged);\n}\n\n/** Dot-path parsing for inputs.* and t.* */\nexport function parseDotPath(textBefore: string): string[] | null {\n const m = textBefore.match(\n /\\b(inputs|t)((?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.\\s*$/\n );\n if (!m) return null;\n\n const root = m[1]!;\n const chain = m[2]!;\n const segments: string[] = [root];\n let i = 0;\n while (i < chain.length) {\n if (chain[i] === '.') {\n i++;\n const id = chain.substring(i).match(/^[a-zA-Z_]\\w*/);\n if (id) {\n segments.push(id[0]);\n i += id[0].length;\n }\n } else if (chain[i] === '[') {\n const close = chain.indexOf(']', i);\n if (close === -1) break;\n segments.push(ELEMENT_KEY);\n i = close + 1;\n } else {\n i++;\n }\n }\n return segments;\n}\n\n/** Resolve a node in the symbol tree by walking segments. */\nexport function resolveNode(\n tree: CelSymbolTree,\n segments: string[],\n tNode?: CelPropertyNode\n): CelPropertyNode | null {\n if (segments.length === 0) return null;\n\n if (segments[0] === 'inputs') {\n if (segments.length === 1)\n return { detail: 'Signal inputs', children: tree };\n let current: CelPropertyNode | undefined = tree[segments[1]!];\n if (!current) return null;\n for (let i = 2; i < segments.length; i++) {\n current = current.children[segments[i]!];\n if (!current) return null;\n }\n return current;\n }\n\n if (segments[0] === 't' && tNode) {\n if (segments.length === 1) return tNode;\n let current: CelPropertyNode | undefined = tNode.children[segments[1]!];\n if (!current) return null;\n for (let i = 2; i < segments.length; i++) {\n current = current.children[segments[i]!];\n if (!current) return null;\n }\n return current;\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// LAMBDA-AWARE RESOLUTION\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 interface LambdaBinding {\n varName: string;\n collectionSegments: string[];\n}\n\nfunction parseExprToSegments(expr: string): string[] {\n const segments: string[] = [];\n const firstId = expr.match(/^[a-zA-Z_]\\w*/);\n if (!firstId) return segments;\n segments.push(firstId[0]);\n let i = firstId[0].length;\n while (i < expr.length) {\n if (expr[i] === '.') {\n i++;\n const id = expr.substring(i).match(/^[a-zA-Z_]\\w*/);\n if (id) {\n segments.push(id[0]);\n i += id[0].length;\n } else break;\n } else if (expr[i] === '[') {\n const close = expr.indexOf(']', i);\n if (close === -1) break;\n segments.push(ELEMENT_KEY);\n i = close + 1;\n } else {\n break;\n }\n }\n return segments;\n}\n\n/**\n * Extract lambda variable bindings from CEL macro calls in the text.\n * e.g. `inputs.items.map(item, ...)` \u2192 [{ varName: \"item\", collectionSegments: [\"inputs\", \"items\"] }]\n */\nexport function extractLambdaBindings(text: string): LambdaBinding[] {\n const bindings: LambdaBinding[] = [];\n const re =\n /([a-zA-Z_]\\w*(?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.(?:map|filter|all|exists_one|exists)\\s*\\(\\s*([a-zA-Z_]\\w*)\\s*,/g;\n let m;\n while ((m = re.exec(text)) !== null) {\n const collectionSegments = parseExprToSegments(m[1]!);\n if (collectionSegments.length > 0) {\n bindings.push({ varName: m[2]!, collectionSegments });\n }\n }\n return bindings;\n}\n\n/** Parse any trailing dot-path from text (not restricted to inputs.*). */\nexport function parseGeneralDotPath(textBefore: string): string[] | null {\n const m = textBefore.match(\n /\\b([a-zA-Z_]\\w*(?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.\\s*$/\n );\n if (!m) return null;\n const segments = parseExprToSegments(m[1]!);\n return segments.length > 0 ? segments : null;\n}\n\n/** Resolve a dot-path that may start with a lambda variable. */\nexport function resolveWithLambdas(\n tree: CelSymbolTree,\n segments: string[],\n lambdaBindings: LambdaBinding[],\n tNode?: CelPropertyNode\n): CelPropertyNode | null {\n if (segments.length === 0) return null;\n const root = segments[0]!;\n\n if (root === 'inputs' || root === 't') {\n return resolveNode(tree, segments, tNode);\n }\n\n // Check lambda bindings (last match = innermost scope)\n for (let i = lambdaBindings.length - 1; i >= 0; i--) {\n const binding = lambdaBindings[i]!;\n if (binding.varName === root) {\n const collectionNode = resolveWithLambdas(\n tree,\n binding.collectionSegments,\n lambdaBindings,\n tNode\n );\n if (!collectionNode) return null;\n\n const elementNode = collectionNode.children[ELEMENT_KEY];\n if (!elementNode) return null;\n\n let current: CelPropertyNode | undefined = elementNode;\n for (let j = 1; j < segments.length; j++) {\n current = current.children[segments[j]!];\n if (!current) return null;\n }\n return current;\n }\n }\n\n return null;\n}\n\n/** Extract the full dot-chain path containing the hovered word. */\nexport function extractHoverSegments(\n lineText: string,\n wordStartCol: number,\n word: string\n): string[] {\n const segments: string[] = [];\n let pos = wordStartCol - 2;\n\n while (pos >= 0 && lineText[pos] === '.') {\n pos--;\n const idEnd = pos + 1;\n while (pos >= 0 && /[a-zA-Z_0-9]/.test(lineText[pos]!)) {\n pos--;\n }\n const idStart = pos + 1;\n const id = lineText.substring(idStart, idEnd);\n if (/^[a-zA-Z_]\\w*$/.test(id) && id.length > 0) {\n segments.unshift(id);\n } else {\n break;\n }\n }\n\n segments.push(word);\n return segments;\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 'root';\n const joined = instancePath\n .map((p, i) => (/^\\d+$/.test(p) ? `[${p}]` : i === 0 ? p : `.${p}`))\n .join('');\n return `'${joined}'`;\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 const paramLabel = path === 'root' ? 'root value' : `parameter ${path}`;\n\n if (lastKey === 'type') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const jtdType = parent?.type as string;\n if (jtdType === 'boolean') return `${paramLabel}: expected boolean`;\n if (jtdType === 'string') return `${paramLabel}: expected string`;\n if (jtdType === 'timestamp')\n return `${paramLabel}: expected timestamp string`;\n if (INTEGER_TYPES.has(jtdType)) return `${paramLabel}: expected integer`;\n return `${paramLabel}: expected number`;\n }\n\n if (lastKey === 'enum') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const enumValues = parent?.enum as string[];\n return `${paramLabel}: expected one of [${enumValues.join(', ')}]`;\n }\n\n if (\n schemaPath.length >= 2 &&\n schemaPath[schemaPath.length - 2] === 'properties' &&\n lastKey\n ) {\n if (path === 'root') {\n return `missing required parameter '${lastKey}'`;\n }\n return `missing required parameter ${path}.${lastKey}`;\n }\n\n if (lastKey === 'elements') return `${paramLabel}: expected array`;\n\n if (\n lastKey === 'properties' ||\n lastKey === 'optionalProperties' ||\n lastKey === 'values'\n ) {\n return `${paramLabel}: expected object`;\n }\n\n if (lastKey === 'discriminator') {\n // Find the discriminator field name from the schema\n const parent = resolveSchemaParent(schema, schemaPath);\n const discField = parent?.discriminator as string | undefined;\n if (discField) {\n return `${paramLabel}: parameter '${discField}' must be a string`;\n }\n return `${paramLabel}: expected string discriminator`;\n }\n\n if (lastKey === 'mapping') {\n const discValue = resolveInstanceValue(value, instancePath);\n // Try to list valid variants from the mapping\n const parent = resolveSchemaParent(schema, schemaPath);\n const mapping = parent?.mapping as Record<string, unknown> | undefined;\n const validVariants = mapping ? Object.keys(mapping) : [];\n if (validVariants.length > 0) {\n return `${paramLabel}: unknown variant \"${discValue}\". Valid values: [${validVariants.join(', ')}]`;\n }\n return `${paramLabel}: unknown variant \"${discValue}\"`;\n }\n\n if (schemaPath.length === 0) return `${paramLabel}: unexpected property`;\n\n return `${paramLabel}: 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}\" in schema`];\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.\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 *\n * JTD `metadata.description` is preserved as JSON Schema `description`.\n * Other metadata fields are appended to the description for context.\n *\n * Top-level `definitions` are emitted as JSON Schema `$defs` and\n * referenced via `$ref` (not inlined), keeping large schemas compact.\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 // Emit top-level definitions as $defs (only at root)\n if (defs && Object.keys(defs).length > 0) {\n result.$defs = {};\n for (const [name, defSchema] of Object.entries(defs)) {\n result.$defs[name] = convertNode(defSchema as JTDSchemaJson, defs);\n }\n }\n }\n\n // Build the schema node \u2014 delegate to convertNode for the actual form logic\n const node = convertNode(jtdSchema, defs);\n Object.assign(result, node);\n\n return result;\n}\n\n/** Convert a single JTD node to JSON Schema. Internal recursive worker. */\nfunction convertNode(\n jtdSchema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined\n): any {\n if (!jtdSchema || typeof jtdSchema !== 'object') {\n return {};\n }\n\n const isNullable = jtdSchema['nullable'];\n const result: any = {};\n\n // Extract metadata.description \u2192 JSON Schema description\n applyMetadata(result, jtdSchema);\n\n // \u2500\u2500 Ref form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['ref']) {\n const refName = jtdSchema['ref'] as string;\n if (defs && defs[refName]) {\n const refResult: any = { $ref: `#/$defs/${refName}` };\n applyMetadata(refResult, jtdSchema);\n\n if (isNullable) {\n return {\n anyOf: [refResult, { type: 'null' }],\n ...(refResult.description\n ? { description: refResult.description }\n : {})\n };\n }\n return refResult;\n }\n return {};\n }\n\n // \u2500\u2500 Type form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 // \u2500\u2500 Enum form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 // \u2500\u2500 Elements form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['elements']) {\n result.type = isNullable ? ['array', 'null'] : 'array';\n result.items = convertNode(jtdSchema['elements'] as JTDSchemaJson, defs);\n return result;\n }\n\n // \u2500\u2500 Properties form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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] = convertNode(value as JTDSchemaJson, defs);\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] = convertNode(value as JTDSchemaJson, defs);\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 // \u2500\u2500 Values form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['values']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.additionalProperties = convertNode(\n jtdSchema['values'] as JTDSchemaJson,\n defs\n );\n return result;\n }\n\n // \u2500\u2500 Discriminator form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 = convertNode(schema as JTDSchemaJson, defs);\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 // \u2500\u2500 Empty form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 return result;\n}\n\n/**\n * Extract JTD metadata and apply as JSON Schema `description`.\n *\n * - `metadata.description` becomes `description` directly.\n * - Other metadata fields are appended as \"key: value\" lines.\n */\nfunction applyMetadata(result: any, jtdSchema: JTDSchemaJson): void {\n const metadata = jtdSchema['metadata'] as Record<string, unknown> | undefined;\n if (!metadata || typeof metadata !== 'object') return;\n\n const parts: string[] = [];\n const desc = metadata['description'];\n if (typeof desc === 'string' && desc) {\n parts.push(desc);\n }\n\n // Fold other metadata fields into description\n for (const [key, value] of Object.entries(metadata)) {\n if (key === 'description') continue;\n if (value === undefined || value === null) continue;\n const str = typeof value === 'string' ? value : JSON.stringify(value);\n parts.push(`${key}: ${str}`);\n }\n\n if (parts.length > 0) {\n result.description = parts.join('\\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// 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
|
-
"names": ["celFunc", "celMethod", "celRun", "CelScalar", "isCelError", "isCelList", "isCelMap", "isCelUint", "listType", "objectType", "stringsExt", "timestampDate", "timestampFromDate", "timestampMs", "timestampNow", "TimestampSchema", "isSchema", "isValidSchema", "jtdValidate", "FUZZ_MAX_DEPTH", "fuzzJTD", "schema", "definitions", "_depth", "def", "obj", "k", "v", "firstKey", "variant", "toNumber", "val", "isCelUint", "celEqual", "a", "b", "aVal", "bVal", "isBytes", "toUint8Array", "wrapBytes", "data", "_hasBuffer", "base64Decode", "s", "c", "base64Encode", "byte", "encodeImpl", "encoding", "json", "celToNative", "decodeImpl", "bytes", "htmlEscapeImpl", "LIST_DYN", "listType", "CelScalar", "DYN", "BOOL", "INT", "formatDateWithPattern", "timestamp", "pattern", "y", "m", "d", "H", "min", "CUSTOM_FUNCS", "celFunc", "list", "total", "n", "celMethod", "result", "count", "element", "
|
|
3
|
+
"sources": ["../../src/cel/index.ts", "../../src/signals/index.ts", "../../src/schema-utils.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n celFunc,\n celMethod,\n run as celRun,\n CelScalar,\n isCelError,\n isCelList,\n isCelMap,\n isCelUint,\n listType,\n objectType,\n type CelFunc as CelFuncType,\n type CelInput,\n type CelValue\n} from '@bufbuild/cel';\nimport { strings as stringsExt } from '@bufbuild/cel/ext';\nimport {\n timestampDate,\n timestampFromDate,\n timestampMs,\n timestampNow,\n TimestampSchema,\n type Timestamp\n} from '@bufbuild/protobuf/wkt';\nimport type { ReflectMessage } from '@bufbuild/protobuf/reflect';\nimport type { JTDSchemaJson, SignalBindingJson } from '../api';\nimport { INTEGER_BOUNDS, MAX_REF_DEPTH } from '../schema-utils';\nimport { fuzzJTD } 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// HELPERS (internal)\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 toNumber(val: unknown): number | null {\n if (typeof val === 'number') return val;\n if (typeof val === 'bigint') return Number(val);\n if (isCelUint(val)) return Number(val.value);\n return null;\n}\n\nfunction celEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n const aVal = isCelUint(a) ? a.value : a;\n const bVal = isCelUint(b) ? b.value : b;\n return aVal === bVal;\n}\n\nfunction isBytes(val: unknown): val is Uint8Array {\n return (\n val instanceof Uint8Array ||\n (ArrayBuffer.isView(val) && !(val instanceof DataView))\n );\n}\n\nfunction toUint8Array(val: unknown): Uint8Array {\n if (val instanceof Uint8Array) return val;\n if (ArrayBuffer.isView(val))\n return new Uint8Array(val.buffer, val.byteOffset, val.byteLength);\n return val as Uint8Array;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction jtdJsonToCelInputInner(\n value: unknown,\n schema: JTDSchemaJson,\n definitions: Record<string, JTDSchemaJson> | undefined,\n depth: number\n): unknown {\n if (value == null || depth > MAX_REF_DEPTH) return value;\n\n if (schema.ref) {\n const def = definitions?.[schema.ref];\n return def\n ? jtdJsonToCelInputInner(value, def, definitions, depth + 1)\n : value;\n }\n\n if (\n schema.type &&\n schema.type in INTEGER_BOUNDS &&\n typeof value === 'number' &&\n Number.isInteger(value)\n ) {\n return BigInt(value);\n }\n\n if (schema.elements && Array.isArray(value)) {\n return value.map((item) =>\n jtdJsonToCelInputInner(item, schema.elements!, definitions, depth + 1)\n );\n }\n\n if (schema.values && isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [\n key,\n jtdJsonToCelInputInner(item, schema.values!, definitions, depth + 1)\n ])\n );\n }\n\n if (schema.discriminator && schema.mapping && isRecord(value)) {\n const tag = value[schema.discriminator];\n const variant = typeof tag === 'string' ? schema.mapping[tag] : undefined;\n return variant\n ? jtdJsonToCelInputInner(value, variant, definitions, depth + 1)\n : value;\n }\n\n const props = {\n ...(schema.properties ?? {}),\n ...(schema.optionalProperties ?? {})\n };\n if (Object.keys(props).length > 0 && isRecord(value)) {\n const converted = { ...value };\n for (const [key, propSchema] of Object.entries(props)) {\n if (Object.prototype.hasOwnProperty.call(value, key)) {\n converted[key] = jtdJsonToCelInputInner(\n value[key],\n propSchema,\n definitions,\n depth + 1\n );\n }\n }\n return converted;\n }\n\n return value;\n}\n\n/** Convert a JSON value matching a JTD schema into CEL input values. */\nexport function jtdJsonToCelInput(\n value: unknown,\n schema: JTDSchemaJson\n): unknown {\n return jtdJsonToCelInputInner(value, schema, getRootDefs(schema), 0);\n}\n\n/** Generate a JSON/JTD sample and convert it for CEL evaluation. */\nexport function fuzzJTDForCel(schema: JTDSchemaJson): CelInput {\n return jtdJsonToCelInput(\n fuzzJTD(schema, schema.definitions),\n schema\n ) as CelInput;\n}\n\n// The CEL runtime uses `instanceof Uint8Array` to recognize bytes values.\n// In jsdom environments (vitest), TextEncoder.encode() returns a Node-native\n// Uint8Array from a different realm, which fails `instanceof` against the\n// jsdom Uint8Array. Re-wrapping forces the current realm's constructor.\nfunction wrapBytes(data: Uint8Array): Uint8Array {\n return new Uint8Array(data);\n}\n\n// Platform capability \u2014 resolved once at module load\nconst _hasBuffer = typeof Buffer !== 'undefined';\n\n// Base64: Node Buffer > Uint8Array.fromBase64/toBase64 (TC39) > atob/btoa fallback\nconst base64Decode: (base64: string) => Uint8Array = (() => {\n if (_hasBuffer) {\n return (s: string) => Buffer.from(s, 'base64');\n }\n if (typeof (Uint8Array as any).fromBase64 === 'function') {\n return (s: string) => (Uint8Array as any).fromBase64(s);\n }\n return (s: string) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0));\n})();\n\nconst base64Encode: (bytes: Uint8Array) => string = (() => {\n if (_hasBuffer) {\n return (b: Uint8Array) =>\n Buffer.from(b.buffer, b.byteOffset, b.byteLength).toString('base64');\n }\n if (typeof (Uint8Array.prototype as any).toBase64 === 'function') {\n return (b: Uint8Array) => (b as any).toBase64();\n }\n return (b: Uint8Array) =>\n btoa(Array.from(b, (byte) => String.fromCharCode(byte)).join(''));\n})();\n\nfunction encodeImpl(val: unknown, encoding = 'utf-8'): Uint8Array {\n if (isBytes(val)) return toUint8Array(val);\n const json = JSON.stringify(celToNative(val as CelValue));\n if (encoding === 'utf-8' || encoding === 'utf8') {\n return wrapBytes(new TextEncoder().encode(json));\n }\n // Node: Buffer handles all encodings natively\n if (_hasBuffer) {\n return new Uint8Array(Buffer.from(json, encoding as BufferEncoding));\n }\n // Browser fallback: charCodeAt only covers single-byte encodings (latin1, ascii)\n return Uint8Array.from(json, (c) => c.charCodeAt(0));\n}\n\nfunction decodeImpl(data: unknown, encoding = 'utf-8'): unknown {\n const bytes = toUint8Array(data);\n return JSON.parse(new TextDecoder(encoding).decode(bytes));\n}\n\nfunction htmlEscapeImpl(s: string): string {\n return s\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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// CEL RUNTIME: Custom Functions\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 LIST_DYN = listType(CelScalar.DYN);\nconst { DYN, BOOL, INT } = CelScalar;\n\n/**\n * Format a timestamp using a pattern string.\n *\n * Supported patterns:\n * - YYYY - 4-digit year\n * - YY - 2-digit year\n * - MM - month (01-12)\n * - DD - day (01-31)\n * - HH - hours (00-23)\n * - mm - minutes (00-59)\n * - ss - seconds (00-59)\n */\nexport function formatDateWithPattern(\n timestamp: Date,\n pattern: string\n): string {\n const y = timestamp.getFullYear();\n const m = timestamp.getMonth() + 1;\n const d = timestamp.getDate();\n const H = timestamp.getHours();\n const min = timestamp.getMinutes();\n const s = timestamp.getSeconds();\n\n return pattern\n .replace(/YYYY/g, String(y))\n .replace(/YY/g, String(y).slice(-2))\n .replace(/MM/g, String(m).padStart(2, '0'))\n .replace(/DD/g, String(d).padStart(2, '0'))\n .replace(/HH/g, String(H).padStart(2, '0'))\n .replace(/mm/g, String(min).padStart(2, '0'))\n .replace(/ss/g, String(s).padStart(2, '0'));\n}\n\n/** Union of all custom CelFunc definitions across all plugins. */\nexport const CUSTOM_FUNCS: CelFuncType[] = [\n // \u2500\u2500 Aggregate: sum \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('sum', [LIST_DYN], DYN, (list) => {\n let total = 0;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null) total += n;\n }\n return total;\n }),\n celMethod('sum', LIST_DYN, [], DYN, function () {\n let total = 0;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null) total += n;\n }\n return total;\n }),\n\n // \u2500\u2500 Aggregate: min \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('min', [LIST_DYN], DYN, (list) => {\n let result: number | null = null;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null && (result === null || n < result)) result = n;\n }\n return result ?? 0;\n }),\n celMethod('min', LIST_DYN, [], DYN, function () {\n let result: number | null = null;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null && (result === null || n < result)) result = n;\n }\n return result ?? 0;\n }),\n\n // \u2500\u2500 Aggregate: max \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('max', [LIST_DYN], DYN, (list) => {\n let result: number | null = null;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null && (result === null || n > result)) result = n;\n }\n return result ?? 0;\n }),\n celMethod('max', LIST_DYN, [], DYN, function () {\n let result: number | null = null;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null && (result === null || n > result)) result = n;\n }\n return result ?? 0;\n }),\n\n // \u2500\u2500 Aggregate: avg \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('avg', [LIST_DYN], DYN, (list) => {\n let total = 0;\n let count = 0;\n for (const val of list) {\n const n = toNumber(val);\n if (n !== null) {\n total += n;\n count++;\n }\n }\n return count > 0 ? total / count : 0;\n }),\n celMethod('avg', LIST_DYN, [], DYN, function () {\n let total = 0;\n let count = 0;\n for (const val of this) {\n const n = toNumber(val);\n if (n !== null) {\n total += n;\n count++;\n }\n }\n return count > 0 ? total / count : 0;\n }),\n\n // \u2500\u2500 Search: includes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('includes', [LIST_DYN, DYN], BOOL, (list, element) => {\n for (const item of list) {\n if (celEqual(item, element)) return true;\n }\n return false;\n }),\n celMethod('includes', LIST_DYN, [DYN], BOOL, function (element) {\n for (const item of this) {\n if (celEqual(item, element)) return true;\n }\n return false;\n }),\n\n // \u2500\u2500 Search: findIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('findIndex', [LIST_DYN, DYN], INT, (list, element) => {\n let index = 0n;\n for (const item of list) {\n if (celEqual(item, element)) return index;\n index++;\n }\n return -1n;\n }),\n celMethod('findIndex', LIST_DYN, [DYN], INT, function (element) {\n let index = 0n;\n for (const item of this) {\n if (celEqual(item, element)) return index;\n index++;\n }\n return -1n;\n }),\n\n // \u2500\u2500 Search: findLastIndex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('findLastIndex', [LIST_DYN, DYN], INT, (list, element) => {\n const arr = [...list];\n for (let i = arr.length - 1; i >= 0; i--) {\n if (celEqual(arr[i], element)) return BigInt(i);\n }\n return -1n;\n }),\n celMethod('findLastIndex', LIST_DYN, [DYN], INT, function (element) {\n const arr = [...this];\n for (let i = arr.length - 1; i >= 0; i--) {\n if (celEqual(arr[i], element)) return BigInt(i);\n }\n return -1n;\n }),\n\n // \u2500\u2500 Utilities \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('now', [], objectType(TimestampSchema), () => timestampNow()),\n celFunc('lower', [CelScalar.STRING], CelScalar.STRING, (s) =>\n s.toLowerCase()\n ),\n celFunc('upper', [CelScalar.STRING], CelScalar.STRING, (s) =>\n s.toUpperCase()\n ),\n celMethod('lower', CelScalar.STRING, [], CelScalar.STRING, function () {\n return (this as unknown as string).toLowerCase();\n }),\n celMethod('upper', CelScalar.STRING, [], CelScalar.STRING, function () {\n return (this as unknown as string).toUpperCase();\n }),\n\n // \u2500\u2500 Encoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celFunc('base64decode', [CelScalar.STRING], DYN, (s) => base64Decode(s)),\n celFunc('base64encode', [DYN], CelScalar.STRING, (data) =>\n base64Encode(toUint8Array(data))\n ),\n celFunc('encode', [DYN], DYN, (val) => encodeImpl(val)),\n celFunc('encode', [DYN, CelScalar.STRING], DYN, (val, enc) =>\n encodeImpl(val, enc)\n ),\n celFunc('decode', [DYN], DYN, (data) => decodeImpl(data) as CelValue),\n celFunc(\n 'decode',\n [DYN, CelScalar.STRING],\n DYN,\n (data, enc) => decodeImpl(data, enc) as CelValue\n ),\n\n // \u2500\u2500 HTML escaping (native implementation, no `he` dependency) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n celFunc('htmlEscape', [CelScalar.STRING], CelScalar.STRING, (s) =>\n htmlEscapeImpl(s)\n ),\n celFunc('attrEscape', [CelScalar.STRING], CelScalar.STRING, (s) =>\n htmlEscapeImpl(s)\n ),\n\n // \u2500\u2500 Date formatting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 celMethod(\n 'formatDate',\n objectType(TimestampSchema),\n [CelScalar.STRING],\n CelScalar.STRING,\n function (\n this: ReflectMessage & { message: Timestamp },\n pattern: string\n ): string {\n const timestamp = this.message;\n const ms =\n Number(timestamp.seconds) * 1000 +\n Math.floor(timestamp.nanos / 1000000);\n const date = new Date(ms);\n return formatDateWithPattern(date, pattern);\n }\n )\n];\n\n/** Ready-to-use options: strings extension + all custom funcs. */\nexport const celOptions = {\n funcs: [...stringsExt, ...CUSTOM_FUNCS]\n};\n\n/** Convert CEL types to native JS (CelList\u2192array, CelMap\u2192object, bigint\u2192number). */\nexport function celToNative(value: CelValue): unknown {\n if (isCelList(value)) {\n return [...value].map((item) => celToNative(item as CelValue));\n }\n if (isCelMap(value)) {\n const obj: Record<string, unknown> = {};\n for (const [k, v] of value) {\n obj[String(k)] = celToNative(v as CelValue);\n }\n return obj;\n }\n if (typeof value === 'bigint') {\n return Number(value);\n }\n return value;\n}\n\n// Re-export types from @bufbuild/cel that plugins commonly need\nexport type { CelFuncType, CelInput, CelValue };\nexport {\n celRun,\n isCelError,\n celFunc,\n celMethod,\n CelScalar,\n objectType,\n listType,\n isCelList,\n isCelMap,\n isCelUint\n};\nexport {\n stringsExt,\n timestampDate,\n timestampFromDate,\n timestampMs,\n timestampNow,\n TimestampSchema\n};\n\n// Re-export fuzzJTD from jtd module for convenience\nexport { fuzzJTD } 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// CEL EXPRESSION VALIDATION\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 allowed CEL expression length (characters). */\nconst MAX_EXPRESSION_LENGTH = 10_000;\n\nexport interface CelVariable {\n name: string;\n schema: JTDSchemaJson;\n optional?: boolean;\n}\n\nexport interface AccessPath {\n variableName: string;\n path: string[];\n fullPath: string;\n}\n\nexport interface OptionalityInfo {\n segmentIndex: number;\n propertyName: string;\n isSignalOptional: boolean;\n}\n\nexport interface ValidationError {\n message: string;\n path?: string;\n isOptionalAccess?: boolean;\n}\n\nexport type ValidationResult =\n | { valid: true }\n | { valid: false; errors: ValidationError[] };\n\n/**\n * Extract all access paths for known variables from a CEL expression.\n * Handles both dot notation (var.a.b) and bracket notation (var[\"a\"]).\n */\nexport function extractAccessPaths(\n expression: string,\n variableNames: string[]\n): AccessPath[] {\n // Filter out empty/whitespace-only variable names (would match every position in the regex)\n const validNames = variableNames.filter(\n (n) => n.length > 0 && /^\\w+$/.test(n)\n );\n if (validNames.length === 0) return [];\n\n const paths: AccessPath[] = [];\n const escapedNames = validNames.map((n) =>\n n.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n );\n const namesPattern = escapedNames.join('|');\n\n // Match variable with dot/bracket access, OR bare variable reference\n const regex = new RegExp(\n `\\\\b(${namesPattern})(?:(?:\\\\.([a-zA-Z_]\\\\w*)|\\\\[\"([^\"]+)\"\\\\]|\\\\['([^']+)'\\\\])|(?=$|[^a-zA-Z_0-9.\\\\[]))`,\n 'g'\n );\n\n let match: RegExpExecArray | null;\n while ((match = regex.exec(expression)) !== null) {\n const varName = match[1]!;\n const firstProp = match[2] || match[3] || match[4];\n\n if (!firstProp) {\n // Bare variable reference (e.g., just `filename`)\n paths.push({ variableName: varName, path: [], fullPath: varName });\n continue;\n }\n\n const pathParts = [firstProp];\n let pos = match.index + match[0].length;\n\n while (pos < expression.length) {\n const dotMatch = expression.slice(pos).match(/^\\.([a-zA-Z_]\\w*)/);\n if (dotMatch) {\n const nextPos = pos + dotMatch[0].length;\n if (expression[nextPos] === '(') break;\n pathParts.push(dotMatch[1]!);\n pos = nextPos;\n continue;\n }\n const bracketMatch = expression\n .slice(pos)\n .match(/^\\[\"([^\"]+)\"\\]|^\\['([^']+)'\\]/);\n if (bracketMatch) {\n pathParts.push(bracketMatch[1] || bracketMatch[2]!);\n pos += bracketMatch[0].length;\n continue;\n }\n break;\n }\n\n const fullPath = varName + '.' + pathParts.join('.');\n paths.push({ variableName: varName, path: pathParts, fullPath });\n }\n\n return deduplicateAccessPaths(paths);\n}\n\nfunction deduplicateAccessPaths(paths: AccessPath[]): AccessPath[] {\n const byVariable = new Map<string, AccessPath[]>();\n for (const path of paths) {\n const existing = byVariable.get(path.variableName) || [];\n existing.push(path);\n byVariable.set(path.variableName, existing);\n }\n\n const result: AccessPath[] = [];\n for (const [, variablePaths] of byVariable) {\n variablePaths.sort((a, b) => b.path.length - a.path.length);\n const kept: AccessPath[] = [];\n for (const candidate of variablePaths) {\n const isPrefix = kept.some((k) => isPathPrefix(candidate, k));\n if (!isPrefix) kept.push(candidate);\n }\n result.push(...kept);\n }\n return result;\n}\n\nfunction isPathPrefix(pathA: AccessPath, pathB: AccessPath): boolean {\n if (pathA.variableName !== pathB.variableName) return false;\n if (pathA.path.length > pathB.path.length) return false;\n for (let i = 0; i < pathA.path.length; i++) {\n if (pathA.path[i] !== pathB.path[i]) return false;\n }\n return true;\n}\n\n/** Find which segments in the path are optional according to the schema. */\nexport function findOptionalSegments(\n path: string[],\n schema: JTDSchemaJson | undefined,\n isSignalOptional: boolean\n): OptionalityInfo[] {\n const optionals: OptionalityInfo[] = [];\n if (isSignalOptional) {\n optionals.push({\n segmentIndex: -1,\n propertyName: '',\n isSignalOptional: true\n });\n }\n if (!schema || path.length === 0) return optionals;\n\n let currentSchema: JTDSchemaJson | undefined = schema;\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]!;\n if (!currentSchema) break;\n\n const optProps: Record<string, JTDSchemaJson> | undefined =\n currentSchema.optionalProperties;\n const reqProps: Record<string, JTDSchemaJson> | undefined =\n currentSchema.properties;\n\n if (optProps && segment in optProps) {\n optionals.push({\n segmentIndex: i,\n propertyName: segment,\n isSignalOptional: false\n });\n currentSchema = optProps[segment];\n } else if (reqProps && segment in reqProps) {\n currentSchema = reqProps[segment];\n } else {\n break;\n }\n }\n return optionals;\n}\n\n/** Generate test permutations for validating optional property access. */\nexport function generateTestPermutations(\n variables: CelVariable[],\n accessedPaths: AccessPath[]\n): {\n bindings: Record<string, unknown>;\n description: string;\n unsetPath?: string;\n}[] {\n const permutations: {\n bindings: Record<string, unknown>;\n description: string;\n unsetPath?: string;\n }[] = [];\n\n const allBindings: Record<string, unknown> = {};\n for (const v of variables) {\n allBindings[v.name] = fuzzJTDForCel(v.schema);\n }\n permutations.push({\n bindings: allBindings,\n description: 'All properties present'\n });\n\n for (const accessPath of accessedPaths) {\n const variable = variables.find((v) => v.name === accessPath.variableName);\n if (!variable) continue;\n\n const optionalSegments = findOptionalSegments(\n accessPath.path,\n variable.schema,\n variable.optional ?? false\n );\n\n for (const opt of optionalSegments) {\n const testBindings: Record<string, unknown> =\n structuredClone(allBindings);\n\n if (opt.isSignalOptional && opt.segmentIndex === -1) {\n delete testBindings[accessPath.variableName];\n permutations.push({\n bindings: testBindings,\n description: `Variable '${accessPath.variableName}' not bound`,\n unsetPath: accessPath.variableName\n });\n } else {\n const pathToUnset = accessPath.path.slice(0, opt.segmentIndex + 1);\n unsetNestedProperty(testBindings[accessPath.variableName], pathToUnset);\n const unsetPathStr = `${accessPath.variableName}.${pathToUnset.join('.')}`;\n permutations.push({\n bindings: testBindings,\n description: `Optional property '${opt.propertyName}' unset`,\n unsetPath: unsetPathStr\n });\n }\n }\n }\n\n return permutations;\n}\n\nfunction unsetNestedProperty(obj: unknown, path: string[]): void {\n if (path.length === 0 || obj === null || typeof obj !== 'object') return;\n let current: unknown = obj;\n for (let i = 0; i < path.length - 1; i++) {\n if (current === null || typeof current !== 'object') return;\n current = (current as Record<string, unknown>)[path[i]!];\n }\n if (current !== null && typeof current === 'object') {\n delete (current as Record<string, unknown>)[path[path.length - 1]!];\n }\n}\n\n/**\n * Evaluate a CEL expression with given bindings and return the result.\n * Generic version \u2014 callers provide their own binding context.\n */\nexport function evaluateExpression(\n expression: string,\n bindings: Record<string, unknown>\n): { result: unknown; error?: never } | { result?: never; error: string } {\n if (expression.length > MAX_EXPRESSION_LENGTH) {\n return {\n error: `Expression exceeds maximum length of ${MAX_EXPRESSION_LENGTH} characters`\n };\n }\n try {\n const celBindings: Record<string, CelInput> = {};\n for (const [k, v] of Object.entries(bindings)) {\n celBindings[k] = v as CelInput;\n }\n const result = celRun(expression, celBindings, celOptions);\n if (isCelError(result)) {\n return { error: result.message };\n }\n return { result: celToNative(result as CelValue) };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { error: message };\n }\n}\n\n/**\n * Validate a CEL expression with exhaustive testing of optional properties.\n * Each CelVariable becomes a top-level binding in the CEL environment.\n */\nexport function validateCelExpression(\n expression: string,\n variables: CelVariable[]\n): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (!expression.trim()) return { valid: true };\n\n // Step 1: Build bindings and syntax-check\n const bindings: Record<string, unknown> = {};\n for (const v of variables) {\n bindings[v.name] = fuzzJTDForCel(v.schema);\n }\n\n const syntaxCheck = evaluateExpression(expression, bindings);\n if (syntaxCheck.error) {\n return {\n valid: false,\n errors: [{ message: `Syntax error: ${syntaxCheck.error}` }]\n };\n }\n\n // Step 2: Extract accessed paths\n const variableNames = variables.map((v) => v.name);\n const accessedPaths = extractAccessPaths(expression, variableNames);\n if (accessedPaths.length === 0) return { valid: true };\n\n // Step 3: Generate test permutations\n const permutations = generateTestPermutations(variables, accessedPaths);\n\n // Step 4: Test each permutation (skip base case)\n for (let i = 1; i < permutations.length; i++) {\n const perm = permutations[i]!;\n const testResult = evaluateExpression(expression, perm.bindings);\n\n if (testResult.error) {\n errors.push({\n message: `Expression fails when ${perm.description}: ${testResult.error}`,\n path: perm.unsetPath,\n isOptionalAccess: true\n });\n }\n }\n\n return errors.length > 0 ? { valid: false, errors } : { valid: true };\n}\n\n/** Quick validation that only checks syntax, without optional property testing. */\nexport function validateCelExpressionSyntax(\n expression: string,\n variables: CelVariable[]\n): ValidationResult {\n if (!expression.trim()) return { valid: true };\n\n const bindings: Record<string, unknown> = {};\n for (const v of variables) {\n bindings[v.name] = fuzzJTDForCel(v.schema);\n }\n\n const result = evaluateExpression(expression, bindings);\n if (result.error) {\n return { valid: false, errors: [{ message: result.error }] };\n }\n return { valid: true };\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 LANGUAGE DEFINITION\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 CEL_LANGUAGE_ID = 'cel';\n\nexport interface FuncDescriptor {\n name: string;\n detail: string;\n documentation: string;\n params: string[];\n}\n\nexport interface MethodDescriptor extends FuncDescriptor {\n receiverType: string;\n}\n\n/** All global function descriptors (union of all plugins). */\nexport const GLOBAL_FUNCTIONS: FuncDescriptor[] = [\n // Type conversions (std/cast)\n {\n name: 'string',\n detail: 'string(x) \u2192 string',\n documentation:\n 'Convert value to string. Works on bool, int, uint, double, bytes, timestamp, duration.',\n params: ['x']\n },\n {\n name: 'int',\n detail: 'int(x) \u2192 int',\n documentation:\n 'Convert value to integer. Works on uint, double, string, timestamp, duration.',\n params: ['x']\n },\n {\n name: 'uint',\n detail: 'uint(x) \u2192 uint',\n documentation:\n 'Convert value to unsigned integer. Works on int, double, string.',\n params: ['x']\n },\n {\n name: 'double',\n detail: 'double(x) \u2192 double',\n documentation: 'Convert value to double. Works on int, uint, string.',\n params: ['x']\n },\n {\n name: 'bool',\n detail: 'bool(x) \u2192 bool',\n documentation:\n 'Convert value to boolean. String values: \"true\", \"false\", \"t\", \"f\", \"1\", \"0\".',\n params: ['x']\n },\n {\n name: 'bytes',\n detail: 'bytes(x) \u2192 bytes',\n documentation: 'Convert value to bytes. String is UTF-8 encoded.',\n params: ['x']\n },\n {\n name: 'timestamp',\n detail: 'timestamp(x) \u2192 timestamp',\n documentation: 'Convert value to timestamp. String must be RFC3339 format.',\n params: ['x']\n },\n {\n name: 'duration',\n detail: 'duration(x) \u2192 duration',\n documentation:\n 'Convert value to duration. String format: \"300s\", \"1.5h\", \"2m30s\".',\n params: ['x']\n },\n {\n name: 'type',\n detail: 'type(x) \u2192 type',\n documentation: 'Returns the type of the value.',\n params: ['x']\n },\n {\n name: 'dyn',\n detail: 'dyn(x) \u2192 dyn',\n documentation: 'Identity function, returns the value unchanged.',\n params: ['x']\n },\n\n // Collection/logic (std)\n {\n name: 'size',\n detail: 'size(x) \u2192 int',\n documentation: 'Returns size of string (codepoints), list, bytes, or map.',\n params: ['x']\n },\n {\n name: 'has',\n detail: 'has(x.field) \u2192 bool',\n documentation:\n 'Check if field exists and is not null. Use to guard optional values.',\n params: ['x.field']\n },\n\n // Date/time\n {\n name: 'now',\n detail: 'now() \u2192 timestamp',\n documentation: 'Returns the current timestamp.',\n params: []\n },\n\n // String functions (ext/strings)\n {\n name: 'strings.quote',\n detail: 'strings.quote(s) \u2192 string',\n documentation: 'Returns a quoted string with escape sequences.',\n params: ['s']\n },\n\n // Aggregate functions\n {\n name: 'sum',\n detail: 'sum(list) \u2192 number',\n documentation: 'Sum of numeric list elements.',\n params: ['list']\n },\n {\n name: 'min',\n detail: 'min(list) \u2192 number',\n documentation: 'Minimum value in a numeric list.',\n params: ['list']\n },\n {\n name: 'max',\n detail: 'max(list) \u2192 number',\n documentation: 'Maximum value in a numeric list.',\n params: ['list']\n },\n {\n name: 'avg',\n detail: 'avg(list) \u2192 number',\n documentation: 'Average of numeric list elements.',\n params: ['list']\n },\n {\n name: 'includes',\n detail: 'includes(list, element) \u2192 bool',\n documentation: 'True if list contains element.',\n params: ['list', 'element']\n },\n {\n name: 'findIndex',\n detail: 'findIndex(list, element) \u2192 int',\n documentation: 'Index of first occurrence, or -1.',\n params: ['list', 'element']\n },\n {\n name: 'findLastIndex',\n detail: 'findLastIndex(list, element) \u2192 int',\n documentation: 'Index of last occurrence, or -1.',\n params: ['list', 'element']\n },\n\n // String transformation\n {\n name: 'lower',\n detail: 'lower(s) \u2192 string',\n documentation: 'Full Unicode lowercase.',\n params: ['s']\n },\n {\n name: 'upper',\n detail: 'upper(s) \u2192 string',\n documentation: 'Full Unicode uppercase.',\n params: ['s']\n },\n\n // Encoding\n {\n name: 'base64decode',\n detail: 'base64decode(s) \u2192 bytes',\n documentation: 'Decode base64 string to bytes.',\n params: ['s']\n },\n {\n name: 'base64encode',\n detail: 'base64encode(data) \u2192 string',\n documentation: 'Encode bytes to base64 string.',\n params: ['data']\n },\n {\n name: 'encode',\n detail: 'encode(value, encoding?) \u2192 bytes',\n documentation:\n 'JSON-serialize any value to bytes. Default encoding: utf-8. If value is already bytes, passes through.',\n params: ['value', 'encoding']\n },\n {\n name: 'decode',\n detail: 'decode(data, encoding?) \u2192 dyn',\n documentation: 'Parse JSON bytes to a value. Default encoding: utf-8.',\n params: ['data', 'encoding']\n },\n\n // HTML escaping\n {\n name: 'htmlEscape',\n detail: 'htmlEscape(s) \u2192 string',\n documentation:\n 'HTML-encode a string for safe insertion into HTML text content.',\n params: ['s']\n },\n {\n name: 'attrEscape',\n detail: 'attrEscape(s) \u2192 string',\n documentation:\n 'HTML-encode a string for safe insertion into an HTML attribute value.',\n params: ['s']\n }\n];\n\n/** All method descriptors (deduplicated union of all plugins). */\nexport const CEL_METHODS: MethodDescriptor[] = [\n // \u2500\u2500\u2500 String methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'contains',\n detail: '.contains(substr) \u2192 bool',\n documentation: 'True if string contains substr.',\n params: ['substr'],\n receiverType: 'string'\n },\n {\n name: 'startsWith',\n detail: '.startsWith(prefix) \u2192 bool',\n documentation: 'True if string starts with prefix.',\n params: ['prefix'],\n receiverType: 'string'\n },\n {\n name: 'endsWith',\n detail: '.endsWith(suffix) \u2192 bool',\n documentation: 'True if string ends with suffix.',\n params: ['suffix'],\n receiverType: 'string'\n },\n {\n name: 'matches',\n detail: '.matches(regex) \u2192 bool',\n documentation: 'True if string matches RE2 regex pattern.',\n params: ['regex'],\n receiverType: 'string'\n },\n {\n name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Returns number of Unicode codepoints in string.',\n params: [],\n receiverType: 'string'\n },\n\n // \u2500\u2500\u2500 String methods (ext/strings) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'charAt',\n detail: '.charAt(index) \u2192 string',\n documentation: 'Returns character at index.',\n params: ['index'],\n receiverType: 'string'\n },\n {\n name: 'indexOf',\n detail: '.indexOf(substr, start?) \u2192 int',\n documentation: 'Index of first occurrence of substr, or -1 if not found.',\n params: ['substr', 'start'],\n receiverType: 'string'\n },\n {\n name: 'lastIndexOf',\n detail: '.lastIndexOf(substr, start?) \u2192 int',\n documentation: 'Index of last occurrence of substr, or -1 if not found.',\n params: ['substr', 'start'],\n receiverType: 'string'\n },\n {\n name: 'lowerAscii',\n detail: '.lowerAscii() \u2192 string',\n documentation: 'Convert ASCII letters to lowercase (A-Z only).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'upperAscii',\n detail: '.upperAscii() \u2192 string',\n documentation: 'Convert ASCII letters to uppercase (a-z only).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'replace',\n detail: '.replace(old, new, count?) \u2192 string',\n documentation:\n 'Replace occurrences of old with new. If count specified, replaces at most count times.',\n params: ['old', 'new', 'count'],\n receiverType: 'string'\n },\n {\n name: 'split',\n detail: '.split(sep, count?) \u2192 list',\n documentation:\n 'Split string by separator. If count specified, splits into at most count parts.',\n params: ['sep', 'count'],\n receiverType: 'string'\n },\n {\n name: 'substring',\n detail: '.substring(start, end?) \u2192 string',\n documentation:\n 'Extract substring from start index to end index (exclusive).',\n params: ['start', 'end'],\n receiverType: 'string'\n },\n {\n name: 'trim',\n detail: '.trim() \u2192 string',\n documentation: 'Remove leading and trailing Unicode whitespace.',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'format',\n detail: '.format(args) \u2192 string',\n documentation:\n 'Format string with arguments. Placeholders: %s (string), %d (decimal), %f (float), %e (exponent), %x (hex), %o (octal), %b (binary).',\n params: ['args'],\n receiverType: 'string'\n },\n {\n name: 'lower',\n detail: '.lower() \u2192 string',\n documentation: 'Lowercase string (full Unicode).',\n params: [],\n receiverType: 'string'\n },\n {\n name: 'upper',\n detail: '.upper() \u2192 string',\n documentation: 'Uppercase string (full Unicode).',\n params: [],\n receiverType: 'string'\n },\n\n // \u2500\u2500\u2500 List methods (ext/strings) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'join',\n detail: '.join(sep?) \u2192 string',\n documentation: 'Join list elements into string with optional separator.',\n params: ['sep'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Number of elements in list.',\n params: [],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List macros (built-in) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'map',\n detail: '.map(x, expr) \u2192 list',\n documentation: 'Transform each element using expression.',\n params: ['x', 'expr'],\n receiverType: 'list'\n },\n {\n name: 'filter',\n detail: '.filter(x, predicate) \u2192 list',\n documentation: 'Filter elements by predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'all',\n detail: '.all(x, predicate) \u2192 bool',\n documentation: 'True if all elements match predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'exists',\n detail: '.exists(x, predicate) \u2192 bool',\n documentation: 'True if any element matches predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n {\n name: 'exists_one',\n detail: '.exists_one(x, predicate) \u2192 bool',\n documentation: 'True if exactly one element matches predicate.',\n params: ['x', 'predicate'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 List aggregate methods (custom) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'sum',\n detail: '.sum() \u2192 number',\n documentation: 'Sum of numeric list elements.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'min',\n detail: '.min() \u2192 number',\n documentation: 'Minimum value in list.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'max',\n detail: '.max() \u2192 number',\n documentation: 'Maximum value in list.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'avg',\n detail: '.avg() \u2192 number',\n documentation: 'Average of list elements.',\n params: [],\n receiverType: 'list'\n },\n {\n name: 'includes',\n detail: '.includes(element) \u2192 bool',\n documentation: 'True if list contains element.',\n params: ['element'],\n receiverType: 'list'\n },\n {\n name: 'findIndex',\n detail: '.findIndex(element) \u2192 int',\n documentation: 'First index of element, or -1.',\n params: ['element'],\n receiverType: 'list'\n },\n {\n name: 'findLastIndex',\n detail: '.findLastIndex(element) \u2192 int',\n documentation: 'Last index of element, or -1.',\n params: ['element'],\n receiverType: 'list'\n },\n\n // \u2500\u2500\u2500 Timestamp methods (std/time) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'getFullYear',\n detail: '.getFullYear(tz?) \u2192 int',\n documentation: '4-digit year. Optional timezone (IANA or fixed offset).',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMonth',\n detail: '.getMonth(tz?) \u2192 int',\n documentation: 'Month (0-11). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDate',\n detail: '.getDate(tz?) \u2192 int',\n documentation: 'Day of month (1-31). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfMonth',\n detail: '.getDayOfMonth(tz?) \u2192 int',\n documentation: 'Day of month (0-30). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfWeek',\n detail: '.getDayOfWeek(tz?) \u2192 int',\n documentation: 'Day of week (0=Sunday). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getDayOfYear',\n detail: '.getDayOfYear(tz?) \u2192 int',\n documentation: 'Day of year (0-365). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getHours',\n detail: '.getHours(tz?) \u2192 int',\n documentation: 'Hours (0-23). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMinutes',\n detail: '.getMinutes(tz?) \u2192 int',\n documentation: 'Minutes (0-59). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getSeconds',\n detail: '.getSeconds(tz?) \u2192 int',\n documentation: 'Seconds (0-59). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'getMilliseconds',\n detail: '.getMilliseconds(tz?) \u2192 int',\n documentation: 'Milliseconds (0-999). Optional timezone.',\n params: ['tz'],\n receiverType: 'timestamp'\n },\n {\n name: 'formatDate',\n detail: '.formatDate(pattern) \u2192 string',\n documentation: 'Format timestamp. Patterns: YYYY, YY, MM, DD, HH, mm, ss.',\n params: ['pattern'],\n receiverType: 'timestamp'\n },\n\n // \u2500\u2500\u2500 Duration methods (std/time) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'getSeconds',\n detail: '.getSeconds() \u2192 int',\n documentation: 'Total seconds in duration.',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getMinutes',\n detail: '.getMinutes() \u2192 int',\n documentation: 'Total minutes in duration (seconds / 60).',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getHours',\n detail: '.getHours() \u2192 int',\n documentation: 'Total hours in duration (seconds / 3600).',\n params: [],\n receiverType: 'duration'\n },\n {\n name: 'getMilliseconds',\n detail: '.getMilliseconds() \u2192 int',\n documentation: 'Milliseconds portion of duration.',\n params: [],\n receiverType: 'duration'\n },\n\n // \u2500\u2500\u2500 Map/bytes methods (std/logic) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 name: 'size',\n detail: '.size() \u2192 int',\n documentation: 'Number of entries in map or bytes in buffer.',\n params: [],\n receiverType: 'map'\n }\n];\n\n/** Lookup table: function name \u2192 descriptors (for hover/signature help). */\nexport const CEL_DESCRIPTORS: Map<string, FuncDescriptor[]> = (() => {\n const map = new Map<string, FuncDescriptor[]>();\n for (const f of GLOBAL_FUNCTIONS) {\n const baseName = f.name.includes('.') ? f.name.split('.')[1]! : f.name;\n map.set(baseName, [f]);\n }\n for (const m of CEL_METHODS) {\n const existing = map.get(m.name);\n if (existing) {\n if (!existing.some((e) => e.detail === m.detail)) existing.push(m);\n } else {\n map.set(m.name, [m]);\n }\n }\n return map;\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// DYNAMIC INPUT VARIABLES (for Monaco autocompletion)\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 interface InputVariable {\n name: string;\n label?: string;\n schema?: JTDSchemaJson;\n}\n\nlet currentInputVariables: InputVariable[] = [];\n\n/** Update the available input variables for Monaco autocompletion. */\nexport function setInputVariables(inputs: InputVariable[]): void {\n currentInputVariables = inputs;\n}\n\n/** Resolve ref to its definition, passthrough otherwise. */\nfunction resolveInputSchema(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson {\n return schema.ref && defs?.[schema.ref]\n ? resolveInputSchema(defs[schema.ref]!, defs)\n : schema;\n}\n\n/** Get the root definitions from a schema (only present on root-level schemas). */\nfunction getRootDefs(\n schema: JTDSchemaJson | undefined\n): Record<string, JTDSchemaJson> | undefined {\n return schema?.definitions;\n}\n\nfunction getSchemaAtPath(\n schema: JTDSchemaJson | undefined,\n path: string[],\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson | undefined {\n if (!schema || path.length === 0) return schema;\n const resolved = resolveInputSchema(schema, defs);\n const [first, ...rest] = path;\n\n // Properties form\n const props = { ...resolved.properties, ...resolved.optionalProperties };\n if (first && props[first]) {\n return getSchemaAtPath(props[first]!, rest, defs);\n }\n\n // Discriminator form \u2014 expose union of all variant properties + discriminator tag\n if (resolved.discriminator && resolved.mapping && first) {\n if (first === resolved.discriminator) {\n // The tag itself \u2014 it's a string enum of mapping keys\n return rest.length === 0\n ? { enum: Object.keys(resolved.mapping) }\n : undefined;\n }\n // Search all variants for the property\n for (const variant of Object.values(resolved.mapping)) {\n const variantProps = {\n ...variant.properties,\n ...variant.optionalProperties\n };\n if (variantProps[first]) {\n return getSchemaAtPath(variantProps[first]!, rest, defs);\n }\n }\n }\n\n return undefined;\n}\n\nfunction describeSchemaType(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): string {\n const resolved = resolveInputSchema(schema, defs);\n if (resolved.type) return resolved.type;\n if (resolved.enum) {\n return `enum(${resolved.enum.slice(0, 3).join(', ')}${resolved.enum.length > 3 ? '...' : ''})`;\n }\n if (resolved.properties || resolved.optionalProperties) return 'object';\n if (resolved.elements) return 'list';\n if (resolved.values) return 'map';\n if (resolved.discriminator) return `union(${resolved.discriminator})`;\n return 'any';\n}\n\nfunction getSchemaProperties(\n schema: JTDSchemaJson | undefined,\n defs?: Record<string, JTDSchemaJson>\n): { name: string; type: string }[] {\n if (!schema) return [];\n const resolved = resolveInputSchema(schema, defs);\n const result: { name: string; type: string }[] = [];\n\n // Properties form\n const props = { ...resolved.properties, ...resolved.optionalProperties };\n for (const [name, propSchema] of Object.entries(props)) {\n result.push({ name, type: describeSchemaType(propSchema, defs) });\n }\n\n // Discriminator form \u2014 expose tag + union of all variant properties\n if (resolved.discriminator && resolved.mapping) {\n const tags = Object.keys(resolved.mapping);\n result.push({ name: resolved.discriminator, type: tags.join(' | ') });\n const seen = new Set<string>([resolved.discriminator]);\n for (const variant of Object.values(resolved.mapping)) {\n const variantProps = {\n ...variant.properties,\n ...variant.optionalProperties\n };\n for (const [name, propSchema] of Object.entries(variantProps)) {\n if (!seen.has(name)) {\n seen.add(name);\n result.push({ name, type: describeSchemaType(propSchema, defs) });\n }\n }\n }\n }\n\n return result;\n}\n\n/** Check if a schema has navigable child properties for autocomplete. */\nfunction hasChildProperties(\n schema: JTDSchemaJson | undefined,\n defs?: Record<string, JTDSchemaJson>\n): boolean {\n if (!schema) return false;\n const resolved = resolveInputSchema(schema, defs);\n return !!(\n resolved.properties ||\n resolved.optionalProperties ||\n (resolved.discriminator && resolved.mapping)\n );\n}\n\n// Deduplicate methods for completion\nfunction deduplicatedMethods(): MethodDescriptor[] {\n const seen = new Set<string>();\n const result: MethodDescriptor[] = [];\n for (const m of CEL_METHODS) {\n const key = `${m.name}|${m.detail}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(m);\n }\n }\n return result;\n}\n\n/**\n * Register CEL language with Monaco editor.\n * Takes a monaco instance as parameter \u2014 no monaco import needed.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function registerCelLanguage(monaco: any): void {\n if (\n monaco.languages\n .getLanguages()\n .some((l: { id: string }) => l.id === CEL_LANGUAGE_ID)\n )\n return;\n\n monaco.languages.register({ id: CEL_LANGUAGE_ID });\n\n // \u2500\u2500 Language configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.setLanguageConfiguration(CEL_LANGUAGE_ID, {\n brackets: [\n ['(', ')'],\n ['[', ']'],\n ['{', '}']\n ],\n autoClosingPairs: [\n { open: '(', close: ')' },\n { open: '[', close: ']' },\n { open: '{', close: '}' }\n ],\n surroundingPairs: [\n { open: '(', close: ')' },\n { open: '[', close: ']' },\n { open: '{', close: '}' },\n { open: '\"', close: '\"' },\n { open: \"'\", close: \"'\" }\n ]\n });\n\n // \u2500\u2500 Monarch tokenizer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.setMonarchTokensProvider(CEL_LANGUAGE_ID, {\n keywords: ['true', 'false', 'null', 'in'],\n builtins: GLOBAL_FUNCTIONS.map((f) => f.name.split('.')[0]!),\n operators: [\n '&&',\n '||',\n '!',\n '==',\n '!=',\n '<=',\n '>=',\n '<',\n '>',\n '+',\n '-',\n '*',\n '/',\n '%',\n '?',\n ':'\n ],\n tokenizer: {\n root: [\n [/\"(?:[^\"\\\\]|\\\\.)*\"/, 'string'],\n [/'(?:[^'\\\\]|\\\\.)*'/, 'string'],\n [/\\d+\\.\\d*([eE][-+]?\\d+)?/, 'number.float'],\n [/\\d*\\.\\d+([eE][-+]?\\d+)?/, 'number.float'],\n [/\\d+[eE][-+]?\\d+/, 'number.float'],\n [/0[xX][0-9a-fA-F]+[uU]?/, 'number.hex'],\n [/\\d+[uU]?/, 'number'],\n [/\\./, 'delimiter', '@afterDot'],\n [\n /[a-zA-Z_]\\w*/,\n {\n cases: {\n '@keywords': 'keyword',\n '@builtins': 'predefined',\n '@default': 'identifier'\n }\n }\n ],\n [/&&|\\|\\||[!=]=|[<>]=?/, 'operator'],\n [/[+\\-*/%?:!]/, 'operator'],\n [/[[\\](){}]/, '@brackets'],\n [/,/, 'delimiter'],\n [/\\s+/, 'white']\n ],\n afterDot: [\n [/[a-zA-Z_]\\w*/, 'variable.property', '@pop'],\n [/\\s+/, 'white'],\n [/./, '@rematch', '@pop']\n ]\n }\n } as never);\n\n // \u2500\u2500 Completion provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerCompletionItemProvider(CEL_LANGUAGE_ID, {\n triggerCharacters: ['.'],\n provideCompletionItems: (model: any, position: any) => {\n const textUntilPosition = model.getValueInRange({\n startLineNumber: position.lineNumber,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column\n });\n\n // Suppress completions inside string literals\n let inDouble = false;\n let inSingle = false;\n for (let i = 0; i < textUntilPosition.length; i++) {\n const ch = textUntilPosition[i];\n if (ch === '\\\\') {\n i++;\n continue;\n }\n if (ch === '\"' && !inSingle) inDouble = !inDouble;\n if (ch === \"'\" && !inDouble) inSingle = !inSingle;\n }\n if (inDouble || inSingle) return { suggestions: [] };\n\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n };\n\n // After \"inputs.X.Y.\" - offer nested JTD properties + methods\n const inputsNestedMatch = textUntilPosition\n .slice(0, textUntilPosition.length - word.word.length)\n .match(/inputs\\.(\\w+(?:\\.\\w+)*)\\.\\s*$/);\n if (inputsNestedMatch) {\n const pathParts = inputsNestedMatch[1]!.split('.');\n const varName = pathParts[0]!;\n const nestedPath = pathParts.slice(1);\n const inputVar = currentInputVariables.find((v) => v.name === varName);\n if (inputVar?.schema) {\n const defs = getRootDefs(inputVar.schema);\n const schemaAtPath = getSchemaAtPath(\n inputVar.schema,\n nestedPath,\n defs\n );\n const properties = getSchemaProperties(schemaAtPath, defs);\n const suggestions: any[] = properties.map((prop, i) => {\n const childSchema = getSchemaAtPath(\n schemaAtPath!,\n [prop.name],\n defs\n );\n const isNavigable = hasChildProperties(childSchema, defs);\n return {\n label: prop.name,\n kind: isNavigable\n ? monaco.languages.CompletionItemKind.Module\n : monaco.languages.CompletionItemKind.Property,\n detail: prop.type,\n documentation: `Property of inputs.${pathParts.join('.')}`,\n insertText: prop.name,\n range,\n sortText: String(i).padStart(3, '0')\n };\n });\n\n // Always include methods (they apply to any value after a dot)\n const methods = deduplicatedMethods();\n for (let mi = 0; mi < methods.length; mi++) {\n const m = methods[mi]!;\n suggestions.push({\n label: m.name,\n kind: monaco.languages.CompletionItemKind.Method,\n detail: `${m.detail} (${m.receiverType})`,\n documentation: m.documentation,\n insertText: m.params.length > 0 ? `${m.name}($0)` : `${m.name}()`,\n insertTextRules:\n m.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule\n .InsertAsSnippet\n : undefined,\n range,\n sortText: String(properties.length + mi).padStart(3, '0')\n });\n }\n\n return { suggestions };\n }\n return { suggestions: [] };\n }\n\n // After just \"inputs.\" - offer top-level input variable names\n if (\n /inputs\\.\\s*$/.test(\n textUntilPosition.slice(\n 0,\n textUntilPosition.length - word.word.length\n )\n )\n ) {\n return {\n suggestions: currentInputVariables.map((v, i) => {\n const hasNestedProps = hasChildProperties(\n v.schema,\n getRootDefs(v.schema)\n );\n return {\n label: v.name,\n kind: hasNestedProps\n ? monaco.languages.CompletionItemKind.Module\n : monaco.languages.CompletionItemKind.Variable,\n detail: v.label || (hasNestedProps ? 'object' : 'Input variable'),\n documentation: `Access as inputs.${v.name}${hasNestedProps ? ' (has nested properties)' : ''}`,\n insertText: v.name,\n range,\n sortText: String(i).padStart(3, '0')\n };\n })\n };\n }\n\n // After any other dot - offer methods\n if (\n /\\.\\s*$/.test(\n textUntilPosition.slice(\n 0,\n textUntilPosition.length - word.word.length\n )\n )\n ) {\n const methods = deduplicatedMethods();\n return {\n suggestions: methods.map((m, i) => ({\n label: m.name,\n kind: monaco.languages.CompletionItemKind.Method,\n detail: `${m.detail} (${m.receiverType})`,\n documentation: m.documentation,\n insertText: m.params.length > 0 ? `${m.name}($0)` : `${m.name}()`,\n insertTextRules:\n m.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet\n : undefined,\n range,\n sortText: String(i).padStart(3, '0')\n }))\n };\n }\n\n // Root level - offer global functions and input variables\n const suggestions: any[] = [];\n let sortIndex = 0;\n\n // inputs variable\n suggestions.push({\n label: 'inputs',\n kind: monaco.languages.CompletionItemKind.Variable,\n detail: 'object',\n documentation: 'Access input signals (e.g., inputs.customerName)',\n insertText: 'inputs.',\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n\n // Dynamic input variables with full path\n for (const v of currentInputVariables) {\n suggestions.push({\n label: `inputs.${v.name}`,\n kind: monaco.languages.CompletionItemKind.Variable,\n detail: v.label || 'Input variable',\n documentation: `Access the \"${v.name}\" input signal`,\n insertText: `inputs.${v.name}`,\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n }\n\n // Global functions\n for (const f of GLOBAL_FUNCTIONS) {\n suggestions.push({\n label: f.name,\n kind: monaco.languages.CompletionItemKind.Function,\n detail: f.detail,\n documentation: f.documentation,\n insertText: f.params.length > 0 ? `${f.name}($0)` : `${f.name}()`,\n insertTextRules:\n f.params.length > 0\n ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet\n : undefined,\n range,\n sortText: String(sortIndex++).padStart(3, '0')\n });\n }\n\n return { suggestions };\n }\n });\n\n // \u2500\u2500 Hover provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerHoverProvider(CEL_LANGUAGE_ID, {\n provideHover: (model: any, position: any) => {\n const word = model.getWordAtPosition(position);\n if (!word) return null;\n\n // Check for input variable\n const inputVar = currentInputVariables.find((v) => v.name === word.word);\n if (inputVar) {\n return {\n range: {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n },\n contents: [\n {\n value: `**inputs.${inputVar.name}**${inputVar.label ? `\\n\\n${inputVar.label}` : ''}`\n }\n ]\n };\n }\n\n // Check functions/methods\n const descriptors = CEL_DESCRIPTORS.get(word.word);\n if (descriptors && descriptors.length > 0) {\n return {\n range: {\n startLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endLineNumber: position.lineNumber,\n endColumn: word.endColumn\n },\n contents: descriptors.map((d) => ({\n value: `**${d.detail}**\\n\\n${d.documentation}`\n }))\n };\n }\n\n return null;\n }\n });\n\n // \u2500\u2500 Signature help provider \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 monaco.languages.registerSignatureHelpProvider(CEL_LANGUAGE_ID, {\n signatureHelpTriggerCharacters: ['(', ','],\n provideSignatureHelp: (model: any, position: any) => {\n const textUntilPosition = model.getValueInRange({\n startLineNumber: position.lineNumber,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column\n });\n\n let depth = 0;\n let commaCount = 0;\n let parenIdx = -1;\n for (let i = textUntilPosition.length - 1; i >= 0; i--) {\n const ch = textUntilPosition[i];\n if (ch === ')') depth++;\n else if (ch === '(') {\n if (depth === 0) {\n parenIdx = i;\n break;\n }\n depth--;\n } else if (ch === ',' && depth === 0) {\n commaCount++;\n }\n }\n if (parenIdx < 0) return null;\n\n const before = textUntilPosition.slice(0, parenIdx);\n const nameMatch = before.match(/([a-zA-Z_]\\w*)\\s*$/);\n if (!nameMatch) return null;\n const funcName = nameMatch[1]!;\n\n const descriptors = CEL_DESCRIPTORS.get(funcName);\n if (!descriptors || descriptors.length === 0) return null;\n\n const signatures = descriptors\n .filter((d) => d.params.length > 0)\n .map((d) => ({\n label: d.detail,\n documentation: d.documentation,\n parameters: d.params.map((p) => ({ label: p }))\n }));\n\n if (signatures.length === 0) return null;\n\n return {\n value: {\n signatures,\n activeSignature: 0,\n activeParameter: Math.min(\n commaCount,\n signatures[0]!.parameters.length - 1\n )\n },\n dispose() {}\n };\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// CEL SYMBOL TREE (for advanced autocomplete with 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\nexport interface CelPropertyNode {\n detail: string;\n children: Record<string, CelPropertyNode>;\n}\n\nexport type CelSymbolTree = Record<string, CelPropertyNode>;\n\nconst ELEMENT_KEY = '[*]';\n\nfunction resolveSchema(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): JTDSchemaJson {\n return schema.ref && defs?.[schema.ref]\n ? resolveSchema(defs[schema.ref]!, defs)\n : schema;\n}\n\nfunction buildNode(\n schema: JTDSchemaJson,\n defs?: Record<string, JTDSchemaJson>\n): CelPropertyNode {\n const r = resolveSchema(schema, defs);\n const children: Record<string, CelPropertyNode> = {};\n let detail: string;\n\n if (r.type) {\n detail = r.type;\n } else if (r.enum) {\n detail = r.enum.map((v) => JSON.stringify(v)).join(' | ');\n } else if (r.elements) {\n const el = buildNode(r.elements, defs);\n children[ELEMENT_KEY] = el;\n detail = `${el.detail}[]`;\n } else if (r.values) {\n const val = buildNode(r.values, defs);\n children[ELEMENT_KEY] = val;\n detail = `map<${val.detail}>`;\n } else if (r.properties || r.optionalProperties) {\n const parts: string[] = [];\n if (r.properties) {\n for (const [k, v] of Object.entries(r.properties)) {\n const child = buildNode(v, defs);\n children[k] = child;\n parts.push(`${k}: ${child.detail}`);\n }\n }\n if (r.optionalProperties) {\n for (const [k, v] of Object.entries(r.optionalProperties)) {\n const child = buildNode(v, defs);\n children[k] = child;\n parts.push(`${k}?: ${child.detail}`);\n }\n }\n detail = `{ ${parts.join(', ')} }`;\n } else if (r.discriminator && r.mapping) {\n const tags = Object.keys(r.mapping);\n children[r.discriminator] = {\n detail: tags.map((t) => JSON.stringify(t)).join(' | '),\n children: {}\n };\n for (const variant of Object.values(r.mapping)) {\n const vNode = buildNode(variant, defs);\n for (const [k, v] of Object.entries(vNode.children)) {\n if (!(k in children)) children[k] = v;\n }\n }\n detail = `union(${r.discriminator}: ${tags.join(' | ')})`;\n } else {\n detail = 'any';\n }\n\n if (schema.nullable) detail += '?';\n if (schema.ref) detail = `ref(${schema.ref})`;\n\n return { detail, children };\n}\n\n/** Build symbol tree from signal bindings (JTD schemas \u2192 property tree). */\nexport function generateCelSymbolTree(\n bindings: SignalBindingJson[]\n): CelSymbolTree {\n const tree: CelSymbolTree = {};\n for (const binding of bindings) {\n if (!binding.name) continue;\n const format = binding.accepts?.[0];\n let node: CelPropertyNode;\n if (format?.jtdSchema) {\n node = buildNode(format.jtdSchema, format.jtdSchema.definitions);\n } else if (format?.mimeType) {\n node = { detail: format.mimeType, children: {} };\n } else {\n node = { detail: 'any', children: {} };\n }\n if (binding.optional) node = { ...node, detail: node.detail + ' | null' };\n tree[binding.name] = node;\n }\n return tree;\n}\n\nfunction buildTranslationNode(obj: Record<string, unknown>): CelPropertyNode {\n const children: Record<string, CelPropertyNode> = {};\n for (const [k, v] of Object.entries(obj)) {\n if (typeof v === 'string') {\n children[k] = { detail: 'string', children: {} };\n } else if (typeof v === 'object' && v !== null) {\n children[k] = buildTranslationNode(v as Record<string, unknown>);\n }\n }\n const parts = Object.entries(children).map(([k, c]) => `${k}: ${c.detail}`);\n return { detail: `{ ${parts.join(', ')} }`, children };\n}\n\nfunction deepMergeForTree(\n target: Record<string, unknown>,\n source: Record<string, unknown>\n): void {\n for (const [k, v] of Object.entries(source)) {\n if (\n typeof v === 'object' &&\n v !== null &&\n typeof target[k] === 'object' &&\n target[k] !== null\n ) {\n deepMergeForTree(\n target[k] as Record<string, unknown>,\n v as Record<string, unknown>\n );\n } else {\n target[k] = v;\n }\n }\n}\n\n/** Build symbol tree from translation dictionaries. */\nexport function generateTranslationsSymbolTree(\n translations: Record<string, Record<string, unknown>>\n): CelPropertyNode {\n const merged: Record<string, unknown> = {};\n for (const dict of Object.values(translations)) {\n deepMergeForTree(merged, dict);\n }\n return buildTranslationNode(merged);\n}\n\n/** Dot-path parsing for inputs.* and t.* */\nexport function parseDotPath(textBefore: string): string[] | null {\n const m = textBefore.match(\n /\\b(inputs|t)((?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.\\s*$/\n );\n if (!m) return null;\n\n const root = m[1]!;\n const chain = m[2]!;\n const segments: string[] = [root];\n let i = 0;\n while (i < chain.length) {\n if (chain[i] === '.') {\n i++;\n const id = chain.substring(i).match(/^[a-zA-Z_]\\w*/);\n if (id) {\n segments.push(id[0]);\n i += id[0].length;\n }\n } else if (chain[i] === '[') {\n const close = chain.indexOf(']', i);\n if (close === -1) break;\n segments.push(ELEMENT_KEY);\n i = close + 1;\n } else {\n i++;\n }\n }\n return segments;\n}\n\n/** Resolve a node in the symbol tree by walking segments. */\nexport function resolveNode(\n tree: CelSymbolTree,\n segments: string[],\n tNode?: CelPropertyNode\n): CelPropertyNode | null {\n if (segments.length === 0) return null;\n\n if (segments[0] === 'inputs') {\n if (segments.length === 1)\n return { detail: 'Signal inputs', children: tree };\n let current: CelPropertyNode | undefined = tree[segments[1]!];\n if (!current) return null;\n for (let i = 2; i < segments.length; i++) {\n current = current.children[segments[i]!];\n if (!current) return null;\n }\n return current;\n }\n\n if (segments[0] === 't' && tNode) {\n if (segments.length === 1) return tNode;\n let current: CelPropertyNode | undefined = tNode.children[segments[1]!];\n if (!current) return null;\n for (let i = 2; i < segments.length; i++) {\n current = current.children[segments[i]!];\n if (!current) return null;\n }\n return current;\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// LAMBDA-AWARE RESOLUTION\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 interface LambdaBinding {\n varName: string;\n collectionSegments: string[];\n}\n\nfunction parseExprToSegments(expr: string): string[] {\n const segments: string[] = [];\n const firstId = expr.match(/^[a-zA-Z_]\\w*/);\n if (!firstId) return segments;\n segments.push(firstId[0]);\n let i = firstId[0].length;\n while (i < expr.length) {\n if (expr[i] === '.') {\n i++;\n const id = expr.substring(i).match(/^[a-zA-Z_]\\w*/);\n if (id) {\n segments.push(id[0]);\n i += id[0].length;\n } else break;\n } else if (expr[i] === '[') {\n const close = expr.indexOf(']', i);\n if (close === -1) break;\n segments.push(ELEMENT_KEY);\n i = close + 1;\n } else {\n break;\n }\n }\n return segments;\n}\n\n/**\n * Extract lambda variable bindings from CEL macro calls in the text.\n * e.g. `inputs.items.map(item, ...)` \u2192 [{ varName: \"item\", collectionSegments: [\"inputs\", \"items\"] }]\n */\nexport function extractLambdaBindings(text: string): LambdaBinding[] {\n const bindings: LambdaBinding[] = [];\n const re =\n /([a-zA-Z_]\\w*(?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.(?:map|filter|all|exists_one|exists)\\s*\\(\\s*([a-zA-Z_]\\w*)\\s*,/g;\n let m;\n while ((m = re.exec(text)) !== null) {\n const collectionSegments = parseExprToSegments(m[1]!);\n if (collectionSegments.length > 0) {\n bindings.push({ varName: m[2]!, collectionSegments });\n }\n }\n return bindings;\n}\n\n/** Parse any trailing dot-path from text (not restricted to inputs.*). */\nexport function parseGeneralDotPath(textBefore: string): string[] | null {\n const m = textBefore.match(\n /\\b([a-zA-Z_]\\w*(?:\\.[a-zA-Z_]\\w*|\\[[^\\]]*\\])*)\\.\\s*$/\n );\n if (!m) return null;\n const segments = parseExprToSegments(m[1]!);\n return segments.length > 0 ? segments : null;\n}\n\n/** Resolve a dot-path that may start with a lambda variable. */\nexport function resolveWithLambdas(\n tree: CelSymbolTree,\n segments: string[],\n lambdaBindings: LambdaBinding[],\n tNode?: CelPropertyNode\n): CelPropertyNode | null {\n if (segments.length === 0) return null;\n const root = segments[0]!;\n\n if (root === 'inputs' || root === 't') {\n return resolveNode(tree, segments, tNode);\n }\n\n // Check lambda bindings (last match = innermost scope)\n for (let i = lambdaBindings.length - 1; i >= 0; i--) {\n const binding = lambdaBindings[i]!;\n if (binding.varName === root) {\n const collectionNode = resolveWithLambdas(\n tree,\n binding.collectionSegments,\n lambdaBindings,\n tNode\n );\n if (!collectionNode) return null;\n\n const elementNode = collectionNode.children[ELEMENT_KEY];\n if (!elementNode) return null;\n\n let current: CelPropertyNode | undefined = elementNode;\n for (let j = 1; j < segments.length; j++) {\n current = current.children[segments[j]!];\n if (!current) return null;\n }\n return current;\n }\n }\n\n return null;\n}\n\n/** Extract the full dot-chain path containing the hovered word. */\nexport function extractHoverSegments(\n lineText: string,\n wordStartCol: number,\n word: string\n): string[] {\n const segments: string[] = [];\n let pos = wordStartCol - 2;\n\n while (pos >= 0 && lineText[pos] === '.') {\n pos--;\n const idEnd = pos + 1;\n while (pos >= 0 && /[a-zA-Z_0-9]/.test(lineText[pos]!)) {\n pos--;\n }\n const idStart = pos + 1;\n const id = lineText.substring(idStart, idEnd);\n if (/^[a-zA-Z_]\\w*$/.test(id) && id.length > 0) {\n segments.unshift(id);\n } else {\n break;\n }\n }\n\n segments.push(word);\n return segments;\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 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 'root';\n const joined = instancePath\n .map((p, i) => (/^\\d+$/.test(p) ? `[${p}]` : i === 0 ? p : `.${p}`))\n .join('');\n return `'${joined}'`;\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 const paramLabel = path === 'root' ? 'root value' : `parameter ${path}`;\n\n if (lastKey === 'type') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const jtdType = parent?.type as string;\n if (jtdType === 'boolean') return `${paramLabel}: expected boolean`;\n if (jtdType === 'string') return `${paramLabel}: expected string`;\n if (jtdType === 'timestamp')\n return `${paramLabel}: expected timestamp string`;\n if (INTEGER_TYPES.has(jtdType)) return `${paramLabel}: expected integer`;\n return `${paramLabel}: expected number`;\n }\n\n if (lastKey === 'enum') {\n const parent = resolveSchemaParent(schema, schemaPath);\n const enumValues = parent?.enum as string[];\n return `${paramLabel}: expected one of [${enumValues.join(', ')}]`;\n }\n\n if (\n schemaPath.length >= 2 &&\n schemaPath[schemaPath.length - 2] === 'properties' &&\n lastKey\n ) {\n if (path === 'root') {\n return `missing required parameter '${lastKey}'`;\n }\n return `missing required parameter ${path}.${lastKey}`;\n }\n\n if (lastKey === 'elements') return `${paramLabel}: expected array`;\n\n if (\n lastKey === 'properties' ||\n lastKey === 'optionalProperties' ||\n lastKey === 'values'\n ) {\n return `${paramLabel}: expected object`;\n }\n\n if (lastKey === 'discriminator') {\n // Find the discriminator field name from the schema\n const parent = resolveSchemaParent(schema, schemaPath);\n const discField = parent?.discriminator as string | undefined;\n if (discField) {\n return `${paramLabel}: parameter '${discField}' must be a string`;\n }\n return `${paramLabel}: expected string discriminator`;\n }\n\n if (lastKey === 'mapping') {\n const discValue = resolveInstanceValue(value, instancePath);\n // Try to list valid variants from the mapping\n const parent = resolveSchemaParent(schema, schemaPath);\n const mapping = parent?.mapping as Record<string, unknown> | undefined;\n const validVariants = mapping ? Object.keys(mapping) : [];\n if (validVariants.length > 0) {\n return `${paramLabel}: unknown variant \"${discValue}\". Valid values: [${validVariants.join(', ')}]`;\n }\n return `${paramLabel}: unknown variant \"${discValue}\"`;\n }\n\n if (schemaPath.length === 0) return `${paramLabel}: unexpected property`;\n\n return `${paramLabel}: 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}\" in schema`];\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.\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 *\n * JTD `metadata.description` is preserved as JSON Schema `description`.\n * Other metadata fields are appended to the description for context.\n *\n * Top-level `definitions` are emitted as JSON Schema `$defs` and\n * referenced via `$ref` (not inlined), keeping large schemas compact.\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 // Emit top-level definitions as $defs (only at root)\n if (defs && Object.keys(defs).length > 0) {\n result.$defs = {};\n for (const [name, defSchema] of Object.entries(defs)) {\n result.$defs[name] = convertNode(defSchema as JTDSchemaJson, defs);\n }\n }\n }\n\n // Build the schema node \u2014 delegate to convertNode for the actual form logic\n const node = convertNode(jtdSchema, defs);\n Object.assign(result, node);\n\n return result;\n}\n\n/** Convert a single JTD node to JSON Schema. Internal recursive worker. */\nfunction convertNode(\n jtdSchema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined\n): any {\n if (!jtdSchema || typeof jtdSchema !== 'object') {\n return {};\n }\n\n const isNullable = jtdSchema['nullable'];\n const result: any = {};\n\n // Extract metadata.description \u2192 JSON Schema description\n applyMetadata(result, jtdSchema);\n\n // \u2500\u2500 Ref form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['ref']) {\n const refName = jtdSchema['ref'] as string;\n if (defs && defs[refName]) {\n const refResult: any = { $ref: `#/$defs/${refName}` };\n applyMetadata(refResult, jtdSchema);\n\n if (isNullable) {\n return {\n anyOf: [refResult, { type: 'null' }],\n ...(refResult.description\n ? { description: refResult.description }\n : {})\n };\n }\n return refResult;\n }\n return {};\n }\n\n // \u2500\u2500 Type form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 // \u2500\u2500 Enum form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 // \u2500\u2500 Elements form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['elements']) {\n result.type = isNullable ? ['array', 'null'] : 'array';\n result.items = convertNode(jtdSchema['elements'] as JTDSchemaJson, defs);\n return result;\n }\n\n // \u2500\u2500 Properties form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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] = convertNode(value as JTDSchemaJson, defs);\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] = convertNode(value as JTDSchemaJson, defs);\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 // \u2500\u2500 Values form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 if (jtdSchema['values']) {\n result.type = isNullable ? ['object', 'null'] : 'object';\n result.additionalProperties = convertNode(\n jtdSchema['values'] as JTDSchemaJson,\n defs\n );\n return result;\n }\n\n // \u2500\u2500 Discriminator form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 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 = convertNode(schema as JTDSchemaJson, defs);\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 // \u2500\u2500 Empty form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 return result;\n}\n\n/**\n * Extract JTD metadata and apply as JSON Schema `description`.\n *\n * - `metadata.description` becomes `description` directly.\n * - Other metadata fields are appended as \"key: value\" lines.\n */\nfunction applyMetadata(result: any, jtdSchema: JTDSchemaJson): void {\n const metadata = jtdSchema['metadata'] as Record<string, unknown> | undefined;\n if (!metadata || typeof metadata !== 'object') return;\n\n const parts: string[] = [];\n const desc = metadata['description'];\n if (typeof desc === 'string' && desc) {\n parts.push(desc);\n }\n\n // Fold other metadata fields into description\n for (const [key, value] of Object.entries(metadata)) {\n if (key === 'description') continue;\n if (value === undefined || value === null) continue;\n const str = typeof value === 'string' ? value : JSON.stringify(value);\n parts.push(`${key}: ${str}`);\n }\n\n if (parts.length > 0) {\n result.description = parts.join('\\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// 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", "/**\n * Shared utilities for JSON Schema providers (OpenAI, Anthropic, Gemini).\n *\n * Contains constants, types, convert output pipeline, definition pooling,\n * and schema inspection helpers used identically across providers.\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// 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\nexport const MAX_REF_DEPTH = 32;\n\nexport const INTEGER_BOUNDS: Record<\n string,\n { minimum: number; maximum: number }\n> = {\n int8: { minimum: -128, maximum: 127 },\n uint8: { minimum: 0, maximum: 255 },\n int16: { minimum: -32768, maximum: 32767 },\n uint16: { minimum: 0, maximum: 65535 },\n int32: { minimum: -2147483648, maximum: 2147483647 },\n uint32: { minimum: 0, maximum: 4294967295 }\n};\n\nexport const FLOAT32_BOUNDS = { minimum: -3.4028235e38, maximum: 3.4028235e38 };\n\nexport const 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\nexport const UNSTRUCTURED_VARIANT_DESC =\n 'The variant data encoded as a valid JSON string ' +\n '(e.g. \\'{\"key\": \"value\"}\\').';\n\nexport const 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\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// Primitives\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 function nullableType(\n baseType: string,\n nullable: boolean\n): string | string[] {\n return nullable ? [baseType, 'null'] : baseType;\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// Deep equal\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 function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a == null || b == null || typeof a !== typeof b) return false;\n if (typeof a !== 'object') return false;\n if (Array.isArray(a))\n return (\n Array.isArray(b) &&\n a.length === b.length &&\n a.every((v, i) => deepEqual(v, b[i]))\n );\n if (Array.isArray(b)) return false;\n const ao = a as Record<string, unknown>,\n bo = b as Record<string, unknown>;\n const keys = Object.keys(ao);\n if (keys.length !== Object.keys(bo).length) return false;\n for (const k of keys) {\n if (!(k in bo) || !deepEqual(ao[k], bo[k])) return false;\n }\n return true;\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 inspection (OpenAI + Anthropic)\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 function 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 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\nexport function 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// JTD definition reachability \u2014 prune unreferenced definitions\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 * Walk one or more JTD root schemas and return the set of definition names\n * that are transitively reachable via `ref`. Definitions not in this set\n * are unreferenced and should be pruned from `$defs`.\n */\nexport function findReferencedJTDDefs(\n roots: JTDSchemaJson[],\n defs: Record<string, JTDSchemaJson>\n): Set<string> {\n const visited = new Set<string>();\n const queue: JTDSchemaJson[] = [...roots];\n\n while (queue.length > 0) {\n const schema = queue.pop()!;\n if (!schema || typeof schema !== 'object') continue;\n\n if (schema.ref) {\n if (!visited.has(schema.ref) && defs[schema.ref]) {\n visited.add(schema.ref);\n queue.push(defs[schema.ref]);\n }\n continue; // ref form \u2014 no other structural fields\n }\n\n if (schema.elements) queue.push(schema.elements);\n if (schema.values) queue.push(schema.values);\n if (schema.properties) {\n for (const v of Object.values(schema.properties)) queue.push(v);\n }\n if (schema.optionalProperties) {\n for (const v of Object.values(schema.optionalProperties)) queue.push(v);\n }\n if (schema.mapping) {\n for (const v of Object.values(schema.mapping)) queue.push(v);\n }\n }\n\n return visited;\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// Convert result 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\nexport interface ConvertSuccessJson {\n success: true;\n kind: 'json';\n data: unknown;\n}\n\nexport interface ConvertSuccessBinary {\n success: true;\n kind: 'binary';\n mimeType: string;\n data: Uint8Array;\n filename?: string;\n}\n\nexport interface ConvertSuccessSignals {\n success: true;\n kind: 'signals';\n signals: Record<string, unknown>;\n}\n\nexport interface ConvertFailure {\n success: false;\n errors: string[];\n}\n\nexport type ConvertSuccess =\n | ConvertSuccessJson\n | ConvertSuccessBinary\n | ConvertSuccessSignals;\nexport type ConvertResult = ConvertSuccess | 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// Convert output pipeline (identical across all 3 providers)\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 function convertJTDOutput(\n jtdSchema: JTDSchemaJson,\n json: unknown,\n coerce: (\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n ) => unknown\n): ConvertResult {\n const defs = jtdSchema.definitions;\n const coerced = coerce(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\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// Reference mode: discriminated anyOf schema builder\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 * Wrap a signal's value schema in a discriminated anyOf with two variants:\n * - `{ _kind: \"_value\", _value: <valueSchema> }` \u2014 inline data\n * - `{ _kind: \"_ref\", _ref: <string> }` \u2014 file reference\n *\n * Field names are prefixed with `_` to avoid collisions with user-defined\n * signal properties (e.g. a signal named \"data\" or \"kind\").\n * The `_kind` value matches its sibling field name for clarity.\n *\n * The caller resolves references before calling convert.\n *\n * Returns a plain object \u2014 cast to the provider's schema type at the call site.\n *\n * @param valueSchema - The signal's original schema (JTD, MIME, or multi-format anyOf).\n * @param description - Optional signal description to include.\n * @param strict - When false, omits `additionalProperties` (required by GeminiFC).\n */\nexport function buildReferenceAnyOf(\n valueSchema: unknown,\n description?: string,\n strict?: boolean\n): { anyOf: unknown[] } {\n const desc = description ? `${description}. ` : '';\n const valueVariant: Record<string, unknown> = {\n type: 'object',\n properties: {\n _kind: { type: 'string', enum: ['_value'] },\n _value: valueSchema\n },\n required: ['_kind', '_value'],\n description: `${desc}Inline value.`\n };\n const refVariant: Record<string, unknown> = {\n type: 'object',\n properties: {\n _kind: { type: 'string', enum: ['_ref'] },\n _ref: {\n type: 'string',\n description:\n 'A file reference. The referenced file MUST contain data that conforms to the same format described in the inline value variant.'\n }\n },\n required: ['_kind', '_ref'],\n description: `${desc}Reference to a file instead of inline data.`\n };\n if (strict !== false) {\n valueVariant.additionalProperties = false;\n refVariant.additionalProperties = false;\n }\n return { anyOf: [valueVariant, refVariant] };\n}\n\n/**\n * Check if a concrete MIME type matches an accepted MIME pattern.\n *\n * - `*\u200B/*` matches everything\n * - `image/*` matches any `image/...` subtype\n * - Exact string match otherwise\n */\nexport function mimeTypeMatches(concrete: string, accepted: string): boolean {\n const c = concrete.trim().toLowerCase();\n const a = accepted.trim().toLowerCase();\n if (a === '*/*') return true;\n if (a.endsWith('/*')) {\n return c.startsWith(a.slice(0, a.indexOf('/') + 1));\n }\n return c === a;\n}\n\n/**\n * Convert a MIME-format signal value to dispatch-ready binary SignalData.\n *\n * Accepts two data shapes:\n * - **Inline (from LLM):** `{ data: \"<base64>\", mimeType: \"image/png\", filename?: \"...\" }`\n * - **Resolved (from file reference):** `{ data: Uint8Array, mimeType: \"image/png\", filename?: \"...\" }`\n *\n * The input's `mimeType` field is the concrete type and ends up in the result.\n * It is validated against the format's accepted pattern (which may be a wildcard).\n *\n * @param acceptedMimeType - MIME pattern from the signal format declaration.\n * @param value - The signal value to convert.\n */\nexport function convertMimeOutput(\n acceptedMimeType: string,\n value: unknown\n): ConvertResult {\n if (typeof value !== 'object' || value === null) {\n return {\n success: false,\n errors: [\n `expected object with 'data' and 'mimeType' fields, got ${typeof value}`\n ]\n };\n }\n\n const fields = value as Record<string, unknown>;\n\n // Concrete mimeType is required \u2014 this is what goes to dispatch\n if (typeof fields.mimeType !== 'string' || !fields.mimeType.includes('/')) {\n return {\n success: false,\n errors: [\n 'parameter \\'mimeType\\': required concrete MIME type (e.g. \"image/png\", \"application/pdf\")'\n ]\n };\n }\n\n // Validate concrete type against the format's accepted pattern\n if (!mimeTypeMatches(fields.mimeType, acceptedMimeType)) {\n return {\n success: false,\n errors: [\n `parameter 'mimeType': \"${fields.mimeType}\" does not match accepted type \"${acceptedMimeType}\"`\n ]\n };\n }\n\n // Resolve data \u2014 either already Uint8Array or base64-encoded string\n let binaryData: Uint8Array;\n if (fields.data instanceof Uint8Array) {\n binaryData = fields.data;\n } else if (typeof fields.data === 'string') {\n binaryData = new Uint8Array(Buffer.from(fields.data, 'base64'));\n } else {\n return {\n success: false,\n errors: [\n `parameter 'data': expected base64 string or Uint8Array, got ${typeof fields.data}`\n ]\n };\n }\n\n const result: ConvertSuccessBinary = {\n success: true,\n kind: 'binary',\n mimeType: fields.mimeType,\n data: binaryData\n };\n if (typeof fields.filename === 'string' && fields.filename) {\n result.filename = fields.filename;\n }\n return result;\n}\n\n/**\n * Convert a single format's value. Dispatches to JTD or MIME conversion.\n *\n * @param fmt - The signal format (has either `jtdSchema` or `mimeType`).\n * @param value - The signal value. JSON for JTD formats, or `{ data, mimeType, filename }` for MIME.\n * @param coerce - Provider-specific JTD coercion function.\n */\nexport function convertSingleFormatOutput(\n fmt: SignalFormatJson,\n value: unknown,\n coerce: (\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n ) => unknown\n): ConvertResult {\n if (fmt.mimeType) return convertMimeOutput(fmt.mimeType, value);\n if (fmt.jtdSchema) return convertJTDOutput(fmt.jtdSchema, value, coerce);\n return {\n success: false,\n errors: ['Signal format has neither jtdSchema nor mimeType']\n };\n}\n\n/**\n * Convert a signal's value against its declared formats.\n *\n * The value is already resolved \u2014 this function knows nothing about file\n * references. When `referenceMode` is used, the **caller** handles the\n * `_kind` discriminator:\n *\n * - `{ _kind: \"_value\", _value: <inline> }` \u2192 caller extracts `_value`, passes here\n * - `{ _kind: \"_ref\", _ref: \"...\" }` \u2192 caller resolves the ref, passes:\n * - Parsed JSON object (for JTD formats)\n * - `{ data: Uint8Array, mimeType, filename }` (for MIME formats)\n *\n * For **single-format** signals, the value is validated directly.\n * For **multi-format** signals, each format is tried in order (anyOf \u2014 first match wins).\n *\n * @param descriptor - The signal descriptor with one or more formats.\n * @param value - The resolved signal value (JSON for JTD, or `{ data, mimeType, filename }` for MIME).\n * @param coerce - Provider-specific JTD coercion function.\n */\nexport function convertSignalOutput(\n descriptor: SignalDescriptorJson,\n value: unknown,\n coerce: (\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n ) => 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 if (formats.length === 1) {\n return convertSingleFormatOutput(formats[0], value, coerce);\n }\n\n // Multi-format: try each format (anyOf semantics \u2014 first match wins).\n // Each format is an independent option. A MIME format and a JTD format\n // in the same signal are ALTERNATIVE input paths, not mutual constraints.\n // The platform validates signal data against the binding's accepted formats\n // at dispatch time.\n const allErrors: string[] = [];\n for (const fmt of formats) {\n const result = convertSingleFormatOutput(fmt, value, coerce);\n if (result.success) return result;\n allErrors.push(...result.errors);\n }\n\n return {\n success: false,\n errors: [\n `No format matched for signal '${descriptor.name ?? 'unnamed'}'. Errors: ${allErrors.join('; ')}`\n ]\n };\n}\n\n/**\n * Convert multiple signals from a compound output.\n *\n * Expects `input` to be an object keyed by signal name. Each signal's\n * value is passed to {@link convertSignalOutput} \u2014 it can be JSON (for\n * JTD formats) or `{ data, mimeType, filename }` (for MIME formats).\n *\n * When using `referenceMode`, the **caller** must unwrap the `kind`\n * discriminator for each signal before calling this function.\n * See {@link convertSignalOutput} for the full reference-mode contract.\n */\nexport function convertSignalsOutput(\n descriptors: SignalDescriptorJson[],\n input: unknown,\n coerce: (\n value: unknown,\n schema: JTDSchemaJson,\n defs: Record<string, JTDSchemaJson> | undefined,\n depth: number\n ) => unknown\n): ConvertResult {\n if (typeof input !== 'object' || input === null) {\n return {\n success: false,\n errors: ['/: expected object with signal properties, got ' + typeof input]\n };\n }\n\n const rec = input as Record<string, unknown>;\n const signals: Record<string, unknown> = {};\n const errors: string[] = [];\n\n for (const desc of descriptors) {\n if (!desc.name) continue;\n const value = rec[desc.name];\n if (value === undefined || value === null) continue;\n\n const result = convertSignalOutput(desc, value, coerce);\n if (!result.success) {\n for (const err of result.errors) {\n errors.push(`parameter '${desc.name}': ${err}`);\n }\n } else if (result.kind === 'binary') {\n signals[desc.name] = {\n data: result.data,\n mimeType: result.mimeType,\n filename: result.filename\n };\n } else if (result.kind === 'json') {\n signals[desc.name] = result.data;\n }\n }\n\n if (errors.length > 0) return { success: false, errors };\n return { success: true, kind: 'signals', signals };\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 tree walk (for providers that use $ref/$defs)\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/** Minimal shape for $ref-bearing schemas (satisfied by OpenAISchema and AnthropicSchema). */\ninterface RefNode {\n properties?: Record<string, RefNode>;\n items?: RefNode;\n anyOf?: RefNode[];\n $defs?: Record<string, RefNode>;\n $ref?: string;\n}\n\nexport function walkSchema<T extends RefNode>(\n schema: T,\n fn: (node: T) => void\n): void {\n fn(schema);\n if (schema.properties)\n for (const v of Object.values(schema.properties)) walkSchema(v as T, fn);\n if (schema.items) walkSchema(schema.items as T, fn);\n if (schema.anyOf) for (const v of schema.anyOf) walkSchema(v as T, fn);\n if (schema.$defs)\n for (const v of Object.values(schema.$defs)) walkSchema(v as T, fn);\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// Definition pooling for fromSignals (OpenAI + Anthropic)\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/** Recursively rewrite JTD `ref` values in a schema according to a rename map. */\nfunction rewriteJtdRefs(\n schema: JTDSchemaJson,\n renames: Map<string, string>\n): JTDSchemaJson {\n if (!schema || typeof schema !== 'object') return schema;\n\n const result: JTDSchemaJson = { ...schema };\n\n if (result.ref && renames.has(result.ref)) {\n result.ref = renames.get(result.ref)!;\n }\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([k, v]) => [\n k,\n rewriteJtdRefs(v, renames)\n ])\n );\n }\n if (result.optionalProperties) {\n result.optionalProperties = Object.fromEntries(\n Object.entries(result.optionalProperties).map(([k, v]) => [\n k,\n rewriteJtdRefs(v, renames)\n ])\n );\n }\n if (result.elements)\n result.elements = rewriteJtdRefs(result.elements, renames);\n if (result.values) result.values = rewriteJtdRefs(result.values, renames);\n if (result.mapping) {\n result.mapping = Object.fromEntries(\n Object.entries(result.mapping).map(([k, v]) => [\n k,\n rewriteJtdRefs(v, renames)\n ])\n );\n }\n // Definitions are rewritten at pool level, strip from the copy\n if (result.definitions) delete result.definitions;\n\n return result;\n}\n\n/**\n * Pre-scan all signal descriptors, pool their JTD definitions.\n * Deduplicates identical definition SETS; renames conflicts with `_N` suffix.\n *\n * Equivalence is checked per-format: all definitions within a single format's\n * `definitions` block are treated as a unit. Two formats with the same set of\n * definition names and identical schemas (deep-equal) share their defs.\n * If ANY definition name conflicts (same name, different schema), ALL defs\n * from that format get their own namespace to preserve internal cross-references.\n *\n * Returns the merged JTD definitions and signal copies with:\n * - refs rewritten to match merged names\n * - definitions stripped (they live in the merged pool now)\n */\nexport function poolSignalDefinitions(signals: SignalDescriptorJson[]): {\n mergedDefs: Record<string, JTDSchemaJson>;\n signalsCopy: SignalDescriptorJson[];\n} {\n const mergedDefs: Record<string, JTDSchemaJson> = {};\n\n // For each format that has definitions, compute its rename map.\n // Key: `signalIdx:formatIdx`, Value: Map<oldName, newName>\n const renamesByFormat = new Map<string, Map<string, string>>();\n\n for (let si = 0; si < signals.length; si++) {\n const formats = signals[si].formats as SignalFormatJson[] | undefined;\n if (!formats) continue;\n for (let fi = 0; fi < formats.length; fi++) {\n const defs = formats[fi].jtdSchema?.definitions;\n if (!defs || Object.keys(defs).length === 0) continue;\n\n // Check each definition against the merged pool\n const renames = new Map<string, string>();\n let hasConflict = false;\n\n for (const [name, defSchema] of Object.entries(defs)) {\n const existing = mergedDefs[name];\n if (!existing) continue; // new name, no conflict\n if (deepEqual(existing, defSchema)) continue; // identical, dedup\n hasConflict = true;\n break;\n }\n\n if (hasConflict) {\n // This format has at least one conflict. Rename ALL its definitions\n // to avoid broken cross-references between shared and renamed defs.\n for (const [name, defSchema] of Object.entries(defs)) {\n const existing = mergedDefs[name];\n if (existing && deepEqual(existing, defSchema)) {\n // Identical to existing \u2014 can still share\n continue;\n }\n if (existing) {\n // Conflict \u2014 find unique name\n let n = 1;\n while (mergedDefs[`${name}_${n}`]) n++;\n const newName = `${name}_${n}`;\n renames.set(name, newName);\n mergedDefs[newName] = defSchema;\n } else {\n mergedDefs[name] = defSchema;\n }\n }\n } else {\n // No conflicts \u2014 all defs are either new or identical (deduped)\n for (const [name, defSchema] of Object.entries(defs)) {\n if (!mergedDefs[name]) mergedDefs[name] = defSchema;\n }\n }\n\n if (renames.size > 0) renamesByFormat.set(`${si}:${fi}`, renames);\n }\n }\n\n // Rewrite refs inside renamed definitions (they may reference other renamed defs)\n for (const [, renames] of renamesByFormat) {\n for (const [, newName] of renames) {\n mergedDefs[newName] = rewriteJtdRefs(mergedDefs[newName], renames);\n }\n }\n\n // Build signal copies with rewritten refs and stripped definitions\n const signalsCopy: SignalDescriptorJson[] = signals.map((signal, si) => {\n const formats = signal.formats as SignalFormatJson[] | undefined;\n if (!formats) return signal;\n\n let hasChanges = false;\n const newFormats = formats.map((fmt, fi) => {\n if (!fmt.jtdSchema) return fmt;\n const renames = renamesByFormat.get(`${si}:${fi}`);\n const hasDefs =\n fmt.jtdSchema.definitions &&\n Object.keys(fmt.jtdSchema.definitions).length > 0;\n if (!renames && !hasDefs) return fmt;\n\n hasChanges = true;\n const rewritten = renames\n ? rewriteJtdRefs(fmt.jtdSchema, renames)\n : { ...fmt.jtdSchema };\n delete rewritten.definitions;\n return { ...fmt, jtdSchema: rewritten };\n });\n\n return hasChanges ? { ...signal, formats: newFormats } : signal;\n });\n\n // Prune definitions that are never transitively referenced from any signal\n const rootSchemas = signalsCopy.flatMap((s) =>\n ((s.formats as SignalFormatJson[] | undefined) ?? [])\n .filter((f) => f.jtdSchema)\n .map((f) => f.jtdSchema!)\n );\n const referenced = findReferencedJTDDefs(rootSchemas, mergedDefs);\n for (const name of Object.keys(mergedDefs)) {\n if (!referenced.has(name)) delete mergedDefs[name];\n }\n\n return { mergedDefs, signalsCopy };\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// Cycle description \u2014 shared by Anthropic and Gemini for recursive ref fallbacks\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 describeJTDType(schema: JTDSchemaJson): string {\n if (!schema || typeof schema !== 'object') return 'any';\n if (schema.ref) return schema.ref;\n if (schema.type) return schema.type;\n if (schema.enum) return `one of: ${schema.enum.join(', ')}`;\n if (schema.elements) return `array of ${describeJTDType(schema.elements)}`;\n if (schema.values) return `map of ${describeJTDType(schema.values)}`;\n if (schema.properties || schema.optionalProperties) return 'object';\n if (schema.discriminator) return `union on '${schema.discriminator}'`;\n return 'any';\n}\n\n/**\n * Build a human-readable description of a JTD definition for use as a\n * fallback at recursive ref break points. Used by both Anthropic and Gemini\n * converters when a cycle is detected.\n */\nexport function describeDefinitionForCycle(\n defName: string,\n def: JTDSchemaJson\n): string {\n const parts: string[] = [\n `Recursive nesting. This field accepts the same object structure as its parent with the following shape:`\n ];\n\n const required: string[] = [];\n const optional: string[] = [];\n\n if (def.properties) {\n for (const [key, prop] of Object.entries(def.properties)) {\n required.push(`${key} (${describeJTDType(prop)})`);\n }\n }\n if (def.optionalProperties) {\n for (const [key, prop] of Object.entries(def.optionalProperties)) {\n optional.push(`${key} (${describeJTDType(prop)})`);\n }\n }\n\n if (required.length > 0) {\n parts.push(`Required: ${required.join(', ')}.`);\n }\n if (optional.length > 0) {\n const shown = optional.slice(0, 8);\n const suffix =\n optional.length > 8 ? `, and ${optional.length - 8} more` : '';\n parts.push(`Optional: ${shown.join(', ')}${suffix}.`);\n }\n\n if (def.elements) {\n parts.push(`Array of ${describeJTDType(def.elements)}.`);\n }\n if (def.values) {\n parts.push(`Map with values of type ${describeJTDType(def.values)}.`);\n }\n\n return parts.join(' ');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["celFunc", "celMethod", "celRun", "CelScalar", "isCelError", "isCelList", "isCelMap", "isCelUint", "listType", "objectType", "stringsExt", "timestampDate", "timestampFromDate", "timestampMs", "timestampNow", "TimestampSchema", "isSchema", "isValidSchema", "jtdValidate", "FUZZ_MAX_DEPTH", "fuzzJTD", "schema", "definitions", "_depth", "def", "obj", "k", "v", "firstKey", "variant", "MAX_REF_DEPTH", "INTEGER_BOUNDS", "toNumber", "val", "isCelUint", "celEqual", "a", "b", "aVal", "bVal", "isBytes", "toUint8Array", "isRecord", "value", "jtdJsonToCelInputInner", "schema", "definitions", "depth", "MAX_REF_DEPTH", "def", "INTEGER_BOUNDS", "item", "key", "tag", "variant", "props", "converted", "propSchema", "jtdJsonToCelInput", "getRootDefs", "fuzzJTDForCel", "fuzzJTD", "wrapBytes", "data", "_hasBuffer", "base64Decode", "s", "c", "base64Encode", "byte", "encodeImpl", "encoding", "json", "celToNative", "decodeImpl", "bytes", "htmlEscapeImpl", "LIST_DYN", "listType", "CelScalar", "DYN", "BOOL", "INT", "formatDateWithPattern", "timestamp", "pattern", "y", "m", "d", "H", "min", "CUSTOM_FUNCS", "celFunc", "list", "total", "n", "celMethod", "result", "count", "element", "index", "arr", "i", "objectType", "TimestampSchema", "timestampNow", "enc", "ms", "date", "celOptions", "stringsExt", "isCelList", "isCelMap", "obj", "k", "v", "MAX_EXPRESSION_LENGTH", "extractAccessPaths", "expression", "variableNames", "validNames", "n", "paths", "namesPattern", "regex", "match", "varName", "firstProp", "pathParts", "pos", "dotMatch", "nextPos", "bracketMatch", "fullPath", "deduplicateAccessPaths", "byVariable", "path", "existing", "result", "variablePaths", "a", "b", "kept", "candidate", "k", "isPathPrefix", "pathA", "pathB", "i", "findOptionalSegments", "schema", "isSignalOptional", "optionals", "currentSchema", "segment", "optProps", "reqProps", "generateTestPermutations", "variables", "accessedPaths", "permutations", "allBindings", "v", "fuzzJTDForCel", "accessPath", "variable", "optionalSegments", "opt", "testBindings", "pathToUnset", "unsetNestedProperty", "unsetPathStr", "obj", "current", "evaluateExpression", "bindings", "celBindings", "celRun", "celOptions", "isCelError", "celToNative", "e", "validateCelExpression", "errors", "syntaxCheck", "perm", "testResult", "validateCelExpressionSyntax", "CEL_LANGUAGE_ID", "GLOBAL_FUNCTIONS", "CEL_METHODS", "CEL_DESCRIPTORS", "map", "f", "baseName", "m", "currentInputVariables", "setInputVariables", "inputs", "resolveInputSchema", "defs", "getRootDefs", "getSchemaAtPath", "resolved", "first", "rest", "props", "variant", "variantProps", "describeSchemaType", "getSchemaProperties", "name", "propSchema", "tags", "seen", "hasChildProperties", "deduplicatedMethods", "key", "registerCelLanguage", "monaco", "l", "model", "position", "textUntilPosition", "inDouble", "inSingle", "ch", "word", "range", "inputsNestedMatch", "nestedPath", "inputVar", "schemaAtPath", "properties", "suggestions", "prop", "childSchema", "isNavigable", "methods", "mi", "hasNestedProps", "sortIndex", "descriptors", "d", "depth", "commaCount", "parenIdx", "nameMatch", "funcName", "signatures", "p", "ELEMENT_KEY", "resolveSchema", "buildNode", "r", "children", "detail", "el", "val", "parts", "child", "t", "vNode", "generateCelSymbolTree", "tree", "binding", "format", "node", "buildTranslationNode", "c", "deepMergeForTree", "target", "source", "generateTranslationsSymbolTree", "translations", "merged", "dict", "parseDotPath", "textBefore", "root", "chain", "segments", "id", "close", "resolveNode", "tNode", "parseExprToSegments", "expr", "firstId", "extractLambdaBindings", "text", "re", "collectionSegments", "parseGeneralDotPath", "resolveWithLambdas", "lambdaBindings", "collectionNode", "elementNode", "j", "extractHoverSegments", "lineText", "wordStartCol", "idEnd", "idStart"]
|
|
7
7
|
}
|