@decocms/bindings 0.2.4-beta.3 → 0.2.4

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.
@@ -42,12 +42,8 @@ function createBindingChecker(binderTools) {
42
42
  if (!matchedTool) {
43
43
  return false;
44
44
  }
45
- const binderInputSchema = normalizeToJsonSchema(
46
- binderTool.inputSchema
47
- );
48
- const toolInputSchema = normalizeToJsonSchema(
49
- matchedTool.inputSchema
50
- );
45
+ const binderInputSchema = normalizeToJsonSchema(binderTool.inputSchema);
46
+ const toolInputSchema = normalizeToJsonSchema(matchedTool.inputSchema);
51
47
  if (binderInputSchema && toolInputSchema) {
52
48
  if (!isSubset(binderInputSchema, toolInputSchema)) {
53
49
  return false;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/binder.ts"],"sourcesContent":["/**\n * Core Binder Types and Utilities\n *\n * This module provides the core types and utilities for the bindings system.\n * Bindings define standardized interfaces that integrations (MCPs) can implement.\n */\n\nimport type { ZodType } from \"zod/v3\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { createMCPFetchStub, MCPClientFetchStub } from \"./client/mcp\";\nimport { MCPConnection } from \"./connection\";\nimport { isSubset } from \"./subset\";\n\ntype JsonSchema = Record<string, unknown>;\n\n/**\n * Checks if a value is a Zod schema by looking for the _def property\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isZodSchema(value: unknown): value is ZodType<any> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"_def\" in value &&\n typeof (value as Record<string, unknown>)._def === \"object\"\n );\n}\n\n/**\n * Normalizes a schema to JSON Schema format.\n * Accepts either a Zod schema or a JSON schema and returns a JSON schema.\n *\n * @param schema - A Zod schema or JSON schema\n * @returns The JSON schema representation, or null if input is null/undefined\n */\nexport function normalizeToJsonSchema(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: ZodType<any> | JsonSchema | null | undefined,\n): JsonSchema | null {\n if (schema == null) {\n return null;\n }\n\n if (isZodSchema(schema)) {\n return zodToJsonSchema(schema) as JsonSchema;\n }\n\n // Already a JSON schema\n return schema as JsonSchema;\n}\n\n/**\n * ToolBinder defines a single tool within a binding.\n * It specifies the tool name, input/output schemas, and whether it's optional.\n *\n * @template TName - The tool name (can be a string or RegExp for pattern matching)\n * @template TInput - The input type (inferred from inputSchema)\n * @template TReturn - The return type (inferred from outputSchema)\n */\nexport interface ToolBinder<\n TName extends string | RegExp = string,\n // biome-ignore lint/suspicious/noExplicitAny: Generic type parameter\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TInput = any,\n TReturn extends object | null | boolean = object,\n TStreamable extends boolean = boolean,\n> {\n /** The name of the tool (e.g., \"DECO_CHAT_CHANNELS_JOIN\") */\n name: TName;\n\n /** Zod schema for validating tool input */\n inputSchema: ZodType<TInput>;\n\n /** Optional Zod schema for validating tool output */\n outputSchema?: TStreamable extends true ? never : ZodType<TReturn>;\n\n /**\n * Whether this tool is streamable.\n */\n streamable?: TStreamable;\n\n /**\n * Whether this tool is optional in the binding.\n * If true, an implementation doesn't need to provide this tool.\n */\n opt?: true;\n}\n\n/**\n * Binder represents a collection of tool definitions that form a binding.\n * A binding is like a TypeScript interface - it defines what tools must be implemented.\n *\n * @template TDefinition - Array of ToolBinder definitions\n *\n * @example\n * ```ts\n * const MY_BINDING = [{\n * name: \"MY_TOOL\" as const,\n * inputSchema: z.object({ id: z.string() }),\n * outputSchema: z.object({ success: z.boolean() }),\n * }] as const satisfies Binder;\n * ```\n */\nexport type Binder<\n TDefinition extends readonly ToolBinder[] = readonly ToolBinder[],\n> = TDefinition;\n\n/**\n * Tool with schemas for validation\n */\nexport interface ToolWithSchemas {\n name: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputSchema?: ZodType<any> | Record<string, unknown>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n outputSchema?: ZodType<any> | Record<string, unknown>;\n}\n\n/**\n * Binding checker interface\n */\nexport interface BindingChecker {\n /**\n * Check if a set of tools implements the binding with full schema validation.\n *\n * Validates:\n * - Tool name matches (exact or regex)\n * - Input schema: Tool accepts what binder requires (no removals from binder to tool)\n * - Output schema: Tool provides what binder expects (no removals from tool to binder)\n *\n * @param tools - Array of tools with names and schemas\n * @returns Promise<boolean> - true if all tools implement the binding correctly\n */\n isImplementedBy: (tools: ToolWithSchemas[]) => boolean;\n}\n\nexport const bindingClient = <TDefinition extends readonly ToolBinder[]>(\n binder: TDefinition,\n) => {\n return {\n ...createBindingChecker(binder),\n forConnection: (\n mcpConnection: MCPConnection,\n ): MCPClientFetchStub<TDefinition> => {\n return createMCPFetchStub<TDefinition>({\n connection: mcpConnection,\n streamable: binder.reduce(\n (acc, tool) => {\n acc[tool.name] = tool.streamable === true;\n return acc;\n },\n {} as Record<string, boolean>,\n ),\n });\n },\n };\n};\n\nexport type MCPBindingClient<T extends ReturnType<typeof bindingClient>> =\n ReturnType<T[\"forConnection\"]>;\n\n/**\n * Creates a binding checker with full schema validation using structural subset checking.\n *\n * This performs strict compatibility checking:\n * - For input schemas: Validates that the tool can accept what the binder requires (binder ⊆ tool)\n * - For output schemas: Validates that the tool provides what the binder expects (binder ⊆ tool)\n *\n * @param binderTools - The binding definition to check against\n * @returns A binding checker with an async isImplementedBy method\n *\n * @example\n * ```ts\n * const checker = createBindingChecker(MY_BINDING);\n * const isCompatible = await checker.isImplementedBy(availableTools);\n * ```\n */\nexport function createBindingChecker<TDefinition extends readonly ToolBinder[]>(\n binderTools: TDefinition,\n): BindingChecker {\n return {\n isImplementedBy: (tools: ToolWithSchemas[]): boolean => {\n for (const binderTool of binderTools) {\n // Find matching tool by name (exact or regex)\n const pattern = typeof binderTool.name === \"string\"\n ? new RegExp(`^${binderTool.name}$`)\n : binderTool.name;\n\n const matchedTool = tools.find((t) => pattern.test(t.name));\n\n // Skip optional tools that aren't present\n if (!matchedTool && binderTool.opt) {\n continue;\n }\n\n // Required tool not found\n if (!matchedTool) {\n return false;\n }\n\n // === INPUT SCHEMA VALIDATION ===\n // Tool must accept what binder requires\n // Check: isSubset(binder, tool) - every value valid under binder is valid under tool\n const binderInputSchema = normalizeToJsonSchema(\n binderTool.inputSchema,\n );\n const toolInputSchema = normalizeToJsonSchema(\n matchedTool.inputSchema,\n );\n\n if (binderInputSchema && toolInputSchema) {\n // Check if binder input is a subset of tool input (tool accepts what binder requires)\n if (!isSubset(binderInputSchema, toolInputSchema)) {\n return false;\n }\n } else if (binderInputSchema && !toolInputSchema) {\n // Binder requires input schema but tool doesn't have one\n return false;\n }\n\n // === OUTPUT SCHEMA VALIDATION ===\n // Tool must provide what binder expects (but can provide more)\n // Check: isSubset(binder, tool) - tool provides at least what binder expects\n const binderOutputSchema = normalizeToJsonSchema(\n binderTool.outputSchema,\n );\n const toolOutputSchema = normalizeToJsonSchema(\n matchedTool.outputSchema,\n );\n\n if (binderOutputSchema && toolOutputSchema) {\n // Check if binder output is a subset of tool output (tool provides what binder expects)\n if (!isSubset(binderOutputSchema, toolOutputSchema)) {\n return false;\n }\n } else if (binderOutputSchema && !toolOutputSchema) {\n // Binder expects output schema but tool doesn't have one\n return false;\n }\n }\n return true;\n },\n };\n}\n"],"mappings":"AAQA,SAAS,uBAAuB;AAChC,SAAS,0BAA8C;AAEvD,SAAS,gBAAgB;AAQzB,SAAS,YAAY,OAAuC;AAC1D,SACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAAkC,SAAS;AAEvD;AASO,SAAS,sBAEd,QACmB;AACnB,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,MAAM,GAAG;AACvB,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAGA,SAAO;AACT;AAuFO,MAAM,gBAAgB,CAC3B,WACG;AACH,SAAO;AAAA,IACL,GAAG,qBAAqB,MAAM;AAAA,IAC9B,eAAe,CACb,kBACoC;AACpC,aAAO,mBAAgC;AAAA,QACrC,YAAY;AAAA,QACZ,YAAY,OAAO;AAAA,UACjB,CAAC,KAAK,SAAS;AACb,gBAAI,KAAK,IAAI,IAAI,KAAK,eAAe;AACrC,mBAAO;AAAA,UACT;AAAA,UACA,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAqBO,SAAS,qBACd,aACgB;AAChB,SAAO;AAAA,IACL,iBAAiB,CAAC,UAAsC;AACtD,iBAAW,cAAc,aAAa;AAEpC,cAAM,UAAU,OAAO,WAAW,SAAS,WACvC,IAAI,OAAO,IAAI,WAAW,IAAI,GAAG,IACjC,WAAW;AAEf,cAAM,cAAc,MAAM,KAAK,CAAC,MAAM,QAAQ,KAAK,EAAE,IAAI,CAAC;AAG1D,YAAI,CAAC,eAAe,WAAW,KAAK;AAClC;AAAA,QACF;AAGA,YAAI,CAAC,aAAa;AAChB,iBAAO;AAAA,QACT;AAKA,cAAM,oBAAoB;AAAA,UACxB,WAAW;AAAA,QACb;AACA,cAAM,kBAAkB;AAAA,UACtB,YAAY;AAAA,QACd;AAEA,YAAI,qBAAqB,iBAAiB;AAExC,cAAI,CAAC,SAAS,mBAAmB,eAAe,GAAG;AACjD,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,qBAAqB,CAAC,iBAAiB;AAEhD,iBAAO;AAAA,QACT;AAKA,cAAM,qBAAqB;AAAA,UACzB,WAAW;AAAA,QACb;AACA,cAAM,mBAAmB;AAAA,UACvB,YAAY;AAAA,QACd;AAEA,YAAI,sBAAsB,kBAAkB;AAE1C,cAAI,CAAC,SAAS,oBAAoB,gBAAgB,GAAG;AACnD,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,sBAAsB,CAAC,kBAAkB;AAElD,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/core/binder.ts"],"sourcesContent":["/**\n * Core Binder Types and Utilities\n *\n * This module provides the core types and utilities for the bindings system.\n * Bindings define standardized interfaces that integrations (MCPs) can implement.\n */\n\nimport type { ZodType } from \"zod/v3\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { createMCPFetchStub, MCPClientFetchStub } from \"./client/mcp\";\nimport { MCPConnection } from \"./connection\";\nimport { isSubset } from \"./subset\";\n\ntype JsonSchema = Record<string, unknown>;\n\n/**\n * Checks if a value is a Zod schema by looking for the _def property\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction isZodSchema(value: unknown): value is ZodType<any> {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"_def\" in value &&\n typeof (value as Record<string, unknown>)._def === \"object\"\n );\n}\n\n/**\n * Normalizes a schema to JSON Schema format.\n * Accepts either a Zod schema or a JSON schema and returns a JSON schema.\n *\n * @param schema - A Zod schema or JSON schema\n * @returns The JSON schema representation, or null if input is null/undefined\n */\nexport function normalizeToJsonSchema(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: ZodType<any> | JsonSchema | null | undefined,\n): JsonSchema | null {\n if (schema == null) {\n return null;\n }\n\n if (isZodSchema(schema)) {\n return zodToJsonSchema(schema) as JsonSchema;\n }\n\n // Already a JSON schema\n return schema as JsonSchema;\n}\n\n/**\n * ToolBinder defines a single tool within a binding.\n * It specifies the tool name, input/output schemas, and whether it's optional.\n *\n * @template TName - The tool name (can be a string or RegExp for pattern matching)\n * @template TInput - The input type (inferred from inputSchema)\n * @template TReturn - The return type (inferred from outputSchema)\n */\nexport interface ToolBinder<\n TName extends string | RegExp = string,\n // biome-ignore lint/suspicious/noExplicitAny: Generic type parameter\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TInput = any,\n TReturn extends object | null | boolean = object,\n TStreamable extends boolean = boolean,\n> {\n /** The name of the tool (e.g., \"DECO_CHAT_CHANNELS_JOIN\") */\n name: TName;\n\n /** Zod schema for validating tool input */\n inputSchema: ZodType<TInput>;\n\n /** Optional Zod schema for validating tool output */\n outputSchema?: TStreamable extends true ? never : ZodType<TReturn>;\n\n /**\n * Whether this tool is streamable.\n */\n streamable?: TStreamable;\n\n /**\n * Whether this tool is optional in the binding.\n * If true, an implementation doesn't need to provide this tool.\n */\n opt?: true;\n}\n\n/**\n * Binder represents a collection of tool definitions that form a binding.\n * A binding is like a TypeScript interface - it defines what tools must be implemented.\n *\n * @template TDefinition - Array of ToolBinder definitions\n *\n * @example\n * ```ts\n * const MY_BINDING = [{\n * name: \"MY_TOOL\" as const,\n * inputSchema: z.object({ id: z.string() }),\n * outputSchema: z.object({ success: z.boolean() }),\n * }] as const satisfies Binder;\n * ```\n */\nexport type Binder<\n TDefinition extends readonly ToolBinder[] = readonly ToolBinder[],\n> = TDefinition;\n\n/**\n * Tool with schemas for validation\n */\nexport interface ToolWithSchemas {\n name: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n inputSchema?: ZodType<any> | Record<string, unknown>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n outputSchema?: ZodType<any> | Record<string, unknown>;\n}\n\n/**\n * Binding checker interface\n */\nexport interface BindingChecker {\n /**\n * Check if a set of tools implements the binding with full schema validation.\n *\n * Validates:\n * - Tool name matches (exact or regex)\n * - Input schema: Tool accepts what binder requires (no removals from binder to tool)\n * - Output schema: Tool provides what binder expects (no removals from tool to binder)\n *\n * @param tools - Array of tools with names and schemas\n * @returns Promise<boolean> - true if all tools implement the binding correctly\n */\n isImplementedBy: (tools: ToolWithSchemas[]) => boolean;\n}\n\nexport const bindingClient = <TDefinition extends readonly ToolBinder[]>(\n binder: TDefinition,\n) => {\n return {\n ...createBindingChecker(binder),\n forConnection: (\n mcpConnection: MCPConnection,\n ): MCPClientFetchStub<TDefinition> => {\n return createMCPFetchStub<TDefinition>({\n connection: mcpConnection,\n streamable: binder.reduce(\n (acc, tool) => {\n acc[tool.name] = tool.streamable === true;\n return acc;\n },\n {} as Record<string, boolean>,\n ),\n });\n },\n };\n};\n\nexport type MCPBindingClient<T extends ReturnType<typeof bindingClient>> =\n ReturnType<T[\"forConnection\"]>;\n\n/**\n * Creates a binding checker with full schema validation using structural subset checking.\n *\n * This performs strict compatibility checking:\n * - For input schemas: Validates that the tool can accept what the binder requires (binder ⊆ tool)\n * - For output schemas: Validates that the tool provides what the binder expects (binder ⊆ tool)\n *\n * @param binderTools - The binding definition to check against\n * @returns A binding checker with an async isImplementedBy method\n *\n * @example\n * ```ts\n * const checker = createBindingChecker(MY_BINDING);\n * const isCompatible = await checker.isImplementedBy(availableTools);\n * ```\n */\nexport function createBindingChecker<TDefinition extends readonly ToolBinder[]>(\n binderTools: TDefinition,\n): BindingChecker {\n return {\n isImplementedBy: (tools: ToolWithSchemas[]): boolean => {\n for (const binderTool of binderTools) {\n // Find matching tool by name (exact or regex)\n const pattern =\n typeof binderTool.name === \"string\"\n ? new RegExp(`^${binderTool.name}$`)\n : binderTool.name;\n\n const matchedTool = tools.find((t) => pattern.test(t.name));\n\n // Skip optional tools that aren't present\n if (!matchedTool && binderTool.opt) {\n continue;\n }\n\n // Required tool not found\n if (!matchedTool) {\n return false;\n }\n\n // === INPUT SCHEMA VALIDATION ===\n // Tool must accept what binder requires\n // Check: isSubset(binder, tool) - every value valid under binder is valid under tool\n const binderInputSchema = normalizeToJsonSchema(binderTool.inputSchema);\n const toolInputSchema = normalizeToJsonSchema(matchedTool.inputSchema);\n\n if (binderInputSchema && toolInputSchema) {\n // Check if binder input is a subset of tool input (tool accepts what binder requires)\n if (!isSubset(binderInputSchema, toolInputSchema)) {\n return false;\n }\n } else if (binderInputSchema && !toolInputSchema) {\n // Binder requires input schema but tool doesn't have one\n return false;\n }\n\n // === OUTPUT SCHEMA VALIDATION ===\n // Tool must provide what binder expects (but can provide more)\n // Check: isSubset(binder, tool) - tool provides at least what binder expects\n const binderOutputSchema = normalizeToJsonSchema(\n binderTool.outputSchema,\n );\n const toolOutputSchema = normalizeToJsonSchema(\n matchedTool.outputSchema,\n );\n\n if (binderOutputSchema && toolOutputSchema) {\n // Check if binder output is a subset of tool output (tool provides what binder expects)\n if (!isSubset(binderOutputSchema, toolOutputSchema)) {\n return false;\n }\n } else if (binderOutputSchema && !toolOutputSchema) {\n // Binder expects output schema but tool doesn't have one\n return false;\n }\n }\n return true;\n },\n };\n}\n"],"mappings":"AAQA,SAAS,uBAAuB;AAChC,SAAS,0BAA8C;AAEvD,SAAS,gBAAgB;AAQzB,SAAS,YAAY,OAAuC;AAC1D,SACE,UAAU,QACV,OAAO,UAAU,YACjB,UAAU,SACV,OAAQ,MAAkC,SAAS;AAEvD;AASO,SAAS,sBAEd,QACmB;AACnB,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,MAAM,GAAG;AACvB,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AAGA,SAAO;AACT;AAuFO,MAAM,gBAAgB,CAC3B,WACG;AACH,SAAO;AAAA,IACL,GAAG,qBAAqB,MAAM;AAAA,IAC9B,eAAe,CACb,kBACoC;AACpC,aAAO,mBAAgC;AAAA,QACrC,YAAY;AAAA,QACZ,YAAY,OAAO;AAAA,UACjB,CAAC,KAAK,SAAS;AACb,gBAAI,KAAK,IAAI,IAAI,KAAK,eAAe;AACrC,mBAAO;AAAA,UACT;AAAA,UACA,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAqBO,SAAS,qBACd,aACgB;AAChB,SAAO;AAAA,IACL,iBAAiB,CAAC,UAAsC;AACtD,iBAAW,cAAc,aAAa;AAEpC,cAAM,UACJ,OAAO,WAAW,SAAS,WACvB,IAAI,OAAO,IAAI,WAAW,IAAI,GAAG,IACjC,WAAW;AAEjB,cAAM,cAAc,MAAM,KAAK,CAAC,MAAM,QAAQ,KAAK,EAAE,IAAI,CAAC;AAG1D,YAAI,CAAC,eAAe,WAAW,KAAK;AAClC;AAAA,QACF;AAGA,YAAI,CAAC,aAAa;AAChB,iBAAO;AAAA,QACT;AAKA,cAAM,oBAAoB,sBAAsB,WAAW,WAAW;AACtE,cAAM,kBAAkB,sBAAsB,YAAY,WAAW;AAErE,YAAI,qBAAqB,iBAAiB;AAExC,cAAI,CAAC,SAAS,mBAAmB,eAAe,GAAG;AACjD,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,qBAAqB,CAAC,iBAAiB;AAEhD,iBAAO;AAAA,QACT;AAKA,cAAM,qBAAqB;AAAA,UACzB,WAAW;AAAA,QACb;AACA,cAAM,mBAAmB;AAAA,UACvB,YAAY;AAAA,QACd;AAEA,YAAI,sBAAsB,kBAAkB;AAE1C,cAAI,CAAC,SAAS,oBAAoB,gBAAgB,GAAG;AACnD,mBAAO;AAAA,UACT;AAAA,QACF,WAAW,sBAAsB,CAAC,kBAAkB;AAElD,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -209,9 +209,7 @@ function isObjectSubset(a, b) {
209
209
  }
210
210
  }
211
211
  if (b.additionalProperties === false) {
212
- const aHasExtraProps = Object.keys(aProps).some(
213
- (key) => !(key in bProps)
214
- );
212
+ const aHasExtraProps = Object.keys(aProps).some((key) => !(key in bProps));
215
213
  if (aHasExtraProps) {
216
214
  return false;
217
215
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/subset.ts"],"sourcesContent":["/**\n * Structural JSON Schema Subset Check\n *\n * This module implements an algorithm to determine if one JSON Schema (A)\n * is a subset of another (B). A ⊆ B means every value valid under A is also\n * valid under B (A is more restrictive or equally restrictive).\n *\n * Core Axiom: A ⊆ B ⟺ Constraints(A) ⊇ Constraints(B)\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JSONSchema = Record<string, any>;\n\n/**\n * Deep equality check for JSON values (for const/enum comparison)\n */\nfunction deepEqual(x: unknown, y: unknown): boolean {\n if (x === y) return true;\n if (typeof x !== typeof y) return false;\n if (x === null || y === null) return x === y;\n if (typeof x !== \"object\") return false;\n\n if (Array.isArray(x)) {\n if (!Array.isArray(y)) return false;\n if (x.length !== y.length) return false;\n for (let i = 0; i < x.length; i++) {\n if (!deepEqual(x[i], y[i])) return false;\n }\n return true;\n }\n\n if (Array.isArray(y)) return false;\n\n const xObj = x as Record<string, unknown>;\n const yObj = y as Record<string, unknown>;\n const xKeys = Object.keys(xObj);\n const yKeys = Object.keys(yObj);\n\n if (xKeys.length !== yKeys.length) return false;\n\n for (const key of xKeys) {\n if (!Object.prototype.hasOwnProperty.call(yObj, key)) return false;\n if (!deepEqual(xObj[key], yObj[key])) return false;\n }\n\n return true;\n}\n\n/**\n * Phase 1: Normalization\n * Convert syntactic sugar to canonical form\n */\nfunction normalize(schema: JSONSchema | boolean): JSONSchema {\n // Boolean schemas\n if (schema === true) return {};\n if (schema === false) return { not: {} };\n\n // Already an object\n const s = { ...schema };\n\n // Type arrays -> anyOf\n if (Array.isArray(s.type)) {\n const types = s.type as string[];\n if (types.length === 1) {\n s.type = types[0];\n } else {\n const { type: _type, ...rest } = s;\n return {\n anyOf: types.map((t) => normalize({ ...rest, type: t })),\n };\n }\n }\n\n // Integer is number with multipleOf: 1\n if (s.type === \"integer\") {\n s.type = \"number\";\n if (s.multipleOf === undefined) {\n s.multipleOf = 1;\n }\n }\n\n return s;\n}\n\n/**\n * Check if set A is a subset of set B (for required fields)\n */\nfunction isSetSubset(a: string[], b: string[]): boolean {\n const setB = new Set(b);\n return a.every((item) => setB.has(item));\n}\n\n/**\n * Get effective minimum value from schema\n */\nfunction getEffectiveMin(schema: JSONSchema): number {\n const min = schema.minimum ?? -Infinity;\n const exMin = schema.exclusiveMinimum;\n\n if (typeof exMin === \"number\") {\n return Math.max(min, exMin);\n }\n if (exMin === true && typeof schema.minimum === \"number\") {\n return schema.minimum;\n }\n return min;\n}\n\n/**\n * Get effective maximum value from schema\n */\nfunction getEffectiveMax(schema: JSONSchema): number {\n const max = schema.maximum ?? Infinity;\n const exMax = schema.exclusiveMaximum;\n\n if (typeof exMax === \"number\") {\n return Math.min(max, exMax);\n }\n if (exMax === true && typeof schema.maximum === \"number\") {\n return schema.maximum;\n }\n return max;\n}\n\n/**\n * Check if multipleOfA is a multiple of multipleOfB\n * (i.e., A's constraint is tighter)\n */\nfunction isMultipleOf(a: number, b: number): boolean {\n if (b === 0) return false;\n // Handle floating point precision\n const ratio = a / b;\n return Math.abs(ratio - Math.round(ratio)) < 1e-10;\n}\n\n/**\n * Check if A's enum values are all valid in B\n */\nfunction isEnumSubset(\n enumA: unknown[],\n schemaB: JSONSchema,\n): boolean {\n // If B has enum, check set inclusion\n if (schemaB.enum) {\n return enumA.every((val) =>\n schemaB.enum.some((bVal: unknown) => deepEqual(val, bVal))\n );\n }\n\n // If B has const, check if A's enum only contains that value\n if (schemaB.const !== undefined) {\n return (\n enumA.length === 1 && deepEqual(enumA[0], schemaB.const)\n );\n }\n\n // Otherwise, enum values must match B's type constraints\n // This is a simplified check - full validation would require more\n return true;\n}\n\n/**\n * Main subset check: isSubset(A, B)\n * Returns true if A ⊆ B (every value valid under A is valid under B)\n */\nexport function isSubset(\n schemaA: JSONSchema | boolean,\n schemaB: JSONSchema | boolean,\n): boolean {\n // Phase 1: Normalize\n const a = normalize(schemaA);\n const b = normalize(schemaB);\n\n // Phase 2: Meta Logic - Universal Terminators\n\n // If B is {} (Any), everything is a subset\n if (Object.keys(b).length === 0) return true;\n\n // If A is false (Never), empty set is subset of everything\n if (a.not && Object.keys(a.not).length === 0) return true;\n\n // Deep equality check\n if (deepEqual(a, b)) return true;\n\n // Phase 2: Unions and Intersections\n\n // Left-side union (anyOf in A): all options must fit in B\n if (a.anyOf) {\n return (a.anyOf as JSONSchema[]).every((optA) => isSubset(optA, b));\n }\n\n // Left-side union (oneOf in A): all options must fit in B\n if (a.oneOf) {\n return (a.oneOf as JSONSchema[]).every((optA) => isSubset(optA, b));\n }\n\n // Right-side union (anyOf in B): A must fit in at least one option\n if (b.anyOf) {\n return (b.anyOf as JSONSchema[]).some((optB) => isSubset(a, optB));\n }\n\n // Right-side union (oneOf in B): A must fit in at least one option\n if (b.oneOf) {\n return (b.oneOf as JSONSchema[]).some((optB) => isSubset(a, optB));\n }\n\n // Right-side intersection (allOf in B): A must satisfy all\n if (b.allOf) {\n return (b.allOf as JSONSchema[]).every((optB) => isSubset(a, optB));\n }\n\n // Left-side intersection (allOf in A): merge and compare\n if (a.allOf) {\n // Simplified: check if any single branch satisfies B\n return (a.allOf as JSONSchema[]).some((optA) => isSubset(optA, b));\n }\n\n // Phase 3: Type-specific logic\n\n // Handle const in A\n if (a.const !== undefined) {\n if (b.const !== undefined) {\n return deepEqual(a.const, b.const);\n }\n if (b.enum) {\n return b.enum.some((v: unknown) => deepEqual(a.const, v));\n }\n // const must match B's type constraints\n return isValueValidForType(a.const, b);\n }\n\n // Handle enum in A\n if (a.enum) {\n return isEnumSubset(a.enum, b);\n }\n\n // Type mismatch check\n if (a.type && b.type && a.type !== b.type) {\n return false;\n }\n\n // If B has a type but A doesn't, A might allow more types\n if (b.type && !a.type) {\n // A is more permissive (no type restriction) so it's not a subset\n // unless A has other constraints that limit it\n if (!a.enum && a.const === undefined) {\n return false;\n }\n }\n\n const type = a.type || b.type;\n\n switch (type) {\n case \"object\":\n return isObjectSubset(a, b);\n case \"array\":\n return isArraySubset(a, b);\n case \"number\":\n return isNumberSubset(a, b);\n case \"string\":\n return isStringSubset(a, b);\n case \"boolean\":\n case \"null\":\n // These types have no additional constraints\n return true;\n default:\n // Unknown type or no type specified\n return true;\n }\n}\n\n/**\n * Check if a value would be valid for a schema's type\n */\nfunction isValueValidForType(value: unknown, schema: JSONSchema): boolean {\n if (!schema.type) return true;\n\n const valueType = typeof value;\n switch (schema.type) {\n case \"string\":\n return valueType === \"string\";\n case \"number\":\n return valueType === \"number\";\n case \"boolean\":\n return valueType === \"boolean\";\n case \"null\":\n return value === null;\n case \"object\":\n return valueType === \"object\" && value !== null && !Array.isArray(value);\n case \"array\":\n return Array.isArray(value);\n default:\n return true;\n }\n}\n\n/**\n * Object subset check\n */\nfunction isObjectSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Required keys: A must require at least everything B requires\n const aRequired = (a.required as string[]) || [];\n const bRequired = (b.required as string[]) || [];\n\n if (!isSetSubset(bRequired, aRequired)) {\n return false;\n }\n\n // Property compatibility\n const aProps = (a.properties as Record<string, JSONSchema>) || {};\n const bProps = (b.properties as Record<string, JSONSchema>) || {};\n\n // Check all properties defined in B\n for (const key of Object.keys(bProps)) {\n if (key in aProps) {\n // Both have the property, check recursively\n if (!isSubset(aProps[key], bProps[key])) {\n return false;\n }\n } else {\n // Property missing in A\n // If A is closed (additionalProperties: false), A won't produce this key\n // which means A values won't have this property, potentially violating B if B requires it\n if (a.additionalProperties === false) {\n // A is closed and doesn't have this property\n // If B requires this property, A can't satisfy it\n if (bRequired.includes(key)) {\n return false;\n }\n // Otherwise, A just won't have this optional property, which is fine\n } else {\n // A is open, check if additionalProperties schema satisfies B's property\n const aAdditional = a.additionalProperties;\n if (aAdditional && typeof aAdditional === \"object\") {\n if (!isSubset(aAdditional, bProps[key])) {\n return false;\n }\n }\n // If additionalProperties is true or undefined, any value is allowed\n // which might not satisfy B's property schema\n }\n }\n }\n\n // Check all properties defined in A (that A requires)\n // If A requires a property, B must also define it (or have compatible additionalProperties)\n for (const key of aRequired) {\n if (key in aProps && !(key in bProps)) {\n // A requires and defines this property, but B doesn't define it\n // B must have additionalProperties that accepts A's property schema\n if (b.additionalProperties === false) {\n // B doesn't allow additional properties, so A's required property would be rejected\n return false;\n } else if (\n b.additionalProperties &&\n typeof b.additionalProperties === \"object\"\n ) {\n // B has a schema for additional properties, check compatibility\n if (!isSubset(aProps[key], b.additionalProperties)) {\n return false;\n }\n }\n // If B's additionalProperties is true or undefined, any value is allowed\n }\n }\n\n // Additional properties constraint\n if (b.additionalProperties === false) {\n // B is closed, A must also be closed or not have extra properties\n const aHasExtraProps = Object.keys(aProps).some(\n (key) => !(key in bProps),\n );\n if (aHasExtraProps) {\n return false;\n }\n // If A is open and B is closed, A could produce extra properties\n if (a.additionalProperties !== false) {\n return false;\n }\n } else if (\n b.additionalProperties &&\n typeof b.additionalProperties === \"object\"\n ) {\n // B has a schema for additional properties\n const aAdditional = a.additionalProperties;\n if (aAdditional && typeof aAdditional === \"object\") {\n if (!isSubset(aAdditional, b.additionalProperties)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Array subset check\n */\nfunction isArraySubset(a: JSONSchema, b: JSONSchema): boolean {\n // Items schema\n if (a.items && b.items) {\n if (Array.isArray(a.items) && Array.isArray(b.items)) {\n // Both are tuples\n if (a.items.length !== b.items.length) {\n return false;\n }\n for (let i = 0; i < a.items.length; i++) {\n if (!isSubset(a.items[i], b.items[i])) {\n return false;\n }\n }\n } else if (Array.isArray(a.items) && !Array.isArray(b.items)) {\n // A is tuple, B is list\n for (const itemSchema of a.items) {\n if (!isSubset(itemSchema, b.items)) {\n return false;\n }\n }\n } else if (!Array.isArray(a.items) && Array.isArray(b.items)) {\n // A is list, B is tuple - A is more permissive\n return false;\n } else {\n // Both are lists\n if (!isSubset(a.items, b.items)) {\n return false;\n }\n }\n } else if (b.items && !a.items) {\n // B has items constraint but A doesn't\n return false;\n }\n\n // Length constraints\n const aMinItems = a.minItems ?? 0;\n const bMinItems = b.minItems ?? 0;\n if (aMinItems < bMinItems) {\n return false;\n }\n\n const aMaxItems = a.maxItems ?? Infinity;\n const bMaxItems = b.maxItems ?? Infinity;\n if (aMaxItems > bMaxItems) {\n return false;\n }\n\n // Uniqueness\n if (b.uniqueItems && !a.uniqueItems) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Number subset check\n */\nfunction isNumberSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Minimum\n const aMin = getEffectiveMin(a);\n const bMin = getEffectiveMin(b);\n if (aMin < bMin) {\n return false;\n }\n\n // Maximum\n const aMax = getEffectiveMax(a);\n const bMax = getEffectiveMax(b);\n if (aMax > bMax) {\n return false;\n }\n\n // MultipleOf\n if (b.multipleOf !== undefined) {\n if (a.multipleOf === undefined) {\n // A doesn't have multipleOf constraint, so it's more permissive\n return false;\n }\n if (!isMultipleOf(a.multipleOf, b.multipleOf)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * String subset check\n */\nfunction isStringSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Length constraints\n const aMinLength = a.minLength ?? 0;\n const bMinLength = b.minLength ?? 0;\n if (aMinLength < bMinLength) {\n return false;\n }\n\n const aMaxLength = a.maxLength ?? Infinity;\n const bMaxLength = b.maxLength ?? Infinity;\n if (aMaxLength > bMaxLength) {\n return false;\n }\n\n // Pattern (regex)\n if (b.pattern) {\n if (!a.pattern) {\n // A has no pattern constraint, more permissive\n return false;\n }\n // Exact match only (full regex subset check is computationally expensive)\n if (a.pattern !== b.pattern) {\n return false;\n }\n }\n\n // Format (treat as informational, exact match required)\n if (b.format && a.format !== b.format) {\n return false;\n }\n\n return true;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/core/subset.ts"],"sourcesContent":["/**\n * Structural JSON Schema Subset Check\n *\n * This module implements an algorithm to determine if one JSON Schema (A)\n * is a subset of another (B). A ⊆ B means every value valid under A is also\n * valid under B (A is more restrictive or equally restrictive).\n *\n * Core Axiom: A ⊆ B ⟺ Constraints(A) ⊇ Constraints(B)\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype JSONSchema = Record<string, any>;\n\n/**\n * Deep equality check for JSON values (for const/enum comparison)\n */\nfunction deepEqual(x: unknown, y: unknown): boolean {\n if (x === y) return true;\n if (typeof x !== typeof y) return false;\n if (x === null || y === null) return x === y;\n if (typeof x !== \"object\") return false;\n\n if (Array.isArray(x)) {\n if (!Array.isArray(y)) return false;\n if (x.length !== y.length) return false;\n for (let i = 0; i < x.length; i++) {\n if (!deepEqual(x[i], y[i])) return false;\n }\n return true;\n }\n\n if (Array.isArray(y)) return false;\n\n const xObj = x as Record<string, unknown>;\n const yObj = y as Record<string, unknown>;\n const xKeys = Object.keys(xObj);\n const yKeys = Object.keys(yObj);\n\n if (xKeys.length !== yKeys.length) return false;\n\n for (const key of xKeys) {\n if (!Object.prototype.hasOwnProperty.call(yObj, key)) return false;\n if (!deepEqual(xObj[key], yObj[key])) return false;\n }\n\n return true;\n}\n\n/**\n * Phase 1: Normalization\n * Convert syntactic sugar to canonical form\n */\nfunction normalize(schema: JSONSchema | boolean): JSONSchema {\n // Boolean schemas\n if (schema === true) return {};\n if (schema === false) return { not: {} };\n\n // Already an object\n const s = { ...schema };\n\n // Type arrays -> anyOf\n if (Array.isArray(s.type)) {\n const types = s.type as string[];\n if (types.length === 1) {\n s.type = types[0];\n } else {\n const { type: _type, ...rest } = s;\n return {\n anyOf: types.map((t) => normalize({ ...rest, type: t })),\n };\n }\n }\n\n // Integer is number with multipleOf: 1\n if (s.type === \"integer\") {\n s.type = \"number\";\n if (s.multipleOf === undefined) {\n s.multipleOf = 1;\n }\n }\n\n return s;\n}\n\n/**\n * Check if set A is a subset of set B (for required fields)\n */\nfunction isSetSubset(a: string[], b: string[]): boolean {\n const setB = new Set(b);\n return a.every((item) => setB.has(item));\n}\n\n/**\n * Get effective minimum value from schema\n */\nfunction getEffectiveMin(schema: JSONSchema): number {\n const min = schema.minimum ?? -Infinity;\n const exMin = schema.exclusiveMinimum;\n\n if (typeof exMin === \"number\") {\n return Math.max(min, exMin);\n }\n if (exMin === true && typeof schema.minimum === \"number\") {\n return schema.minimum;\n }\n return min;\n}\n\n/**\n * Get effective maximum value from schema\n */\nfunction getEffectiveMax(schema: JSONSchema): number {\n const max = schema.maximum ?? Infinity;\n const exMax = schema.exclusiveMaximum;\n\n if (typeof exMax === \"number\") {\n return Math.min(max, exMax);\n }\n if (exMax === true && typeof schema.maximum === \"number\") {\n return schema.maximum;\n }\n return max;\n}\n\n/**\n * Check if multipleOfA is a multiple of multipleOfB\n * (i.e., A's constraint is tighter)\n */\nfunction isMultipleOf(a: number, b: number): boolean {\n if (b === 0) return false;\n // Handle floating point precision\n const ratio = a / b;\n return Math.abs(ratio - Math.round(ratio)) < 1e-10;\n}\n\n/**\n * Check if A's enum values are all valid in B\n */\nfunction isEnumSubset(enumA: unknown[], schemaB: JSONSchema): boolean {\n // If B has enum, check set inclusion\n if (schemaB.enum) {\n return enumA.every((val) =>\n schemaB.enum.some((bVal: unknown) => deepEqual(val, bVal)),\n );\n }\n\n // If B has const, check if A's enum only contains that value\n if (schemaB.const !== undefined) {\n return enumA.length === 1 && deepEqual(enumA[0], schemaB.const);\n }\n\n // Otherwise, enum values must match B's type constraints\n // This is a simplified check - full validation would require more\n return true;\n}\n\n/**\n * Main subset check: isSubset(A, B)\n * Returns true if A ⊆ B (every value valid under A is valid under B)\n */\nexport function isSubset(\n schemaA: JSONSchema | boolean,\n schemaB: JSONSchema | boolean,\n): boolean {\n // Phase 1: Normalize\n const a = normalize(schemaA);\n const b = normalize(schemaB);\n\n // Phase 2: Meta Logic - Universal Terminators\n\n // If B is {} (Any), everything is a subset\n if (Object.keys(b).length === 0) return true;\n\n // If A is false (Never), empty set is subset of everything\n if (a.not && Object.keys(a.not).length === 0) return true;\n\n // Deep equality check\n if (deepEqual(a, b)) return true;\n\n // Phase 2: Unions and Intersections\n\n // Left-side union (anyOf in A): all options must fit in B\n if (a.anyOf) {\n return (a.anyOf as JSONSchema[]).every((optA) => isSubset(optA, b));\n }\n\n // Left-side union (oneOf in A): all options must fit in B\n if (a.oneOf) {\n return (a.oneOf as JSONSchema[]).every((optA) => isSubset(optA, b));\n }\n\n // Right-side union (anyOf in B): A must fit in at least one option\n if (b.anyOf) {\n return (b.anyOf as JSONSchema[]).some((optB) => isSubset(a, optB));\n }\n\n // Right-side union (oneOf in B): A must fit in at least one option\n if (b.oneOf) {\n return (b.oneOf as JSONSchema[]).some((optB) => isSubset(a, optB));\n }\n\n // Right-side intersection (allOf in B): A must satisfy all\n if (b.allOf) {\n return (b.allOf as JSONSchema[]).every((optB) => isSubset(a, optB));\n }\n\n // Left-side intersection (allOf in A): merge and compare\n if (a.allOf) {\n // Simplified: check if any single branch satisfies B\n return (a.allOf as JSONSchema[]).some((optA) => isSubset(optA, b));\n }\n\n // Phase 3: Type-specific logic\n\n // Handle const in A\n if (a.const !== undefined) {\n if (b.const !== undefined) {\n return deepEqual(a.const, b.const);\n }\n if (b.enum) {\n return b.enum.some((v: unknown) => deepEqual(a.const, v));\n }\n // const must match B's type constraints\n return isValueValidForType(a.const, b);\n }\n\n // Handle enum in A\n if (a.enum) {\n return isEnumSubset(a.enum, b);\n }\n\n // Type mismatch check\n if (a.type && b.type && a.type !== b.type) {\n return false;\n }\n\n // If B has a type but A doesn't, A might allow more types\n if (b.type && !a.type) {\n // A is more permissive (no type restriction) so it's not a subset\n // unless A has other constraints that limit it\n if (!a.enum && a.const === undefined) {\n return false;\n }\n }\n\n const type = a.type || b.type;\n\n switch (type) {\n case \"object\":\n return isObjectSubset(a, b);\n case \"array\":\n return isArraySubset(a, b);\n case \"number\":\n return isNumberSubset(a, b);\n case \"string\":\n return isStringSubset(a, b);\n case \"boolean\":\n case \"null\":\n // These types have no additional constraints\n return true;\n default:\n // Unknown type or no type specified\n return true;\n }\n}\n\n/**\n * Check if a value would be valid for a schema's type\n */\nfunction isValueValidForType(value: unknown, schema: JSONSchema): boolean {\n if (!schema.type) return true;\n\n const valueType = typeof value;\n switch (schema.type) {\n case \"string\":\n return valueType === \"string\";\n case \"number\":\n return valueType === \"number\";\n case \"boolean\":\n return valueType === \"boolean\";\n case \"null\":\n return value === null;\n case \"object\":\n return valueType === \"object\" && value !== null && !Array.isArray(value);\n case \"array\":\n return Array.isArray(value);\n default:\n return true;\n }\n}\n\n/**\n * Object subset check\n */\nfunction isObjectSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Required keys: A must require at least everything B requires\n const aRequired = (a.required as string[]) || [];\n const bRequired = (b.required as string[]) || [];\n\n if (!isSetSubset(bRequired, aRequired)) {\n return false;\n }\n\n // Property compatibility\n const aProps = (a.properties as Record<string, JSONSchema>) || {};\n const bProps = (b.properties as Record<string, JSONSchema>) || {};\n\n // Check all properties defined in B\n for (const key of Object.keys(bProps)) {\n if (key in aProps) {\n // Both have the property, check recursively\n if (!isSubset(aProps[key], bProps[key])) {\n return false;\n }\n } else {\n // Property missing in A\n // If A is closed (additionalProperties: false), A won't produce this key\n // which means A values won't have this property, potentially violating B if B requires it\n if (a.additionalProperties === false) {\n // A is closed and doesn't have this property\n // If B requires this property, A can't satisfy it\n if (bRequired.includes(key)) {\n return false;\n }\n // Otherwise, A just won't have this optional property, which is fine\n } else {\n // A is open, check if additionalProperties schema satisfies B's property\n const aAdditional = a.additionalProperties;\n if (aAdditional && typeof aAdditional === \"object\") {\n if (!isSubset(aAdditional, bProps[key])) {\n return false;\n }\n }\n // If additionalProperties is true or undefined, any value is allowed\n // which might not satisfy B's property schema\n }\n }\n }\n\n // Check all properties defined in A (that A requires)\n // If A requires a property, B must also define it (or have compatible additionalProperties)\n for (const key of aRequired) {\n if (key in aProps && !(key in bProps)) {\n // A requires and defines this property, but B doesn't define it\n // B must have additionalProperties that accepts A's property schema\n if (b.additionalProperties === false) {\n // B doesn't allow additional properties, so A's required property would be rejected\n return false;\n } else if (\n b.additionalProperties &&\n typeof b.additionalProperties === \"object\"\n ) {\n // B has a schema for additional properties, check compatibility\n if (!isSubset(aProps[key], b.additionalProperties)) {\n return false;\n }\n }\n // If B's additionalProperties is true or undefined, any value is allowed\n }\n }\n\n // Additional properties constraint\n if (b.additionalProperties === false) {\n // B is closed, A must also be closed or not have extra properties\n const aHasExtraProps = Object.keys(aProps).some((key) => !(key in bProps));\n if (aHasExtraProps) {\n return false;\n }\n // If A is open and B is closed, A could produce extra properties\n if (a.additionalProperties !== false) {\n return false;\n }\n } else if (\n b.additionalProperties &&\n typeof b.additionalProperties === \"object\"\n ) {\n // B has a schema for additional properties\n const aAdditional = a.additionalProperties;\n if (aAdditional && typeof aAdditional === \"object\") {\n if (!isSubset(aAdditional, b.additionalProperties)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Array subset check\n */\nfunction isArraySubset(a: JSONSchema, b: JSONSchema): boolean {\n // Items schema\n if (a.items && b.items) {\n if (Array.isArray(a.items) && Array.isArray(b.items)) {\n // Both are tuples\n if (a.items.length !== b.items.length) {\n return false;\n }\n for (let i = 0; i < a.items.length; i++) {\n if (!isSubset(a.items[i], b.items[i])) {\n return false;\n }\n }\n } else if (Array.isArray(a.items) && !Array.isArray(b.items)) {\n // A is tuple, B is list\n for (const itemSchema of a.items) {\n if (!isSubset(itemSchema, b.items)) {\n return false;\n }\n }\n } else if (!Array.isArray(a.items) && Array.isArray(b.items)) {\n // A is list, B is tuple - A is more permissive\n return false;\n } else {\n // Both are lists\n if (!isSubset(a.items, b.items)) {\n return false;\n }\n }\n } else if (b.items && !a.items) {\n // B has items constraint but A doesn't\n return false;\n }\n\n // Length constraints\n const aMinItems = a.minItems ?? 0;\n const bMinItems = b.minItems ?? 0;\n if (aMinItems < bMinItems) {\n return false;\n }\n\n const aMaxItems = a.maxItems ?? Infinity;\n const bMaxItems = b.maxItems ?? Infinity;\n if (aMaxItems > bMaxItems) {\n return false;\n }\n\n // Uniqueness\n if (b.uniqueItems && !a.uniqueItems) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Number subset check\n */\nfunction isNumberSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Minimum\n const aMin = getEffectiveMin(a);\n const bMin = getEffectiveMin(b);\n if (aMin < bMin) {\n return false;\n }\n\n // Maximum\n const aMax = getEffectiveMax(a);\n const bMax = getEffectiveMax(b);\n if (aMax > bMax) {\n return false;\n }\n\n // MultipleOf\n if (b.multipleOf !== undefined) {\n if (a.multipleOf === undefined) {\n // A doesn't have multipleOf constraint, so it's more permissive\n return false;\n }\n if (!isMultipleOf(a.multipleOf, b.multipleOf)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * String subset check\n */\nfunction isStringSubset(a: JSONSchema, b: JSONSchema): boolean {\n // Length constraints\n const aMinLength = a.minLength ?? 0;\n const bMinLength = b.minLength ?? 0;\n if (aMinLength < bMinLength) {\n return false;\n }\n\n const aMaxLength = a.maxLength ?? Infinity;\n const bMaxLength = b.maxLength ?? Infinity;\n if (aMaxLength > bMaxLength) {\n return false;\n }\n\n // Pattern (regex)\n if (b.pattern) {\n if (!a.pattern) {\n // A has no pattern constraint, more permissive\n return false;\n }\n // Exact match only (full regex subset check is computationally expensive)\n if (a.pattern !== b.pattern) {\n return false;\n }\n }\n\n // Format (treat as informational, exact match required)\n if (b.format && a.format !== b.format) {\n return false;\n }\n\n return true;\n}\n"],"mappings":"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","names":[]}
@@ -14,8 +14,7 @@ const AgentSchema = BaseCollectionEntitySchema.extend({
14
14
  });
15
15
  const AGENTS_COLLECTION_BINDING = createCollectionBindings(
16
16
  "agent",
17
- AgentSchema,
18
- { readOnly: true }
17
+ AgentSchema
19
18
  );
20
19
  const AGENTS_BINDING = [
21
20
  ...AGENTS_COLLECTION_BINDING
@@ -25,4 +24,4 @@ export {
25
24
  AGENTS_COLLECTION_BINDING,
26
25
  AgentSchema
27
26
  };
28
- //# sourceMappingURL=agents.js.map
27
+ //# sourceMappingURL=agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/well-known/agent.ts"],"sourcesContent":["/**\n * Agents Well-Known Binding\n *\n * Defines the interface for AI agent providers.\n * Any MCP that implements this binding can provide configurable AI agents\n * with custom instructions and tool access controls.\n *\n * This binding uses collection bindings for LIST and GET operations (read-only).\n */\n\nimport { z } from \"zod/v3\";\nimport type { Binder } from \"../core/binder\";\nimport {\n BaseCollectionEntitySchema,\n createCollectionBindings,\n} from \"./collections\";\n\n/**\n * Agent entity schema for AI agents\n * Extends BaseCollectionEntitySchema with agent-specific fields\n * Base schema already includes: id, title, created_at, updated_at, created_by, updated_by\n */\nexport const AgentSchema = BaseCollectionEntitySchema.extend({\n // Agent-specific fields\n description: z.string().describe(\"Brief description of the agent's purpose\"),\n instructions: z\n .string()\n .describe(\"System instructions that define the agent's behavior\"),\n tool_set: z\n .record(z.string(), z.array(z.string()))\n .describe(\n \"Map of connection IDs to arrays of allowed tool names for this agent\",\n ),\n avatar: z.string().url().describe(\"URL to the agent's avatar image\"),\n});\n\n/**\n * AGENT Collection Binding\n *\n * Collection bindings for agents (read-only).\n * Provides LIST and GET operations for AI agents.\n */\nexport const AGENTS_COLLECTION_BINDING = createCollectionBindings(\n \"agent\",\n AgentSchema,\n);\n\n/**\n * AGENTS Binding\n *\n * Defines the interface for AI agent providers.\n * Any MCP that implements this binding can provide configurable AI agents.\n *\n * Required tools:\n * - COLLECTION_AGENT_LIST: List available AI agents with their configurations\n * - COLLECTION_AGENT_GET: Get a single agent by ID (includes instructions and tool_set)\n */\nexport const AGENTS_BINDING = [\n ...AGENTS_COLLECTION_BINDING,\n] as const satisfies Binder;\n"],"mappings":"AAUA,SAAS,SAAS;AAElB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAOA,MAAM,cAAc,2BAA2B,OAAO;AAAA;AAAA,EAE3D,aAAa,EAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EAC3E,cAAc,EACX,OAAO,EACP,SAAS,sDAAsD;AAAA,EAClE,UAAU,EACP,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EACtC;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,iCAAiC;AACrE,CAAC;AAQM,MAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AACF;AAYO,MAAM,iBAAiB;AAAA,EAC5B,GAAG;AACL;","names":[]}