From d00aa59a5e491f5fb8c7f49dd42ad9cae4b557d9 Mon Sep 17 00:00:00 2001 From: Michael Doyle Date: Mon, 3 Mar 2025 21:47:18 -0500 Subject: [PATCH] fix: sync model types in genkit-tools (#2229) --- genkit-tools/common/src/types/model.ts | 181 ++++++++++++++++++-- genkit-tools/genkit-schema.json | 219 ++++++++++++++++--------- 2 files changed, 307 insertions(+), 93 deletions(-) diff --git a/genkit-tools/common/src/types/model.ts b/genkit-tools/common/src/types/model.ts index 757c0b4d3..381b07e3e 100644 --- a/genkit-tools/common/src/types/model.ts +++ b/genkit-tools/common/src/types/model.ts @@ -20,21 +20,32 @@ import { DocumentDataSchema } from './document'; // IMPORTANT: Keep this file in sync with genkit/ai/src/model.ts! // -export const EmptyPartSchema = z.object({ +const EmptyPartSchema = z.object({ text: z.never().optional(), media: z.never().optional(), toolRequest: z.never().optional(), toolResponse: z.never().optional(), data: z.unknown().optional(), metadata: z.record(z.unknown()).optional(), + custom: z.record(z.unknown()).optional(), }); +/** + * Zod schema for a text part. + */ export const TextPartSchema = EmptyPartSchema.extend({ /** The text of the message. */ text: z.string(), }); + +/** + * Text part. + */ export type TextPart = z.infer; +/** + * Zod schema of a media part. + */ export const MediaPartSchema = EmptyPartSchema.extend({ media: z.object({ /** The media content type. Inferred from data uri if not provided. */ @@ -43,8 +54,15 @@ export const MediaPartSchema = EmptyPartSchema.extend({ url: z.string(), }), }); + +/** + * Media part. + */ export type MediaPart = z.infer; +/** + * Zod schema of a tool request part. + */ export const ToolRequestPartSchema = EmptyPartSchema.extend({ /** A request for a tool to be executed, usually provided by a model. */ toolRequest: z.object({ @@ -56,8 +74,15 @@ export const ToolRequestPartSchema = EmptyPartSchema.extend({ input: z.unknown().optional(), }), }); + +/** + * Tool part. + */ export type ToolRequestPart = z.infer; +/** + * Zod schema of a tool response part. + */ export const ToolResponsePartSchema = EmptyPartSchema.extend({ /** A provided response to a tool call. */ toolResponse: z.object({ @@ -69,35 +94,80 @@ export const ToolResponsePartSchema = EmptyPartSchema.extend({ output: z.unknown().optional(), }), }); + +/** + * Tool response part. + */ export type ToolResponsePart = z.infer; +/** + * Zod schema of a data part. + */ export const DataPartSchema = EmptyPartSchema.extend({ data: z.unknown(), }); +/** + * Data part. + */ export type DataPart = z.infer; +/** + * Zod schema of a custom part. + */ +export const CustomPartSchema = EmptyPartSchema.extend({ + custom: z.record(z.any()), +}); + +/** + * Custom part. + */ +export type CustomPart = z.infer; + +/** + * Zod schema of message part. + */ export const PartSchema = z.union([ TextPartSchema, MediaPartSchema, ToolRequestPartSchema, ToolResponsePartSchema, DataPartSchema, + CustomPartSchema, ]); + +/** + * Message part. + */ export type Part = z.infer; +/** + * Zod schema of a message role. + */ export const RoleSchema = z.enum(['system', 'user', 'model', 'tool']); + +/** + * Message role. + */ export type Role = z.infer; +/** + * Zod schema of a message. + */ export const MessageSchema = z.object({ role: RoleSchema, content: z.array(PartSchema), metadata: z.record(z.unknown()).optional(), }); -export type MessageData = z.infer; -export const OutputFormatSchema = z.enum(['json', 'text', 'media']); +/** + * Model message data. + */ +export type MessageData = z.infer; +/** + * Zod schema of model info metadata. + */ export const ModelInfoSchema = z.object({ /** Acceptable names for this model (e.g. different versions). */ versions: z.array(z.string()).optional(), @@ -126,26 +196,51 @@ export const ModelInfoSchema = z.object({ toolChoice: z.boolean().optional(), }) .optional(), + /** At which stage of development this model is. + * - `featured` models are recommended for general use. + * - `stable` models are well-tested and reliable. + * - `unstable` models are experimental and may change. + * - `legacy` models are no longer recommended for new projects. + * - `deprecated` models are deprecated by the provider and may be removed in future versions. + */ + stage: z + .enum(['featured', 'stable', 'unstable', 'legacy', 'deprecated']) + .optional(), }); + +/** + * Model info metadata. + */ export type ModelInfo = z.infer; +/** + * Zod schema of a tool definition. + */ export const ToolDefinitionSchema = z.object({ name: z.string(), description: z.string(), inputSchema: z .record(z.any()) - .describe('Valid JSON Schema representing the input of the tool.'), + .describe('Valid JSON Schema representing the input of the tool.') + .nullish(), outputSchema: z .record(z.any()) .describe('Valid JSON Schema describing the output of the tool.') - .optional(), + .nullish(), metadata: z .record(z.any()) .describe('additional metadata for this tool definition') .optional(), }); + +/** + * Tool definition. + */ export type ToolDefinition = z.infer; +/** + * Zod schema of a common config object. + */ export const GenerationCommonConfigSchema = z.object({ /** A specific version of a model family, e.g. `gemini-1.0-pro-001` for the `gemini-1.0-pro` family. */ version: z.string().optional(), @@ -155,14 +250,26 @@ export const GenerationCommonConfigSchema = z.object({ topP: z.number().optional(), stopSequences: z.array(z.string()).optional(), }); + +/** + * Common config object. + */ export type GenerationCommonConfig = typeof GenerationCommonConfigSchema; +/** + * Zod schema of output config. + */ export const OutputConfigSchema = z.object({ - format: OutputFormatSchema.optional(), + format: z.string().optional(), schema: z.record(z.any()).optional(), constrained: z.boolean().optional(), + instructions: z.string().optional(), contentType: z.string().optional(), }); + +/** + * Output config. + */ export type OutputConfig = z.infer; /** ModelRequestSchema represents the parameters that are passed to a model when generating content. */ @@ -172,7 +279,7 @@ export const ModelRequestSchema = z.object({ tools: z.array(ToolDefinitionSchema).optional(), toolChoice: z.enum(['auto', 'required', 'none']).optional(), output: OutputConfigSchema.optional(), - context: z.array(DocumentDataSchema).optional(), + docs: z.array(DocumentDataSchema).optional(), }); /** ModelRequest represents the parameters that are passed to a model when generating content. */ export interface ModelRequest< @@ -180,21 +287,31 @@ export interface ModelRequest< > extends z.infer { config?: z.infer; } - +/** + * Zod schema of a generate request. + */ export const GenerateRequestSchema = ModelRequestSchema.extend({ - /** @deprecated Use `docs` instead. */ - context: z.array(DocumentDataSchema).optional(), /** @deprecated All responses now return a single candidate. This will always be `undefined`. */ candidates: z.number().optional(), }); + +/** + * Generate request data. + */ export type GenerateRequestData = z.infer; +/** + * Generate request. + */ export interface GenerateRequest< CustomOptionsSchema extends z.ZodTypeAny = z.ZodTypeAny, > extends z.infer { config?: z.infer; } +/** + * Zod schema of usage info from a generate request. + */ export const GenerationUsageSchema = z.object({ inputTokens: z.number().optional(), outputTokens: z.number().optional(), @@ -209,10 +326,14 @@ export const GenerationUsageSchema = z.object({ outputAudioFiles: z.number().optional(), custom: z.record(z.number()).optional(), }); + +/** + * Usage info from a generate request. + */ export type GenerationUsage = z.infer; /** Model response finish reason enum. */ -export const FinishReasonSchema = z.enum([ +const FinishReasonSchema = z.enum([ 'stop', 'length', 'blocked', @@ -242,22 +363,38 @@ export const CandidateErrorSchema = z.object({ /** @deprecated All responses now return a single candidate. Only the first candidate will be used if supplied. */ export type CandidateError = z.infer; +/** + * Zod schema of a model response. + */ export const ModelResponseSchema = z.object({ message: MessageSchema.optional(), finishReason: FinishReasonSchema, finishMessage: z.string().optional(), latencyMs: z.number().optional(), usage: GenerationUsageSchema.optional(), + /** @deprecated use `raw` instead */ custom: z.unknown(), + raw: z.unknown(), request: GenerateRequestSchema.optional(), }); + +/** + * Model response data. + */ export type ModelResponseData = z.infer; +/** + * Zod schema of generaete response. + */ export const GenerateResponseSchema = ModelResponseSchema.extend({ /** @deprecated All responses now return a single candidate. Only the first candidate will be used if supplied. Return `message`, `finishReason`, and `finishMessage` instead. */ candidates: z.array(CandidateSchema).optional(), finishReason: FinishReasonSchema.optional(), }); + +/** + * Generate response data. + */ export type GenerateResponseData = z.infer; /** ModelResponseChunkSchema represents a chunk of content to stream to the client. */ @@ -274,11 +411,19 @@ export const ModelResponseChunkSchema = z.object({ }); export type ModelResponseChunkData = z.infer; -export const GenerateResponseChunkSchema = ModelResponseChunkSchema.extend({}); +export const GenerateResponseChunkSchema = ModelResponseChunkSchema; export type GenerateResponseChunkData = z.infer< typeof GenerateResponseChunkSchema >; +export const GenerateActionOutputConfig = z.object({ + format: z.string().optional(), + contentType: z.string().optional(), + instructions: z.union([z.boolean(), z.string()]).optional(), + jsonSchema: z.any().optional(), + constrained: z.boolean().optional(), +}); + export const GenerateActionOptionsSchema = z.object({ /** A model name (e.g. `vertexai/gemini-1.0-pro`). */ model: z.string(), @@ -293,13 +438,13 @@ export const GenerateActionOptionsSchema = z.object({ /** Configuration for the generation request. */ config: z.any().optional(), /** Configuration for the desired output of the request. Defaults to the model's default output if unspecified. */ - output: z + output: GenerateActionOutputConfig.optional(), + /** Options for resuming an interrupted generation. */ + resume: z .object({ - format: z.string().optional(), - contentType: z.string().optional(), - instructions: z.union([z.boolean(), z.string()]).optional(), - jsonSchema: z.any().optional(), - constrained: z.boolean().optional(), + respond: z.array(ToolResponsePartSchema).optional(), + restart: z.array(ToolRequestPartSchema).optional(), + metadata: z.record(z.any()).optional(), }) .optional(), /** When true, return tool calls for manual processing instead of automatically resolving them. */ diff --git a/genkit-tools/genkit-schema.json b/genkit-tools/genkit-schema.json index 092b0c5a0..8ae8574e2 100644 --- a/genkit-tools/genkit-schema.json +++ b/genkit-tools/genkit-schema.json @@ -297,7 +297,15 @@ "$ref": "#/$defs/GenerationUsage" }, "finishReason": { - "$ref": "#/$defs/FinishReason" + "type": "string", + "enum": [ + "stop", + "length", + "blocked", + "interrupted", + "other", + "unknown" + ] }, "finishMessage": { "type": "string" @@ -311,7 +319,7 @@ ], "additionalProperties": false }, - "DataPart": { + "CustomPart": { "type": "object", "properties": { "text": { @@ -330,43 +338,43 @@ "metadata": { "type": "object", "additionalProperties": {} + }, + "custom": { + "type": "object", + "additionalProperties": {} } }, + "required": [ + "custom" + ], "additionalProperties": false }, - "EmptyPart": { + "DataPart": { "type": "object", "properties": { "text": { - "$ref": "#/$defs/DataPart/properties/text" + "$ref": "#/$defs/CustomPart/properties/text" }, "media": { - "$ref": "#/$defs/DataPart/properties/media" + "$ref": "#/$defs/CustomPart/properties/media" }, "toolRequest": { - "$ref": "#/$defs/DataPart/properties/toolRequest" + "$ref": "#/$defs/CustomPart/properties/toolRequest" }, "toolResponse": { - "$ref": "#/$defs/DataPart/properties/toolResponse" + "$ref": "#/$defs/CustomPart/properties/toolResponse" }, "data": {}, "metadata": { - "$ref": "#/$defs/DataPart/properties/metadata" + "$ref": "#/$defs/CustomPart/properties/metadata" + }, + "custom": { + "type": "object", + "additionalProperties": {} } }, "additionalProperties": false }, - "FinishReason": { - "type": "string", - "enum": [ - "stop", - "length", - "blocked", - "interrupted", - "other", - "unknown" - ] - }, "GenerateActionOptions": { "type": "object", "properties": { @@ -460,23 +468,26 @@ }, "config": {}, "output": { + "$ref": "#/$defs/GenerateActionOutputConfig" + }, + "resume": { "type": "object", "properties": { - "format": { - "type": "string" - }, - "contentType": { - "type": "string" + "respond": { + "type": "array", + "items": { + "$ref": "#/$defs/ToolResponsePart" + } }, - "instructions": { - "type": [ - "boolean", - "string" - ] + "restart": { + "type": "array", + "items": { + "$ref": "#/$defs/ToolRequestPart" + } }, - "jsonSchema": {}, - "constrained": { - "type": "boolean" + "metadata": { + "type": "object", + "additionalProperties": {} } }, "additionalProperties": false @@ -494,6 +505,28 @@ ], "additionalProperties": false }, + "GenerateActionOutputConfig": { + "type": "object", + "properties": { + "format": { + "type": "string" + }, + "contentType": { + "type": "string" + }, + "instructions": { + "type": [ + "boolean", + "string" + ] + }, + "jsonSchema": {}, + "constrained": { + "type": "boolean" + } + }, + "additionalProperties": false + }, "GenerateRequest": { "type": "object", "properties": { @@ -521,7 +554,7 @@ "output": { "$ref": "#/$defs/OutputConfig" }, - "context": { + "docs": { "type": "array", "items": { "$ref": "#/$defs/GenerateActionOptions/properties/docs/items" @@ -568,7 +601,7 @@ "$ref": "#/$defs/Message" }, "finishReason": { - "$ref": "#/$defs/FinishReason" + "$ref": "#/$defs/Candidate/properties/finishReason" }, "finishMessage": { "type": "string" @@ -580,6 +613,7 @@ "$ref": "#/$defs/GenerationUsage" }, "custom": {}, + "raw": {}, "request": { "$ref": "#/$defs/GenerateRequest" }, @@ -668,7 +702,7 @@ "type": "object", "properties": { "text": { - "$ref": "#/$defs/DataPart/properties/text" + "$ref": "#/$defs/CustomPart/properties/text" }, "media": { "type": "object", @@ -686,16 +720,19 @@ "additionalProperties": false }, "toolRequest": { - "$ref": "#/$defs/DataPart/properties/toolRequest" + "$ref": "#/$defs/CustomPart/properties/toolRequest" }, "toolResponse": { - "$ref": "#/$defs/DataPart/properties/toolResponse" + "$ref": "#/$defs/CustomPart/properties/toolResponse" }, "data": { - "$ref": "#/$defs/EmptyPart/properties/data" + "$ref": "#/$defs/CustomPart/properties/data" }, "metadata": { - "$ref": "#/$defs/DataPart/properties/metadata" + "$ref": "#/$defs/CustomPart/properties/metadata" + }, + "custom": { + "$ref": "#/$defs/DataPart/properties/custom" } }, "required": [ @@ -781,6 +818,16 @@ } }, "additionalProperties": false + }, + "stage": { + "type": "string", + "enum": [ + "featured", + "stable", + "unstable", + "legacy", + "deprecated" + ] } }, "additionalProperties": false @@ -803,11 +850,8 @@ "output": { "$ref": "#/$defs/GenerateRequest/properties/output" }, - "context": { - "type": "array", - "items": { - "$ref": "#/$defs/GenerateActionOptions/properties/docs/items" - } + "docs": { + "$ref": "#/$defs/GenerateRequest/properties/docs" } }, "required": [ @@ -846,7 +890,7 @@ "$ref": "#/$defs/GenerateResponse/properties/message" }, "finishReason": { - "$ref": "#/$defs/FinishReason" + "$ref": "#/$defs/Candidate/properties/finishReason" }, "finishMessage": { "$ref": "#/$defs/GenerateResponse/properties/finishMessage" @@ -860,6 +904,9 @@ "custom": { "$ref": "#/$defs/GenerateResponse/properties/custom" }, + "raw": { + "$ref": "#/$defs/GenerateResponse/properties/raw" + }, "request": { "$ref": "#/$defs/GenerateResponse/properties/request" } @@ -873,7 +920,7 @@ "type": "object", "properties": { "format": { - "$ref": "#/$defs/OutputFormat" + "type": "string" }, "schema": { "type": "object", @@ -882,20 +929,15 @@ "constrained": { "type": "boolean" }, + "instructions": { + "type": "string" + }, "contentType": { "type": "string" } }, "additionalProperties": false }, - "OutputFormat": { - "type": "string", - "enum": [ - "json", - "text", - "media" - ] - }, "Part": { "anyOf": [ { @@ -912,6 +954,9 @@ }, { "$ref": "#/$defs/DataPart" + }, + { + "$ref": "#/$defs/CustomPart" } ] }, @@ -931,19 +976,22 @@ "type": "string" }, "media": { - "$ref": "#/$defs/DataPart/properties/media" + "$ref": "#/$defs/CustomPart/properties/media" }, "toolRequest": { - "$ref": "#/$defs/DataPart/properties/toolRequest" + "$ref": "#/$defs/CustomPart/properties/toolRequest" }, "toolResponse": { - "$ref": "#/$defs/DataPart/properties/toolResponse" + "$ref": "#/$defs/CustomPart/properties/toolResponse" }, "data": { - "$ref": "#/$defs/EmptyPart/properties/data" + "$ref": "#/$defs/CustomPart/properties/data" }, "metadata": { - "$ref": "#/$defs/DataPart/properties/metadata" + "$ref": "#/$defs/CustomPart/properties/metadata" + }, + "custom": { + "$ref": "#/$defs/DataPart/properties/custom" } }, "required": [ @@ -961,13 +1009,29 @@ "type": "string" }, "inputSchema": { - "type": "object", - "additionalProperties": {}, + "anyOf": [ + { + "type": "object", + "additionalProperties": {}, + "description": "Valid JSON Schema representing the input of the tool." + }, + { + "type": "null" + } + ], "description": "Valid JSON Schema representing the input of the tool." }, "outputSchema": { - "type": "object", - "additionalProperties": {}, + "anyOf": [ + { + "type": "object", + "additionalProperties": {}, + "description": "Valid JSON Schema describing the output of the tool." + }, + { + "type": "null" + } + ], "description": "Valid JSON Schema describing the output of the tool." }, "metadata": { @@ -978,8 +1042,7 @@ }, "required": [ "name", - "description", - "inputSchema" + "description" ], "additionalProperties": false }, @@ -987,10 +1050,10 @@ "type": "object", "properties": { "text": { - "$ref": "#/$defs/DataPart/properties/text" + "$ref": "#/$defs/CustomPart/properties/text" }, "media": { - "$ref": "#/$defs/DataPart/properties/media" + "$ref": "#/$defs/CustomPart/properties/media" }, "toolRequest": { "type": "object", @@ -1009,13 +1072,16 @@ "additionalProperties": false }, "toolResponse": { - "$ref": "#/$defs/DataPart/properties/toolResponse" + "$ref": "#/$defs/CustomPart/properties/toolResponse" }, "data": { - "$ref": "#/$defs/EmptyPart/properties/data" + "$ref": "#/$defs/CustomPart/properties/data" }, "metadata": { - "$ref": "#/$defs/DataPart/properties/metadata" + "$ref": "#/$defs/CustomPart/properties/metadata" + }, + "custom": { + "$ref": "#/$defs/DataPart/properties/custom" } }, "required": [ @@ -1027,13 +1093,13 @@ "type": "object", "properties": { "text": { - "$ref": "#/$defs/DataPart/properties/text" + "$ref": "#/$defs/CustomPart/properties/text" }, "media": { - "$ref": "#/$defs/DataPart/properties/media" + "$ref": "#/$defs/CustomPart/properties/media" }, "toolRequest": { - "$ref": "#/$defs/DataPart/properties/toolRequest" + "$ref": "#/$defs/CustomPart/properties/toolRequest" }, "toolResponse": { "type": "object", @@ -1052,10 +1118,13 @@ "additionalProperties": false }, "data": { - "$ref": "#/$defs/EmptyPart/properties/data" + "$ref": "#/$defs/CustomPart/properties/data" }, "metadata": { - "$ref": "#/$defs/DataPart/properties/metadata" + "$ref": "#/$defs/CustomPart/properties/metadata" + }, + "custom": { + "$ref": "#/$defs/DataPart/properties/custom" } }, "required": [