import schema from './codex-link-control.schema.json' import type { CodexLinkControlRequest, CodexLinkControlResponse } from './codex-link-control.types' import { canonicalJson, CodexLinkValidationError, parseStrictJson } from './codex-link-json' export const CODEX_LINK_REQUEST_BYTES = 64 * 1024 export const CODEX_LINK_RESPONSE_BYTES = 1024 * 1024 type Rule = Record const definitions: Record = schema.$defs function matches(value: any, rule: Rule): boolean { if (rule.$ref) { const target = definitions[rule.$ref.replace('#/$defs/', '')] return !!target && matches(value, target) } if (rule.oneOf) { return rule.oneOf.filter((r: Rule) => matches(value, r)).length === 1 } if (rule.anyOf) { return rule.anyOf.some((r: Rule) => matches(value, r)) } if ('const' in rule && value !== rule.const) { return false } if (rule.enum && !rule.enum.includes(value)) { return false } switch (rule.type) { case 'object': { if (value === null || typeof value !== 'object' || Array.isArray(value)) { return false } const keys = Object.keys(value) return ( keys.length >= (rule.minProperties ?? 0) && rule.required.every((key: string) => Object.hasOwn(value, key)) && keys.every(key => Object.hasOwn(rule.properties, key) && matches(value[key], rule.properties[key])) ) } case 'array': return ( Array.isArray(value) && value.length >= (rule.minItems ?? 0) && (!rule.uniqueItems || new Set(value.map(canonicalJson)).size === value.length) && value.every(item => matches(item, rule.items)) ) case 'string': return ( typeof value === 'string' && [...value].length >= (rule.minLength ?? 0) && (!rule.pattern || new RegExp(rule.pattern).test(value)) ) case 'integer': return ( Number.isSafeInteger(value) && value >= (rule.minimum ?? -Number.MAX_SAFE_INTEGER) && value <= (rule.maximum ?? Number.MAX_SAFE_INTEGER) ) case 'boolean': return typeof value === 'boolean' case 'null': return value === null case undefined: return 'const' in rule || 'enum' in rule default: return false } } export function validateControlRequest(value: unknown): asserts value is CodexLinkControlRequest { const text = canonicalJson(value) if ( new TextEncoder().encode(text).byteLength > CODEX_LINK_REQUEST_BYTES || !matches(value, definitions.control_request) ) { throw new CodexLinkValidationError('invalid_control_request') } } export function parseControlResponse( raw: Uint8Array | string, request: CodexLinkControlRequest ): CodexLinkControlResponse { const value = parseStrictJson(raw, CODEX_LINK_RESPONSE_BYTES) as CodexLinkControlResponse if ( !matches(value, definitions.control_response) || value.request_id !== request.request_id || value.operation_id !== request.operation_id ) { throw new CodexLinkValidationError('invalid_control_response') } const expected = { settings_get: 'settings_result', settings_update: 'settings_result', status_get: 'status_result', context_views_get: 'context_views_result', catalog_sync: 'control_accepted', context_compact_view: 'control_accepted' } if (value.kind !== 'control_error' && value.kind !== expected[request.kind]) { throw new CodexLinkValidationError('unexpected_control_response') } return value }