diff --git a/scripts/generate.js b/scripts/generate.js index fab39c3..e3f3b93 100644 --- a/scripts/generate.js +++ b/scripts/generate.js @@ -36,7 +36,10 @@ async function main() { postProcess: ["prettier"], }, plugins: [ - "zod", + { + name: "zod", + "~resolvers": createDeserializationResolvers(), + }, { bigInt: false, name: "@hey-api/transformers" }, "@hey-api/typescript", ], @@ -177,6 +180,211 @@ function updateDocs(src, schemaDefs) { return result; } +function createDeserializationResolvers() { + return { + array(ctx) { + const base = ctx.schema["x-deserialize-skip-invalid-items"] + ? vecSkipErrorExpression(ctx) + : ctx.nodes.base(ctx); + + ctx.chain.current = base; + const lengthResult = ctx.nodes.length(ctx); + if (lengthResult) { + ctx.chain.current = lengthResult; + } else { + const minLengthResult = ctx.nodes.minLength(ctx); + if (minLengthResult) ctx.chain.current = minLengthResult; + const maxLengthResult = ctx.nodes.maxLength(ctx); + if (maxLengthResult) ctx.chain.current = maxLengthResult; + } + + return ctx.chain.current; + }, + + object(ctx) { + if (!hasDefaultOnErrorProperties(ctx.schema)) return undefined; + + const shape = ctx.$.object().pretty(); + for (const name in ctx.schema.properties) { + const property = ctx.schema.properties[name]; + const isRequired = ctx.schema.required?.includes(name) === true; + const propertyResult = ctx.walk( + property, + childContext( + { path: ctx.path, plugin: ctx.plugin }, + "properties", + name, + ), + ); + ctx._childResults.push(propertyResult); + + const finalExpression = propertyExpression( + ctx, + name, + property, + propertyResult, + isRequired, + ); + + shape.prop( + name, + property["x-deserialize-default-on-error"] + ? defaultOnErrorExpression( + ctx, + finalExpression, + property, + isRequired, + ) + : finalExpression, + ); + } + + const defaultShape = ctx.nodes.shape; + ctx.nodes.shape = () => shape; + const base = ctx.nodes.base(ctx); + ctx.nodes.shape = defaultShape; + return base; + }, + }; +} + +function childContext(ctx, ...segments) { + return { + path: ref([...fromRef(ctx.path), ...segments]), + plugin: ctx.plugin, + }; +} + +function ref(path) { + return { "~ref": path }; +} + +function fromRef(ref) { + return ref?.["~ref"]; +} + +function jsonPointerPath(ref) { + return `#/${fromRef(ref).map(jsonPointerSegment).join("/")}`; +} + +function jsonPointerSegment(segment) { + return String(segment).replaceAll("~", "~0").replaceAll("/", "~1"); +} + +function hasDefaultOnErrorProperties(schema) { + return Object.values(schema.properties ?? {}).some( + (property) => property["x-deserialize-default-on-error"], + ); +} + +function propertyExpression(ctx, name, property, propertyResult, isRequired) { + if (!property["x-deserialize-skip-invalid-items"]) { + return ctx.applyModifiers(propertyResult, { optional: !isRequired }).chain; + } + + const itemSchema = getArrayItemSchema(property); + if (!itemSchema) { + throw new Error( + `Unable to apply x-deserialize-skip-invalid-items to ${jsonPointerPath(childContext(ctx, "properties", name).path)}`, + ); + } + + const itemResult = ctx.walk( + itemSchema, + childContext( + { path: ctx.path, plugin: ctx.plugin }, + "properties", + name, + "items", + 0, + ), + ); + + return ctx.applyModifiers( + { + chain: ctx + .$(schemaDeserializeSymbol(ctx.plugin, "vecSkipError")) + .call(ctx.applyModifiers(itemResult, { optional: false }).chain), + meta: propertyResult.meta, + }, + { optional: !isRequired }, + ).chain; +} + +function getArrayItemSchema(schema) { + if (schema.type === "array" && schema.items) { + return Array.isArray(schema.items) ? schema.items[0] : schema.items; + } + + const items = Array.isArray(schema.items) ? schema.items : []; + for (const item of items) { + const itemSchema = getArrayItemSchema(item); + if (itemSchema) return itemSchema; + } + + return undefined; +} + +function vecSkipErrorExpression(ctx) { + const vecSkipError = schemaDeserializeSymbol(ctx.plugin, "vecSkipError"); + + if (ctx.childResults.length !== 1) { + throw new Error( + `Unable to apply x-deserialize-skip-invalid-items to ${jsonPointerPath(ctx.path)}`, + ); + } + + return ctx + .$(vecSkipError) + .call(ctx.applyModifiers(ctx.childResults[0], { optional: false }).chain); +} + +function defaultOnErrorExpression(ctx, schemaExpression, schema, isRequired) { + const helper = schemaDeserializeSymbol( + ctx.plugin, + isRequired ? "requiredDefaultOnError" : "defaultOnError", + ); + + return ctx + .$(helper) + .call( + schemaExpression, + fallbackFunctionExpression(ctx, schema, isRequired), + ); +} + +function schemaDeserializeSymbol(plugin, name) { + return plugin.symbolOnce(name, { + external: "../schema-deserialize.js", + }); +} + +function fallbackFunctionExpression(ctx, schema, isRequired) { + return ctx.$.func().do( + ctx.$.return(fallbackValueExpression(ctx, schema, isRequired)), + ); +} + +function fallbackValueExpression(ctx, schema, isRequired) { + if (Object.hasOwn(schema, "default")) { + return ctx.$.fromValue(schema.default); + } + + if (isArraySchema(schema) && (isRequired || !isNullableSchema(schema))) { + return ctx.$.array(); + } + + return ctx.$.id("undefined"); +} + +function isArraySchema(schema) { + return schema.type === "array"; +} + +function isNullableSchema(schema) { + return schema.nullable === true; +} + function injectDocIfMissing(src, exportStr, description) { const idx = src.indexOf(exportStr); if (idx === -1) return src; diff --git a/src/acp.test.ts b/src/acp.test.ts index cc0632a..95aa043 100644 --- a/src/acp.test.ts +++ b/src/acp.test.ts @@ -1,7 +1,12 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import { + zAnnotations, + zClientCapabilities, zCreateElicitationRequest, zCreateElicitationResponse, + zInitializeResponse, + zPlan, + zToolCall, } from "./schema/zod.gen.js"; import { Agent, @@ -2852,3 +2857,83 @@ describe("CreateElicitationResponse schema", () => { expect(result.success).toBe(false); }); }); + +describe("Schema deserialization compatibility", () => { + it("defaults invalid optional values to undefined", () => { + const response = zInitializeResponse.parse({ + protocolVersion: 1, + agentInfo: "invalid", + }); + + expect(response.agentInfo).toBeUndefined(); + }); + + it("keeps explicit schema defaults and skips invalid array items", () => { + const response = zInitializeResponse.parse({ + protocolVersion: 1, + authMethods: [ + { id: "agent-auth", name: "Agent auth" }, + { type: "terminal", id: "missing-name" }, + ], + }); + + expect(response.authMethods).toEqual([ + { id: "agent-auth", name: "Agent auth" }, + ]); + expect( + zInitializeResponse.parse({ + protocolVersion: 1, + authMethods: "invalid", + }).authMethods, + ).toEqual([]); + }); + + it("keeps required default-on-error arrays required when missing", () => { + expect(zPlan.safeParse({}).success).toBe(false); + + expect(zPlan.parse({ entries: "invalid" }).entries).toEqual([]); + expect( + zPlan.parse({ + entries: [ + { content: "done", priority: "high", status: "completed" }, + { content: "missing status", priority: "low" }, + ], + }).entries, + ).toEqual([{ content: "done", priority: "high", status: "completed" }]); + }); + + it("defaults optional non-null arrays to [] only for invalid present values", () => { + expect(zClientCapabilities.parse({}).positionEncodings).toBeUndefined(); + expect( + zClientCapabilities.parse({ positionEncodings: "invalid" }) + .positionEncodings, + ).toEqual([]); + }); + + it("defaults optional nullable arrays to undefined for invalid present values", () => { + expect( + zAnnotations.parse({ audience: "invalid" }).audience, + ).toBeUndefined(); + expect( + zAnnotations.parse({ audience: ["user", "invalid", "assistant"] }) + .audience, + ).toEqual(["user", "assistant"]); + }); + + it("skips invalid nested tool call content and locations", () => { + const toolCall = zToolCall.parse({ + content: [ + { type: "content", content: { type: "text", text: "hello" } }, + { type: "terminal" }, + ], + locations: [{ path: "/tmp/file.ts", line: 1 }, { path: 1 }], + title: "Read file", + toolCallId: "tool-call-1", + }); + + expect(toolCall.content).toEqual([ + { type: "content", content: { type: "text", text: "hello" } }, + ]); + expect(toolCall.locations).toEqual([{ path: "/tmp/file.ts", line: 1 }]); + }); +}); diff --git a/src/schema-deserialize.ts b/src/schema-deserialize.ts new file mode 100644 index 0000000..3c2909d --- /dev/null +++ b/src/schema-deserialize.ts @@ -0,0 +1,38 @@ +import { z } from "zod/v4"; + +type Fallback = () => Output; +const skippedItem = Symbol("skippedItem"); + +export function defaultOnError( + schema: Schema, + fallback: Fallback>, +) { + return schema.catch(fallback as () => never); +} + +export function requiredDefaultOnError( + schema: Schema, + fallback: Fallback>, +) { + const schemaWithCatch = schema.catch(fallback as () => never); + + return z.unknown().transform((value, context): z.output => { + if (value !== undefined) return schemaWithCatch.parse(value); + context.addIssue({ + code: "custom", + message: "Required value is missing", + }); + return z.NEVER; + }); +} + +export function vecSkipError( + itemSchema: ItemSchema, +) { + return z + .array(itemSchema.catch(skippedItem as never)) + .transform( + (items): Array> => + items.filter((item) => item !== skippedItem), + ); +} diff --git a/src/schema/zod.gen.ts b/src/schema/zod.gen.ts index f79454d..9f26a42 100644 --- a/src/schema/zod.gen.ts +++ b/src/schema/zod.gen.ts @@ -1,5 +1,10 @@ // This file is auto-generated by @hey-api/openapi-ts +import { + defaultOnError, + requiredDefaultOnError, + vecSkipError, +} from "../schema-deserialize.js"; import { z } from "zod/v4"; /** @@ -369,8 +374,8 @@ export const zElicitationUrlCapabilities = z.object({ */ export const zElicitationCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - form: zElicitationFormCapabilities.nullish(), - url: zElicitationUrlCapabilities.nullish(), + form: defaultOnError(zElicitationFormCapabilities.nullish(), () => undefined), + url: defaultOnError(zElicitationUrlCapabilities.nullish(), () => undefined), }); /** @@ -569,7 +574,7 @@ export const zLogoutCapabilities = z.object({ */ export const zAgentAuthCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - logout: zLogoutCapabilities.nullish(), + logout: defaultOnError(zLogoutCapabilities.nullish(), () => undefined), }); /** @@ -962,9 +967,12 @@ export const zNesSearchAndReplaceCapabilities = z.object({ */ export const zClientNesCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - jump: zNesJumpCapabilities.nullish(), - rename: zNesRenameCapabilities.nullish(), - searchAndReplace: zNesSearchAndReplaceCapabilities.nullish(), + jump: defaultOnError(zNesJumpCapabilities.nullish(), () => undefined), + rename: defaultOnError(zNesRenameCapabilities.nullish(), () => undefined), + searchAndReplace: defaultOnError( + zNesSearchAndReplaceCapabilities.nullish(), + () => undefined, + ), }); /** @@ -1007,12 +1015,30 @@ export const zNesUserActionsCapabilities = z.object({ */ export const zNesContextCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - diagnostics: zNesDiagnosticsCapabilities.nullish(), - editHistory: zNesEditHistoryCapabilities.nullish(), - openFiles: zNesOpenFilesCapabilities.nullish(), - recentFiles: zNesRecentFilesCapabilities.nullish(), - relatedSnippets: zNesRelatedSnippetsCapabilities.nullish(), - userActions: zNesUserActionsCapabilities.nullish(), + diagnostics: defaultOnError( + zNesDiagnosticsCapabilities.nullish(), + () => undefined, + ), + editHistory: defaultOnError( + zNesEditHistoryCapabilities.nullish(), + () => undefined, + ), + openFiles: defaultOnError( + zNesOpenFilesCapabilities.nullish(), + () => undefined, + ), + recentFiles: defaultOnError( + zNesRecentFilesCapabilities.nullish(), + () => undefined, + ), + relatedSnippets: defaultOnError( + zNesRelatedSnippetsCapabilities.nullish(), + () => undefined, + ), + userActions: defaultOnError( + zNesUserActionsCapabilities.nullish(), + () => undefined, + ), }); /** @@ -1128,7 +1154,7 @@ export const zPlanEntry = z.object({ */ export const zPlan = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - entries: z.array(zPlanEntry), + entries: requiredDefaultOnError(vecSkipError(zPlanEntry), () => []), }); /** @@ -1168,7 +1194,7 @@ export const zPlanFile = z.object({ */ export const zPlanItems = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - entries: z.array(zPlanEntry), + entries: requiredDefaultOnError(vecSkipError(zPlanEntry), () => []), id: zPlanId, }); @@ -1307,13 +1333,22 @@ export const zPositionEncodingKind = z.union([ export const zClientCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), auth: zAuthCapabilities.optional().default({ terminal: false }), - elicitation: zElicitationCapabilities.nullish(), + elicitation: defaultOnError( + zElicitationCapabilities.nullish(), + () => undefined, + ), fs: zFileSystemCapabilities .optional() .default({ readTextFile: false, writeTextFile: false }), - nes: zClientNesCapabilities.nullish(), - planCapabilities: zPlanCapabilities.nullish(), - positionEncodings: z.array(zPositionEncodingKind).optional(), + nes: defaultOnError(zClientNesCapabilities.nullish(), () => undefined), + planCapabilities: defaultOnError( + zPlanCapabilities.nullish(), + () => undefined, + ), + positionEncodings: defaultOnError( + vecSkipError(zPositionEncodingKind).optional(), + () => [], + ), terminal: z.boolean().optional().default(false), }); @@ -1360,7 +1395,7 @@ export const zInitializeRequest = z.object({ fs: { readTextFile: false, writeTextFile: false }, terminal: false, }), - clientInfo: zImplementation.nullish(), + clientInfo: defaultOnError(zImplementation.nullish(), () => undefined), protocolVersion: zProtocolVersion, }); @@ -1392,7 +1427,7 @@ export const zProviderInfo = z.object({ current: zProviderCurrentConfig.nullish(), id: z.string(), required: z.boolean(), - supported: z.array(zLlmProtocol), + supported: requiredDefaultOnError(vecSkipError(zLlmProtocol), () => []), }); /** @@ -1406,7 +1441,7 @@ export const zProviderInfo = z.object({ */ export const zListProvidersResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - providers: z.array(zProviderInfo), + providers: requiredDefaultOnError(vecSkipError(zProviderInfo), () => []), }); /** @@ -1447,9 +1482,9 @@ export const zNesDiagnostic = z.object({ */ export const zNesOpenFile = z.object({ languageId: z.string(), - lastFocusedMs: z.number().nullish(), + lastFocusedMs: defaultOnError(z.number().nullish(), () => undefined), uri: z.string(), - visibleRange: zRange.nullish(), + visibleRange: defaultOnError(zRange.nullish(), () => undefined), }); /** @@ -1457,12 +1492,30 @@ export const zNesOpenFile = z.object({ */ export const zNesSuggestContext = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - diagnostics: z.array(zNesDiagnostic).nullish(), - editHistory: z.array(zNesEditHistoryEntry).nullish(), - openFiles: z.array(zNesOpenFile).nullish(), - recentFiles: z.array(zNesRecentFile).nullish(), - relatedSnippets: z.array(zNesRelatedSnippet).nullish(), - userActions: z.array(zNesUserAction).nullish(), + diagnostics: defaultOnError( + vecSkipError(zNesDiagnostic).nullish(), + () => undefined, + ), + editHistory: defaultOnError( + vecSkipError(zNesEditHistoryEntry).nullish(), + () => undefined, + ), + openFiles: defaultOnError( + vecSkipError(zNesOpenFile).nullish(), + () => undefined, + ), + recentFiles: defaultOnError( + vecSkipError(zNesRecentFile).nullish(), + () => undefined, + ), + relatedSnippets: defaultOnError( + vecSkipError(zNesRelatedSnippet).nullish(), + () => undefined, + ), + userActions: defaultOnError( + vecSkipError(zNesUserAction).nullish(), + () => undefined, + ), }); /** @@ -1477,7 +1530,7 @@ export const zNesTextEdit = z.object({ * A text edit suggestion. */ export const zNesEditSuggestion = z.object({ - cursorPosition: zPosition.nullish(), + cursorPosition: defaultOnError(zPosition.nullish(), () => undefined), edits: z.array(zNesTextEdit), id: z.string(), uri: z.string(), @@ -1577,7 +1630,7 @@ export const zRole = z.enum(["assistant", "user"]); */ export const zAnnotations = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - audience: z.array(zRole).nullish(), + audience: defaultOnError(vecSkipError(zRole).nullish(), () => undefined), lastModified: z.string().nullish(), priority: z.number().nullish(), }); @@ -1587,7 +1640,7 @@ export const zAnnotations = z.object({ */ export const zAudioContent = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - annotations: zAnnotations.nullish(), + annotations: defaultOnError(zAnnotations.nullish(), () => undefined), data: z.string(), mimeType: z.string(), }); @@ -1597,7 +1650,7 @@ export const zAudioContent = z.object({ */ export const zImageContent = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - annotations: zAnnotations.nullish(), + annotations: defaultOnError(zAnnotations.nullish(), () => undefined), data: z.string(), mimeType: z.string(), uri: z.string().nullish(), @@ -1608,7 +1661,7 @@ export const zImageContent = z.object({ */ export const zResourceLink = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - annotations: zAnnotations.nullish(), + annotations: defaultOnError(zAnnotations.nullish(), () => undefined), description: z.string().nullish(), mimeType: z.string().nullish(), name: z.string(), @@ -1768,7 +1821,10 @@ export const zSessionConfigOption = z.intersection( ]), z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - category: zSessionConfigOptionCategory.nullish(), + category: defaultOnError( + zSessionConfigOptionCategory.nullish(), + () => undefined, + ), description: z.string().nullish(), id: zSessionConfigId, name: z.string(), @@ -1780,7 +1836,10 @@ export const zSessionConfigOption = z.intersection( */ export const zConfigOptionUpdate = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption), + configOptions: requiredDefaultOnError( + vecSkipError(zSessionConfigOption), + () => [], + ), }); /** @@ -2017,7 +2076,7 @@ export const zReadTextFileRequest = z.object({ export const zRejectNesNotification = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), id: z.string(), - reason: zNesRejectReason.nullish(), + reason: defaultOnError(zNesRejectReason.nullish(), () => undefined), sessionId: zSessionId, }); @@ -2054,8 +2113,8 @@ export const zSessionInfo = z.object({ additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), sessionId: zSessionId, - title: z.string().nullish(), - updatedAt: z.string().nullish(), + title: defaultOnError(z.string().nullish(), () => undefined), + updatedAt: defaultOnError(z.string().nullish(), () => undefined), }); /** @@ -2064,7 +2123,7 @@ export const zSessionInfo = z.object({ export const zListSessionsResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), nextCursor: z.string().nullish(), - sessions: z.array(zSessionInfo), + sessions: requiredDefaultOnError(vecSkipError(zSessionInfo), () => []), }); /** @@ -2120,7 +2179,7 @@ export const zSessionMode = z.object({ */ export const zSessionModeState = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - availableModes: z.array(zSessionMode), + availableModes: requiredDefaultOnError(vecSkipError(zSessionMode), () => []), currentModeId: zSessionModeId, }); @@ -2135,8 +2194,11 @@ export const zSessionModeState = z.object({ */ export const zForkSessionResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption).nullish(), - modes: zSessionModeState.nullish(), + configOptions: defaultOnError( + vecSkipError(zSessionConfigOption).nullish(), + () => undefined, + ), + modes: defaultOnError(zSessionModeState.nullish(), () => undefined), sessionId: zSessionId, }); @@ -2145,8 +2207,11 @@ export const zForkSessionResponse = z.object({ */ export const zLoadSessionResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption).nullish(), - modes: zSessionModeState.nullish(), + configOptions: defaultOnError( + vecSkipError(zSessionConfigOption).nullish(), + () => undefined, + ), + modes: defaultOnError(zSessionModeState.nullish(), () => undefined), }); /** @@ -2156,8 +2221,11 @@ export const zLoadSessionResponse = z.object({ */ export const zNewSessionResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption).nullish(), - modes: zSessionModeState.nullish(), + configOptions: defaultOnError( + vecSkipError(zSessionConfigOption).nullish(), + () => undefined, + ), + modes: defaultOnError(zSessionModeState.nullish(), () => undefined), sessionId: zSessionId, }); @@ -2166,8 +2234,11 @@ export const zNewSessionResponse = z.object({ */ export const zResumeSessionResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption).nullish(), - modes: zSessionModeState.nullish(), + configOptions: defaultOnError( + vecSkipError(zSessionConfigOption).nullish(), + () => undefined, + ), + modes: defaultOnError(zSessionModeState.nullish(), () => undefined), }); /** @@ -2192,12 +2263,15 @@ export const zSessionResumeCapabilities = z.object({ */ export const zSessionCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - additionalDirectories: zSessionAdditionalDirectoriesCapabilities.nullish(), - close: zSessionCloseCapabilities.nullish(), - delete: zSessionDeleteCapabilities.nullish(), - fork: zSessionForkCapabilities.nullish(), - list: zSessionListCapabilities.nullish(), - resume: zSessionResumeCapabilities.nullish(), + additionalDirectories: defaultOnError( + zSessionAdditionalDirectoriesCapabilities.nullish(), + () => undefined, + ), + close: defaultOnError(zSessionCloseCapabilities.nullish(), () => undefined), + delete: defaultOnError(zSessionDeleteCapabilities.nullish(), () => undefined), + fork: defaultOnError(zSessionForkCapabilities.nullish(), () => undefined), + list: defaultOnError(zSessionListCapabilities.nullish(), () => undefined), + resume: defaultOnError(zSessionResumeCapabilities.nullish(), () => undefined), }); /** @@ -2257,7 +2331,10 @@ export const zSetSessionConfigOptionRequest = z.intersection( */ export const zSetSessionConfigOptionResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - configOptions: z.array(zSessionConfigOption), + configOptions: requiredDefaultOnError( + vecSkipError(zSessionConfigOption), + () => [], + ), }); /** @@ -2344,9 +2421,9 @@ export const zStringPropertySchema = z.object({ */ export const zSuggestNesRequest = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - context: zNesSuggestContext.nullish(), + context: defaultOnError(zNesSuggestContext.nullish(), () => undefined), position: zPosition, - selection: zRange.nullish(), + selection: defaultOnError(zRange.nullish(), () => undefined), sessionId: zSessionId, triggerKind: zNesTriggerKind, uri: z.string(), @@ -2358,7 +2435,7 @@ export const zSuggestNesRequest = z.object({ */ export const zSuggestNesResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - suggestions: z.array(zNesSuggestion), + suggestions: requiredDefaultOnError(vecSkipError(zNesSuggestion), () => []), }); /** @@ -2413,7 +2490,7 @@ export const zTerminalOutputResponse = z.object({ */ export const zTextContent = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - annotations: zAnnotations.nullish(), + annotations: defaultOnError(zAnnotations.nullish(), () => undefined), text: z.string(), }); @@ -2478,11 +2555,26 @@ export const zNesDocumentDidChangeCapabilities = z.object({ */ export const zNesDocumentEventCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - didChange: zNesDocumentDidChangeCapabilities.nullish(), - didClose: zNesDocumentDidCloseCapabilities.nullish(), - didFocus: zNesDocumentDidFocusCapabilities.nullish(), - didOpen: zNesDocumentDidOpenCapabilities.nullish(), - didSave: zNesDocumentDidSaveCapabilities.nullish(), + didChange: defaultOnError( + zNesDocumentDidChangeCapabilities.nullish(), + () => undefined, + ), + didClose: defaultOnError( + zNesDocumentDidCloseCapabilities.nullish(), + () => undefined, + ), + didFocus: defaultOnError( + zNesDocumentDidFocusCapabilities.nullish(), + () => undefined, + ), + didOpen: defaultOnError( + zNesDocumentDidOpenCapabilities.nullish(), + () => undefined, + ), + didSave: defaultOnError( + zNesDocumentDidSaveCapabilities.nullish(), + () => undefined, + ), }); /** @@ -2490,7 +2582,10 @@ export const zNesDocumentEventCapabilities = z.object({ */ export const zNesEventCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - document: zNesDocumentEventCapabilities.nullish(), + document: defaultOnError( + zNesDocumentEventCapabilities.nullish(), + () => undefined, + ), }); /** @@ -2498,8 +2593,8 @@ export const zNesEventCapabilities = z.object({ */ export const zNesCapabilities = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - context: zNesContextCapabilities.nullish(), - events: zNesEventCapabilities.nullish(), + context: defaultOnError(zNesContextCapabilities.nullish(), () => undefined), + events: defaultOnError(zNesEventCapabilities.nullish(), () => undefined), }); /** @@ -2519,14 +2614,17 @@ export const zAgentCapabilities = z.object({ http: false, sse: false, }), - nes: zNesCapabilities.nullish(), - positionEncoding: zPositionEncodingKind.nullish(), + nes: defaultOnError(zNesCapabilities.nullish(), () => undefined), + positionEncoding: defaultOnError( + zPositionEncodingKind.nullish(), + () => undefined, + ), promptCapabilities: zPromptCapabilities.optional().default({ audio: false, embeddedContext: false, image: false, }), - providers: zProvidersCapabilities.nullish(), + providers: defaultOnError(zProvidersCapabilities.nullish(), () => undefined), sessionCapabilities: zSessionCapabilities.optional().default({}), }); @@ -2554,8 +2652,11 @@ export const zInitializeResponse = z.object({ }, sessionCapabilities: {}, }), - agentInfo: zImplementation.nullish(), - authMethods: z.array(zAuthMethod).optional().default([]), + agentInfo: defaultOnError(zImplementation.nullish(), () => undefined), + authMethods: defaultOnError( + vecSkipError(zAuthMethod).optional().default([]), + () => [], + ), protocolVersion: zProtocolVersion, }); @@ -2582,7 +2683,7 @@ export const zEmbeddedResourceResource = z.union([ */ export const zEmbeddedResource = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - annotations: zAnnotations.nullish(), + annotations: defaultOnError(zAnnotations.nullish(), () => undefined), resource: zEmbeddedResourceResource, }); @@ -2800,9 +2901,12 @@ export const zToolKind = z.union([ */ export const zToolCall = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - content: z.array(zToolCallContent).optional(), + content: defaultOnError(vecSkipError(zToolCallContent).optional(), () => []), kind: zToolKind.optional(), - locations: z.array(zToolCallLocation).optional(), + locations: defaultOnError( + vecSkipError(zToolCallLocation).optional(), + () => [], + ), rawInput: z.unknown().optional(), rawOutput: z.unknown().optional(), status: zToolCallStatus.optional(), @@ -2820,12 +2924,18 @@ export const zToolCall = z.object({ */ export const zToolCallUpdate = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - content: z.array(zToolCallContent).nullish(), - kind: zToolKind.nullish(), - locations: z.array(zToolCallLocation).nullish(), + content: defaultOnError( + vecSkipError(zToolCallContent).nullish(), + () => undefined, + ), + kind: defaultOnError(zToolKind.nullish(), () => undefined), + locations: defaultOnError( + vecSkipError(zToolCallLocation).nullish(), + () => undefined, + ), rawInput: z.unknown().optional(), rawOutput: z.unknown().optional(), - status: zToolCallStatus.nullish(), + status: defaultOnError(zToolCallStatus.nullish(), () => undefined), title: z.string().nullish(), toolCallId: zToolCallId, }); @@ -2865,7 +2975,7 @@ export const zAvailableCommandInput = zUnstructuredCommandInput; export const zAvailableCommand = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), description: z.string(), - input: zAvailableCommandInput.nullish(), + input: defaultOnError(zAvailableCommandInput.nullish(), () => undefined), name: z.string(), }); @@ -2874,7 +2984,10 @@ export const zAvailableCommand = z.object({ */ export const zAvailableCommandsUpdate = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - availableCommands: z.array(zAvailableCommand), + availableCommands: requiredDefaultOnError( + vecSkipError(zAvailableCommand), + () => [], + ), }); /** @@ -3031,7 +3144,7 @@ export const zUsage = z.object({ export const zPromptResponse = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), stopReason: zStopReason, - usage: zUsage.nullish(), + usage: defaultOnError(zUsage.nullish(), () => undefined), userMessageId: z.string().nullish(), }); @@ -3079,7 +3192,7 @@ export const zAgentResponse = z.union([ */ export const zUsageUpdate = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - cost: zCost.nullish(), + cost: defaultOnError(zCost.nullish(), () => undefined), size: z.number(), used: z.number(), }); @@ -3222,8 +3335,11 @@ export const zWorkspaceFolder = z.object({ */ export const zStartNesRequest = z.object({ _meta: z.record(z.string(), z.unknown()).nullish(), - repository: zNesRepository.nullish(), - workspaceFolders: z.array(zWorkspaceFolder).nullish(), + repository: defaultOnError(zNesRepository.nullish(), () => undefined), + workspaceFolders: defaultOnError( + vecSkipError(zWorkspaceFolder).nullish(), + () => undefined, + ), workspaceUri: z.string().nullish(), });