ont-run 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Utility functions for inspecting Zod 4 schemas.
3
+ * These use duck typing to work across bundle boundaries.
4
+ */
5
+
6
+ /**
7
+ * Check if a value is a Zod 3 schema (has _def but not _zod)
8
+ */
9
+ export function isZod3Schema(val: unknown): boolean {
10
+ if (val === null || typeof val !== "object") return false;
11
+ // Zod 3 uses _def property without _zod
12
+ if ("_def" in val && "safeParse" in val && !("_zod" in val)) return true;
13
+ return false;
14
+ }
15
+
16
+ /**
17
+ * Check if a value is a Zod schema (duck typing to work across bundle boundaries)
18
+ */
19
+ export function isZodSchema(val: unknown): boolean {
20
+ if (val === null || typeof val !== "object") return false;
21
+ // Zod 4 uses _zod property
22
+ if ("_zod" in val && "safeParse" in val) return true;
23
+ return false;
24
+ }
25
+
26
+ /**
27
+ * Get the Zod type name from a schema
28
+ */
29
+ export function getZodTypeName(schema: unknown): string | undefined {
30
+ if (!isZodSchema(schema)) return undefined;
31
+ const s = schema as Record<string, unknown>;
32
+ // Zod 4: check _zod.def.typeName
33
+ if (s._zod && typeof s._zod === "object") {
34
+ const zod = s._zod as Record<string, unknown>;
35
+ if (zod.def && typeof zod.def === "object") {
36
+ const def = zod.def as Record<string, unknown>;
37
+ if (typeof def.typeName === "string") return def.typeName;
38
+ }
39
+ }
40
+ return undefined;
41
+ }
42
+
43
+ /**
44
+ * Check if schema is a ZodObject
45
+ */
46
+ export function isZodObject(schema: unknown): boolean {
47
+ const typeName = getZodTypeName(schema);
48
+ return typeName === "ZodObject";
49
+ }
50
+
51
+ /**
52
+ * Check if schema is a ZodOptional
53
+ */
54
+ export function isZodOptional(schema: unknown): boolean {
55
+ const typeName = getZodTypeName(schema);
56
+ return typeName === "ZodOptional";
57
+ }
58
+
59
+ /**
60
+ * Check if schema is a ZodNullable
61
+ */
62
+ export function isZodNullable(schema: unknown): boolean {
63
+ const typeName = getZodTypeName(schema);
64
+ return typeName === "ZodNullable";
65
+ }
66
+
67
+ /**
68
+ * Check if schema is a ZodArray
69
+ */
70
+ export function isZodArray(schema: unknown): boolean {
71
+ const typeName = getZodTypeName(schema);
72
+ return typeName === "ZodArray";
73
+ }
74
+
75
+ /**
76
+ * Check if schema is a ZodDefault
77
+ */
78
+ export function isZodDefault(schema: unknown): boolean {
79
+ const typeName = getZodTypeName(schema);
80
+ return typeName === "ZodDefault";
81
+ }
82
+
83
+ /**
84
+ * Get the shape of a ZodObject schema
85
+ */
86
+ export function getObjectShape(schema: unknown): Record<string, unknown> | undefined {
87
+ if (!isZodObject(schema)) return undefined;
88
+ const s = schema as Record<string, unknown>;
89
+ // Zod 4: shape is in _zod.def.shape
90
+ if (s._zod && typeof s._zod === "object") {
91
+ const zod = s._zod as Record<string, unknown>;
92
+ if (zod.def && typeof zod.def === "object") {
93
+ const def = zod.def as Record<string, unknown>;
94
+ if (def.shape && typeof def.shape === "object") {
95
+ return def.shape as Record<string, unknown>;
96
+ }
97
+ }
98
+ }
99
+ return undefined;
100
+ }
101
+
102
+ /**
103
+ * Get the inner schema from Optional/Nullable/Default
104
+ */
105
+ export function getInnerSchema(schema: unknown): unknown {
106
+ const s = schema as Record<string, unknown>;
107
+ // Zod 4: innerType is in _zod.def.innerType
108
+ if (s._zod && typeof s._zod === "object") {
109
+ const zod = s._zod as Record<string, unknown>;
110
+ if (zod.def && typeof zod.def === "object") {
111
+ const def = zod.def as Record<string, unknown>;
112
+ if (def.innerType) return def.innerType;
113
+ }
114
+ }
115
+ return undefined;
116
+ }
117
+
118
+ /**
119
+ * Get the element schema from a ZodArray
120
+ */
121
+ export function getArrayElement(schema: unknown): unknown {
122
+ if (!isZodArray(schema)) return undefined;
123
+ const s = schema as Record<string, unknown>;
124
+ // Zod 4: element is in _zod.def.element
125
+ if (s._zod && typeof s._zod === "object") {
126
+ const zod = s._zod as Record<string, unknown>;
127
+ if (zod.def && typeof zod.def === "object") {
128
+ const def = zod.def as Record<string, unknown>;
129
+ if (def.element) return def.element;
130
+ }
131
+ }
132
+ return undefined;
133
+ }
@@ -1,8 +1,17 @@
1
1
  import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
- import { zodToJsonSchema } from "zod-to-json-schema";
4
3
  import type { OntologyConfig } from "../config/types.js";
5
4
  import { getFieldFromMetadata, getUserContextFields } from "../config/categorical.js";
5
+ import {
6
+ isZodObject,
7
+ isZodOptional,
8
+ isZodNullable,
9
+ isZodArray,
10
+ isZodDefault,
11
+ getObjectShape,
12
+ getInnerSchema,
13
+ getArrayElement,
14
+ } from "../config/zod-utils.js";
6
15
  import type {
7
16
  OntologySnapshot,
8
17
  FunctionShape,
@@ -28,34 +37,48 @@ function extractFieldReferences(
28
37
  }
29
38
 
30
39
  // Handle ZodObject - recurse into properties
31
- if (schema instanceof z.ZodObject) {
32
- const shape = schema.shape;
33
- for (const [key, value] of Object.entries(shape)) {
34
- const fieldPath = path ? `${path}.${key}` : key;
35
- results.push(
36
- ...extractFieldReferences(value as z.ZodType<unknown>, fieldPath)
37
- );
40
+ if (isZodObject(schema)) {
41
+ const shape = getObjectShape(schema);
42
+ if (shape) {
43
+ for (const [key, value] of Object.entries(shape)) {
44
+ const fieldPath = path ? `${path}.${key}` : key;
45
+ results.push(
46
+ ...extractFieldReferences(value as z.ZodType<unknown>, fieldPath)
47
+ );
48
+ }
38
49
  }
39
50
  }
40
51
 
41
52
  // Handle ZodOptional - unwrap
42
- if (schema instanceof z.ZodOptional) {
43
- results.push(...extractFieldReferences(schema.unwrap(), path));
53
+ if (isZodOptional(schema)) {
54
+ const inner = getInnerSchema(schema);
55
+ if (inner) {
56
+ results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
57
+ }
44
58
  }
45
59
 
46
60
  // Handle ZodNullable - unwrap
47
- if (schema instanceof z.ZodNullable) {
48
- results.push(...extractFieldReferences(schema.unwrap(), path));
61
+ if (isZodNullable(schema)) {
62
+ const inner = getInnerSchema(schema);
63
+ if (inner) {
64
+ results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
65
+ }
49
66
  }
50
67
 
51
68
  // Handle ZodArray - recurse into element
52
- if (schema instanceof z.ZodArray) {
53
- results.push(...extractFieldReferences(schema.element, `${path}[]`));
69
+ if (isZodArray(schema)) {
70
+ const element = getArrayElement(schema);
71
+ if (element) {
72
+ results.push(...extractFieldReferences(element as z.ZodType<unknown>, `${path}[]`));
73
+ }
54
74
  }
55
75
 
56
76
  // Handle ZodDefault - unwrap
57
- if (schema instanceof z.ZodDefault) {
58
- results.push(...extractFieldReferences(schema._def.innerType, path));
77
+ if (isZodDefault(schema)) {
78
+ const inner = getInnerSchema(schema);
79
+ if (inner) {
80
+ results.push(...extractFieldReferences(inner as z.ZodType<unknown>, path));
81
+ }
59
82
  }
60
83
 
61
84
  return results;
@@ -85,14 +108,14 @@ export function extractOntology(config: OntologyConfig): OntologySnapshot {
85
108
  // This ensures we're comparing the shape, not the Zod instance
86
109
  let inputsSchema: Record<string, unknown>;
87
110
  try {
88
- inputsSchema = zodToJsonSchema(fn.inputs, {
89
- // Remove $schema to make hashing more stable
90
- $refStrategy: "none",
111
+ inputsSchema = z.toJSONSchema(fn.inputs, {
112
+ reused: "inline",
113
+ unrepresentable: "any",
91
114
  }) as Record<string, unknown>;
92
115
  // Remove $schema key if present
93
116
  delete inputsSchema.$schema;
94
117
  } catch {
95
- // If zodToJsonSchema fails, use a placeholder
118
+ // If z.toJSONSchema fails, use a placeholder
96
119
  inputsSchema = { type: "unknown" };
97
120
  }
98
121
 
@@ -100,8 +123,9 @@ export function extractOntology(config: OntologyConfig): OntologySnapshot {
100
123
  let outputsSchema: Record<string, unknown> | undefined;
101
124
  if (fn.outputs) {
102
125
  try {
103
- outputsSchema = zodToJsonSchema(fn.outputs, {
104
- $refStrategy: "none",
126
+ outputsSchema = z.toJSONSchema(fn.outputs, {
127
+ reused: "inline",
128
+ unrepresentable: "any",
105
129
  }) as Record<string, unknown>;
106
130
  delete outputsSchema.$schema;
107
131
  } catch {
@@ -1,5 +1,4 @@
1
1
  import { z } from "zod";
2
- import { zodToJsonSchema } from "zod-to-json-schema";
3
2
  import type {
4
3
  OntologyConfig,
5
4
  FunctionDefinition,
@@ -8,6 +7,16 @@ import type {
8
7
  AuthResult,
9
8
  } from "../../config/types.js";
10
9
  import { getFieldFromMetadata, getUserContextFields, hasUserContextMetadata } from "../../config/categorical.js";
10
+ import {
11
+ isZodObject,
12
+ isZodOptional,
13
+ isZodNullable,
14
+ isZodArray,
15
+ isZodDefault,
16
+ getObjectShape,
17
+ getInnerSchema,
18
+ getArrayElement,
19
+ } from "../../config/zod-utils.js";
11
20
  import type { Logger } from "../resolver.js";
12
21
 
13
22
  /**
@@ -94,36 +103,48 @@ function extractFieldReferencesForMcp(
94
103
  }
95
104
 
96
105
  // Handle ZodObject - recurse into properties
97
- if (schema instanceof z.ZodObject) {
98
- const shape = schema.shape;
99
- for (const [key, value] of Object.entries(shape)) {
100
- const fieldPath = path ? `${path}.${key}` : key;
101
- results.push(
102
- ...extractFieldReferencesForMcp(value as z.ZodType<unknown>, fieldPath)
103
- );
106
+ if (isZodObject(schema)) {
107
+ const shape = getObjectShape(schema);
108
+ if (shape) {
109
+ for (const [key, value] of Object.entries(shape)) {
110
+ const fieldPath = path ? `${path}.${key}` : key;
111
+ results.push(
112
+ ...extractFieldReferencesForMcp(value as z.ZodType<unknown>, fieldPath)
113
+ );
114
+ }
104
115
  }
105
116
  }
106
117
 
107
118
  // Handle ZodOptional - unwrap
108
- if (schema instanceof z.ZodOptional) {
109
- results.push(...extractFieldReferencesForMcp(schema.unwrap(), path));
119
+ if (isZodOptional(schema)) {
120
+ const inner = getInnerSchema(schema);
121
+ if (inner) {
122
+ results.push(...extractFieldReferencesForMcp(inner as z.ZodType<unknown>, path));
123
+ }
110
124
  }
111
125
 
112
126
  // Handle ZodNullable - unwrap
113
- if (schema instanceof z.ZodNullable) {
114
- results.push(...extractFieldReferencesForMcp(schema.unwrap(), path));
127
+ if (isZodNullable(schema)) {
128
+ const inner = getInnerSchema(schema);
129
+ if (inner) {
130
+ results.push(...extractFieldReferencesForMcp(inner as z.ZodType<unknown>, path));
131
+ }
115
132
  }
116
133
 
117
134
  // Handle ZodArray - recurse into element
118
- if (schema instanceof z.ZodArray) {
119
- results.push(...extractFieldReferencesForMcp(schema.element, `${path}[]`));
135
+ if (isZodArray(schema)) {
136
+ const element = getArrayElement(schema);
137
+ if (element) {
138
+ results.push(...extractFieldReferencesForMcp(element as z.ZodType<unknown>, `${path}[]`));
139
+ }
120
140
  }
121
141
 
122
142
  // Handle ZodDefault - unwrap
123
- if (schema instanceof z.ZodDefault) {
124
- results.push(
125
- ...extractFieldReferencesForMcp(schema._def.innerType, path)
126
- );
143
+ if (isZodDefault(schema)) {
144
+ const inner = getInnerSchema(schema);
145
+ if (inner) {
146
+ results.push(...extractFieldReferencesForMcp(inner as z.ZodType<unknown>, path));
147
+ }
127
148
  }
128
149
 
129
150
  return results;
@@ -139,8 +160,9 @@ export function generateMcpTools(config: OntologyConfig): McpTool[] {
139
160
  // Convert Zod schema to JSON Schema for MCP
140
161
  let inputSchema: Record<string, unknown>;
141
162
  try {
142
- inputSchema = zodToJsonSchema(fn.inputs, {
143
- $refStrategy: "none",
163
+ inputSchema = z.toJSONSchema(fn.inputs, {
164
+ reused: "inline",
165
+ unrepresentable: "any",
144
166
  }) as Record<string, unknown>;
145
167
  // Remove $schema key if present
146
168
  delete inputSchema.$schema;
@@ -154,8 +176,9 @@ export function generateMcpTools(config: OntologyConfig): McpTool[] {
154
176
  let outputSchema: Record<string, unknown> | undefined;
155
177
  if (fn.outputs) {
156
178
  try {
157
- outputSchema = zodToJsonSchema(fn.outputs, {
158
- $refStrategy: "none",
179
+ outputSchema = z.toJSONSchema(fn.outputs, {
180
+ reused: "inline",
181
+ unrepresentable: "any",
159
182
  }) as Record<string, unknown>;
160
183
  delete outputSchema.$schema;
161
184
  } catch {