@jackchen_me/open-multi-agent 0.1.0
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/LICENSE +21 -0
- package/README.md +280 -0
- package/dist/agent/agent.d.ts +121 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +294 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/pool.d.ts +128 -0
- package/dist/agent/pool.d.ts.map +1 -0
- package/dist/agent/pool.js +236 -0
- package/dist/agent/pool.js.map +1 -0
- package/dist/agent/runner.d.ts +120 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +274 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/adapter.d.ts +38 -0
- package/dist/llm/adapter.d.ts.map +1 -0
- package/dist/llm/adapter.js +46 -0
- package/dist/llm/adapter.js.map +1 -0
- package/dist/llm/anthropic.d.ts +56 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +307 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/openai.d.ts +62 -0
- package/dist/llm/openai.d.ts.map +1 -0
- package/dist/llm/openai.js +424 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/memory/shared.d.ts +86 -0
- package/dist/memory/shared.d.ts.map +1 -0
- package/dist/memory/shared.js +155 -0
- package/dist/memory/shared.js.map +1 -0
- package/dist/memory/store.d.ts +64 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +103 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +173 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +698 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/scheduler.d.ts +112 -0
- package/dist/orchestrator/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.js +282 -0
- package/dist/orchestrator/scheduler.js.map +1 -0
- package/dist/task/queue.d.ts +160 -0
- package/dist/task/queue.d.ts.map +1 -0
- package/dist/task/queue.js +337 -0
- package/dist/task/queue.js.map +1 -0
- package/dist/task/task.d.ts +86 -0
- package/dist/task/task.d.ts.map +1 -0
- package/dist/task/task.js +201 -0
- package/dist/task/task.js.map +1 -0
- package/dist/team/messaging.d.ts +106 -0
- package/dist/team/messaging.d.ts.map +1 -0
- package/dist/team/messaging.js +182 -0
- package/dist/team/messaging.js.map +1 -0
- package/dist/team/team.d.ts +141 -0
- package/dist/team/team.d.ts.map +1 -0
- package/dist/team/team.js +282 -0
- package/dist/team/team.js.map +1 -0
- package/dist/tool/built-in/bash.d.ts +12 -0
- package/dist/tool/built-in/bash.d.ts.map +1 -0
- package/dist/tool/built-in/bash.js +133 -0
- package/dist/tool/built-in/bash.js.map +1 -0
- package/dist/tool/built-in/file-edit.d.ts +14 -0
- package/dist/tool/built-in/file-edit.d.ts.map +1 -0
- package/dist/tool/built-in/file-edit.js +130 -0
- package/dist/tool/built-in/file-edit.js.map +1 -0
- package/dist/tool/built-in/file-read.d.ts +12 -0
- package/dist/tool/built-in/file-read.d.ts.map +1 -0
- package/dist/tool/built-in/file-read.js +82 -0
- package/dist/tool/built-in/file-read.js.map +1 -0
- package/dist/tool/built-in/file-write.d.ts +11 -0
- package/dist/tool/built-in/file-write.d.ts.map +1 -0
- package/dist/tool/built-in/file-write.js +70 -0
- package/dist/tool/built-in/file-write.js.map +1 -0
- package/dist/tool/built-in/grep.d.ts +15 -0
- package/dist/tool/built-in/grep.d.ts.map +1 -0
- package/dist/tool/built-in/grep.js +287 -0
- package/dist/tool/built-in/grep.js.map +1 -0
- package/dist/tool/built-in/index.d.ts +36 -0
- package/dist/tool/built-in/index.d.ts.map +1 -0
- package/dist/tool/built-in/index.js +45 -0
- package/dist/tool/built-in/index.js.map +1 -0
- package/dist/tool/executor.d.ts +71 -0
- package/dist/tool/executor.d.ts.map +1 -0
- package/dist/tool/executor.js +116 -0
- package/dist/tool/executor.js.map +1 -0
- package/dist/tool/framework.d.ts +143 -0
- package/dist/tool/framework.d.ts.map +1 -0
- package/dist/tool/framework.js +371 -0
- package/dist/tool/framework.js.map +1 -0
- package/dist/types.d.ts +285 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/semaphore.d.ts +47 -0
- package/dist/utils/semaphore.d.ts.map +1 -0
- package/dist/utils/semaphore.js +85 -0
- package/dist/utils/semaphore.js.map +1 -0
- package/examples/01-single-agent.ts +131 -0
- package/examples/02-team-collaboration.ts +167 -0
- package/examples/03-task-pipeline.ts +201 -0
- package/examples/04-multi-model-team.ts +261 -0
- package/package.json +49 -0
- package/src/agent/agent.ts +364 -0
- package/src/agent/pool.ts +278 -0
- package/src/agent/runner.ts +413 -0
- package/src/index.ts +166 -0
- package/src/llm/adapter.ts +74 -0
- package/src/llm/anthropic.ts +388 -0
- package/src/llm/openai.ts +522 -0
- package/src/memory/shared.ts +181 -0
- package/src/memory/store.ts +124 -0
- package/src/orchestrator/orchestrator.ts +851 -0
- package/src/orchestrator/scheduler.ts +352 -0
- package/src/task/queue.ts +394 -0
- package/src/task/task.ts +232 -0
- package/src/team/messaging.ts +230 -0
- package/src/team/team.ts +334 -0
- package/src/tool/built-in/bash.ts +187 -0
- package/src/tool/built-in/file-edit.ts +154 -0
- package/src/tool/built-in/file-read.ts +105 -0
- package/src/tool/built-in/file-write.ts +81 -0
- package/src/tool/built-in/grep.ts +362 -0
- package/src/tool/built-in/index.ts +50 -0
- package/src/tool/executor.ts +178 -0
- package/src/tool/framework.ts +557 -0
- package/src/types.ts +362 -0
- package/src/utils/semaphore.ts +89 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool definition framework for open-multi-agent.
|
|
3
|
+
*
|
|
4
|
+
* Provides the core primitives for declaring, registering, and converting
|
|
5
|
+
* tools to the JSON Schema format that LLM APIs expect.
|
|
6
|
+
*
|
|
7
|
+
* Types shared with the rest of the framework (`ToolDefinition`, `ToolResult`,
|
|
8
|
+
* `ToolUseContext`) are imported from `../types` to ensure a single source of
|
|
9
|
+
* truth. This file re-exports them for the convenience of downstream callers
|
|
10
|
+
* who only need to import from `tool/framework`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { type ZodSchema } from 'zod'
|
|
14
|
+
import type {
|
|
15
|
+
ToolDefinition,
|
|
16
|
+
ToolResult,
|
|
17
|
+
ToolUseContext,
|
|
18
|
+
LLMToolDef,
|
|
19
|
+
} from '../types.js'
|
|
20
|
+
|
|
21
|
+
// Re-export so consumers can `import { ToolDefinition } from './framework.js'`
|
|
22
|
+
export type { ToolDefinition, ToolResult, ToolUseContext }
|
|
23
|
+
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// LLM-facing JSON Schema types
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
/** Minimal JSON Schema for a single property. */
|
|
29
|
+
export type JSONSchemaProperty =
|
|
30
|
+
| { type: 'string'; description?: string; enum?: string[] }
|
|
31
|
+
| { type: 'number'; description?: string }
|
|
32
|
+
| { type: 'integer'; description?: string }
|
|
33
|
+
| { type: 'boolean'; description?: string }
|
|
34
|
+
| { type: 'null'; description?: string }
|
|
35
|
+
| { type: 'array'; items: JSONSchemaProperty; description?: string }
|
|
36
|
+
| {
|
|
37
|
+
type: 'object'
|
|
38
|
+
properties: Record<string, JSONSchemaProperty>
|
|
39
|
+
required?: string[]
|
|
40
|
+
description?: string
|
|
41
|
+
}
|
|
42
|
+
| { anyOf: JSONSchemaProperty[]; description?: string }
|
|
43
|
+
| { const: unknown; description?: string }
|
|
44
|
+
// Fallback for types we don't explicitly model
|
|
45
|
+
| Record<string, unknown>
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// defineTool
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Define a typed tool. This is the single entry-point for creating tools
|
|
53
|
+
* that can be registered with a {@link ToolRegistry}.
|
|
54
|
+
*
|
|
55
|
+
* The returned object satisfies the {@link ToolDefinition} interface imported
|
|
56
|
+
* from `../types`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* const echoTool = defineTool({
|
|
61
|
+
* name: 'echo',
|
|
62
|
+
* description: 'Echo the input message back to the caller.',
|
|
63
|
+
* inputSchema: z.object({ message: z.string() }),
|
|
64
|
+
* execute: async ({ message }) => ({
|
|
65
|
+
* data: message,
|
|
66
|
+
* isError: false,
|
|
67
|
+
* }),
|
|
68
|
+
* })
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function defineTool<TInput>(config: {
|
|
72
|
+
name: string
|
|
73
|
+
description: string
|
|
74
|
+
inputSchema: ZodSchema<TInput>
|
|
75
|
+
execute: (input: TInput, context: ToolUseContext) => Promise<ToolResult>
|
|
76
|
+
}): ToolDefinition<TInput> {
|
|
77
|
+
return {
|
|
78
|
+
name: config.name,
|
|
79
|
+
description: config.description,
|
|
80
|
+
inputSchema: config.inputSchema,
|
|
81
|
+
execute: config.execute,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// ToolRegistry
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Registry that holds a set of named tools and can produce the JSON Schema
|
|
91
|
+
* representation expected by LLM APIs (Anthropic, OpenAI, etc.).
|
|
92
|
+
*/
|
|
93
|
+
export class ToolRegistry {
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
95
|
+
private readonly tools = new Map<string, ToolDefinition<any>>()
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Add a tool to the registry. Throws if a tool with the same name has
|
|
99
|
+
* already been registered — prevents silent overwrites.
|
|
100
|
+
*/
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
register(tool: ToolDefinition<any>): void {
|
|
103
|
+
if (this.tools.has(tool.name)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`ToolRegistry: a tool named "${tool.name}" is already registered. ` +
|
|
106
|
+
'Use a unique name or deregister the existing one first.',
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
this.tools.set(tool.name, tool)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Return a tool by name, or `undefined` if not found. */
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
|
+
get(name: string): ToolDefinition<any> | undefined {
|
|
115
|
+
return this.tools.get(name)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Return all registered tool definitions as an array.
|
|
120
|
+
*
|
|
121
|
+
* Callers that only need names can do `registry.list().map(t => t.name)`.
|
|
122
|
+
* This matches the agent's `getTools()` pattern.
|
|
123
|
+
*/
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
125
|
+
list(): ToolDefinition<any>[] {
|
|
126
|
+
return Array.from(this.tools.values())
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Return all registered tool definitions as an array.
|
|
131
|
+
* Alias for {@link list} — available for callers that prefer explicit naming.
|
|
132
|
+
*/
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
+
getAll(): ToolDefinition<any>[] {
|
|
135
|
+
return Array.from(this.tools.values())
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Return true when a tool with the given name is registered. */
|
|
139
|
+
has(name: string): boolean {
|
|
140
|
+
return this.tools.has(name)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Remove a tool by name.
|
|
145
|
+
* No-op if the tool was not registered — matches the agent's expected
|
|
146
|
+
* behaviour where `removeTool` is a graceful operation.
|
|
147
|
+
*/
|
|
148
|
+
unregister(name: string): void {
|
|
149
|
+
this.tools.delete(name)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Alias for {@link unregister} — available for symmetry with `register`. */
|
|
153
|
+
deregister(name: string): void {
|
|
154
|
+
this.tools.delete(name)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Convert all registered tools to the {@link LLMToolDef} format used by LLM
|
|
159
|
+
* adapters. This is the primary method called by the agent runner before
|
|
160
|
+
* each LLM API call.
|
|
161
|
+
*/
|
|
162
|
+
toToolDefs(): LLMToolDef[] {
|
|
163
|
+
return Array.from(this.tools.values()).map((tool) => {
|
|
164
|
+
const schema = zodToJsonSchema(tool.inputSchema)
|
|
165
|
+
return {
|
|
166
|
+
name: tool.name,
|
|
167
|
+
description: tool.description,
|
|
168
|
+
inputSchema: schema,
|
|
169
|
+
} satisfies LLMToolDef
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Convert all registered tools to the Anthropic-style `input_schema`
|
|
175
|
+
* format. Prefer {@link toToolDefs} for normal use; this method is exposed
|
|
176
|
+
* for callers that construct their own API payloads.
|
|
177
|
+
*/
|
|
178
|
+
toLLMTools(): Array<{
|
|
179
|
+
name: string
|
|
180
|
+
description: string
|
|
181
|
+
input_schema: {
|
|
182
|
+
type: 'object'
|
|
183
|
+
properties: Record<string, JSONSchemaProperty>
|
|
184
|
+
required?: string[]
|
|
185
|
+
}
|
|
186
|
+
}> {
|
|
187
|
+
return Array.from(this.tools.values()).map((tool) => {
|
|
188
|
+
const schema = zodToJsonSchema(tool.inputSchema)
|
|
189
|
+
return {
|
|
190
|
+
name: tool.name,
|
|
191
|
+
description: tool.description,
|
|
192
|
+
input_schema: {
|
|
193
|
+
type: 'object' as const,
|
|
194
|
+
properties:
|
|
195
|
+
(schema.properties as Record<string, JSONSchemaProperty>) ?? {},
|
|
196
|
+
...(schema.required !== undefined
|
|
197
|
+
? { required: schema.required as string[] }
|
|
198
|
+
: {}),
|
|
199
|
+
},
|
|
200
|
+
}
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
// zodToJsonSchema
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Convert a Zod schema to a plain JSON Schema object suitable for inclusion
|
|
211
|
+
* in LLM API calls.
|
|
212
|
+
*
|
|
213
|
+
* Supported Zod types:
|
|
214
|
+
* z.string(), z.number(), z.boolean(), z.enum(), z.array(), z.object(),
|
|
215
|
+
* z.optional(), z.union(), z.literal(), z.describe(), z.nullable(),
|
|
216
|
+
* z.default(), z.intersection(), z.discriminatedUnion(), z.record(),
|
|
217
|
+
* z.tuple(), z.any(), z.unknown(), z.never(), z.effects() (transforms)
|
|
218
|
+
*
|
|
219
|
+
* Unsupported types fall back to `{}` (any) which is still valid JSON Schema.
|
|
220
|
+
*/
|
|
221
|
+
export function zodToJsonSchema(schema: ZodSchema): Record<string, unknown> {
|
|
222
|
+
return convertZodType(schema)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Internal recursive converter. We access Zod's internal `_def` structure
|
|
226
|
+
// because Zod v3 does not ship a first-class JSON Schema exporter.
|
|
227
|
+
function convertZodType(schema: ZodSchema): Record<string, unknown> {
|
|
228
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
229
|
+
const def = (schema as any)._def as ZodTypeDef
|
|
230
|
+
|
|
231
|
+
const description: string | undefined = def.description
|
|
232
|
+
|
|
233
|
+
const withDesc = (result: Record<string, unknown>): Record<string, unknown> =>
|
|
234
|
+
description !== undefined ? { ...result, description } : result
|
|
235
|
+
|
|
236
|
+
switch (def.typeName) {
|
|
237
|
+
// -----------------------------------------------------------------------
|
|
238
|
+
// Primitives
|
|
239
|
+
// -----------------------------------------------------------------------
|
|
240
|
+
case ZodTypeName.ZodString:
|
|
241
|
+
return withDesc({ type: 'string' })
|
|
242
|
+
|
|
243
|
+
case ZodTypeName.ZodNumber:
|
|
244
|
+
return withDesc({ type: 'number' })
|
|
245
|
+
|
|
246
|
+
case ZodTypeName.ZodBigInt:
|
|
247
|
+
return withDesc({ type: 'integer' })
|
|
248
|
+
|
|
249
|
+
case ZodTypeName.ZodBoolean:
|
|
250
|
+
return withDesc({ type: 'boolean' })
|
|
251
|
+
|
|
252
|
+
case ZodTypeName.ZodNull:
|
|
253
|
+
return withDesc({ type: 'null' })
|
|
254
|
+
|
|
255
|
+
case ZodTypeName.ZodUndefined:
|
|
256
|
+
return withDesc({ type: 'null' })
|
|
257
|
+
|
|
258
|
+
case ZodTypeName.ZodDate:
|
|
259
|
+
return withDesc({ type: 'string', format: 'date-time' })
|
|
260
|
+
|
|
261
|
+
// -----------------------------------------------------------------------
|
|
262
|
+
// Literals
|
|
263
|
+
// -----------------------------------------------------------------------
|
|
264
|
+
case ZodTypeName.ZodLiteral: {
|
|
265
|
+
const literalDef = def as ZodLiteralDef
|
|
266
|
+
return withDesc({ const: literalDef.value })
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// -----------------------------------------------------------------------
|
|
270
|
+
// Enums
|
|
271
|
+
// -----------------------------------------------------------------------
|
|
272
|
+
case ZodTypeName.ZodEnum: {
|
|
273
|
+
const enumDef = def as ZodEnumDef
|
|
274
|
+
return withDesc({ type: 'string', enum: enumDef.values })
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
case ZodTypeName.ZodNativeEnum: {
|
|
278
|
+
const nativeEnumDef = def as ZodNativeEnumDef
|
|
279
|
+
const values = Object.values(nativeEnumDef.values as object).filter(
|
|
280
|
+
(v) => typeof v === 'string' || typeof v === 'number',
|
|
281
|
+
)
|
|
282
|
+
return withDesc({ enum: values })
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// -----------------------------------------------------------------------
|
|
286
|
+
// Arrays
|
|
287
|
+
// -----------------------------------------------------------------------
|
|
288
|
+
case ZodTypeName.ZodArray: {
|
|
289
|
+
const arrayDef = def as ZodArrayDef
|
|
290
|
+
return withDesc({
|
|
291
|
+
type: 'array',
|
|
292
|
+
items: convertZodType(arrayDef.type),
|
|
293
|
+
})
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
case ZodTypeName.ZodTuple: {
|
|
297
|
+
const tupleDef = def as ZodTupleDef
|
|
298
|
+
return withDesc({
|
|
299
|
+
type: 'array',
|
|
300
|
+
prefixItems: tupleDef.items.map(convertZodType),
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// -----------------------------------------------------------------------
|
|
305
|
+
// Objects
|
|
306
|
+
// -----------------------------------------------------------------------
|
|
307
|
+
case ZodTypeName.ZodObject: {
|
|
308
|
+
const objectDef = def as ZodObjectDef
|
|
309
|
+
const properties: Record<string, unknown> = {}
|
|
310
|
+
const required: string[] = []
|
|
311
|
+
|
|
312
|
+
for (const [key, value] of Object.entries(objectDef.shape())) {
|
|
313
|
+
properties[key] = convertZodType(value as ZodSchema)
|
|
314
|
+
|
|
315
|
+
const innerDef = ((value as ZodSchema) as unknown as { _def: ZodTypeDef })._def
|
|
316
|
+
const isOptional =
|
|
317
|
+
innerDef.typeName === ZodTypeName.ZodOptional ||
|
|
318
|
+
innerDef.typeName === ZodTypeName.ZodDefault ||
|
|
319
|
+
innerDef.typeName === ZodTypeName.ZodNullable
|
|
320
|
+
if (!isOptional) {
|
|
321
|
+
required.push(key)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const result: Record<string, unknown> = { type: 'object', properties }
|
|
326
|
+
if (required.length > 0) result.required = required
|
|
327
|
+
return withDesc(result)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
case ZodTypeName.ZodRecord: {
|
|
331
|
+
const recordDef = def as ZodRecordDef
|
|
332
|
+
return withDesc({
|
|
333
|
+
type: 'object',
|
|
334
|
+
additionalProperties: convertZodType(recordDef.valueType),
|
|
335
|
+
})
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// -----------------------------------------------------------------------
|
|
339
|
+
// Optional / Nullable / Default
|
|
340
|
+
// -----------------------------------------------------------------------
|
|
341
|
+
case ZodTypeName.ZodOptional: {
|
|
342
|
+
const optionalDef = def as ZodOptionalDef
|
|
343
|
+
const inner = convertZodType(optionalDef.innerType)
|
|
344
|
+
return description !== undefined ? { ...inner, description } : inner
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
case ZodTypeName.ZodNullable: {
|
|
348
|
+
const nullableDef = def as ZodNullableDef
|
|
349
|
+
const inner = convertZodType(nullableDef.innerType)
|
|
350
|
+
const type = inner.type
|
|
351
|
+
if (typeof type === 'string') {
|
|
352
|
+
return withDesc({ ...inner, type: [type, 'null'] })
|
|
353
|
+
}
|
|
354
|
+
return withDesc({ anyOf: [inner, { type: 'null' }] })
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
case ZodTypeName.ZodDefault: {
|
|
358
|
+
const defaultDef = def as ZodDefaultDef
|
|
359
|
+
const inner = convertZodType(defaultDef.innerType)
|
|
360
|
+
return withDesc({ ...inner, default: defaultDef.defaultValue() })
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// -----------------------------------------------------------------------
|
|
364
|
+
// Union / Intersection / Discriminated Union
|
|
365
|
+
// -----------------------------------------------------------------------
|
|
366
|
+
case ZodTypeName.ZodUnion: {
|
|
367
|
+
const unionDef = def as ZodUnionDef
|
|
368
|
+
const options = (unionDef.options as ZodSchema[]).map(convertZodType)
|
|
369
|
+
return withDesc({ anyOf: options })
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
case ZodTypeName.ZodDiscriminatedUnion: {
|
|
373
|
+
const duDef = def as ZodDiscriminatedUnionDef
|
|
374
|
+
const options = (duDef.options as ZodSchema[]).map(convertZodType)
|
|
375
|
+
return withDesc({ anyOf: options })
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
case ZodTypeName.ZodIntersection: {
|
|
379
|
+
const intDef = def as ZodIntersectionDef
|
|
380
|
+
return withDesc({
|
|
381
|
+
allOf: [convertZodType(intDef.left), convertZodType(intDef.right)],
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// -----------------------------------------------------------------------
|
|
386
|
+
// Wrappers that forward to their inner type
|
|
387
|
+
// -----------------------------------------------------------------------
|
|
388
|
+
case ZodTypeName.ZodEffects: {
|
|
389
|
+
const effectsDef = def as ZodEffectsDef
|
|
390
|
+
const inner = convertZodType(effectsDef.schema)
|
|
391
|
+
return description !== undefined ? { ...inner, description } : inner
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
case ZodTypeName.ZodBranded: {
|
|
395
|
+
const brandedDef = def as ZodBrandedDef
|
|
396
|
+
return withDesc(convertZodType(brandedDef.type))
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
case ZodTypeName.ZodReadonly: {
|
|
400
|
+
const readonlyDef = def as ZodReadonlyDef
|
|
401
|
+
return withDesc(convertZodType(readonlyDef.innerType))
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
case ZodTypeName.ZodCatch: {
|
|
405
|
+
const catchDef = def as ZodCatchDef
|
|
406
|
+
return withDesc(convertZodType(catchDef.innerType))
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
case ZodTypeName.ZodPipeline: {
|
|
410
|
+
const pipelineDef = def as ZodPipelineDef
|
|
411
|
+
return withDesc(convertZodType(pipelineDef.in))
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// -----------------------------------------------------------------------
|
|
415
|
+
// Any / Unknown – JSON Schema wildcard
|
|
416
|
+
// -----------------------------------------------------------------------
|
|
417
|
+
case ZodTypeName.ZodAny:
|
|
418
|
+
case ZodTypeName.ZodUnknown:
|
|
419
|
+
return withDesc({})
|
|
420
|
+
|
|
421
|
+
case ZodTypeName.ZodNever:
|
|
422
|
+
return withDesc({ not: {} })
|
|
423
|
+
|
|
424
|
+
case ZodTypeName.ZodVoid:
|
|
425
|
+
return withDesc({ type: 'null' })
|
|
426
|
+
|
|
427
|
+
// -----------------------------------------------------------------------
|
|
428
|
+
// Fallback
|
|
429
|
+
// -----------------------------------------------------------------------
|
|
430
|
+
default:
|
|
431
|
+
return withDesc({})
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// ---------------------------------------------------------------------------
|
|
436
|
+
// Internal Zod type-name enum (mirrors Zod's internal ZodFirstPartyTypeKind)
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
|
|
439
|
+
const enum ZodTypeName {
|
|
440
|
+
ZodString = 'ZodString',
|
|
441
|
+
ZodNumber = 'ZodNumber',
|
|
442
|
+
ZodBigInt = 'ZodBigInt',
|
|
443
|
+
ZodBoolean = 'ZodBoolean',
|
|
444
|
+
ZodDate = 'ZodDate',
|
|
445
|
+
ZodUndefined = 'ZodUndefined',
|
|
446
|
+
ZodNull = 'ZodNull',
|
|
447
|
+
ZodAny = 'ZodAny',
|
|
448
|
+
ZodUnknown = 'ZodUnknown',
|
|
449
|
+
ZodNever = 'ZodNever',
|
|
450
|
+
ZodVoid = 'ZodVoid',
|
|
451
|
+
ZodArray = 'ZodArray',
|
|
452
|
+
ZodObject = 'ZodObject',
|
|
453
|
+
ZodUnion = 'ZodUnion',
|
|
454
|
+
ZodDiscriminatedUnion = 'ZodDiscriminatedUnion',
|
|
455
|
+
ZodIntersection = 'ZodIntersection',
|
|
456
|
+
ZodTuple = 'ZodTuple',
|
|
457
|
+
ZodRecord = 'ZodRecord',
|
|
458
|
+
ZodMap = 'ZodMap',
|
|
459
|
+
ZodSet = 'ZodSet',
|
|
460
|
+
ZodFunction = 'ZodFunction',
|
|
461
|
+
ZodLazy = 'ZodLazy',
|
|
462
|
+
ZodLiteral = 'ZodLiteral',
|
|
463
|
+
ZodEnum = 'ZodEnum',
|
|
464
|
+
ZodEffects = 'ZodEffects',
|
|
465
|
+
ZodNativeEnum = 'ZodNativeEnum',
|
|
466
|
+
ZodOptional = 'ZodOptional',
|
|
467
|
+
ZodNullable = 'ZodNullable',
|
|
468
|
+
ZodDefault = 'ZodDefault',
|
|
469
|
+
ZodCatch = 'ZodCatch',
|
|
470
|
+
ZodPromise = 'ZodPromise',
|
|
471
|
+
ZodBranded = 'ZodBranded',
|
|
472
|
+
ZodPipeline = 'ZodPipeline',
|
|
473
|
+
ZodReadonly = 'ZodReadonly',
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// ---------------------------------------------------------------------------
|
|
477
|
+
// Internal Zod _def structure typings (narrow only what we access)
|
|
478
|
+
// ---------------------------------------------------------------------------
|
|
479
|
+
|
|
480
|
+
interface ZodTypeDef {
|
|
481
|
+
typeName: string
|
|
482
|
+
description?: string
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
interface ZodLiteralDef extends ZodTypeDef {
|
|
486
|
+
value: unknown
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
interface ZodEnumDef extends ZodTypeDef {
|
|
490
|
+
values: string[]
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
interface ZodNativeEnumDef extends ZodTypeDef {
|
|
494
|
+
values: object
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
interface ZodArrayDef extends ZodTypeDef {
|
|
498
|
+
type: ZodSchema
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
interface ZodTupleDef extends ZodTypeDef {
|
|
502
|
+
items: ZodSchema[]
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
interface ZodObjectDef extends ZodTypeDef {
|
|
506
|
+
shape: () => Record<string, ZodSchema>
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
interface ZodRecordDef extends ZodTypeDef {
|
|
510
|
+
valueType: ZodSchema
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
interface ZodUnionDef extends ZodTypeDef {
|
|
514
|
+
options: unknown
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
interface ZodDiscriminatedUnionDef extends ZodTypeDef {
|
|
518
|
+
options: unknown
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
interface ZodIntersectionDef extends ZodTypeDef {
|
|
522
|
+
left: ZodSchema
|
|
523
|
+
right: ZodSchema
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
interface ZodOptionalDef extends ZodTypeDef {
|
|
527
|
+
innerType: ZodSchema
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
interface ZodNullableDef extends ZodTypeDef {
|
|
531
|
+
innerType: ZodSchema
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
interface ZodDefaultDef extends ZodTypeDef {
|
|
535
|
+
innerType: ZodSchema
|
|
536
|
+
defaultValue: () => unknown
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
interface ZodEffectsDef extends ZodTypeDef {
|
|
540
|
+
schema: ZodSchema
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
interface ZodBrandedDef extends ZodTypeDef {
|
|
544
|
+
type: ZodSchema
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
interface ZodReadonlyDef extends ZodTypeDef {
|
|
548
|
+
innerType: ZodSchema
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
interface ZodCatchDef extends ZodTypeDef {
|
|
552
|
+
innerType: ZodSchema
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
interface ZodPipelineDef extends ZodTypeDef {
|
|
556
|
+
in: ZodSchema
|
|
557
|
+
}
|