From 72f12710618da8e459675320af24b5fb0fd9930b Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 2 Dec 2025 16:30:27 +0000 Subject: [PATCH 01/30] feat(anthropic): add structured output --- js/plugins/anthropic/package.json | 2 +- js/plugins/anthropic/src/runner/beta.ts | 40 ++++++++++++++++++------- js/testapps/anthropic/src/beta/basic.ts | 7 ++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/js/plugins/anthropic/package.json b/js/plugins/anthropic/package.json index 32b1c4ba87..d8bbd2196b 100644 --- a/js/plugins/anthropic/package.json +++ b/js/plugins/anthropic/package.json @@ -29,7 +29,7 @@ "genkit": "workspace:^" }, "dependencies": { - "@anthropic-ai/sdk": "^0.68.0" + "@anthropic-ai/sdk": "^0.71.0" }, "devDependencies": { "@types/node": "^20.11.16", diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 6a71fa71d5..34e2f1faa2 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -66,6 +66,29 @@ const BETA_UNSUPPORTED_SERVER_TOOL_BLOCK_TYPES = new Set([ 'container_upload', ]); +const BETA_APIS = [ + // 'message-batches-2024-09-24', + // 'prompt-caching-2024-07-31', + // 'computer-use-2025-01-24', + // 'pdfs-2024-09-25', + // 'token-counting-2024-11-01', + // 'token-efficient-tools-2025-02-19', + // 'output-128k-2025-02-19', + // 'files-api-2025-04-14', + // 'mcp-client-2025-04-04', + // 'dev-full-thinking-2025-05-14', + // 'interleaved-thinking-2025-05-14', + // 'code-execution-2025-05-22', + // 'extended-cache-ttl-2025-04-11', + // 'context-1m-2025-08-07', + // 'context-management-2025-06-27', + // 'model-context-window-exceeded-2025-08-26', + // 'skills-2025-10-02', + // 'effort-param-2025-11-24', + // 'advanced-tool-use-2025-11-20', + 'structured-outputs-2025-11-13', +] + const unsupportedServerToolError = (blockType: string): string => `Anthropic beta runner does not yet support server-managed tool block '${blockType}'. Please retry against the stable API or wait for dedicated support.`; @@ -281,12 +304,6 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } - if (request.output?.format && request.output.format !== 'text') { - throw new Error( - `Only text output format is supported for Claude models currently` - ); - } - return body; } @@ -349,12 +366,15 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } - if (request.output?.format && request.output.format !== 'text') { - throw new Error( - `Only text output format is supported for Claude models currently` - ); + if (request.output?.schema) { + body.output_format = { + type: 'json_schema', + schema: request.output?.schema, + } } + body.betas = BETA_APIS; + return body; } diff --git a/js/testapps/anthropic/src/beta/basic.ts b/js/testapps/anthropic/src/beta/basic.ts index d1309b3400..d5623310f8 100644 --- a/js/testapps/anthropic/src/beta/basic.ts +++ b/js/testapps/anthropic/src/beta/basic.ts @@ -20,7 +20,11 @@ import { genkit } from 'genkit'; const ai = genkit({ plugins: [ // Default all flows in this sample to the beta surface - anthropic({ apiVersion: 'beta', cacheSystemPrompt: true }), + anthropic({ + apiVersion: 'beta', + cacheSystemPrompt: true, + apiKey: process.env.ANTHROPIC_API_KEY, + }), ], }); @@ -34,6 +38,7 @@ ai.defineFlow('anthropic-beta-hello', async () => { prompt: 'You are Claude on the beta API. Provide a concise greeting that mentions that you are using the beta API.', config: { temperature: 0.6 }, + output: {}, }); return text; From 2c0fa8a25b35fd3eca755f81d517c46282ed35ce Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 2 Dec 2025 16:49:34 +0000 Subject: [PATCH 02/30] test(js/plugins/anthropic): add live test for structured output --- js/plugins/anthropic/package.json | 1 + js/plugins/anthropic/src/runner/beta.ts | 4 +- js/plugins/anthropic/tests/live_test.ts | 49 +++++++++++++++++++++++++ js/pnpm-lock.yaml | 10 ++--- 4 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 js/plugins/anthropic/tests/live_test.ts diff --git a/js/plugins/anthropic/package.json b/js/plugins/anthropic/package.json index d8bbd2196b..998296e1cf 100644 --- a/js/plugins/anthropic/package.json +++ b/js/plugins/anthropic/package.json @@ -64,6 +64,7 @@ "build": "npm-run-all build:clean check compile", "build:watch": "tsup-node --watch", "test": "tsx --test tests/*_test.ts", + "test:live": "tsx --test tests/live_test.ts", "test:file": "tsx --test", "test:coverage": "check-node-version --node '>=22' && tsx --test --experimental-test-coverage --test-coverage-include='src/**/*.ts' ./tests/**/*_test.ts" } diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 34e2f1faa2..dc84455723 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -87,7 +87,7 @@ const BETA_APIS = [ // 'effort-param-2025-11-24', // 'advanced-tool-use-2025-11-20', 'structured-outputs-2025-11-13', -] +]; const unsupportedServerToolError = (blockType: string): string => `Anthropic beta runner does not yet support server-managed tool block '${blockType}'. Please retry against the stable API or wait for dedicated support.`; @@ -370,7 +370,7 @@ export class BetaRunner extends BaseRunner { body.output_format = { type: 'json_schema', schema: request.output?.schema, - } + }; } body.betas = BETA_APIS; diff --git a/js/plugins/anthropic/tests/live_test.ts b/js/plugins/anthropic/tests/live_test.ts new file mode 100644 index 0000000000..5f95beddd8 --- /dev/null +++ b/js/plugins/anthropic/tests/live_test.ts @@ -0,0 +1,49 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import { genkit, z } from 'genkit'; +import { describe, it } from 'node:test'; +import { anthropic } from '../src/index.js'; + +const SKIP_LIVE_TESTS = !process.env.ANTHROPIC_API_KEY; + +describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { + it('should return structured output matching the schema', async () => { + const ai = genkit({ + plugins: [anthropic({ apiVersion: 'beta' })], + }); + + const schema = z.object({ + name: z.string(), + age: z.number(), + city: z.string(), + }); + + const result = await ai.generate({ + model: 'anthropic/claude-sonnet-4-5', + prompt: + 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', + output: { schema }, + }); + + const parsed = result.output; + assert.ok(parsed, 'Should have parsed output'); + assert.strictEqual(parsed.name, 'Alice'); + assert.strictEqual(parsed.age, 30); + assert.strictEqual(parsed.city, 'New York'); + }); +}); diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 109b07c772..8ca620edda 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -260,8 +260,8 @@ importers: plugins/anthropic: dependencies: '@anthropic-ai/sdk': - specifier: ^0.68.0 - version: 0.68.0(zod@3.25.67) + specifier: ^0.71.0 + version: 0.71.0(zod@3.25.67) devDependencies: '@types/node': specifier: ^20.11.16 @@ -2092,8 +2092,8 @@ packages: '@anthropic-ai/sdk@0.24.3': resolution: {integrity: sha512-916wJXO6T6k8R6BAAcLhLPv/pnLGy7YSEBZXZ1XTFbLcTZE8oTy3oDW9WJf9KKZwMvVcePIfoTSvzXHRcGxkQQ==} - '@anthropic-ai/sdk@0.68.0': - resolution: {integrity: sha512-SMYAmbbiprG8k1EjEPMTwaTqssDT7Ae+jxcR5kWXiqTlbwMR2AthXtscEVWOHkRfyAV5+y3PFYTJRNa3OJWIEw==} + '@anthropic-ai/sdk@0.71.0': + resolution: {integrity: sha512-go1XeWXmpxuiTkosSXpb8tokLk2ZLkIRcXpbWVwJM6gH5OBtHOVsfPfGuqI1oW7RRt4qc59EmYbrXRZ0Ng06Jw==} hasBin: true peerDependencies: zod: ^3.25.0 || ^4.0.0 @@ -7931,7 +7931,7 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/sdk@0.68.0(zod@3.25.67)': + '@anthropic-ai/sdk@0.71.0(zod@3.25.67)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: From f76acf27282b30c99cb629f76a440989b0c9e688 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 2 Dec 2025 17:13:24 +0000 Subject: [PATCH 03/30] fix(js/plugins/anthropic): filter by model and dynamically enhance outputs --- js/plugins/anthropic/src/models.ts | 29 ++++++++++-- js/plugins/anthropic/src/runner/beta.ts | 61 ++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index 2ee33d933c..555d701a15 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -201,6 +201,15 @@ export function claudeModelReference( }); } +/** + * Models that support structured outputs in the beta API. + * @see https://docs.anthropic.com/en/docs/build-with-claude/structured-outputs + */ +const STRUCTURED_OUTPUT_MODELS = new Set([ + 'claude-sonnet-4-5', + 'claude-opus-4-1', +]); + /** * Defines a Claude model with the given name and Anthropic client. * Accepts any model name and lets the API validate it. If the model is in KNOWN_CLAUDE_MODELS, uses that modelRef @@ -216,9 +225,23 @@ export function claudeModel( defaultApiVersion: apiVersion, } = params; // Use supported model ref if available, otherwise create generic model ref - const modelRef = KNOWN_CLAUDE_MODELS[name]; - const modelInfo = modelRef ? modelRef.info : GENERIC_CLAUDE_MODEL_INFO; - const configSchema = modelRef?.configSchema ?? AnthropicConfigSchema; + const knownModelRef = KNOWN_CLAUDE_MODELS[name]; + let modelInfo = knownModelRef + ? knownModelRef.info + : GENERIC_CLAUDE_MODEL_INFO; + const configSchema = knownModelRef?.configSchema ?? AnthropicConfigSchema; + + // Enhance model info with structured output support when using beta API + if (apiVersion === 'beta' && STRUCTURED_OUTPUT_MODELS.has(name)) { + modelInfo = { + ...modelInfo, + supports: { + ...modelInfo?.supports, + output: ['text', 'json'], + constrained: 'all', + }, + }; + } return model< AnthropicBaseConfigSchemaType | AnthropicThinkingConfigSchemaType diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index dc84455723..73f8757d37 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -89,6 +89,42 @@ const BETA_APIS = [ 'structured-outputs-2025-11-13', ]; +/** + * Models that support structured outputs (JSON schema). + * See: https://docs.anthropic.com/en/docs/build-with-claude/structured-outputs + */ +const STRUCTURED_OUTPUT_MODELS = new Set([ + 'claude-sonnet-4-5', + 'claude-opus-4-1', +]); + +/** + * Transforms a JSON schema to be compatible with Anthropic's structured output requirements. + * Anthropic requires `additionalProperties: false` on all object types. + */ +function toAnthropicSchema( + schema: Record +): Record { + const out = structuredClone(schema); + + // Remove $schema if present + delete out.$schema; + + // Add additionalProperties: false to objects + if (out.type === 'object') { + out.additionalProperties = false; + } + + // Recursively process nested objects + for (const key in out) { + if (typeof out[key] === 'object' && out[key] !== null) { + out[key] = toAnthropicSchema(out[key] as Record); + } + } + + return out; +} + const unsupportedServerToolError = (blockType: string): string => `Anthropic beta runner does not yet support server-managed tool block '${blockType}'. Please retry against the stable API or wait for dedicated support.`; @@ -304,6 +340,21 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } + // Apply structured output when model supports it and constrained output is requested + const useStructuredOutput = + STRUCTURED_OUTPUT_MODELS.has(modelName) && + request.output?.constrained && + request.output?.schema; + + if (useStructuredOutput) { + body.output_format = { + type: 'json_schema', + schema: toAnthropicSchema(request.output.schema), + }; + } + + body.betas = BETA_APIS; + return body; } @@ -366,10 +417,16 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } - if (request.output?.schema) { + // Apply structured output when model supports it and constrained output is requested + const useStructuredOutput = + STRUCTURED_OUTPUT_MODELS.has(modelName) && + request.output?.constrained && + request.output?.schema; + + if (useStructuredOutput) { body.output_format = { type: 'json_schema', - schema: request.output?.schema, + schema: toAnthropicSchema(request.output.schema), }; } From e79bea51f8812762f218c27e7af2f94bb6c6d5dd Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Wed, 3 Dec 2025 12:35:48 +0000 Subject: [PATCH 04/30] fix(js/plugins/anthropic): pass through constrained output options correctly --- js/plugins/anthropic/src/models.ts | 45 ++- js/plugins/anthropic/src/runner/beta.ts | 30 +- js/plugins/anthropic/tests/live_test.ts | 14 +- .../anthropic/tests/mocks/anthropic-client.ts | 1 + .../anthropic/tests/structured_output_test.ts | 307 ++++++++++++++++++ 5 files changed, 357 insertions(+), 40 deletions(-) create mode 100644 js/plugins/anthropic/tests/structured_output_test.ts diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index 555d701a15..1c5cb99d68 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -81,7 +81,17 @@ export const KNOWN_CLAUDE_MODELS: Record< 'claude-opus-4': commonRef('claude-opus-4', AnthropicThinkingConfigSchema), 'claude-sonnet-4-5': commonRef( 'claude-sonnet-4-5', - AnthropicThinkingConfigSchema + AnthropicThinkingConfigSchema, + { + supports: { + multiturn: true, + tools: true, + media: true, + systemRole: true, + output: ['text', 'json'], + constrained: 'all', + }, + } ), 'claude-haiku-4-5': commonRef( 'claude-haiku-4-5', @@ -89,7 +99,17 @@ export const KNOWN_CLAUDE_MODELS: Record< ), 'claude-opus-4-1': commonRef( 'claude-opus-4-1', - AnthropicThinkingConfigSchema + AnthropicThinkingConfigSchema, + { + supports: { + multiturn: true, + tools: true, + media: true, + systemRole: true, + output: ['text', 'json'], + constrained: 'all', + }, + } ), }; @@ -201,15 +221,6 @@ export function claudeModelReference( }); } -/** - * Models that support structured outputs in the beta API. - * @see https://docs.anthropic.com/en/docs/build-with-claude/structured-outputs - */ -const STRUCTURED_OUTPUT_MODELS = new Set([ - 'claude-sonnet-4-5', - 'claude-opus-4-1', -]); - /** * Defines a Claude model with the given name and Anthropic client. * Accepts any model name and lets the API validate it. If the model is in KNOWN_CLAUDE_MODELS, uses that modelRef @@ -231,18 +242,6 @@ export function claudeModel( : GENERIC_CLAUDE_MODEL_INFO; const configSchema = knownModelRef?.configSchema ?? AnthropicConfigSchema; - // Enhance model info with structured output support when using beta API - if (apiVersion === 'beta' && STRUCTURED_OUTPUT_MODELS.has(name)) { - modelInfo = { - ...modelInfo, - supports: { - ...modelInfo?.supports, - output: ['text', 'json'], - constrained: 'all', - }, - }; - } - return model< AnthropicBaseConfigSchemaType | AnthropicThinkingConfigSchemaType >( diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 73f8757d37..65bcc1bc53 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -89,15 +89,6 @@ const BETA_APIS = [ 'structured-outputs-2025-11-13', ]; -/** - * Models that support structured outputs (JSON schema). - * See: https://docs.anthropic.com/en/docs/build-with-claude/structured-outputs - */ -const STRUCTURED_OUTPUT_MODELS = new Set([ - 'claude-sonnet-4-5', - 'claude-opus-4-1', -]); - /** * Transforms a JSON schema to be compatible with Anthropic's structured output requirements. * Anthropic requires `additionalProperties: false` on all object types. @@ -341,15 +332,19 @@ export class BetaRunner extends BaseRunner { } // Apply structured output when model supports it and constrained output is requested + + // TODO: factor out into a helper function? and make it cleaner const useStructuredOutput = - STRUCTURED_OUTPUT_MODELS.has(modelName) && - request.output?.constrained && - request.output?.schema; + request.output !== undefined && + request.output.schema !== undefined && + request.output.constrained && + request.output?.schema !== undefined && + request.output?.format === 'json'; if (useStructuredOutput) { body.output_format = { type: 'json_schema', - schema: toAnthropicSchema(request.output.schema), + schema: toAnthropicSchema(request.output!.schema!), }; } @@ -418,15 +413,18 @@ export class BetaRunner extends BaseRunner { } // Apply structured output when model supports it and constrained output is requested + // TODO: factor out into a helper function? and make it cleaner const useStructuredOutput = - STRUCTURED_OUTPUT_MODELS.has(modelName) && + request.output !== undefined && + request.output.schema !== undefined && request.output?.constrained && - request.output?.schema; + request.output?.schema !== undefined && + request.output?.format === 'json'; if (useStructuredOutput) { body.output_format = { type: 'json_schema', - schema: toAnthropicSchema(request.output.schema), + schema: toAnthropicSchema(request.output!.schema!), }; } diff --git a/js/plugins/anthropic/tests/live_test.ts b/js/plugins/anthropic/tests/live_test.ts index 5f95beddd8..bf249bd6a6 100644 --- a/js/plugins/anthropic/tests/live_test.ts +++ b/js/plugins/anthropic/tests/live_test.ts @@ -21,6 +21,7 @@ import { anthropic } from '../src/index.js'; const SKIP_LIVE_TESTS = !process.env.ANTHROPIC_API_KEY; +// TODO: clean this test up a little bit describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { it('should return structured output matching the schema', async () => { const ai = genkit({ @@ -31,13 +32,18 @@ describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { name: z.string(), age: z.number(), city: z.string(), + isStudent: z.boolean(), + isEmployee: z.boolean(), + isRetired: z.boolean(), + isUnemployed: z.boolean(), + isDisabled: z.boolean(), }); const result = await ai.generate({ model: 'anthropic/claude-sonnet-4-5', prompt: 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', - output: { schema }, + output: { schema, format: 'json', constrained: true }, }); const parsed = result.output; @@ -45,5 +51,11 @@ describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { assert.strictEqual(parsed.name, 'Alice'); assert.strictEqual(parsed.age, 30); assert.strictEqual(parsed.city, 'New York'); + // assert the others are NOT undefined + assert.notStrictEqual(parsed.isStudent, undefined); + assert.notStrictEqual(parsed.isEmployee, undefined); + assert.notStrictEqual(parsed.isRetired, undefined); + assert.notStrictEqual(parsed.isUnemployed, undefined); + assert.notStrictEqual(parsed.isDisabled, undefined); }); }); diff --git a/js/plugins/anthropic/tests/mocks/anthropic-client.ts b/js/plugins/anthropic/tests/mocks/anthropic-client.ts index 321df8f24f..e2dd4a7458 100644 --- a/js/plugins/anthropic/tests/mocks/anthropic-client.ts +++ b/js/plugins/anthropic/tests/mocks/anthropic-client.ts @@ -366,6 +366,7 @@ export function mockMessageWithContent( } function toBetaMessage(message: Message): BetaMessage { + // @ts-ignore return { ...message, container: null, diff --git a/js/plugins/anthropic/tests/structured_output_test.ts b/js/plugins/anthropic/tests/structured_output_test.ts new file mode 100644 index 0000000000..585e8a3de2 --- /dev/null +++ b/js/plugins/anthropic/tests/structured_output_test.ts @@ -0,0 +1,307 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from 'assert'; +import { genkit, z } from 'genkit'; +import { describe, test } from 'node:test'; +import { anthropic } from '../src/index.js'; +import { __testClient } from '../src/types.js'; +import { + createMockAnthropicClient, + createMockAnthropicMessage, +} from './mocks/anthropic-client.js'; + +describe('Structured Output Tests', () => { + test('should pass output_format to API when using beta API with constrained output', async () => { + // Set up mock client to return a mock response + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: '{"name":"Alice","age":30,"city":"New York","isStudent":false,"isEmployee":true,"isRetired":false,"isUnemployed":false,"isDisabled":false}', + }), + }); + + // Set up plugin with beta API enabled + const plugin = anthropic({ + apiKey: 'test-key', + apiVersion: 'beta', + // @ts-ignore + [__testClient]: mockClient, + }); + + // Create Genkit instance with the plugin + const ai = genkit({ + plugins: [plugin], + }); + + // Call generate with sonnet 4.5 (supports native constrained output) + await ai.generate({ + model: 'anthropic/claude-sonnet-4-5', + prompt: + 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', + output: { + schema: z.object({ + name: z.string(), + age: z.number(), + city: z.string(), + isStudent: z.boolean(), + isEmployee: z.boolean(), + isRetired: z.boolean(), + isUnemployed: z.boolean(), + isDisabled: z.boolean(), + }), + format: 'json', + constrained: true, + }, + }); + + // Verify the beta API was called with output_format + const betaCreateStub = mockClient.beta.messages.create as any; + assert.strictEqual( + betaCreateStub.mock.calls.length, + 1, + 'Beta API should be called once' + ); + + const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; + assert.ok(apiRequest.output_format, 'Request should have output_format'); + assert.strictEqual( + apiRequest.output_format.type, + 'json_schema', + 'output_format type should be json_schema' + ); + assert.ok( + apiRequest.output_format.schema, + 'output_format should have schema' + ); + + // Verify schema transformation: additionalProperties should be false + assert.strictEqual( + apiRequest.output_format.schema.additionalProperties, + false, + 'Schema should have additionalProperties: false' + ); + }); + + // TODO: finish off this test suite + // test('should NOT pass output_format when constrained is false', async () => { + // const mockClient = createMockAnthropicClient({ + // messageResponse: createMockAnthropicMessage({ + // text: '{"name":"Alice"}', + // }), + // }); + + // const plugin = anthropic({ + // apiKey: 'test-key', + // apiVersion: 'beta', + // // @ts-ignore + // [__testClient]: mockClient, + // }); + + // // @ts-ignore + // const modelAction = plugin.resolve( + // 'model', + // 'claude-3-5-sonnet-20241022' + // ) as ModelAction; + + // const request: GenerateRequest = { + // messages: [ + // { + // role: 'user', + // content: [{ text: 'Generate JSON' }], + // }, + // ], + // output: { + // format: 'json', + // constrained: false, + // schema: { + // type: 'object', + // properties: { + // name: { type: 'string' }, + // }, + // }, + // }, + // }; + + // await modelAction(request, { + // streamingRequested: false, + // sendChunk: mock.fn(), + // abortSignal: new AbortController().signal, + // }); + + // const betaCreateStub = mockClient.beta.messages.create as any; + // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; + // assert.strictEqual( + // apiRequest.output_format, + // undefined, + // 'Request should NOT have output_format when constrained is false' + // ); + // }); + + // test('should NOT pass output_format when using stable API', async () => { + // const mockClient = createMockAnthropicClient({ + // messageResponse: createMockAnthropicMessage({ + // text: '{"name":"Alice","age":30,"city":"New York"}', + // }), + // }); + + // const plugin = anthropic({ + // apiKey: 'test-key', + // apiVersion: 'stable', + // // @ts-ignore + // [__testClient]: mockClient, + // }); + + // const modelAction = plugin.resolve( + // 'model', + // 'claude-3-5-sonnet-20241022' + // ) as ModelAction; + + // const request: GenerateRequest = { + // messages: [ + // { + // role: 'user', + // content: [{ text: 'Generate JSON' }], + // }, + // ], + // output: { + // format: 'json', + // constrained: true, + // schema: { + // type: 'object', + // properties: { + // name: { type: 'string' }, + // age: { type: 'number' }, + // city: { type: 'string' }, + // }, + // }, + // }, + // }; + + // await modelAction(request, { + // streamingRequested: false, + // sendChunk: mock.fn(), + // abortSignal: new AbortController().signal, + // }); + + // // Stable API should be called, not beta + // const stableCreateStub = mockClient.messages.create as any; + // assert.strictEqual( + // stableCreateStub.mock.calls.length, + // 1, + // 'Stable API should be called once' + // ); + + // const apiRequest = stableCreateStub.mock.calls[0].arguments[0]; + // assert.strictEqual( + // apiRequest.output_format, + // undefined, + // 'Stable API request should NOT have output_format' + // ); + // }); + + // test('should NOT pass output_format when format is not json', async () => { + // const mockClient = createMockAnthropicClient({ + // messageResponse: createMockAnthropicMessage({ + // text: 'Some text response', + // }), + // }); + + // const plugin = anthropic({ + // apiKey: 'test-key', + // apiVersion: 'beta', + // [__testClient]: mockClient, + // }); + + // const modelAction = plugin.resolve( + // 'model', + // 'claude-3-5-sonnet-20241022' + // ) as ModelAction; + + // const request: GenerateRequest = { + // messages: [ + // { + // role: 'user', + // content: [{ text: 'Generate text' }], + // }, + // ], + // output: { + // format: 'text', + // constrained: true, + // }, + // }; + + // await modelAction(request, { + // streamingRequested: false, + // sendChunk: mock.fn(), + // abortSignal: new AbortController().signal, + // }); + + // const betaCreateStub = mockClient.beta.messages.create as any; + // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; + // assert.strictEqual( + // apiRequest.output_format, + // undefined, + // 'Request should NOT have output_format when format is text' + // ); + // }); + + // test('should NOT pass output_format when schema is not provided', async () => { + // const mockClient = createMockAnthropicClient({ + // messageResponse: createMockAnthropicMessage({ + // text: '{"anything": "goes"}', + // }), + // }); + + // const plugin = anthropic({ + // apiKey: 'test-key', + // apiVersion: 'beta', + // [__testClient]: mockClient, + // }); + + // const modelAction = plugin.resolve( + // 'model', + // 'claude-3-5-sonnet-20241022' + // ) as ModelAction; + + // const request: GenerateRequest = { + // messages: [ + // { + // role: 'user', + // content: [{ text: 'Generate JSON' }], + // }, + // ], + // output: { + // format: 'json', + // constrained: true, + // // No schema provided + // }, + // }; + + // await modelAction(request, { + // streamingRequested: false, + // sendChunk: mock.fn(), + // abortSignal: new AbortController().signal, + // }); + + // const betaCreateStub = mockClient.beta.messages.create as any; + // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; + // assert.strictEqual( + // apiRequest.output_format, + // undefined, + // 'Request should NOT have output_format when schema is not provided' + // ); + // }); +}); From 30f65ae509fe44ffae6f72a31045340f6d946352 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Wed, 3 Dec 2025 18:25:20 +0000 Subject: [PATCH 05/30] fix(anthropic): fix and add tests --- .../anthropic/tests/structured_output_test.ts | 509 ++++++++++-------- 1 file changed, 280 insertions(+), 229 deletions(-) diff --git a/js/plugins/anthropic/tests/structured_output_test.ts b/js/plugins/anthropic/tests/structured_output_test.ts index 585e8a3de2..9a1e31fcd5 100644 --- a/js/plugins/anthropic/tests/structured_output_test.ts +++ b/js/plugins/anthropic/tests/structured_output_test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type Anthropic from '@anthropic-ai/sdk'; import * as assert from 'assert'; import { genkit, z } from 'genkit'; import { describe, test } from 'node:test'; @@ -24,9 +25,89 @@ import { createMockAnthropicMessage, } from './mocks/anthropic-client.js'; +/** + * Test constants for consistent test setup + */ +const TEST_API_KEY = 'test-key'; +const SUPPORTING_MODEL = 'anthropic/claude-sonnet-4-5'; +const NON_SUPPORTING_MODEL = 'anthropic/claude-sonnet-4'; + +/** + * Options for creating a plugin with a mock client + */ +interface CreatePluginOptions { + apiVersion?: 'beta' | 'stable'; + mockClient: Anthropic; +} + +/** + * Creates an Anthropic plugin configured with a mock client for testing + */ +function createPlugin(options: CreatePluginOptions) { + return anthropic({ + apiKey: TEST_API_KEY, + apiVersion: options.apiVersion, + // @ts-ignore + [__testClient]: options.mockClient, + }); +} + +/** + * Creates a Genkit instance with the given plugin + */ +function createGenkitInstance(plugin: ReturnType) { + return genkit({ + plugins: [plugin], + }); +} + +/** + * Helper to get the proper create stub from the mock client for a given API version. + */ +function getCreateStub(mockClient: Anthropic, apiVersion: 'beta' | 'stable') { + return apiVersion === 'beta' + ? (mockClient.beta.messages.create as any) + : (mockClient.messages.create as any); +} + +/** + * Extracts the API request object from the mock for verification + * @param apiVersion - 'beta' or 'stable' to determine which API endpoint to check + */ +function getApiRequest( + mockClient: Anthropic, + apiVersion: 'beta' | 'stable', + callIndex: number = 0 +) { + const stub = getCreateStub(mockClient, apiVersion); + return stub.mock.calls[callIndex]?.arguments[0]; +} + +/** + * Verifies that the API was called the expected number of times + * @param apiVersion - 'beta' or 'stable' to determine which API endpoint to verify + */ +function verifyApiCalled( + mockClient: Anthropic, + apiVersion: 'beta' | 'stable', + expectedCalls: number = 1 +) { + const stub = getCreateStub(mockClient, apiVersion); + assert.strictEqual( + stub.mock.calls.length, + expectedCalls, + `${apiVersion === 'beta' ? 'Beta' : 'Stable'} API should be called ${expectedCalls} time(s)` + ); +} + +/** + * Tests for structured output (constrained generation) functionality. + * These tests verify that output_format is correctly passed to the Anthropic API + * when using the beta API with constrained output, and that it's NOT passed + * in various edge cases (stable API, non-json format, missing schema, etc.) + */ describe('Structured Output Tests', () => { test('should pass output_format to API when using beta API with constrained output', async () => { - // Set up mock client to return a mock response const mockClient = createMockAnthropicClient({ messageResponse: createMockAnthropicMessage({ text: '{"name":"Alice","age":30,"city":"New York","isStudent":false,"isEmployee":true,"isRetired":false,"isUnemployed":false,"isDisabled":false}', @@ -34,21 +115,16 @@ describe('Structured Output Tests', () => { }); // Set up plugin with beta API enabled - const plugin = anthropic({ - apiKey: 'test-key', + const plugin = createPlugin({ apiVersion: 'beta', - // @ts-ignore - [__testClient]: mockClient, + mockClient, }); - // Create Genkit instance with the plugin - const ai = genkit({ - plugins: [plugin], - }); + const ai = createGenkitInstance(plugin); // Call generate with sonnet 4.5 (supports native constrained output) await ai.generate({ - model: 'anthropic/claude-sonnet-4-5', + model: SUPPORTING_MODEL, prompt: 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', output: { @@ -67,15 +143,11 @@ describe('Structured Output Tests', () => { }, }); - // Verify the beta API was called with output_format - const betaCreateStub = mockClient.beta.messages.create as any; - assert.strictEqual( - betaCreateStub.mock.calls.length, - 1, - 'Beta API should be called once' - ); + // Verify the beta API was called + verifyApiCalled(mockClient, 'beta'); - const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; + // Verify output_format was included in the API request + const apiRequest = getApiRequest(mockClient, 'beta'); assert.ok(apiRequest.output_format, 'Request should have output_format'); assert.strictEqual( apiRequest.output_format.type, @@ -86,8 +158,7 @@ describe('Structured Output Tests', () => { apiRequest.output_format.schema, 'output_format should have schema' ); - - // Verify schema transformation: additionalProperties should be false + // Verify schema transformation: additionalProperties should be false for constrained output assert.strictEqual( apiRequest.output_format.schema.additionalProperties, false, @@ -95,213 +166,193 @@ describe('Structured Output Tests', () => { ); }); - // TODO: finish off this test suite - // test('should NOT pass output_format when constrained is false', async () => { - // const mockClient = createMockAnthropicClient({ - // messageResponse: createMockAnthropicMessage({ - // text: '{"name":"Alice"}', - // }), - // }); - - // const plugin = anthropic({ - // apiKey: 'test-key', - // apiVersion: 'beta', - // // @ts-ignore - // [__testClient]: mockClient, - // }); - - // // @ts-ignore - // const modelAction = plugin.resolve( - // 'model', - // 'claude-3-5-sonnet-20241022' - // ) as ModelAction; - - // const request: GenerateRequest = { - // messages: [ - // { - // role: 'user', - // content: [{ text: 'Generate JSON' }], - // }, - // ], - // output: { - // format: 'json', - // constrained: false, - // schema: { - // type: 'object', - // properties: { - // name: { type: 'string' }, - // }, - // }, - // }, - // }; - - // await modelAction(request, { - // streamingRequested: false, - // sendChunk: mock.fn(), - // abortSignal: new AbortController().signal, - // }); - - // const betaCreateStub = mockClient.beta.messages.create as any; - // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; - // assert.strictEqual( - // apiRequest.output_format, - // undefined, - // 'Request should NOT have output_format when constrained is false' - // ); - // }); - - // test('should NOT pass output_format when using stable API', async () => { - // const mockClient = createMockAnthropicClient({ - // messageResponse: createMockAnthropicMessage({ - // text: '{"name":"Alice","age":30,"city":"New York"}', - // }), - // }); - - // const plugin = anthropic({ - // apiKey: 'test-key', - // apiVersion: 'stable', - // // @ts-ignore - // [__testClient]: mockClient, - // }); - - // const modelAction = plugin.resolve( - // 'model', - // 'claude-3-5-sonnet-20241022' - // ) as ModelAction; - - // const request: GenerateRequest = { - // messages: [ - // { - // role: 'user', - // content: [{ text: 'Generate JSON' }], - // }, - // ], - // output: { - // format: 'json', - // constrained: true, - // schema: { - // type: 'object', - // properties: { - // name: { type: 'string' }, - // age: { type: 'number' }, - // city: { type: 'string' }, - // }, - // }, - // }, - // }; - - // await modelAction(request, { - // streamingRequested: false, - // sendChunk: mock.fn(), - // abortSignal: new AbortController().signal, - // }); - - // // Stable API should be called, not beta - // const stableCreateStub = mockClient.messages.create as any; - // assert.strictEqual( - // stableCreateStub.mock.calls.length, - // 1, - // 'Stable API should be called once' - // ); - - // const apiRequest = stableCreateStub.mock.calls[0].arguments[0]; - // assert.strictEqual( - // apiRequest.output_format, - // undefined, - // 'Stable API request should NOT have output_format' - // ); - // }); - - // test('should NOT pass output_format when format is not json', async () => { - // const mockClient = createMockAnthropicClient({ - // messageResponse: createMockAnthropicMessage({ - // text: 'Some text response', - // }), - // }); - - // const plugin = anthropic({ - // apiKey: 'test-key', - // apiVersion: 'beta', - // [__testClient]: mockClient, - // }); - - // const modelAction = plugin.resolve( - // 'model', - // 'claude-3-5-sonnet-20241022' - // ) as ModelAction; - - // const request: GenerateRequest = { - // messages: [ - // { - // role: 'user', - // content: [{ text: 'Generate text' }], - // }, - // ], - // output: { - // format: 'text', - // constrained: true, - // }, - // }; - - // await modelAction(request, { - // streamingRequested: false, - // sendChunk: mock.fn(), - // abortSignal: new AbortController().signal, - // }); - - // const betaCreateStub = mockClient.beta.messages.create as any; - // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; - // assert.strictEqual( - // apiRequest.output_format, - // undefined, - // 'Request should NOT have output_format when format is text' - // ); - // }); - - // test('should NOT pass output_format when schema is not provided', async () => { - // const mockClient = createMockAnthropicClient({ - // messageResponse: createMockAnthropicMessage({ - // text: '{"anything": "goes"}', - // }), - // }); - - // const plugin = anthropic({ - // apiKey: 'test-key', - // apiVersion: 'beta', - // [__testClient]: mockClient, - // }); - - // const modelAction = plugin.resolve( - // 'model', - // 'claude-3-5-sonnet-20241022' - // ) as ModelAction; - - // const request: GenerateRequest = { - // messages: [ - // { - // role: 'user', - // content: [{ text: 'Generate JSON' }], - // }, - // ], - // output: { - // format: 'json', - // constrained: true, - // // No schema provided - // }, - // }; - - // await modelAction(request, { - // streamingRequested: false, - // sendChunk: mock.fn(), - // abortSignal: new AbortController().signal, - // }); - - // const betaCreateStub = mockClient.beta.messages.create as any; - // const apiRequest = betaCreateStub.mock.calls[0].arguments[0]; - // assert.strictEqual( - // apiRequest.output_format, - // undefined, - // 'Request should NOT have output_format when schema is not provided' - // ); - // }); + test('should NOT pass output_format to API when constrained is false and using beta API', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: '{"name":"Alice"}', + }), + }); + + // Set up plugin with beta API enabled + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + // Call generate with constrained: false + await ai.generate({ + model: SUPPORTING_MODEL, + prompt: 'Generate JSON', + output: { + format: 'json', + constrained: false, + schema: z.object({ + name: z.string(), + }), + }, + }); + + // Verify the beta API was called + verifyApiCalled(mockClient, 'beta'); + + // Verify output_format was NOT included when constrained is false + const apiRequest = getApiRequest(mockClient, 'beta'); + assert.strictEqual( + apiRequest.output_format, + undefined, + 'Request should NOT have output_format when constrained is false' + ); + }); + + test('should NOT pass output_format to API when format is not json and using beta API', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: 'Some text response', + }), + }); + + // Set up plugin with beta API enabled + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + // Call generate with format: 'text' (not 'json') + await ai.generate({ + model: SUPPORTING_MODEL, + prompt: 'Generate text', + output: { + format: 'text', + constrained: true, + }, + }); + + // Verify the beta API was called + verifyApiCalled(mockClient, 'beta'); + + // Verify output_format was NOT included when format is not json + const apiRequest = getApiRequest(mockClient, 'beta'); + assert.strictEqual( + apiRequest.output_format, + undefined, + 'Request should NOT have output_format when format is text' + ); + }); + + test('should NOT pass output_format to API when schema is not provided and using beta API', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: '{"anything": "goes"}', + }), + }); + + // Set up plugin with beta API enabled + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + // Call generate with constrained: true but no schema + await ai.generate({ + model: SUPPORTING_MODEL, + prompt: 'Generate JSON', + output: { + format: 'json', + constrained: true, + // No schema provided + }, + }); + + // Verify the beta API was called + verifyApiCalled(mockClient, 'beta'); + + // Verify output_format was NOT included when schema is missing + const apiRequest = getApiRequest(mockClient, 'beta'); + assert.strictEqual( + apiRequest.output_format, + undefined, + 'Request should NOT have output_format when schema is not provided' + ); + }); + + test('should NOT pass output_format to API when model does not support structured output and using beta API', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: '{"name":"Alice"}', + }), + }); + + // Set up plugin with beta API enabled + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + // Call generate with model that does not support structured output + await ai.generate({ + model: NON_SUPPORTING_MODEL, + prompt: 'Generate JSON', + output: { + format: 'json', + constrained: true, + }, + }); + + // Verify the beta API was called + verifyApiCalled(mockClient, 'beta'); + + // Verify output_format was NOT included when model does not support structured output + const apiRequest = getApiRequest(mockClient, 'beta'); + assert.strictEqual( + apiRequest.output_format, + undefined, + 'Request should NOT have output_format when model does not support structured output' + ); + }); + + test('should throw an error when using stable API with non-text output format', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: '{"name":"Alice","age":30,"city":"New York"}', + }), + }); + + // Set up plugin with stable API (not beta) + const plugin = createPlugin({ + apiVersion: 'stable', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + // Call generate with constrained output (would work with beta API) + // Expect an error to be thrown since only text output is supported for stable API + await assert.rejects( + async () => { + await ai.generate({ + model: SUPPORTING_MODEL, + prompt: 'Generate JSON', + output: { + format: 'json', + constrained: true, + schema: z.object({ + name: z.string(), + age: z.number(), + city: z.string(), + }), + }, + }); + }, + /Only text output format is supported for Claude models currently/, + 'Should throw an error for non-text output on stable API' + ); + }); }); From 5366cc48bb4f19cb76e988aaeb3de68c80be20b9 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Thu, 4 Dec 2025 15:21:38 +0000 Subject: [PATCH 06/30] refactor(anthropic): beta api addition moved --- js/plugins/anthropic/src/runner/beta.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 65bcc1bc53..8291353456 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -304,6 +304,7 @@ export class BetaRunner extends BaseRunner { max_tokens: request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, + betas: BETA_APIS, }; if (betaSystem !== undefined) body.system = betaSystem; @@ -348,8 +349,6 @@ export class BetaRunner extends BaseRunner { }; } - body.betas = BETA_APIS; - return body; } @@ -385,6 +384,7 @@ export class BetaRunner extends BaseRunner { request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, stream: true, + betas: BETA_APIS, }; if (betaSystem !== undefined) body.system = betaSystem; @@ -428,8 +428,6 @@ export class BetaRunner extends BaseRunner { }; } - body.betas = BETA_APIS; - return body; } From ccde30aa06785e769318103193f8b611c5695eed Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Thu, 4 Dec 2025 15:23:10 +0000 Subject: [PATCH 07/30] chore(anthropic): remove some comments --- js/plugins/anthropic/src/runner/beta.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 8291353456..2a085fdfb2 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -332,9 +332,6 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } - // Apply structured output when model supports it and constrained output is requested - - // TODO: factor out into a helper function? and make it cleaner const useStructuredOutput = request.output !== undefined && request.output.schema !== undefined && From ba9b86a0d6c26932d1a19803c6fd33ac6e8de023 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Thu, 4 Dec 2025 15:33:38 +0000 Subject: [PATCH 08/30] refactor(anthropic): clean code a bit --- js/plugins/anthropic/src/runner/beta.ts | 29 ++++++++++--------------- js/plugins/anthropic/tests/live_test.ts | 26 ++++++++++++---------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 2a085fdfb2..92ad7c2598 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -332,14 +332,8 @@ export class BetaRunner extends BaseRunner { body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; } - const useStructuredOutput = - request.output !== undefined && - request.output.schema !== undefined && - request.output.constrained && - request.output?.schema !== undefined && - request.output?.format === 'json'; - - if (useStructuredOutput) { + // Apply structured output when model supports it and constrained output is requested + if (this.isStructuredOutputEnabled(request)) { body.output_format = { type: 'json_schema', schema: toAnthropicSchema(request.output!.schema!), @@ -410,21 +404,12 @@ export class BetaRunner extends BaseRunner { } // Apply structured output when model supports it and constrained output is requested - // TODO: factor out into a helper function? and make it cleaner - const useStructuredOutput = - request.output !== undefined && - request.output.schema !== undefined && - request.output?.constrained && - request.output?.schema !== undefined && - request.output?.format === 'json'; - - if (useStructuredOutput) { + if (this.isStructuredOutputEnabled(request)) { body.output_format = { type: 'json_schema', schema: toAnthropicSchema(request.output!.schema!), }; } - return body; } @@ -561,4 +546,12 @@ export class BetaRunner extends BaseRunner { return 'other'; } } + + private isStructuredOutputEnabled(request: GenerateRequest): boolean { + return !!( + request.output?.schema && + request.output.constrained && + request.output.format === 'json' + ); + } } diff --git a/js/plugins/anthropic/tests/live_test.ts b/js/plugins/anthropic/tests/live_test.ts index bf249bd6a6..287413351f 100644 --- a/js/plugins/anthropic/tests/live_test.ts +++ b/js/plugins/anthropic/tests/live_test.ts @@ -21,7 +21,6 @@ import { anthropic } from '../src/index.js'; const SKIP_LIVE_TESTS = !process.env.ANTHROPIC_API_KEY; -// TODO: clean this test up a little bit describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { it('should return structured output matching the schema', async () => { const ai = genkit({ @@ -41,21 +40,24 @@ describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { const result = await ai.generate({ model: 'anthropic/claude-sonnet-4-5', - prompt: - 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', + prompt: 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', output: { schema, format: 'json', constrained: true }, }); const parsed = result.output; assert.ok(parsed, 'Should have parsed output'); - assert.strictEqual(parsed.name, 'Alice'); - assert.strictEqual(parsed.age, 30); - assert.strictEqual(parsed.city, 'New York'); - // assert the others are NOT undefined - assert.notStrictEqual(parsed.isStudent, undefined); - assert.notStrictEqual(parsed.isEmployee, undefined); - assert.notStrictEqual(parsed.isRetired, undefined); - assert.notStrictEqual(parsed.isUnemployed, undefined); - assert.notStrictEqual(parsed.isDisabled, undefined); + assert.deepStrictEqual( + { name: parsed.name, age: parsed.age, city: parsed.city }, + { name: 'Alice', age: 30, city: 'New York' } + ); + + // Check that boolean fields are present and are actually booleans + for (const key of ['isStudent', 'isEmployee', 'isRetired', 'isUnemployed', 'isDisabled']) { + assert.strictEqual( + typeof parsed[key], + 'boolean', + `Field ${key} should be a boolean but got: ${typeof parsed[key]}` + ); + } }); }); From 17abcd7c42f51917355cb680f01a33955df151cf Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Mon, 8 Dec 2025 08:31:14 +0000 Subject: [PATCH 09/30] feat(testapps/anthropic): add testapp for structured outputs --- js/testapps/anthropic/package.json | 1 + .../anthropic/src/beta/structured_output.ts | 85 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 js/testapps/anthropic/src/beta/structured_output.ts diff --git a/js/testapps/anthropic/package.json b/js/testapps/anthropic/package.json index 08e1a0d2fd..fd54741017 100644 --- a/js/testapps/anthropic/package.json +++ b/js/testapps/anthropic/package.json @@ -10,6 +10,7 @@ "start:beta": "node lib/beta/basic.js", "dev:stable": "genkit start -- npx tsx --watch src/stable/basic.ts", "dev:beta": "genkit start -- npx tsx --watch src/beta/basic.ts", + "dev:beta:structured-output": "genkit start -- npx tsx --watch src/beta/structured_output.ts", "dev:stable:text-plain": "genkit start -- npx tsx --watch src/stable/text-plain.ts", "dev:stable:webp": "genkit start -- npx tsx --watch src/stable/webp.ts", "dev:stable:pdf": "genkit start -- npx tsx --watch src/stable/pdf.ts", diff --git a/js/testapps/anthropic/src/beta/structured_output.ts b/js/testapps/anthropic/src/beta/structured_output.ts new file mode 100644 index 0000000000..725c9a0681 --- /dev/null +++ b/js/testapps/anthropic/src/beta/structured_output.ts @@ -0,0 +1,85 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { anthropic } from '@genkit-ai/anthropic'; +import { genkit, z } from 'genkit'; + +const ai = genkit({ + plugins: [ + // Default all flows in this sample to the beta surface + anthropic({ + apiVersion: 'beta', + cacheSystemPrompt: true, + apiKey: process.env.ANTHROPIC_API_KEY, + }), + ], +}); + +const betaSonnet = anthropic.model('claude-sonnet-4-5', { apiVersion: 'beta' }); + +ai.defineFlow('anthropic-beta-generate-person-json', async () => { + const { text } = await ai.generate({ + model: betaSonnet, + prompt: + 'Generate a fictional person with a random name, random age, and random city.', + config: { temperature: 0.6 }, + output: { + schema: z.object({ + name: z.string(), + age: z.number(), + city: z.string(), + }), + format: 'json', + constrained: true, + }, + }); + + return text; +}); + +ai.defineFlow( + 'anthropic-beta-generate-person-json-stream', + async (_, { sendChunk }) => { + const { stream } = ai.generateStream({ + model: betaSonnet, + prompt: [ + { + text: 'Generate a fictional person with a random name, random age, and random city.', + }, + ], + config: { temperature: 0.6 }, + output: { + schema: z.object({ + name: z.string(), + age: z.number(), + city: z.string(), + }), + format: 'json', + constrained: true, + }, + }); + + const collected: string[] = []; + for await (const chunk of stream) { + if (chunk.text) { + collected.push(chunk.text); + sendChunk(chunk.text); + } + } + + return collected.join(''); + } +); From a221d2126b9cb4f2928d3638af465e972d84aaf9 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Mon, 8 Dec 2025 08:35:22 +0000 Subject: [PATCH 10/30] chore: format --- js/plugins/anthropic/src/runner/beta.ts | 4 +++- js/plugins/anthropic/tests/live_test.ts | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 92ad7c2598..9fd7a306a1 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -547,7 +547,9 @@ export class BetaRunner extends BaseRunner { } } - private isStructuredOutputEnabled(request: GenerateRequest): boolean { + private isStructuredOutputEnabled( + request: GenerateRequest + ): boolean { return !!( request.output?.schema && request.output.constrained && diff --git a/js/plugins/anthropic/tests/live_test.ts b/js/plugins/anthropic/tests/live_test.ts index 287413351f..ae83a4d4fc 100644 --- a/js/plugins/anthropic/tests/live_test.ts +++ b/js/plugins/anthropic/tests/live_test.ts @@ -40,7 +40,8 @@ describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { const result = await ai.generate({ model: 'anthropic/claude-sonnet-4-5', - prompt: 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', + prompt: + 'Generate a fictional person with name "Alice", age 30, and city "New York". Return only the JSON.', output: { schema, format: 'json', constrained: true }, }); @@ -52,7 +53,13 @@ describe('Anthropic Live Tests', { skip: SKIP_LIVE_TESTS }, () => { ); // Check that boolean fields are present and are actually booleans - for (const key of ['isStudent', 'isEmployee', 'isRetired', 'isUnemployed', 'isDisabled']) { + for (const key of [ + 'isStudent', + 'isEmployee', + 'isRetired', + 'isUnemployed', + 'isDisabled', + ]) { assert.strictEqual( typeof parsed[key], 'boolean', From a0f3a6de76565b2dcf1506956fb89ed8c3b79661 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Mon, 8 Dec 2025 13:23:42 +0000 Subject: [PATCH 11/30] refactor(anthropic): body request simplified and allowed additional params --- js/plugins/anthropic/src/runner/beta.ts | 123 ++++++++++------------ js/plugins/anthropic/src/runner/stable.ts | 107 ++++++++----------- js/plugins/anthropic/src/types.ts | 2 +- 3 files changed, 98 insertions(+), 134 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 9fd7a306a1..86451317a8 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -299,47 +299,41 @@ export class BetaRunner extends BaseRunner { : system; } + const thinkingConfig = this.toAnthropicThinkingConfig( + request.config?.thinking + ) as BetaMessageCreateParams['thinking'] | undefined; + + const { thinking: defaultThinkingConfig, ...restConfig } = + request.config || {}; + const body: BetaMessageCreateParamsNonStreaming = { model: mappedModelName, max_tokens: request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, - betas: BETA_APIS, + system: betaSystem, + stop_sequences: request.config?.stopSequences, + temperature: request.config?.temperature, + top_k: request.config?.topK, + top_p: request.config?.topP, + tool_choice: request.config?.tool_choice, + metadata: request.config?.metadata, + tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), + thinking: + (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? + thinkingConfig, + output_format: this.isStructuredOutputEnabled(request) + ? { + type: 'json_schema', + schema: toAnthropicSchema(request.output!.schema!), + } + : undefined, + betas: Array.isArray(request.config?.betas) + ? [...BETA_APIS, ...(request.config?.betas ?? [])] + : [...BETA_APIS], + ...restConfig, }; - if (betaSystem !== undefined) body.system = betaSystem; - if (request.config?.stopSequences !== undefined) - body.stop_sequences = request.config.stopSequences; - if (request.config?.temperature !== undefined) - body.temperature = request.config.temperature; - if (request.config?.topK !== undefined) body.top_k = request.config.topK; - if (request.config?.topP !== undefined) body.top_p = request.config.topP; - if (request.config?.tool_choice !== undefined) { - body.tool_choice = request.config - .tool_choice as BetaMessageCreateParams['tool_choice']; - } - if (request.config?.metadata !== undefined) { - body.metadata = request.config - .metadata as BetaMessageCreateParams['metadata']; - } - if (request.tools) { - body.tools = request.tools.map((tool) => this.toAnthropicTool(tool)); - } - const thinkingConfig = this.toAnthropicThinkingConfig( - request.config?.thinking - ); - if (thinkingConfig) { - body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; - } - - // Apply structured output when model supports it and constrained output is requested - if (this.isStructuredOutputEnabled(request)) { - body.output_format = { - type: 'json_schema', - schema: toAnthropicSchema(request.output!.schema!), - }; - } - return body; } @@ -369,47 +363,42 @@ export class BetaRunner extends BaseRunner { ] : system; + const thinkingConfig = this.toAnthropicThinkingConfig( + request.config?.thinking + ) as BetaMessageCreateParams['thinking'] | undefined; + + const { thinking: defaultThinkingConfig, ...restConfig } = + request.config || {}; + const body: BetaMessageCreateParamsStreaming = { model: mappedModelName, max_tokens: request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, stream: true, - betas: BETA_APIS, + system: betaSystem, + stop_sequences: request.config?.stopSequences, + temperature: request.config?.temperature, + top_k: request.config?.topK, + top_p: request.config?.topP, + tool_choice: request.config?.tool_choice, + metadata: request.config?.metadata, + tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), + thinking: + (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? + thinkingConfig, + output_format: this.isStructuredOutputEnabled(request) + ? { + type: 'json_schema', + schema: toAnthropicSchema(request.output!.schema!), + } + : undefined, + betas: Array.isArray(request.config?.betas) + ? [...BETA_APIS, ...(request.config?.betas ?? [])] + : [...BETA_APIS], + ...restConfig, }; - if (betaSystem !== undefined) body.system = betaSystem; - if (request.config?.stopSequences !== undefined) - body.stop_sequences = request.config.stopSequences; - if (request.config?.temperature !== undefined) - body.temperature = request.config.temperature; - if (request.config?.topK !== undefined) body.top_k = request.config.topK; - if (request.config?.topP !== undefined) body.top_p = request.config.topP; - if (request.config?.tool_choice !== undefined) { - body.tool_choice = request.config - .tool_choice as BetaMessageCreateParams['tool_choice']; - } - if (request.config?.metadata !== undefined) { - body.metadata = request.config - .metadata as BetaMessageCreateParams['metadata']; - } - if (request.tools) { - body.tools = request.tools.map((tool) => this.toAnthropicTool(tool)); - } - const thinkingConfig = this.toAnthropicThinkingConfig( - request.config?.thinking - ); - if (thinkingConfig) { - body.thinking = thinkingConfig as BetaMessageCreateParams['thinking']; - } - - // Apply structured output when model supports it and constrained output is requested - if (this.isStructuredOutputEnabled(request)) { - body.output_format = { - type: 'json_schema', - schema: toAnthropicSchema(request.output!.schema!), - }; - } return body; } diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 0c8f7ffc4f..08fda1ee00 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -16,11 +16,11 @@ import { MessageStream } from '@anthropic-ai/sdk/lib/MessageStream.js'; import type { + MessageCreateParams as BetaMessageCreateParams, ContentBlock, DocumentBlockParam, ImageBlockParam, Message, - MessageCreateParams, MessageCreateParamsNonStreaming, MessageCreateParamsStreaming, MessageParam, @@ -197,50 +197,38 @@ export class Runner extends BaseRunner { ] : system; + const thinkingConfig = this.toAnthropicThinkingConfig( + request.config?.thinking + ) as BetaMessageCreateParams['thinking'] | undefined; + + const { thinking: defaultThinkingConfig, ...restConfig } = + request.config || {}; + const body: MessageCreateParamsNonStreaming = { model: mappedModelName, max_tokens: request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, + system: systemValue, + stop_sequences: request.config?.stopSequences, + temperature: request.config?.temperature, + top_k: request.config?.topK, + top_p: request.config?.topP, + tool_choice: request.config?.tool_choice, + metadata: request.config?.metadata, + tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), + thinking: + (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? + thinkingConfig, + ...restConfig, }; - if (systemValue !== undefined) { - body.system = systemValue; - } - - if (request.tools) { - body.tools = request.tools.map((tool) => this.toAnthropicTool(tool)); - } - if (request.config?.topK !== undefined) { - body.top_k = request.config.topK; - } - if (request.config?.topP !== undefined) { - body.top_p = request.config.topP; - } - if (request.config?.temperature !== undefined) { - body.temperature = request.config.temperature; - } - if (request.config?.stopSequences !== undefined) { - body.stop_sequences = request.config.stopSequences; - } - if (request.config?.metadata !== undefined) { - body.metadata = request.config.metadata; - } - if (request.config?.tool_choice !== undefined) { - body.tool_choice = request.config.tool_choice; - } - const thinkingConfig = this.toAnthropicThinkingConfig( - request.config?.thinking - ); - if (thinkingConfig) { - body.thinking = thinkingConfig as MessageCreateParams['thinking']; - } - if (request.output?.format && request.output.format !== 'text') { throw new Error( `Only text output format is supported for Claude models currently` ); } + return body; } @@ -267,52 +255,39 @@ export class Runner extends BaseRunner { ] : system; + const thinkingConfig = this.toAnthropicThinkingConfig( + request.config?.thinking + ) as BetaMessageCreateParams['thinking'] | undefined; + + const { thinking: defaultThinkingConfig, ...restConfig } = + request.config || {}; + const body: MessageCreateParamsStreaming = { model: mappedModelName, max_tokens: request.config?.maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS, messages, stream: true, + system: systemValue, + stop_sequences: request.config?.stopSequences, + temperature: request.config?.temperature, + top_k: request.config?.topK, + top_p: request.config?.topP, + tool_choice: request.config?.tool_choice, + metadata: request.config?.metadata, + tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), + thinking: + (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? + thinkingConfig, + ...restConfig, }; - if (systemValue !== undefined) { - body.system = systemValue; - } - - if (request.tools) { - body.tools = request.tools.map((tool) => this.toAnthropicTool(tool)); - } - if (request.config?.topK !== undefined) { - body.top_k = request.config.topK; - } - if (request.config?.topP !== undefined) { - body.top_p = request.config.topP; - } - if (request.config?.temperature !== undefined) { - body.temperature = request.config.temperature; - } - if (request.config?.stopSequences !== undefined) { - body.stop_sequences = request.config.stopSequences; - } - if (request.config?.metadata !== undefined) { - body.metadata = request.config.metadata; - } - if (request.config?.tool_choice !== undefined) { - body.tool_choice = request.config.tool_choice; - } - const thinkingConfig = this.toAnthropicThinkingConfig( - request.config?.thinking - ); - if (thinkingConfig) { - body.thinking = - thinkingConfig as MessageCreateParamsStreaming['thinking']; - } - if (request.output?.format && request.output.format !== 'text') { throw new Error( `Only text output format is supported for Claude models currently` ); } + return body; } diff --git a/js/plugins/anthropic/src/types.ts b/js/plugins/anthropic/src/types.ts index 9796d71c36..0e83f15f97 100644 --- a/js/plugins/anthropic/src/types.ts +++ b/js/plugins/anthropic/src/types.ts @@ -86,7 +86,7 @@ export const AnthropicBaseConfigSchema = GenerationCommonConfigSchema.extend({ .optional(), /** Optional shorthand to pick API surface for this request. */ apiVersion: z.enum(['stable', 'beta']).optional(), -}); +}).passthrough(); export type AnthropicBaseConfigSchemaType = typeof AnthropicBaseConfigSchema; From b85f6757bd7dc33b855912a8a664f6779d45a0c1 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 9 Dec 2025 12:33:28 +0000 Subject: [PATCH 12/30] feat(testapps/anthropic): add test app for additional params --- js/testapps/anthropic/package.json | 1 + .../anthropic/src/beta/additional_params.ts | 83 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 js/testapps/anthropic/src/beta/additional_params.ts diff --git a/js/testapps/anthropic/package.json b/js/testapps/anthropic/package.json index 08e1a0d2fd..56a2ffc613 100644 --- a/js/testapps/anthropic/package.json +++ b/js/testapps/anthropic/package.json @@ -10,6 +10,7 @@ "start:beta": "node lib/beta/basic.js", "dev:stable": "genkit start -- npx tsx --watch src/stable/basic.ts", "dev:beta": "genkit start -- npx tsx --watch src/beta/basic.ts", + "dev:beta:additional-params": "genkit start -- npx tsx --watch src/beta/additional_params.ts", "dev:stable:text-plain": "genkit start -- npx tsx --watch src/stable/text-plain.ts", "dev:stable:webp": "genkit start -- npx tsx --watch src/stable/webp.ts", "dev:stable:pdf": "genkit start -- npx tsx --watch src/stable/pdf.ts", diff --git a/js/testapps/anthropic/src/beta/additional_params.ts b/js/testapps/anthropic/src/beta/additional_params.ts new file mode 100644 index 0000000000..2e443fc01a --- /dev/null +++ b/js/testapps/anthropic/src/beta/additional_params.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { anthropic } from '@genkit-ai/anthropic'; +import { genkit } from 'genkit'; + +const ai = genkit({ + plugins: [ + // Default all flows in this sample to the beta surface + anthropic({ + apiVersion: 'beta', + cacheSystemPrompt: true, + apiKey: process.env.ANTHROPIC_API_KEY, + }), + ], +}); + +const betaOpus45 = anthropic.model('claude-opus-4-5', { apiVersion: 'beta' }); + +ai.defineFlow('anthropic-beta-additional-params', async () => { + const { text } = await ai.generate({ + model: betaOpus45, + prompt: + 'You are Claude on the beta API. Provide a concise greeting that mentions that you are using the beta API.', + config: { + temperature: 0.6, + // Additional param (not directly supported by the plugin, but can be passed through to the API) + betas: ['effort-2025-11-24'], + // Additional param (not directly supported by the plugin, but can be passed through to the API) + output_config: { + effort: 'medium', + }, + }, + }); + + return text; +}); + +ai.defineFlow( + 'anthropic-beta-additional-params-stream', + async (_, { sendChunk }) => { + const { stream } = ai.generateStream({ + model: betaOpus45, + prompt: [ + { + text: 'Outline two experimental capabilities unlocked by the Anthropic beta API.', + }, + ], + config: { + temperature: 0.4, + // Additional param (not directly supported by the plugin, but can be passed through to the API) + betas: ['effort-2025-11-24'], + // Additional param (not directly supported by the plugin, but can be passed through to the API) + output_config: { + effort: 'medium', + }, + }, + }); + + const collected: string[] = []; + for await (const chunk of stream) { + if (chunk.text) { + collected.push(chunk.text); + sendChunk(chunk.text); + } + } + + return collected.join(''); + } +); From 806bb09938e1cda4c5d2e8c8252420a0d2c84c0e Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 9 Dec 2025 12:33:50 +0000 Subject: [PATCH 13/30] fix(anthropic): sending wrong properties to Anthropic --- js/plugins/anthropic/src/runner/beta.ts | 38 +++++++++++---- js/plugins/anthropic/src/runner/stable.ts | 58 +++++++++++++++-------- js/plugins/anthropic/src/types.ts | 46 +++++++++++++----- 3 files changed, 99 insertions(+), 43 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 86451317a8..42d71c1f39 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -303,8 +303,17 @@ export class BetaRunner extends BaseRunner { request.config?.thinking ) as BetaMessageCreateParams['thinking'] | undefined; - const { thinking: defaultThinkingConfig, ...restConfig } = - request.config || {}; + // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body + // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. + // Thinking is extracted separately to avoid type issues. + // ApiVersion is extracted separately as it's not a valid property for the Anthropic API. + const { + topP, + topK, + apiVersion: _, + thinking: defaultThinkingConfig, + ...restConfig + } = request.config ?? {}; const body: BetaMessageCreateParamsNonStreaming = { model: mappedModelName, @@ -314,8 +323,8 @@ export class BetaRunner extends BaseRunner { system: betaSystem, stop_sequences: request.config?.stopSequences, temperature: request.config?.temperature, - top_k: request.config?.topK, - top_p: request.config?.topP, + top_k: topK, + top_p: topP, tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), @@ -329,7 +338,7 @@ export class BetaRunner extends BaseRunner { } : undefined, betas: Array.isArray(request.config?.betas) - ? [...BETA_APIS, ...(request.config?.betas ?? [])] + ? [...(request.config?.betas ?? [])] : [...BETA_APIS], ...restConfig, }; @@ -367,8 +376,17 @@ export class BetaRunner extends BaseRunner { request.config?.thinking ) as BetaMessageCreateParams['thinking'] | undefined; - const { thinking: defaultThinkingConfig, ...restConfig } = - request.config || {}; + // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body + // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. + // Thinking is extracted separately to avoid type issues. + // ApiVersion is extracted separately as it's not a valid property for the Anthropic API. + const { + topP, + topK, + apiVersion: _, + thinking: defaultThinkingConfig, + ...restConfig + } = request.config ?? {}; const body: BetaMessageCreateParamsStreaming = { model: mappedModelName, @@ -379,8 +397,8 @@ export class BetaRunner extends BaseRunner { system: betaSystem, stop_sequences: request.config?.stopSequences, temperature: request.config?.temperature, - top_k: request.config?.topK, - top_p: request.config?.topP, + top_k: topK, + top_p: topP, tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), @@ -394,7 +412,7 @@ export class BetaRunner extends BaseRunner { } : undefined, betas: Array.isArray(request.config?.betas) - ? [...BETA_APIS, ...(request.config?.betas ?? [])] + ? [...(request.config?.betas ?? [])] : [...BETA_APIS], ...restConfig, }; diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 08fda1ee00..3a86288f24 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -179,6 +179,12 @@ export class Runner extends BaseRunner { request: GenerateRequest, cacheSystemPrompt?: boolean ): MessageCreateParamsNonStreaming { + if (request.output?.format && request.output.format !== 'text') { + throw new Error( + `Only text output format is supported for Claude models currently` + ); + } + const model = KNOWN_CLAUDE_MODELS[modelName]; const { system, messages } = this.toAnthropicMessages(request.messages); const mappedModelName = @@ -201,8 +207,17 @@ export class Runner extends BaseRunner { request.config?.thinking ) as BetaMessageCreateParams['thinking'] | undefined; - const { thinking: defaultThinkingConfig, ...restConfig } = - request.config || {}; + // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body + // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. + // Thinking is extracted separately to avoid type issues. + // ApiVersion is extracted separately as it's not a valid property for the Anthropic API. + const { + topP, + topK, + apiVersion: _, + thinking: defaultThinkingConfig, + ...restConfig + } = request.config ?? {}; const body: MessageCreateParamsNonStreaming = { model: mappedModelName, @@ -212,8 +227,8 @@ export class Runner extends BaseRunner { system: systemValue, stop_sequences: request.config?.stopSequences, temperature: request.config?.temperature, - top_k: request.config?.topK, - top_p: request.config?.topP, + top_k: topK, + top_p: topP, tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), @@ -223,12 +238,6 @@ export class Runner extends BaseRunner { ...restConfig, }; - if (request.output?.format && request.output.format !== 'text') { - throw new Error( - `Only text output format is supported for Claude models currently` - ); - } - return body; } @@ -237,6 +246,12 @@ export class Runner extends BaseRunner { request: GenerateRequest, cacheSystemPrompt?: boolean ): MessageCreateParamsStreaming { + if (request.output?.format && request.output.format !== 'text') { + throw new Error( + `Only text output format is supported for Claude models currently` + ); + } + const model = KNOWN_CLAUDE_MODELS[modelName]; const { system, messages } = this.toAnthropicMessages(request.messages); const mappedModelName = @@ -259,8 +274,17 @@ export class Runner extends BaseRunner { request.config?.thinking ) as BetaMessageCreateParams['thinking'] | undefined; - const { thinking: defaultThinkingConfig, ...restConfig } = - request.config || {}; + // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body + // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. + // Thinking is extracted separately to avoid type issues. + // ApiVersion is extracted separately as it's not a valid property for the Anthropic API. + const { + topP, + topK, + apiVersion: _, + thinking: defaultThinkingConfig, + ...restConfig + } = request.config ?? {}; const body: MessageCreateParamsStreaming = { model: mappedModelName, @@ -271,8 +295,8 @@ export class Runner extends BaseRunner { system: systemValue, stop_sequences: request.config?.stopSequences, temperature: request.config?.temperature, - top_k: request.config?.topK, - top_p: request.config?.topP, + top_k: topK, + top_p: topP, tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), @@ -282,12 +306,6 @@ export class Runner extends BaseRunner { ...restConfig, }; - if (request.output?.format && request.output.format !== 'text') { - throw new Error( - `Only text output format is supported for Claude models currently` - ); - } - return body; } diff --git a/js/plugins/anthropic/src/types.ts b/js/plugins/anthropic/src/types.ts index 0e83f15f97..5947bc1a52 100644 --- a/js/plugins/anthropic/src/types.ts +++ b/js/plugins/anthropic/src/types.ts @@ -67,25 +67,41 @@ export interface ClaudeRunnerParams extends ClaudeHelperParamsBase {} export const AnthropicBaseConfigSchema = GenerationCommonConfigSchema.extend({ tool_choice: z .union([ - z.object({ - type: z.literal('auto'), - }), - z.object({ - type: z.literal('any'), - }), - z.object({ - type: z.literal('tool'), - name: z.string(), - }), + z + .object({ + type: z.literal('auto'), + }) + .passthrough(), + z + .object({ + type: z.literal('any'), + }) + .passthrough(), + z + .object({ + type: z.literal('tool'), + name: z.string(), + }) + .passthrough(), ]) + .describe( + 'The tool choice to use for the request. This can be used to specify the tool to use for the request. If not specified, the model will choose the tool to use.' + ) .optional(), metadata: z .object({ user_id: z.string().optional(), }) + .describe('The metadata to include in the request.') + .passthrough() .optional(), /** Optional shorthand to pick API surface for this request. */ - apiVersion: z.enum(['stable', 'beta']).optional(), + apiVersion: z + .enum(['stable', 'beta']) + .optional() + .describe( + 'The API version to use for the request. Both stable and beta features are available on the beta API surface.' + ), }).passthrough(); export type AnthropicBaseConfigSchemaType = typeof AnthropicBaseConfigSchema; @@ -95,6 +111,8 @@ export const ThinkingConfigSchema = z enabled: z.boolean().optional(), budgetTokens: z.number().int().min(1_024).optional(), }) + .passthrough() + .passthrough() .superRefine((value, ctx) => { if (value.enabled && value.budgetTokens === undefined) { ctx.addIssue({ @@ -106,8 +124,10 @@ export const ThinkingConfigSchema = z }); export const AnthropicThinkingConfigSchema = AnthropicBaseConfigSchema.extend({ - thinking: ThinkingConfigSchema.optional(), -}); + thinking: ThinkingConfigSchema.optional().describe( + 'The thinking configuration to use for the request. Thinking is a feature that allows the model to think about the request and provide a better response.' + ), +}).passthrough(); export const AnthropicConfigSchema = AnthropicThinkingConfigSchema; From f849352abf2d5c3ae61eb6237f00fd1d6e60c396 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 9 Dec 2025 17:13:48 +0000 Subject: [PATCH 14/30] feat(anthropic): support structured outputs for Claude Haiku 4.5 --- js/plugins/anthropic/package.json | 2 +- js/plugins/anthropic/src/models.ts | 12 ++++++- js/pnpm-lock.yaml | 50 ++++++++++++++++++++---------- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/js/plugins/anthropic/package.json b/js/plugins/anthropic/package.json index 998296e1cf..b2262b0d7c 100644 --- a/js/plugins/anthropic/package.json +++ b/js/plugins/anthropic/package.json @@ -29,7 +29,7 @@ "genkit": "workspace:^" }, "dependencies": { - "@anthropic-ai/sdk": "^0.71.0" + "@anthropic-ai/sdk": "^0.71.2" }, "devDependencies": { "@types/node": "^20.11.16", diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index 1c5cb99d68..54225f2b24 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -95,7 +95,17 @@ export const KNOWN_CLAUDE_MODELS: Record< ), 'claude-haiku-4-5': commonRef( 'claude-haiku-4-5', - AnthropicThinkingConfigSchema + AnthropicThinkingConfigSchema, + { + supports: { + multiturn: true, + tools: true, + media: true, + systemRole: true, + output: ['text', 'json'], + constrained: 'all', + }, + } ), 'claude-opus-4-1': commonRef( 'claude-opus-4-1', diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 8ca620edda..2565d73c8c 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -153,6 +153,10 @@ importers: zod-to-json-schema: specifier: ^3.22.4 version: 3.24.5(zod@3.25.67) + optionalDependencies: + '@genkit-ai/firebase': + specifier: ^1.16.1 + version: 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.24.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)) devDependencies: '@types/express': specifier: ^4.17.21 @@ -178,10 +182,6 @@ importers: typescript: specifier: ^4.9.0 version: 4.9.5 - optionalDependencies: - '@genkit-ai/firebase': - specifier: ^1.16.1 - version: 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.24.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)) doc-snippets: dependencies: @@ -260,8 +260,8 @@ importers: plugins/anthropic: dependencies: '@anthropic-ai/sdk': - specifier: ^0.71.0 - version: 0.71.0(zod@3.25.67) + specifier: ^0.71.2 + version: 0.71.2(zod@3.25.67) devDependencies: '@types/node': specifier: ^20.11.16 @@ -961,7 +961,7 @@ importers: version: 0.24.3(encoding@0.1.13) '@anthropic-ai/vertex-sdk': specifier: ^0.4.0 - version: 0.4.3(encoding@0.1.13) + version: 0.4.3(encoding@0.1.13)(zod@3.25.67) '@google-cloud/aiplatform': specifier: ^3.23.0 version: 3.35.0(encoding@0.1.13) @@ -986,6 +986,13 @@ importers: openai: specifier: ^4.52.7 version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) + optionalDependencies: + '@google-cloud/bigquery': + specifier: ^7.8.0 + version: 7.9.4(encoding@0.1.13) + firebase-admin: + specifier: '>=12.2' + version: 13.4.0(encoding@0.1.13) devDependencies: '@types/node': specifier: ^20.11.16 @@ -1017,13 +1024,6 @@ importers: typescript: specifier: ^4.9.0 version: 4.9.5 - optionalDependencies: - '@google-cloud/bigquery': - specifier: ^7.8.0 - version: 7.9.4(encoding@0.1.13) - firebase-admin: - specifier: '>=12.2' - version: 13.4.0(encoding@0.1.13) testapps/anthropic: dependencies: @@ -2101,6 +2101,15 @@ packages: zod: optional: true + '@anthropic-ai/sdk@0.71.2': + resolution: {integrity: sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==} + hasBin: true + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + '@anthropic-ai/sdk@0.9.1': resolution: {integrity: sha512-wa1meQ2WSfoY8Uor3EdrJq0jTiZJoKoSii2ZVWRY1oN4Tlr5s59pADg9T79FTbPe1/se5c3pBeZgJL63wmuoBA==} @@ -6564,6 +6573,7 @@ packages: next@15.3.3: resolution: {integrity: sha512-JqNj29hHNmCLtNvd090SyRbXJiivQ+58XjCcrC50Crb5g5u2zi7Y2YivbsEfzk6AtVI80akdOQbaMZwWB1Hthw==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + deprecated: This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/CVE-2025-66478 for more details. hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -7271,6 +7281,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -7937,6 +7948,12 @@ snapshots: optionalDependencies: zod: 3.25.67 + '@anthropic-ai/sdk@0.71.2(zod@3.25.67)': + dependencies: + json-schema-to-ts: 3.1.1 + optionalDependencies: + zod: 3.25.67 + '@anthropic-ai/sdk@0.9.1(encoding@0.1.13)': dependencies: '@types/node': 18.19.112 @@ -7951,13 +7968,14 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/vertex-sdk@0.4.3(encoding@0.1.13)': + '@anthropic-ai/vertex-sdk@0.4.3(encoding@0.1.13)(zod@3.25.67)': dependencies: - '@anthropic-ai/sdk': 0.24.3(encoding@0.1.13) + '@anthropic-ai/sdk': 0.71.0(zod@3.25.67) google-auth-library: 9.15.1(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color + - zod '@babel/code-frame@7.25.7': dependencies: From 14bfcde6c49fd191e6473bffcea4b66ed1549c39 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Wed, 10 Dec 2025 12:47:39 +0000 Subject: [PATCH 15/30] fix(anthropic): handling of thinking was incorrect. now removes undefined params to prevent possible issues --- js/plugins/anthropic/src/runner/beta.ts | 21 ++++++++----------- js/plugins/anthropic/src/runner/stable.ts | 22 +++++++++----------- js/plugins/anthropic/src/utils.ts | 25 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 js/plugins/anthropic/src/utils.ts diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 42d71c1f39..56fae83b9a 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -44,6 +44,7 @@ import { logger } from 'genkit/logging'; import { KNOWN_CLAUDE_MODELS, extractVersion } from '../models.js'; import { AnthropicConfigSchema, type ClaudeRunnerParams } from '../types.js'; +import { removeUndefinedProperties } from '../utils.js'; import { BaseRunner } from './base.js'; import { RunnerTypes } from './types.js'; @@ -310,8 +311,8 @@ export class BetaRunner extends BaseRunner { const { topP, topK, - apiVersion: _, - thinking: defaultThinkingConfig, + apiVersion: _1, + thinking: _2, ...restConfig } = request.config ?? {}; @@ -328,9 +329,7 @@ export class BetaRunner extends BaseRunner { tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), - thinking: - (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? - thinkingConfig, + thinking: thinkingConfig, output_format: this.isStructuredOutputEnabled(request) ? { type: 'json_schema', @@ -343,7 +342,7 @@ export class BetaRunner extends BaseRunner { ...restConfig, }; - return body; + return removeUndefinedProperties(body); } /** @@ -383,8 +382,8 @@ export class BetaRunner extends BaseRunner { const { topP, topK, - apiVersion: _, - thinking: defaultThinkingConfig, + apiVersion: _1, + thinking: _2, ...restConfig } = request.config ?? {}; @@ -402,9 +401,7 @@ export class BetaRunner extends BaseRunner { tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), - thinking: - (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? - thinkingConfig, + thinking: thinkingConfig, output_format: this.isStructuredOutputEnabled(request) ? { type: 'json_schema', @@ -417,7 +414,7 @@ export class BetaRunner extends BaseRunner { ...restConfig, }; - return body; + return removeUndefinedProperties(body); } protected toGenkitResponse(message: BetaMessage): GenerateResponseData { diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 3a86288f24..7ec0895774 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -42,8 +42,10 @@ import { logger } from 'genkit/logging'; import { KNOWN_CLAUDE_MODELS, extractVersion } from '../models.js'; import { AnthropicConfigSchema, type ClaudeRunnerParams } from '../types.js'; +import { removeUndefinedProperties } from '../utils.js'; import { BaseRunner } from './base.js'; import { RunnerTypes as BaseRunnerTypes } from './types.js'; + interface RunnerTypes extends BaseRunnerTypes { Message: Message; Stream: MessageStream; @@ -214,8 +216,8 @@ export class Runner extends BaseRunner { const { topP, topK, - apiVersion: _, - thinking: defaultThinkingConfig, + apiVersion: _1, + thinking: _2, ...restConfig } = request.config ?? {}; @@ -232,13 +234,11 @@ export class Runner extends BaseRunner { tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), - thinking: - (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? - thinkingConfig, + thinking: thinkingConfig, ...restConfig, }; - return body; + return removeUndefinedProperties(body); } protected toAnthropicStreamingRequestBody( @@ -281,8 +281,8 @@ export class Runner extends BaseRunner { const { topP, topK, - apiVersion: _, - thinking: defaultThinkingConfig, + apiVersion: _1, + thinking: _2, ...restConfig } = request.config ?? {}; @@ -300,13 +300,11 @@ export class Runner extends BaseRunner { tool_choice: request.config?.tool_choice, metadata: request.config?.metadata, tools: request.tools?.map((tool) => this.toAnthropicTool(tool)), - thinking: - (defaultThinkingConfig as BetaMessageCreateParams['thinking']) ?? - thinkingConfig, + thinking: thinkingConfig, ...restConfig, }; - return body; + return removeUndefinedProperties(body); } protected async createMessage( diff --git a/js/plugins/anthropic/src/utils.ts b/js/plugins/anthropic/src/utils.ts new file mode 100644 index 0000000000..6678eabc19 --- /dev/null +++ b/js/plugins/anthropic/src/utils.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function removeUndefinedProperties(obj: T): T { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + + return Object.fromEntries( + Object.entries(obj).filter(([_, value]) => value !== undefined) + ) as T; +} From 5a613e4424fdc3e763833e22edffdba5f2e05c1e Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Wed, 10 Dec 2025 18:40:26 +0000 Subject: [PATCH 16/30] fix(plugins/vertexai): VertexAI plugin's anthropic sdk version conflicting with Anthropic plugin's anthropic sdk version --- js/package.json | 5 ++++- js/pnpm-lock.yaml | 49 +++++++++++++++++------------------------------ 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/js/package.json b/js/package.json index 4250d1b142..1171a97a97 100644 --- a/js/package.json +++ b/js/package.json @@ -31,7 +31,10 @@ }, "pnpm": { "overrides": { - "cross-spawn": "^7.0.5" + "cross-spawn": "^7.0.5", + "@genkit-ai/vertexai>@anthropic-ai/sdk": "^0.24.3", + "@anthropic-ai/vertex-sdk>@anthropic-ai/sdk": "^0.24.3", + "@genkit-ai/anthropic>@anthropic-ai/sdk": "^0.71.2" } }, "packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b" diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 2565d73c8c..a6df405e34 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -6,6 +6,9 @@ settings: overrides: cross-spawn: ^7.0.5 + '@genkit-ai/vertexai>@anthropic-ai/sdk': ^0.24.3 + '@anthropic-ai/vertex-sdk>@anthropic-ai/sdk': ^0.24.3 + '@genkit-ai/anthropic>@anthropic-ai/sdk': ^0.71.2 importers: @@ -153,10 +156,6 @@ importers: zod-to-json-schema: specifier: ^3.22.4 version: 3.24.5(zod@3.25.67) - optionalDependencies: - '@genkit-ai/firebase': - specifier: ^1.16.1 - version: 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.24.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)) devDependencies: '@types/express': specifier: ^4.17.21 @@ -182,6 +181,10 @@ importers: typescript: specifier: ^4.9.0 version: 4.9.5 + optionalDependencies: + '@genkit-ai/firebase': + specifier: ^1.16.1 + version: 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.24.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.4.0(encoding@0.1.13))(firebase@11.9.1)) doc-snippets: dependencies: @@ -961,7 +964,7 @@ importers: version: 0.24.3(encoding@0.1.13) '@anthropic-ai/vertex-sdk': specifier: ^0.4.0 - version: 0.4.3(encoding@0.1.13)(zod@3.25.67) + version: 0.4.3(encoding@0.1.13) '@google-cloud/aiplatform': specifier: ^3.23.0 version: 3.35.0(encoding@0.1.13) @@ -986,13 +989,6 @@ importers: openai: specifier: ^4.52.7 version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) - optionalDependencies: - '@google-cloud/bigquery': - specifier: ^7.8.0 - version: 7.9.4(encoding@0.1.13) - firebase-admin: - specifier: '>=12.2' - version: 13.4.0(encoding@0.1.13) devDependencies: '@types/node': specifier: ^20.11.16 @@ -1024,6 +1020,13 @@ importers: typescript: specifier: ^4.9.0 version: 4.9.5 + optionalDependencies: + '@google-cloud/bigquery': + specifier: ^7.8.0 + version: 7.9.4(encoding@0.1.13) + firebase-admin: + specifier: '>=12.2' + version: 13.4.0(encoding@0.1.13) testapps/anthropic: dependencies: @@ -2092,15 +2095,6 @@ packages: '@anthropic-ai/sdk@0.24.3': resolution: {integrity: sha512-916wJXO6T6k8R6BAAcLhLPv/pnLGy7YSEBZXZ1XTFbLcTZE8oTy3oDW9WJf9KKZwMvVcePIfoTSvzXHRcGxkQQ==} - '@anthropic-ai/sdk@0.71.0': - resolution: {integrity: sha512-go1XeWXmpxuiTkosSXpb8tokLk2ZLkIRcXpbWVwJM6gH5OBtHOVsfPfGuqI1oW7RRt4qc59EmYbrXRZ0Ng06Jw==} - hasBin: true - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - peerDependenciesMeta: - zod: - optional: true - '@anthropic-ai/sdk@0.71.2': resolution: {integrity: sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==} hasBin: true @@ -7932,7 +7926,7 @@ snapshots: '@anthropic-ai/sdk@0.24.3(encoding@0.1.13)': dependencies: '@types/node': 18.19.112 - '@types/node-fetch': 2.6.11 + '@types/node-fetch': 2.6.12 abort-controller: 3.0.0 agentkeepalive: 4.5.0 form-data-encoder: 1.7.2 @@ -7942,12 +7936,6 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/sdk@0.71.0(zod@3.25.67)': - dependencies: - json-schema-to-ts: 3.1.1 - optionalDependencies: - zod: 3.25.67 - '@anthropic-ai/sdk@0.71.2(zod@3.25.67)': dependencies: json-schema-to-ts: 3.1.1 @@ -7968,14 +7956,13 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/vertex-sdk@0.4.3(encoding@0.1.13)(zod@3.25.67)': + '@anthropic-ai/vertex-sdk@0.4.3(encoding@0.1.13)': dependencies: - '@anthropic-ai/sdk': 0.71.0(zod@3.25.67) + '@anthropic-ai/sdk': 0.24.3(encoding@0.1.13) google-auth-library: 9.15.1(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color - - zod '@babel/code-frame@7.25.7': dependencies: From 077d86d51420af494c466a687426bbb1d4643ddf Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 13:41:12 +0000 Subject: [PATCH 17/30] fix(js/plugins/anthropic): cast in test mock --- js/plugins/anthropic/tests/mocks/anthropic-client.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/plugins/anthropic/tests/mocks/anthropic-client.ts b/js/plugins/anthropic/tests/mocks/anthropic-client.ts index e2dd4a7458..35742c76c2 100644 --- a/js/plugins/anthropic/tests/mocks/anthropic-client.ts +++ b/js/plugins/anthropic/tests/mocks/anthropic-client.ts @@ -366,7 +366,6 @@ export function mockMessageWithContent( } function toBetaMessage(message: Message): BetaMessage { - // @ts-ignore return { ...message, container: null, @@ -380,7 +379,7 @@ function toBetaMessage(message: Message): BetaMessage { server_tool_use: message.usage.server_tool_use as any, service_tier: message.usage.service_tier, }, - }; + } as BetaMessage; } function toBetaStreamEvent( From 6d6af62eabc83e6bd5a060a0529d4527ecbca86f Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 13:49:14 +0000 Subject: [PATCH 18/30] fix(js/plugins/anthropic): fix merge conflict in lockfile --- js/pnpm-lock.yaml | 77 ++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 955f090481..ef7cd9a5bc 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -184,7 +184,7 @@ importers: optionalDependencies: '@genkit-ai/firebase': specifier: ^1.16.1 - version: 1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + version: 1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) doc-snippets: dependencies: @@ -263,13 +263,8 @@ importers: plugins/anthropic: dependencies: '@anthropic-ai/sdk': -<<<<<<< HEAD specifier: ^0.71.2 - version: 0.71.2(zod@3.25.67) -======= - specifier: ^0.68.0 - version: 0.68.0(zod@3.25.76) ->>>>>>> public/main + version: 0.71.2(zod@3.25.76) devDependencies: '@types/node': specifier: ^20.11.16 @@ -1096,7 +1091,7 @@ importers: version: link:../../plugins/compat-oai '@genkit-ai/express': specifier: ^1.1.0 - version: 1.12.0(@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit) + version: 1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit) genkit: specifier: workspace:* version: link:../../genkit @@ -1713,7 +1708,7 @@ importers: version: link:../../plugins/ollama genkitx-openai: specifier: ^0.10.1 - version: 0.10.1(@genkit-ai/ai@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3) + version: 0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3) devDependencies: rimraf: specifier: ^6.0.1 @@ -2775,11 +2770,11 @@ packages: '@firebase/webchannel-wrapper@1.0.3': resolution: {integrity: sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==} - '@genkit-ai/ai@1.26.0-rc.0': - resolution: {integrity: sha512-TrNRK/fSuhM8XHOGAV6lDH9daGYfWCPyW55ZDtH3IeDAVNtfcvOhgmM+uvgtsvjKYeJiDHdwVQeabL1e9tzdYg==} + '@genkit-ai/ai@1.26.0': + resolution: {integrity: sha512-L6sX2pocyGQTJU77w/Y6DP/VfWEgD/WyFZL/P2RSxz/xr25/twbdPE45xzjP7KTaFHFhAAp+lOMYhvh9kEBS3g==} - '@genkit-ai/core@1.26.0-rc.0': - resolution: {integrity: sha512-ZnzyWLeb364csirXJusPKKV5i6ZqzsKHUc9ZKRGBSoPXkrz/w0hLGoPCFjCSbfm3DmRvC45/HOn3uEVtwkN2MA==} + '@genkit-ai/core@1.26.0': + resolution: {integrity: sha512-wLcfyWjRyDMeyIcx2De0Sl8P4MxuTVPdCyr7wSR4YZmLIOA02LrdhQXGPcx8Rh7N0z5IxUAxPZ5rVdsUitxIzA==} '@genkit-ai/express@1.12.0': resolution: {integrity: sha512-QAxSS07dX5ovSfsUB4s90KaDnv4zg1wnoxCZCa+jBsYUyv9NvCCTsOk25xAQgGxc7xi3+MD+3AsPier5oZILIg==} @@ -5956,8 +5951,8 @@ packages: resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} engines: {node: '>=18'} - genkit@1.26.0-rc.0: - resolution: {integrity: sha512-Yx4qtT0ImwE2Nu8ts1lrq4eL/qCa+vFmgNOWnCJLc205Vcco0yZEQ0Wr0OL3sBhIAyLuAfx6CCUPJE735ypTsg==} + genkit@1.26.0: + resolution: {integrity: sha512-+bfQWefF56mZU8RTH0zHwlXyreA1rMkEXBBb5mNqP1OVuv92F8eJWP80/8M+wvL8OeaxBiejtbGIjcepOJRgpA==} genkitx-openai@0.10.1: resolution: {integrity: sha512-E9/DzyQcBUSTy81xT2pvEmdnn9Q/cKoojEt6lD/EdOeinhqE9oa59d/kuXTokCMekTrj3Rk7LtNBQIDjnyjNOA==} @@ -9221,7 +9216,7 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/sdk@0.68.0(zod@3.25.76)': + '@anthropic-ai/sdk@0.71.2(zod@3.25.76)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: @@ -9952,9 +9947,9 @@ snapshots: '@firebase/webchannel-wrapper@1.0.3': {} - '@genkit-ai/ai@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: - '@genkit-ai/core': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) '@opentelemetry/api': 1.9.0 '@types/node': 20.19.26 colorette: 2.0.20 @@ -9973,9 +9968,9 @@ snapshots: - supports-color optional: true - '@genkit-ai/ai@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': + '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': dependencies: - '@genkit-ai/core': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) '@opentelemetry/api': 1.9.0 '@types/node': 20.19.26 colorette: 2.0.20 @@ -9993,7 +9988,7 @@ snapshots: - genkit - supports-color - '@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) @@ -10015,7 +10010,7 @@ snapshots: zod: 3.25.76 zod-to-json-schema: 3.25.0(zod@3.25.76) optionalDependencies: - '@genkit-ai/firebase': 1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/firebase': 1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) transitivePeerDependencies: - '@google-cloud/firestore' - encoding @@ -10025,7 +10020,7 @@ snapshots: - supports-color optional: true - '@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': + '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) @@ -10056,9 +10051,9 @@ snapshots: - genkit - supports-color - '@genkit-ai/express@1.12.0(@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit)': + '@genkit-ai/express@1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit)': dependencies: - '@genkit-ai/core': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) body-parser: 1.20.3 cors: 2.8.5 express: 5.1.0 @@ -10066,12 +10061,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@genkit-ai/firebase@1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/firebase@1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: - '@genkit-ai/google-cloud': 1.16.1(encoding@0.1.13)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/google-cloud': 1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) '@google-cloud/firestore': 7.11.6(encoding@0.1.13) firebase-admin: 13.5.0(encoding@0.1.13) - genkit: 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) optionalDependencies: firebase: 11.9.1 transitivePeerDependencies: @@ -10079,12 +10074,12 @@ snapshots: - supports-color optional: true - '@genkit-ai/firebase@1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/firebase@1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: - '@genkit-ai/google-cloud': 1.25.0(encoding@0.1.13)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/google-cloud': 1.25.0(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) '@google-cloud/firestore': 7.11.6(encoding@0.1.13) firebase-admin: 13.5.0(encoding@0.1.13) - genkit: 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) optionalDependencies: firebase: 11.9.1 transitivePeerDependencies: @@ -10105,7 +10100,7 @@ snapshots: - supports-color optional: true - '@genkit-ai/google-cloud@1.16.1(encoding@0.1.13)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/google-cloud@1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.17.0) '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) @@ -10121,7 +10116,7 @@ snapshots: '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - genkit: 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) google-auth-library: 9.15.1(encoding@0.1.13) node-fetch: 3.3.2 winston: 3.17.0 @@ -10130,7 +10125,7 @@ snapshots: - supports-color optional: true - '@genkit-ai/google-cloud@1.25.0(encoding@0.1.13)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/google-cloud@1.25.0(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.19.0) '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) @@ -10146,7 +10141,7 @@ snapshots: '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - genkit: 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) google-auth-library: 9.15.1(encoding@0.1.13) node-fetch: 3.3.2 winston: 3.19.0 @@ -13995,10 +13990,10 @@ snapshots: transitivePeerDependencies: - supports-color - genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1): + genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1): dependencies: - '@genkit-ai/ai': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) - '@genkit-ai/core': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) uuid: 10.0.0 transitivePeerDependencies: - '@google-cloud/firestore' @@ -14008,10 +14003,10 @@ snapshots: - supports-color optional: true - genkitx-openai@0.10.1(@genkit-ai/ai@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3): + genkitx-openai@0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3): dependencies: - '@genkit-ai/ai': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) - '@genkit-ai/core': 1.26.0-rc.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) zod: 3.25.67 transitivePeerDependencies: From ad234effd8875dc172637b31ae9c62b04541af57 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Thu, 4 Dec 2025 15:05:01 +0000 Subject: [PATCH 19/30] feat(anthropic): add files api --- js/plugins/anthropic/src/runner/beta.ts | 22 +- js/pnpm-lock.yaml | 1036 ++++------------- js/testapps/anthropic/package.json | 5 +- .../src/{stable => }/attention-first-page.pdf | Bin js/testapps/anthropic/src/beta/files_api.ts | 116 ++ js/testapps/anthropic/src/stable/pdf.ts | 2 +- 6 files changed, 384 insertions(+), 797 deletions(-) rename js/testapps/anthropic/src/{stable => }/attention-first-page.pdf (100%) create mode 100644 js/testapps/anthropic/src/beta/files_api.ts diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 9fd7a306a1..3c81431f0e 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -74,7 +74,7 @@ const BETA_APIS = [ // 'token-counting-2024-11-01', // 'token-efficient-tools-2025-02-19', // 'output-128k-2025-02-19', - // 'files-api-2025-04-14', + 'files-api-2025-04-14', // 'mcp-client-2025-04-04', // 'dev-full-thinking-2025-05-14', // 'interleaved-thinking-2025-05-14', @@ -190,6 +190,26 @@ export class BetaRunner extends BaseRunner { // Media if (part.media) { + if (part.media.contentType === 'file/document') { + return { + type: 'document', + source: { + type: 'file', + file_id: part.media.url, + }, + }; + } + + if (part.media.contentType === 'file/image') { + return { + type: 'image', + source: { + type: 'file', + file_id: part.media.url, + }, + }; + } + if (part.media.contentType === 'application/pdf') { return { type: 'document', diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index ef7cd9a5bc..ce58b1b38c 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -174,7 +174,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -184,7 +184,7 @@ importers: optionalDependencies: '@genkit-ai/firebase': specifier: ^1.16.1 - version: 1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + version: 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) doc-snippets: dependencies: @@ -202,7 +202,7 @@ importers: version: 5.0.0 firebase-functions: specifier: ^6.3.1 - version: 6.3.2(firebase-admin@13.5.0(encoding@0.1.13)) + version: 6.3.2(firebase-admin@13.6.0(encoding@0.1.13)) genkit: specifier: workspace:* version: link:../genkit @@ -252,7 +252,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -264,7 +264,7 @@ importers: dependencies: '@anthropic-ai/sdk': specifier: ^0.71.2 - version: 0.71.2(zod@3.25.76) + version: 0.71.2(zod@3.25.67) devDependencies: '@types/node': specifier: ^20.11.16 @@ -283,7 +283,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -317,7 +317,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.0.2 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.7.0 version: 4.20.3 @@ -329,7 +329,7 @@ importers: dependencies: chromadb: specifier: 1.8.1 - version: 1.8.1(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76)) + version: 1.8.1(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)) genkit: specifier: workspace:^ version: link:../../genkit @@ -348,7 +348,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -406,7 +406,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5)))(typescript@4.9.5) tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -421,7 +421,7 @@ importers: version: link:../../genkit openai: specifier: ^4.95.0 - version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) devDependencies: '@jest/globals': specifier: ^29.7.0 @@ -440,7 +440,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) tsup: specifier: ^8.0.2 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) typescript: specifier: ^5.4.5 version: 5.8.3 @@ -468,7 +468,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -508,7 +508,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -554,7 +554,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -572,7 +572,7 @@ importers: version: 7.11.1(encoding@0.1.13) firebase-admin: specifier: '>=12.2' - version: 13.5.0(encoding@0.1.13) + version: 13.4.0(encoding@0.1.13) devDependencies: '@jest/globals': specifier: ^29.7.0 @@ -606,7 +606,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5)))(typescript@4.9.5) tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -694,7 +694,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5)))(typescript@4.9.5) tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -734,7 +734,7 @@ importers: version: 21.0.0 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -768,7 +768,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -792,7 +792,7 @@ importers: version: link:../../genkit langchain: specifier: ^0.1.36 - version: 0.1.37(@google-cloud/storage@7.18.0(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(chromadb@1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)))(encoding@0.1.13)(fast-xml-parser@4.5.3)(firebase-admin@12.3.1(encoding@0.1.13))(google-auth-library@8.9.0(encoding@0.1.13))(handlebars@4.7.8)(ignore@5.3.1)(jsonwebtoken@9.0.2)(lodash@4.17.21)(pdf-parse@1.1.1)(pg@8.16.2)(ws@8.18.3) + version: 0.1.37(@google-cloud/storage@7.16.0(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(chromadb@1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)))(encoding@0.1.13)(fast-xml-parser@4.5.3)(firebase-admin@12.3.1(encoding@0.1.13))(google-auth-library@8.9.0(encoding@0.1.13))(handlebars@4.7.8)(ignore@5.3.1)(jsonwebtoken@9.0.2)(lodash@4.17.21)(pdf-parse@1.1.1)(pg@8.16.2)(ws@8.18.3) devDependencies: '@types/node': specifier: ^20.11.16 @@ -805,7 +805,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -848,7 +848,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -875,7 +875,7 @@ importers: version: 29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5)) next: specifier: ^15.4.10 - version: 15.4.10(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 15.5.9(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -887,7 +887,7 @@ importers: version: 29.4.0(@babel/core@7.25.7)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.7))(jest-util@29.7.0)(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5)))(typescript@4.9.5) tsup: specifier: ^8.0.2 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.7.0 version: 4.20.3 @@ -918,7 +918,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -949,7 +949,7 @@ importers: version: 6.0.1 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -973,7 +973,7 @@ importers: version: 1.10.0(encoding@0.1.13) '@mistralai/mistralai-gcp': specifier: ^1.3.5 - version: 1.5.0(encoding@0.1.13)(zod@3.25.76) + version: 1.5.0(encoding@0.1.13)(zod@3.25.67) genkit: specifier: workspace:^ version: link:../../genkit @@ -988,7 +988,7 @@ importers: version: 3.3.2 openai: specifier: ^4.52.7 - version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76) + version: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) devDependencies: '@types/node': specifier: ^20.11.16 @@ -1013,7 +1013,7 @@ importers: version: 21.0.0 tsup: specifier: ^8.3.5 - version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2) + version: 8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.0) tsx: specifier: ^4.19.2 version: 4.20.3 @@ -1026,16 +1026,22 @@ importers: version: 7.9.4(encoding@0.1.13) firebase-admin: specifier: '>=12.2' - version: 13.5.0(encoding@0.1.13) + version: 13.4.0(encoding@0.1.13) testapps/anthropic: dependencies: '@genkit-ai/anthropic': specifier: workspace:* version: link:../../plugins/anthropic + form-data: + specifier: ^4.0.5 + version: 4.0.5 genkit: specifier: workspace:* version: link:../../genkit + node-fetch: + specifier: ^3.3.2 + version: 3.3.2 devDependencies: cross-env: specifier: ^10.1.0 @@ -1075,7 +1081,7 @@ importers: version: 1.0.2 zod-to-json-schema: specifier: ^3.24.5 - version: 3.24.5(zod@3.25.76) + version: 3.24.5(zod@3.25.67) devDependencies: '@types/wav': specifier: ^1.0.4 @@ -1091,7 +1097,7 @@ importers: version: link:../../plugins/compat-oai '@genkit-ai/express': specifier: ^1.1.0 - version: 1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit) + version: 1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit) genkit: specifier: workspace:* version: link:../../genkit @@ -1302,7 +1308,7 @@ importers: version: 5.1.0 firebase-admin: specifier: ^13.5.0 - version: 13.5.0(encoding@0.1.13) + version: 13.6.0(encoding@0.1.13) genkit: specifier: workspace:^ version: link:../../genkit @@ -1622,7 +1628,7 @@ importers: version: 2025.7.1 '@modelcontextprotocol/server-filesystem': specifier: ^2025.3.28 - version: 2025.7.1(zod@3.25.76) + version: 2025.7.1(zod@3.25.67) '@types/express': specifier: ^4.17.21 version: 4.17.23 @@ -1677,7 +1683,7 @@ importers: version: link:../../genkit zod: specifier: ^3.22.4 - version: 3.25.76 + version: 3.25.67 devDependencies: tsx: specifier: ^4.7.1 @@ -1708,7 +1714,7 @@ importers: version: link:../../plugins/ollama genkitx-openai: specifier: ^0.10.1 - version: 0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3) + version: 0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3) devDependencies: rimraf: specifier: ^6.0.1 @@ -1828,7 +1834,7 @@ importers: version: link:../../genkit next: specifier: ^15.4.10 - version: 15.4.10(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 15.5.9(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) zod: specifier: ^3.24.1 version: 3.25.67 @@ -2354,9 +2360,6 @@ packages: '@dabh/diagnostics@2.0.3': resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - '@dabh/diagnostics@2.0.8': - resolution: {integrity: sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==} - '@electric-sql/pglite@0.2.17': resolution: {integrity: sha512-qEpKRT2oUaWDH6tjRxLHjdzMqRUGYDnGZlKrnL4dJ77JVMcP2Hpo3NYnOSPKdZdeec57B6QPprCUFg0picx5Pw==} @@ -2519,8 +2522,8 @@ packages: '@fastify/busboy@3.0.0': resolution: {integrity: sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==} - '@fastify/busboy@3.2.0': - resolution: {integrity: sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==} + '@fastify/busboy@3.1.1': + resolution: {integrity: sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==} '@firebase/ai@1.4.0': resolution: {integrity: sha512-wvF33gtU6TXb6Co8TEC1pcl4dnVstYmRE/vs9XjUGE7he7Sgf5TqSu+EoXk/fuzhw5tKr1LC5eG9KdYFM+eosw==} @@ -2628,9 +2631,6 @@ packages: '@firebase/database-types@1.0.14': resolution: {integrity: sha512-8a0Q1GrxM0akgF0RiQHliinhmZd+UQPrxEmUv7MnQBYfVFiLtKOgs3g6ghRt/WEGJHyQNslZ+0PocIwNfoDwKw==} - '@firebase/database-types@1.0.16': - resolution: {integrity: sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==} - '@firebase/database-types@1.0.6': resolution: {integrity: sha512-sMI7IynSZBsyGbUugc8PKE1jwKbnvaieAz/RxuM57PZQNCi6Rteiviwcw/jqZOX6igqYJwXWZ3UzKOZo2nUDRA==} @@ -2763,10 +2763,6 @@ packages: resolution: {integrity: sha512-Z4rK23xBCwgKDqmzGVMef+Vb4xso2j5Q8OG0vVL4m4fA5ZjPMYQazu8OJJC3vtQRC3SQ/Pgx/6TPNVsCd70QRw==} engines: {node: '>=18.0.0'} - '@firebase/util@1.13.0': - resolution: {integrity: sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==} - engines: {node: '>=20.0.0'} - '@firebase/webchannel-wrapper@1.0.3': resolution: {integrity: sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==} @@ -2794,27 +2790,11 @@ packages: firebase: optional: true - '@genkit-ai/firebase@1.25.0': - resolution: {integrity: sha512-Z0FbnJHQs8qS0yxG++Dn3CZ7gv+YNaihGaWXoDKy02mNOkeRzHA6UPaWxSTaWkWHYdB0MyOnMGlyqxnWyqVdmg==} - peerDependencies: - '@google-cloud/firestore': ^7.11.0 - firebase: '>=11.5.0' - firebase-admin: '>=12.2' - genkit: ^1.25.0 - peerDependenciesMeta: - firebase: - optional: true - '@genkit-ai/google-cloud@1.16.1': resolution: {integrity: sha512-uujjdGr/sra7iKHApufwkt5jGo7CQcRCJNWPgnSg4g179CjtvtZBGjxmFRVBtKzuF61ktkY6E9JoLz83nWEyAA==} peerDependencies: genkit: ^1.16.1 - '@genkit-ai/google-cloud@1.25.0': - resolution: {integrity: sha512-wHCa8JSTv7MtwzXjUQ9AT5v0kCTJrz0In+ffgAYw1yt8ComAz5o7Ir+xks+sX1vJfN8ptvW0GUa6rsUaXCB3kA==} - peerDependencies: - genkit: ^1.25.0 - '@gerrit0/mini-shiki@1.27.2': resolution: {integrity: sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==} @@ -2842,10 +2822,6 @@ packages: resolution: {integrity: sha512-ZxOdH8Wr01hBDvKCQfMWqwUcfNcN3JY19k1LtS1fTFhEyorYPLsbWN+VxIRL46pOYGHTPkU3Or5HbT/SLQM5nA==} engines: {node: '>=14.0.0'} - '@google-cloud/firestore@7.11.6': - resolution: {integrity: sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==} - engines: {node: '>=14.0.0'} - '@google-cloud/logging-winston@6.0.1': resolution: {integrity: sha512-tgA/qe/aGZITMrJ/5Tuykv234pLb/Qo6iDZ8SDkjbsiIy69mLQmbphrUd/IqnE17BSDfrwDUckvWdghiy8b+Qg==} engines: {node: '>=14.0.0'} @@ -2912,10 +2888,6 @@ packages: resolution: {integrity: sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw==} engines: {node: '>=14'} - '@google-cloud/storage@7.18.0': - resolution: {integrity: sha512-r3ZwDMiz4nwW6R922Z1pwpePxyRwE5GdevYX63hRmAQUkUQJcBH/79EnQPDv5cOv1mFBgevdNWQfi3tie3dHrQ==} - engines: {node: '>=14'} - '@google-cloud/vertexai@1.10.0': resolution: {integrity: sha512-HqYqoivNtkq59po8m7KI0n+lWKdz4kabENncYQXZCX/hBWJfXtKAfR/2nUQsP+TwSfHKoA7zDL2RrJYIv/j3VQ==} engines: {node: '>=18.0.0'} @@ -2953,8 +2925,8 @@ packages: resolution: {integrity: sha512-HPa/K5NX6ahMoeBv15njAc/sfF4/jmiXLar9UlC2UfHFKZzsCVLc3wbe7+7qua7w9VPh2/L6EBxyAV7/E8Wftg==} engines: {node: '>=12.10.0'} - '@grpc/grpc-js@1.14.2': - resolution: {integrity: sha512-QzVUtEFyu05UNx2xr0fCQmStUO17uVQhGNowtxs00IgTZT6/W2PBLfUkj30s0FKJ29VtTa3ArVNIhNP6akQhqA==} + '@grpc/grpc-js@1.14.3': + resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} engines: {node: '>=12.10.0'} '@grpc/grpc-js@1.9.15': @@ -3113,8 +3085,8 @@ packages: cpu: [x64] os: [win32] - '@inquirer/external-editor@1.0.2': - resolution: {integrity: sha512-yy9cOoBnx58TlsPrIxauKIFQTiyH+0MK4e97y4sV9ERbI+zDxw7i2hxHLCIEGIE/8PPvDxGhgzIOTSOWcs6/MQ==} + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} engines: {node: '>=18'} peerDependencies: '@types/node': '>=18' @@ -3222,9 +3194,6 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -3624,53 +3593,53 @@ packages: resolution: {integrity: sha512-92ybDocKl6JM48ZpYbj+A7Qt45IaTABDk0y3sDecEQfgdhfNzJtEityqNHoCZ4Vty2dldPkJhxgvOnbrQMXTTA==} engines: {node: '>= 10'} - '@next/env@15.4.10': - resolution: {integrity: sha512-knhmoJ0Vv7VRf6pZEPSnciUG1S4bIhWx+qTYBW/AjxEtlzsiNORPk8sFDCEvqLfmKuey56UB9FL1UdHEV3uBrg==} + '@next/env@15.5.9': + resolution: {integrity: sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==} - '@next/swc-darwin-arm64@15.4.8': - resolution: {integrity: sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A==} + '@next/swc-darwin-arm64@15.5.7': + resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.4.8': - resolution: {integrity: sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw==} + '@next/swc-darwin-x64@15.5.7': + resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.4.8': - resolution: {integrity: sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw==} + '@next/swc-linux-arm64-gnu@15.5.7': + resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.4.8': - resolution: {integrity: sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A==} + '@next/swc-linux-arm64-musl@15.5.7': + resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.4.8': - resolution: {integrity: sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA==} + '@next/swc-linux-x64-gnu@15.5.7': + resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.4.8': - resolution: {integrity: sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA==} + '@next/swc-linux-x64-musl@15.5.7': + resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.4.8': - resolution: {integrity: sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw==} + '@next/swc-win32-arm64-msvc@15.5.7': + resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.4.8': - resolution: {integrity: sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg==} + '@next/swc-win32-x64-msvc@15.5.7': + resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -4323,9 +4292,6 @@ packages: '@sinonjs/samsam@8.0.2': resolution: {integrity: sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==} - '@so-ric/colorspace@1.1.6': - resolution: {integrity: sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==} - '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -4336,8 +4302,8 @@ packages: '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@tsconfig/node10@1.0.12': - resolution: {integrity: sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==} + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} @@ -4397,15 +4363,9 @@ packages: '@types/express-serve-static-core@4.17.43': resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} - '@types/express-serve-static-core@4.19.7': - resolution: {integrity: sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==} - '@types/express@4.17.23': resolution: {integrity: sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==} - '@types/express@4.17.25': - resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/graceful-fs@4.1.9': resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} @@ -4419,9 +4379,6 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-errors@2.0.5': - resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -4476,18 +4433,9 @@ packages: '@types/node@20.19.1': resolution: {integrity: sha512-jJD50LtlD2dodAEO653i3YF04NWak6jN3ky+Ri3Em3mGR39/glWiboM/IePaRbgwSfqM1TpGXfAg8ohn/4dTgA==} - '@types/node@20.19.25': - resolution: {integrity: sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==} - - '@types/node@20.19.26': - resolution: {integrity: sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==} - '@types/node@22.15.32': resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==} - '@types/node@22.19.2': - resolution: {integrity: sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==} - '@types/pdf-parse@1.1.5': resolution: {integrity: sha512-kBfrSXsloMnUJOKi25s3+hRmkycHfLK6A09eRGqF/N8BkQoPUmaCr+q8Cli5FnfohEz/rsv82zAiPz/LXtOGhA==} @@ -4497,9 +4445,6 @@ packages: '@types/pg@8.6.1': resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} - '@types/qs@6.14.0': - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} - '@types/qs@6.9.14': resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} @@ -4518,15 +4463,6 @@ packages: '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - '@types/send@0.17.6': - resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} - - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - - '@types/serve-static@1.15.10': - resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} - '@types/serve-static@1.15.5': resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} @@ -4664,8 +4600,8 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.1.1: - resolution: {integrity: sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==} + ansi-escapes@7.2.0: + resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} engines: {node: '>=18'} ansi-regex@5.0.1: @@ -4804,8 +4740,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.8.1: - resolution: {integrity: sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ==} + bare-events@2.8.2: + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: @@ -4849,10 +4785,6 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@1.20.4: - resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@2.2.0: resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} engines: {node: '>=18'} @@ -4964,8 +4896,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001760: - resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==} + caniuse-lite@1.0.30001667: + resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -5111,34 +5043,18 @@ packages: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-convert@3.1.3: - resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==} - engines: {node: '>=14.6'} - color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - color-name@2.1.0: - resolution: {integrity: sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==} - engines: {node: '>=12.20'} - color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - color-string@2.1.4: - resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} - engines: {node: '>=18'} - color@3.2.1: resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} - color@5.0.3: - resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} - engines: {node: '>=18'} - colorette@2.0.19: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} @@ -5231,9 +5147,6 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - cookie-signature@1.0.7: - resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} - cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -5367,15 +5280,6 @@ packages: supports-color: optional: true - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} @@ -5481,9 +5385,6 @@ packages: dotprompt@1.1.1: resolution: {integrity: sha512-xll31JxDiE7FaF030t0Dx4EMSV60Qn/pONDn6Hs5bBBeEANbtqIu6fPfaAOoSNbF1Y9TK+pj9Xnvud7G7GHpaA==} - dotprompt@1.1.2: - resolution: {integrity: sha512-24EU+eORQbPywBicIP44BiqykzEXFwZq1ZQKO5TEr9KrrENyDA7I1NzqhtmmEdQVfAXka0DEbSLPN5nerCqJ8A==} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -5709,10 +5610,6 @@ packages: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} - express@4.22.1: - resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} - engines: {node: '>= 0.10.0'} - express@5.1.0: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} engines: {node: '>= 18'} @@ -5791,10 +5688,6 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} - finalhandler@1.3.2: - resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} - engines: {node: '>= 0.8'} - finalhandler@2.1.0: resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} engines: {node: '>= 0.8'} @@ -5814,8 +5707,8 @@ packages: resolution: {integrity: sha512-Y8DcyKK+4pl4B93ooiy1G8qvdyRMkcNFfBSh+8rbVcw4cW8dgG0VXCCTp5NUwub8sn9vSPsOwpb9tE2OuFmcfQ==} engines: {node: '>=18'} - firebase-admin@13.5.0: - resolution: {integrity: sha512-QZOpv1DJRJpH8NcWiL1xXE10tw3L/bdPFlgjcWrqU3ufyOJDYfxB1MMtxiVTwxK16NlybQbEM6ciSich2uWEIQ==} + firebase-admin@13.6.0: + resolution: {integrity: sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw==} engines: {node: '>=18'} firebase-functions@6.3.2: @@ -5862,8 +5755,8 @@ packages: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} - form-data@4.0.4: - resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} formdata-node@4.4.1: @@ -6026,8 +5919,8 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true glob@11.0.0: @@ -6191,10 +6084,6 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - http-parser-js@0.5.10: resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} @@ -6233,8 +6122,8 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.0: - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + iconv-lite@0.7.1: + resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} engines: {node: '>=0.10.0'} idb@7.1.1: @@ -6302,8 +6191,8 @@ packages: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} - ip-address@10.0.1: - resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} ip-regex@4.3.0: @@ -6796,9 +6685,6 @@ packages: jwa@2.0.0: resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} - jwa@2.0.1: - resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - jwks-rsa@3.1.0: resolution: {integrity: sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==} engines: {node: '>=14'} @@ -6813,9 +6699,6 @@ packages: jws@4.0.0: resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} - jws@4.0.1: - resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} - kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} engines: {node: '>=0.10.0'} @@ -7449,10 +7332,9 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - next@15.4.10: - resolution: {integrity: sha512-itVlc79QjpKMFMRhP+kbGKaSG/gZM6RCvwhEbwmCNF06CdDiNaoHcbeg0PqkEa2GOcn8KJ0nnc7+yL7EjoYLHQ==} + next@15.5.9: + resolution: {integrity: sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - deprecated: This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/CVE-2025-66478 for more details. hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 @@ -7500,10 +7382,6 @@ packages: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} - node-forge@1.3.3: - resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} - engines: {node: '>= 6.13.0'} - node-gyp@11.5.0: resolution: {integrity: sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==} engines: {node: ^18.17.0 || >=20.5.0} @@ -7649,8 +7527,8 @@ packages: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} - p-map@7.0.3: - resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} + p-map@7.0.4: + resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} engines: {node: '>=18'} p-queue@6.6.2: @@ -7956,8 +7834,8 @@ packages: resolution: {integrity: sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==} engines: {node: '>=12.0.0'} - protobufjs@7.5.4: - resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + protobufjs@7.5.3: + resolution: {integrity: sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -8021,10 +7899,6 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} - engines: {node: '>= 0.8'} - raw-body@3.0.0: resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} engines: {node: '>= 0.8'} @@ -8033,8 +7907,8 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - re2@1.22.1: - resolution: {integrity: sha512-E4J0EtgyNLdIr0wTg0dQPefuiqNY29KaLacytiUAYYRzxCG+zOkWoUygt1rI+TA1LrhN49/njrfSO1DHtVC5Vw==} + re2@1.22.3: + resolution: {integrity: sha512-002aE82U91DiaUA16U6vbiJusvPXn1OWiQukOxJkVUTXbzrSuQbFNHYKcGw8QK/uifRCfjl2Hd/vXYDanKkmaQ==} react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} @@ -8207,10 +8081,6 @@ packages: resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} engines: {node: '>=10'} - safe-stable-stringify@2.5.0: - resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} - engines: {node: '>=10'} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -8248,10 +8118,6 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} - send@0.19.1: - resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} - engines: {node: '>= 0.8.0'} - send@1.2.0: resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} engines: {node: '>= 18'} @@ -8392,8 +8258,8 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sql-formatter@15.6.10: - resolution: {integrity: sha512-0bJOPQrRO/JkjQhiThVayq0hOKnI1tHI+2OTkmT7TGtc6kqS+V7kveeMzRW+RNQGxofmTmet9ILvztyuxv0cJQ==} + sql-formatter@15.6.12: + resolution: {integrity: sha512-mkpF+RG402P66VMsnQkWewTRzDBWfu9iLbOfxaW/nAKOS/2A9MheQmcU5cmX0D0At9azrorZwpvcBRNNBozACQ==} hasBin: true ssri@12.0.0: @@ -8415,10 +8281,6 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -9053,10 +8915,6 @@ packages: resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} engines: {node: '>= 12.0.0'} - winston@3.19.0: - resolution: {integrity: sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==} - engines: {node: '>= 12.0.0'} - wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} @@ -9144,11 +9002,6 @@ packages: engines: {node: '>= 14.6'} hasBin: true - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} - engines: {node: '>= 14.6'} - hasBin: true - yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} @@ -9182,20 +9035,12 @@ packages: peerDependencies: zod: ^3.24.1 - zod-to-json-schema@3.25.0: - resolution: {integrity: sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==} - peerDependencies: - zod: ^3.25 || ^4 - zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - snapshots: '@ampproject/remapping@2.3.0': @@ -9206,7 +9051,7 @@ snapshots: '@anthropic-ai/sdk@0.24.3(encoding@0.1.13)': dependencies: '@types/node': 18.19.112 - '@types/node-fetch': 2.6.12 + '@types/node-fetch': 2.6.11 abort-controller: 3.0.0 agentkeepalive: 4.5.0 form-data-encoder: 1.7.2 @@ -9216,11 +9061,11 @@ snapshots: transitivePeerDependencies: - encoding - '@anthropic-ai/sdk@0.71.2(zod@3.25.76)': + '@anthropic-ai/sdk@0.71.2(zod@3.25.67)': dependencies: json-schema-to-ts: 3.1.1 optionalDependencies: - zod: 3.25.76 + zod: 3.25.67 '@anthropic-ai/sdk@0.9.1(encoding@0.1.13)': dependencies: @@ -9470,13 +9315,6 @@ snapshots: enabled: 2.0.0 kuler: 2.0.0 - '@dabh/diagnostics@2.0.8': - dependencies: - '@so-ric/colorspace': 1.1.6 - enabled: 2.0.0 - kuler: 2.0.0 - optional: true - '@electric-sql/pglite@0.2.17': {} '@emnapi/runtime@1.7.1': @@ -9563,8 +9401,7 @@ snapshots: '@fastify/busboy@3.0.0': {} - '@fastify/busboy@3.2.0': - optional: true + '@fastify/busboy@3.1.1': {} '@firebase/ai@1.4.0(@firebase/app-types@0.9.3)(@firebase/app@0.13.1)': dependencies: @@ -9721,12 +9558,6 @@ snapshots: '@firebase/app-types': 0.9.3 '@firebase/util': 1.12.0 - '@firebase/database-types@1.0.16': - dependencies: - '@firebase/app-types': 0.9.3 - '@firebase/util': 1.13.0 - optional: true - '@firebase/database-types@1.0.6': dependencies: '@firebase/app-types': 0.9.2 @@ -9940,20 +9771,15 @@ snapshots: dependencies: tslib: 2.8.1 - '@firebase/util@1.13.0': - dependencies: - tslib: 2.8.1 - optional: true - '@firebase/webchannel-wrapper@1.0.3': {} - '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: - '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) '@opentelemetry/api': 1.9.0 - '@types/node': 20.19.26 + '@types/node': 20.19.1 colorette: 2.0.20 - dotprompt: 1.1.2 + dotprompt: 1.1.1 json5: 2.2.3 node-fetch: 3.3.2 partial-json: 0.1.7 @@ -9968,13 +9794,13 @@ snapshots: - supports-color optional: true - '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': + '@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': dependencies: - '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) '@opentelemetry/api': 1.9.0 - '@types/node': 20.19.26 + '@types/node': 20.19.1 colorette: 2.0.20 - dotprompt: 1.1.2 + dotprompt: 1.1.1 json5: 2.2.3 node-fetch: 3.3.2 partial-json: 0.1.7 @@ -9988,7 +9814,7 @@ snapshots: - genkit - supports-color - '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) @@ -10001,16 +9827,16 @@ snapshots: ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) async-mutex: 0.5.0 - body-parser: 1.20.4 + body-parser: 1.20.3 cors: 2.8.5 - dotprompt: 1.1.2 - express: 4.22.1 + dotprompt: 1.1.1 + express: 4.21.2 get-port: 5.1.1 json-schema: 0.4.0 - zod: 3.25.76 - zod-to-json-schema: 3.25.0(zod@3.25.76) + zod: 3.25.67 + zod-to-json-schema: 3.24.5(zod@3.25.67) optionalDependencies: - '@genkit-ai/firebase': 1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/firebase': 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) transitivePeerDependencies: - '@google-cloud/firestore' - encoding @@ -10020,7 +9846,7 @@ snapshots: - supports-color optional: true - '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': + '@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) @@ -10033,16 +9859,16 @@ snapshots: ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) async-mutex: 0.5.0 - body-parser: 1.20.4 + body-parser: 1.20.3 cors: 2.8.5 - dotprompt: 1.1.2 - express: 4.22.1 + dotprompt: 1.1.1 + express: 4.21.2 get-port: 5.1.1 json-schema: 0.4.0 - zod: 3.25.76 - zod-to-json-schema: 3.25.0(zod@3.25.76) + zod: 3.25.67 + zod-to-json-schema: 3.24.5(zod@3.25.67) optionalDependencies: - '@genkit-ai/firebase': 1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/firebase': 1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) transitivePeerDependencies: - '@google-cloud/firestore' - encoding @@ -10051,9 +9877,9 @@ snapshots: - genkit - supports-color - '@genkit-ai/express@1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit)': + '@genkit-ai/express@1.12.0(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(express@5.1.0)(genkit@genkit)': dependencies: - '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) body-parser: 1.20.3 cors: 2.8.5 express: 5.1.0 @@ -10061,12 +9887,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@genkit-ai/firebase@1.16.1(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/firebase@1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: - '@genkit-ai/google-cloud': 1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) - '@google-cloud/firestore': 7.11.6(encoding@0.1.13) - firebase-admin: 13.5.0(encoding@0.1.13) - genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + '@genkit-ai/google-cloud': 1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) + '@google-cloud/firestore': 7.11.1(encoding@0.1.13) + firebase-admin: 13.6.0(encoding@0.1.13) + genkit: 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1) optionalDependencies: firebase: 11.9.1 transitivePeerDependencies: @@ -10074,24 +9900,11 @@ snapshots: - supports-color optional: true - '@genkit-ai/firebase@1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/firebase@1.16.1(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': dependencies: - '@genkit-ai/google-cloud': 1.25.0(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) - '@google-cloud/firestore': 7.11.6(encoding@0.1.13) - firebase-admin: 13.5.0(encoding@0.1.13) - genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) - optionalDependencies: - firebase: 11.9.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - - '@genkit-ai/firebase@1.25.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit)': - dependencies: - '@genkit-ai/google-cloud': 1.25.0(encoding@0.1.13)(genkit@genkit) - '@google-cloud/firestore': 7.11.6(encoding@0.1.13) - firebase-admin: 13.5.0(encoding@0.1.13) + '@genkit-ai/google-cloud': 1.16.1(encoding@0.1.13)(genkit@genkit) + '@google-cloud/firestore': 7.11.1(encoding@0.1.13) + firebase-admin: 13.6.0(encoding@0.1.13) genkit: link:genkit optionalDependencies: firebase: 11.9.1 @@ -10100,7 +9913,7 @@ snapshots: - supports-color optional: true - '@genkit-ai/google-cloud@1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/google-cloud@1.16.1(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1))': dependencies: '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.17.0) '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) @@ -10116,7 +9929,7 @@ snapshots: '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) + genkit: 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1) google-auth-library: 9.15.1(encoding@0.1.13) node-fetch: 3.3.2 winston: 3.17.0 @@ -10125,34 +9938,9 @@ snapshots: - supports-color optional: true - '@genkit-ai/google-cloud@1.25.0(encoding@0.1.13)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1))': + '@genkit-ai/google-cloud@1.16.1(encoding@0.1.13)(genkit@genkit)': dependencies: - '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.19.0) - '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) - '@google-cloud/opentelemetry-cloud-trace-exporter': 2.4.1(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) - '@google-cloud/opentelemetry-resource-util': 2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) - '@opentelemetry/api': 1.9.0 - '@opentelemetry/auto-instrumentations-node': 0.49.2(@opentelemetry/api@1.9.0)(encoding@0.1.13) - '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-pino': 0.41.0(@opentelemetry/api@1.9.0) - '@opentelemetry/instrumentation-winston': 0.39.0(@opentelemetry/api@1.9.0) - '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-metrics': 1.25.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-node': 0.52.1(@opentelemetry/api@1.9.0) - '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) - genkit: 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1) - google-auth-library: 9.15.1(encoding@0.1.13) - node-fetch: 3.3.2 - winston: 3.19.0 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - - '@genkit-ai/google-cloud@1.25.0(encoding@0.1.13)(genkit@genkit)': - dependencies: - '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.19.0) + '@google-cloud/logging-winston': 6.0.1(encoding@0.1.13)(winston@3.17.0) '@google-cloud/opentelemetry-cloud-monitoring-exporter': 0.19.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-metrics@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) '@google-cloud/opentelemetry-cloud-trace-exporter': 2.4.1(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) '@google-cloud/opentelemetry-resource-util': 2.4.0(@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0))(encoding@0.1.13) @@ -10169,7 +9957,7 @@ snapshots: genkit: link:genkit google-auth-library: 9.15.1(encoding@0.1.13) node-fetch: 3.3.2 - winston: 3.19.0 + winston: 3.17.0 transitivePeerDependencies: - encoding - supports-color @@ -10254,18 +10042,6 @@ snapshots: - encoding - supports-color - '@google-cloud/firestore@7.11.6(encoding@0.1.13)': - dependencies: - '@opentelemetry/api': 1.9.0 - fast-deep-equal: 3.1.3 - functional-red-black-tree: 1.0.1 - google-gax: 4.6.1(encoding@0.1.13) - protobufjs: 7.5.4 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - '@google-cloud/logging-winston@6.0.1(encoding@0.1.13)(winston@3.17.0)': dependencies: '@google-cloud/logging': 11.0.0(encoding@0.1.13) @@ -10277,18 +10053,6 @@ snapshots: - encoding - supports-color - '@google-cloud/logging-winston@6.0.1(encoding@0.1.13)(winston@3.19.0)': - dependencies: - '@google-cloud/logging': 11.0.0(encoding@0.1.13) - google-auth-library: 9.15.1(encoding@0.1.13) - lodash.mapvalues: 4.6.0 - winston: 3.19.0 - winston-transport: 4.7.0 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - '@google-cloud/logging@11.0.0(encoding@0.1.13)': dependencies: '@google-cloud/common': 5.0.1(encoding@0.1.13) @@ -10411,28 +10175,6 @@ snapshots: - supports-color optional: true - '@google-cloud/storage@7.18.0(encoding@0.1.13)': - dependencies: - '@google-cloud/paginator': 5.0.2 - '@google-cloud/projectify': 4.0.0 - '@google-cloud/promisify': 4.0.0 - abort-controller: 3.0.0 - async-retry: 1.3.3 - duplexify: 4.1.3 - fast-xml-parser: 4.5.3 - gaxios: 6.7.1(encoding@0.1.13) - google-auth-library: 9.15.1(encoding@0.1.13) - html-entities: 2.6.0 - mime: 3.0.0 - p-limit: 3.1.0 - retry-request: 7.0.2(encoding@0.1.13) - teeny-request: 9.0.0(encoding@0.1.13) - uuid: 8.3.2 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - '@google-cloud/vertexai@1.10.0(encoding@0.1.13)': dependencies: google-auth-library: 9.15.1(encoding@0.1.13) @@ -10474,7 +10216,7 @@ snapshots: '@grpc/proto-loader': 0.7.13 '@js-sdsl/ordered-map': 4.4.2 - '@grpc/grpc-js@1.14.2': + '@grpc/grpc-js@1.14.3': dependencies: '@grpc/proto-loader': 0.8.0 '@js-sdsl/ordered-map': 4.4.2 @@ -10495,14 +10237,14 @@ snapshots: dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.5.4 + protobufjs: 7.5.3 yargs: 17.7.2 '@grpc/proto-loader@0.8.0': dependencies: lodash.camelcase: 4.3.0 long: 5.3.2 - protobufjs: 7.5.4 + protobufjs: 7.5.3 yargs: 17.7.2 '@img/colour@1.0.0': @@ -10602,10 +10344,10 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@inquirer/external-editor@1.0.2(@types/node@20.19.1)': + '@inquirer/external-editor@1.0.3(@types/node@20.19.1)': dependencies: chardet: 2.1.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.1 optionalDependencies: '@types/node': 20.19.1 @@ -10844,9 +10586,6 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} - '@jridgewell/sourcemap-codec@1.5.5': - optional: true - '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -10855,7 +10594,7 @@ snapshots: '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.5.0 optional: true '@js-sdsl/ordered-map@4.4.2': {} @@ -10911,9 +10650,9 @@ snapshots: dependencies: '@langchain/core': 0.1.63 js-tiktoken: 1.0.11 - openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76) - zod: 3.25.76 - zod-to-json-schema: 3.24.5(zod@3.25.76) + openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) + zod: 3.25.67 + zod-to-json-schema: 3.24.5(zod@3.25.67) transitivePeerDependencies: - encoding - ws @@ -10923,10 +10662,10 @@ snapshots: '@langchain/core': 0.1.63 js-tiktoken: 1.0.11 - '@mistralai/mistralai-gcp@1.5.0(encoding@0.1.13)(zod@3.25.76)': + '@mistralai/mistralai-gcp@1.5.0(encoding@0.1.13)(zod@3.25.67)': dependencies: google-auth-library: 9.15.1(encoding@0.1.13) - zod: 3.25.76 + zod: 3.25.67 transitivePeerDependencies: - encoding - supports-color @@ -10965,13 +10704,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@modelcontextprotocol/server-filesystem@2025.7.1(zod@3.25.76)': + '@modelcontextprotocol/server-filesystem@2025.7.1(zod@3.25.67)': dependencies: '@modelcontextprotocol/sdk': 1.15.0 diff: 5.2.0 glob: 10.3.12 minimatch: 10.0.1 - zod-to-json-schema: 3.24.5(zod@3.25.76) + zod-to-json-schema: 3.24.5(zod@3.25.67) transitivePeerDependencies: - supports-color - zod @@ -11020,30 +10759,30 @@ snapshots: '@napi-rs/canvas-win32-x64-msvc': 0.1.71 optional: true - '@next/env@15.4.10': {} + '@next/env@15.5.9': {} - '@next/swc-darwin-arm64@15.4.8': + '@next/swc-darwin-arm64@15.5.7': optional: true - '@next/swc-darwin-x64@15.4.8': + '@next/swc-darwin-x64@15.5.7': optional: true - '@next/swc-linux-arm64-gnu@15.4.8': + '@next/swc-linux-arm64-gnu@15.5.7': optional: true - '@next/swc-linux-arm64-musl@15.4.8': + '@next/swc-linux-arm64-musl@15.5.7': optional: true - '@next/swc-linux-x64-gnu@15.4.8': + '@next/swc-linux-x64-gnu@15.5.7': optional: true - '@next/swc-linux-x64-musl@15.4.8': + '@next/swc-linux-x64-musl@15.5.7': optional: true - '@next/swc-win32-arm64-msvc@15.4.8': + '@next/swc-win32-arm64-msvc@15.5.7': optional: true - '@next/swc-win32-x64-msvc@15.4.8': + '@next/swc-win32-x64-msvc@15.5.7': optional: true '@npmcli/agent@3.0.0': @@ -11059,7 +10798,7 @@ snapshots: '@npmcli/fs@4.0.0': dependencies: - semver: 7.7.3 + semver: 7.7.2 optional: true '@opentelemetry/api-logs@0.52.1': @@ -11846,12 +11585,6 @@ snapshots: lodash.get: 4.4.2 type-detect: 4.1.0 - '@so-ric/colorspace@1.1.6': - dependencies: - color: 5.0.3 - text-hex: 1.0.0 - optional: true - '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -11860,7 +11593,7 @@ snapshots: '@tootallnate/quickjs-emscripten@0.23.0': {} - '@tsconfig/node10@1.0.12': + '@tsconfig/node10@1.0.11': optional: true '@tsconfig/node12@1.0.11': @@ -11941,14 +11674,6 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - '@types/express-serve-static-core@4.19.7': - dependencies: - '@types/node': 20.19.26 - '@types/qs': 6.14.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - optional: true - '@types/express@4.17.23': dependencies: '@types/body-parser': 1.19.5 @@ -11956,14 +11681,6 @@ snapshots: '@types/qs': 6.9.14 '@types/serve-static': 1.15.5 - '@types/express@4.17.25': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.7 - '@types/qs': 6.14.0 - '@types/serve-static': 1.15.10 - optional: true - '@types/graceful-fs@4.1.9': dependencies: '@types/node': 20.19.1 @@ -11978,9 +11695,6 @@ snapshots: '@types/http-errors@2.0.4': {} - '@types/http-errors@2.0.5': - optional: true - '@types/istanbul-lib-coverage@2.0.6': {} '@types/istanbul-lib-report@3.0.3': @@ -12003,8 +11717,7 @@ snapshots: '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 - '@types/node': 20.19.26 - optional: true + '@types/node': 20.19.1 '@types/jsonwebtoken@9.0.6': dependencies: @@ -12020,8 +11733,7 @@ snapshots: '@types/mime@3.0.4': {} - '@types/ms@2.1.0': - optional: true + '@types/ms@2.1.0': {} '@types/mysql@2.15.22': dependencies: @@ -12045,23 +11757,10 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@20.19.25': - dependencies: - undici-types: 6.21.0 - - '@types/node@20.19.26': - dependencies: - undici-types: 6.21.0 - '@types/node@22.15.32': dependencies: undici-types: 6.21.0 - '@types/node@22.19.2': - dependencies: - undici-types: 6.21.0 - optional: true - '@types/pdf-parse@1.1.5': dependencies: '@types/node': 20.19.1 @@ -12076,9 +11775,6 @@ snapshots: pg-protocol: 1.6.0 pg-types: 2.2.0 - '@types/qs@6.14.0': - optional: true - '@types/qs@6.9.14': {} '@types/range-parser@1.2.7': {} @@ -12101,24 +11797,6 @@ snapshots: '@types/mime': 1.3.5 '@types/node': 20.19.1 - '@types/send@0.17.6': - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.19.26 - optional: true - - '@types/send@1.2.1': - dependencies: - '@types/node': 20.19.26 - optional: true - - '@types/serve-static@1.15.10': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 20.19.26 - '@types/send': 0.17.6 - optional: true - '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 @@ -12249,7 +11927,7 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@7.1.1: + ansi-escapes@7.2.0: dependencies: environment: 1.1.0 @@ -12280,7 +11958,7 @@ snapshots: archiver-utils@5.0.2: dependencies: - glob: 10.4.5 + glob: 10.5.0 graceful-fs: 4.2.11 is-stream: 2.0.1 lazystream: 1.0.1 @@ -12417,7 +12095,7 @@ snapshots: balanced-match@1.0.2: {} - bare-events@2.8.1: {} + bare-events@2.8.2: {} base-64@0.1.0: {} @@ -12464,23 +12142,6 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@1.20.4: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.14.0 - raw-body: 2.5.3 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - body-parser@2.2.0: dependencies: bytes: 3.1.2 @@ -12525,7 +12186,7 @@ snapshots: browserslist@4.24.0: dependencies: - caniuse-lite: 1.0.30001760 + caniuse-lite: 1.0.30001667 electron-to-chromium: 1.5.33 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.0) @@ -12583,13 +12244,13 @@ snapshots: dependencies: '@npmcli/fs': 4.0.0 fs-minipass: 3.0.3 - glob: 10.4.5 + glob: 10.5.0 lru-cache: 10.2.0 minipass: 7.1.2 minipass-collect: 2.0.1 minipass-flush: 1.0.5 minipass-pipeline: 1.2.4 - p-map: 7.0.3 + p-map: 7.0.4 ssri: 12.0.0 tar: 7.5.2 unique-filename: 4.0.0 @@ -12605,7 +12266,7 @@ snapshots: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 set-function-length: 1.2.2 call-bind@1.0.8: @@ -12628,7 +12289,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001760: {} + caniuse-lite@1.0.30001667: {} chalk@2.4.2: dependencies: @@ -12684,12 +12345,12 @@ snapshots: chownr@3.0.0: optional: true - chromadb@1.8.1(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76)): + chromadb@1.8.1(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)): dependencies: cliui: 8.0.1 isomorphic-fetch: 3.0.0(encoding@0.1.13) optionalDependencies: - openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76) + openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) transitivePeerDependencies: - encoding @@ -12766,39 +12427,20 @@ snapshots: dependencies: color-name: 1.1.4 - color-convert@3.1.3: - dependencies: - color-name: 2.1.0 - optional: true - color-name@1.1.3: {} color-name@1.1.4: {} - color-name@2.1.0: - optional: true - color-string@1.9.1: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - color-string@2.1.4: - dependencies: - color-name: 2.1.0 - optional: true - color@3.2.1: dependencies: color-convert: 1.9.3 color-string: 1.9.1 - color@5.0.3: - dependencies: - color-convert: 3.1.3 - color-string: 2.1.4 - optional: true - colorette@2.0.19: {} colorette@2.0.20: {} @@ -12906,8 +12548,6 @@ snapshots: cookie-signature@1.0.6: {} - cookie-signature@1.0.7: {} - cookie-signature@1.2.2: {} cookie@0.7.1: {} @@ -13037,11 +12677,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.3: - dependencies: - ms: 2.1.3 - optional: true - decamelize@1.2.0: {} dedent@1.5.3: {} @@ -13126,11 +12761,6 @@ snapshots: handlebars: 4.7.8 yaml: 2.7.0 - dotprompt@1.1.2: - dependencies: - handlebars: 4.7.8 - yaml: 2.8.2 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -13260,7 +12890,7 @@ snapshots: es-define-property@1.0.0: dependencies: - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 es-define-property@1.0.1: {} @@ -13353,7 +12983,7 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.8.1 + bare-events: 2.8.2 transitivePeerDependencies: - bare-abort-controller @@ -13392,7 +13022,7 @@ snapshots: content-type: 1.0.5 deep-freeze: 0.0.1 events-listener: 1.1.0 - glob: 10.4.5 + glob: 10.5.0 json-ptr: 3.1.1 json-schema-traverse: 1.0.0 lodash: 4.17.21 @@ -13459,42 +13089,6 @@ snapshots: transitivePeerDependencies: - supports-color - express@4.22.1: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.4 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.7 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.2 - fresh: 0.5.2 - http-errors: 2.0.1 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.14.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.1 - serve-static: 1.16.2 - setprototypeof: 1.2.0 - statuses: 2.0.2 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - express@5.1.0: dependencies: accepts: 2.0.0 @@ -13606,18 +13200,6 @@ snapshots: transitivePeerDependencies: - supports-color - finalhandler@1.3.2: - dependencies: - debug: 2.6.9 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - finalhandler@2.1.0: dependencies: debug: 4.4.1 @@ -13640,18 +13222,18 @@ snapshots: firebase-admin@12.3.1(encoding@0.1.13): dependencies: - '@fastify/busboy': 3.2.0 + '@fastify/busboy': 3.1.1 '@firebase/database-compat': 1.0.10 - '@firebase/database-types': 1.0.16 - '@types/node': 22.19.2 + '@firebase/database-types': 1.0.14 + '@types/node': 22.15.32 farmhash-modern: 1.1.0 jsonwebtoken: 9.0.2 jwks-rsa: 3.2.0 - node-forge: 1.3.3 + node-forge: 1.3.1 uuid: 10.0.0 optionalDependencies: - '@google-cloud/firestore': 7.11.6(encoding@0.1.13) - '@google-cloud/storage': 7.18.0(encoding@0.1.13) + '@google-cloud/firestore': 7.11.1(encoding@0.1.13) + '@google-cloud/storage': 7.16.0(encoding@0.1.13) transitivePeerDependencies: - encoding - supports-color @@ -13676,9 +13258,9 @@ snapshots: - encoding - supports-color - firebase-admin@13.5.0(encoding@0.1.13): + firebase-admin@13.6.0(encoding@0.1.13): dependencies: - '@fastify/busboy': 3.0.0 + '@fastify/busboy': 3.1.1 '@firebase/database-compat': 2.0.10 '@firebase/database-types': 1.0.14 '@types/node': 22.15.32 @@ -13686,11 +13268,11 @@ snapshots: fast-deep-equal: 3.1.3 google-auth-library: 9.15.1(encoding@0.1.13) jsonwebtoken: 9.0.2 - jwks-rsa: 3.1.0 + jwks-rsa: 3.2.0 node-forge: 1.3.1 uuid: 11.1.0 optionalDependencies: - '@google-cloud/firestore': 7.11.0(encoding@0.1.13) + '@google-cloud/firestore': 7.11.1(encoding@0.1.13) '@google-cloud/storage': 7.16.0(encoding@0.1.13) transitivePeerDependencies: - encoding @@ -13707,13 +13289,13 @@ snapshots: transitivePeerDependencies: - supports-color - firebase-functions@6.3.2(firebase-admin@13.5.0(encoding@0.1.13)): + firebase-functions@6.3.2(firebase-admin@13.6.0(encoding@0.1.13)): dependencies: '@types/cors': 2.8.19 '@types/express': 4.17.23 cors: 2.8.5 express: 4.21.2 - firebase-admin: 13.5.0(encoding@0.1.13) + firebase-admin: 13.6.0(encoding@0.1.13) protobufjs: 7.3.2 transitivePeerDependencies: - supports-color @@ -13744,11 +13326,11 @@ snapshots: exegesis-express: 4.0.0 express: 4.21.2 filesize: 6.4.0 - form-data: 4.0.4 + form-data: 4.0.5 fs-extra: 10.1.0 fuzzy: 0.1.3 gaxios: 6.7.1(encoding@0.1.13) - glob: 10.4.5 + glob: 10.5.0 google-auth-library: 9.15.1(encoding@0.1.13) inquirer: 8.2.7(@types/node@20.19.1) inquirer-autocomplete-prompt: 2.0.1(inquirer@8.2.7(@types/node@20.19.1)) @@ -13773,7 +13355,7 @@ snapshots: proxy-agent: 6.5.0 retry: 0.13.1 semver: 7.7.2 - sql-formatter: 15.6.10 + sql-formatter: 15.6.12 stream-chain: 2.2.5 stream-json: 1.9.1 superstatic: 9.2.0(encoding@0.1.13) @@ -13864,7 +13446,7 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - form-data@4.0.4: + form-data@4.0.5: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -13990,10 +13572,10 @@ snapshots: transitivePeerDependencies: - supports-color - genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1): + genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1): dependencies: - '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) - '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)) uuid: 10.0.0 transitivePeerDependencies: - '@google-cloud/firestore' @@ -14003,10 +13585,10 @@ snapshots: - supports-color optional: true - genkitx-openai@0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3): + genkitx-openai@0.10.1(@genkit-ai/ai@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(@genkit-ai/core@1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit))(encoding@0.1.13)(ws@8.18.3): dependencies: - '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) - '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.6(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.5.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/ai': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) + '@genkit-ai/core': 1.26.0(@google-cloud/firestore@7.11.1(encoding@0.1.13))(encoding@0.1.13)(firebase-admin@13.6.0(encoding@0.1.13))(firebase@11.9.1)(genkit@genkit) openai: 4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67) zod: 3.25.67 transitivePeerDependencies: @@ -14095,7 +13677,7 @@ snapshots: minipass: 7.1.2 path-scurry: 1.10.2 - glob@10.4.5: + glob@10.5.0: dependencies: foreground-child: 3.1.1 jackspeak: 3.4.3 @@ -14154,7 +13736,7 @@ snapshots: gaxios: 5.1.3(encoding@0.1.13) gcp-metadata: 5.3.0(encoding@0.1.13) gtoken: 6.1.2(encoding@0.1.13) - jws: 4.0.1 + jws: 4.0.0 lru-cache: 6.0.0 transitivePeerDependencies: - encoding @@ -14193,7 +13775,7 @@ snapshots: google-gax@5.0.6: dependencies: - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@grpc/proto-loader': 0.8.0 duplexify: 4.1.3 google-auth-library: 10.5.0 @@ -14201,7 +13783,7 @@ snapshots: node-fetch: 3.3.2 object-hash: 3.0.0 proto3-json-serializer: 3.0.4 - protobufjs: 7.5.4 + protobufjs: 7.5.3 retry-request: 8.0.2 rimraf: 5.0.10 transitivePeerDependencies: @@ -14211,7 +13793,7 @@ snapshots: google-p12-pem@4.0.1: dependencies: - node-forge: 1.3.3 + node-forge: 1.3.1 optional: true googleapis-common@7.2.0(encoding@0.1.13): @@ -14252,7 +13834,7 @@ snapshots: dependencies: gaxios: 5.1.3(encoding@0.1.13) google-p12-pem: 4.0.1 - jws: 4.0.1 + jws: 4.0.0 transitivePeerDependencies: - encoding - supports-color @@ -14341,14 +13923,6 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - http-parser-js@0.5.10: {} http-proxy-agent@5.0.0: @@ -14401,7 +13975,7 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.7.0: + iconv-lite@0.7.1: dependencies: safer-buffer: 2.1.2 @@ -14452,7 +14026,7 @@ snapshots: inquirer@8.2.7(@types/node@20.19.1): dependencies: - '@inquirer/external-editor': 1.0.2(@types/node@20.19.1) + '@inquirer/external-editor': 1.0.3(@types/node@20.19.1) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -14481,7 +14055,7 @@ snapshots: interpret@2.2.0: {} - ip-address@10.0.1: {} + ip-address@10.1.0: {} ip-regex@4.3.0: {} @@ -14695,7 +14269,7 @@ snapshots: '@babel/parser': 7.25.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.7.3 + semver: 7.7.2 transitivePeerDependencies: - supports-color @@ -15130,8 +14704,7 @@ snapshots: jose@4.15.5: {} - jose@4.15.9: - optional: true + jose@4.15.9: {} joycon@3.1.1: {} @@ -15226,13 +14799,6 @@ snapshots: ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jwa@2.0.1: - dependencies: - buffer-equal-constant-time: 1.0.1 - ecdsa-sig-formatter: 1.0.11 - safe-buffer: 5.2.1 - optional: true - jwks-rsa@3.1.0: dependencies: '@types/express': 4.17.23 @@ -15246,15 +14812,14 @@ snapshots: jwks-rsa@3.2.0: dependencies: - '@types/express': 4.17.25 + '@types/express': 4.17.23 '@types/jsonwebtoken': 9.0.10 - debug: 4.4.3 + debug: 4.4.1 jose: 4.15.9 limiter: 1.1.5 lru-memoizer: 2.3.0 transitivePeerDependencies: - supports-color - optional: true jws@3.2.2: dependencies: @@ -15266,12 +14831,6 @@ snapshots: jwa: 2.0.0 safe-buffer: 5.2.1 - jws@4.0.1: - dependencies: - jwa: 2.0.1 - safe-buffer: 5.2.1 - optional: true - kind-of@3.2.2: dependencies: is-buffer: 1.1.6 @@ -15301,7 +14860,7 @@ snapshots: kuler@2.0.0: {} - langchain@0.1.37(@google-cloud/storage@7.18.0(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(chromadb@1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)))(encoding@0.1.13)(fast-xml-parser@4.5.3)(firebase-admin@12.3.1(encoding@0.1.13))(google-auth-library@8.9.0(encoding@0.1.13))(handlebars@4.7.8)(ignore@5.3.1)(jsonwebtoken@9.0.2)(lodash@4.17.21)(pdf-parse@1.1.1)(pg@8.16.2)(ws@8.18.3): + langchain@0.1.37(@google-cloud/storage@7.16.0(encoding@0.1.13))(@pinecone-database/pinecone@2.2.2)(chromadb@1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)))(encoding@0.1.13)(fast-xml-parser@4.5.3)(firebase-admin@12.3.1(encoding@0.1.13))(google-auth-library@8.9.0(encoding@0.1.13))(handlebars@4.7.8)(ignore@5.3.1)(jsonwebtoken@9.0.2)(lodash@4.17.21)(pdf-parse@1.1.1)(pg@8.16.2)(ws@8.18.3): dependencies: '@anthropic-ai/sdk': 0.9.1(encoding@0.1.13) '@langchain/community': 0.0.53(@pinecone-database/pinecone@2.2.2)(chromadb@1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)))(encoding@0.1.13)(firebase-admin@12.3.1(encoding@0.1.13))(google-auth-library@8.9.0(encoding@0.1.13))(jsonwebtoken@9.0.2)(lodash@4.17.21)(pg@8.16.2)(ws@8.18.3) @@ -15322,7 +14881,7 @@ snapshots: zod: 3.25.67 zod-to-json-schema: 3.24.5(zod@3.25.67) optionalDependencies: - '@google-cloud/storage': 7.18.0(encoding@0.1.13) + '@google-cloud/storage': 7.16.0(encoding@0.1.13) '@pinecone-database/pinecone': 2.2.2 chromadb: 1.9.2(encoding@0.1.13)(openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.67)) fast-xml-parser: 4.5.3 @@ -15549,7 +15108,6 @@ snapshots: dependencies: lodash.clonedeep: 4.5.0 lru-cache: 6.0.0 - optional: true lsofi@1.0.0: dependencies: @@ -15568,7 +15126,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.7.2 make-error@1.3.6: {} @@ -15606,7 +15164,7 @@ snapshots: marked-terminal@7.3.0(marked@13.0.3): dependencies: - ansi-escapes: 7.1.1 + ansi-escapes: 7.2.0 ansi-regex: 6.2.2 chalk: 5.6.2 cli-highlight: 2.1.11 @@ -15820,24 +15378,24 @@ snapshots: netmask@2.0.2: {} - next@15.4.10(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@15.5.9(@babel/core@7.25.7)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 15.4.10 + '@next/env': 15.5.9 '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001760 + caniuse-lite: 1.0.30001667 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.6(@babel/core@7.25.7)(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.4.8 - '@next/swc-darwin-x64': 15.4.8 - '@next/swc-linux-arm64-gnu': 15.4.8 - '@next/swc-linux-arm64-musl': 15.4.8 - '@next/swc-linux-x64-gnu': 15.4.8 - '@next/swc-linux-x64-musl': 15.4.8 - '@next/swc-win32-arm64-msvc': 15.4.8 - '@next/swc-win32-x64-msvc': 15.4.8 + '@next/swc-darwin-arm64': 15.5.7 + '@next/swc-darwin-x64': 15.5.7 + '@next/swc-linux-arm64-gnu': 15.5.7 + '@next/swc-linux-arm64-musl': 15.5.7 + '@next/swc-linux-x64-gnu': 15.5.7 + '@next/swc-linux-x64-musl': 15.5.7 + '@next/swc-win32-arm64-msvc': 15.5.7 + '@next/swc-win32-x64-msvc': 15.5.7 '@opentelemetry/api': 1.9.0 sharp: 0.34.5 transitivePeerDependencies: @@ -15869,9 +15427,6 @@ snapshots: node-forge@1.3.1: {} - node-forge@1.3.3: - optional: true - node-gyp@11.5.0: dependencies: env-paths: 2.2.1 @@ -15880,7 +15435,7 @@ snapshots: make-fetch-happen: 14.0.3 nopt: 8.1.0 proc-log: 5.0.0 - semver: 7.7.3 + semver: 7.7.2 tar: 7.5.2 tinyglobby: 0.2.14 which: 5.0.0 @@ -15994,21 +15549,6 @@ snapshots: transitivePeerDependencies: - encoding - openai@4.104.0(encoding@0.1.13)(ws@8.18.3)(zod@3.25.76): - dependencies: - '@types/node': 18.19.112 - '@types/node-fetch': 2.6.11 - abort-controller: 3.0.0 - agentkeepalive: 4.5.0 - form-data-encoder: 1.7.2 - formdata-node: 4.4.1 - node-fetch: 2.7.0(encoding@0.1.13) - optionalDependencies: - ws: 8.18.3 - zod: 3.25.76 - transitivePeerDependencies: - - encoding - openapi-types@12.1.3: {} openapi3-ts@3.2.0: @@ -16051,7 +15591,7 @@ snapshots: dependencies: p-limit: 2.3.0 - p-map@7.0.3: + p-map@7.0.4: optional: true p-queue@6.6.2: @@ -16269,14 +15809,6 @@ snapshots: tsx: 4.20.3 yaml: 2.8.0 - postcss-load-config@6.0.1(postcss@8.4.47)(tsx@4.20.3)(yaml@2.8.2): - dependencies: - lilconfig: 3.1.2 - optionalDependencies: - postcss: 8.4.47 - tsx: 4.20.3 - yaml: 2.8.2 - postcss@8.4.31: dependencies: nanoid: 3.3.11 @@ -16338,7 +15870,7 @@ snapshots: proto3-json-serializer@3.0.4: dependencies: - protobufjs: 7.5.4 + protobufjs: 7.5.3 protobuf.js@1.1.2: dependencies: @@ -16359,7 +15891,7 @@ snapshots: '@types/node': 20.19.1 long: 5.2.3 - protobufjs@7.5.4: + protobufjs@7.5.3: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -16371,7 +15903,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.19.25 + '@types/node': 20.19.1 long: 5.3.2 proxy-addr@2.0.7: @@ -16443,13 +15975,6 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - raw-body@2.5.3: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - raw-body@3.0.0: dependencies: bytes: 3.1.2 @@ -16464,7 +15989,7 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - re2@1.22.1: + re2@1.22.3: dependencies: install-artifact-from-github: 1.4.0 nan: 2.24.0 @@ -16706,9 +16231,6 @@ snapshots: safe-stable-stringify@2.4.3: {} - safe-stable-stringify@2.5.0: - optional: true - safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -16729,7 +16251,8 @@ snapshots: semver@7.7.2: {} - semver@7.7.3: {} + semver@7.7.3: + optional: true send@0.19.0: dependencies: @@ -16749,24 +16272,6 @@ snapshots: transitivePeerDependencies: - supports-color - send@0.19.1: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - send@1.2.0: dependencies: debug: 4.4.1 @@ -16938,7 +16443,7 @@ snapshots: socks@2.8.7: dependencies: - ip-address: 10.0.1 + ip-address: 10.1.0 smart-buffer: 4.2.0 sort-any@2.0.0: @@ -16976,7 +16481,7 @@ snapshots: sprintf-js@1.0.3: {} - sql-formatter@15.6.10: + sql-formatter@15.6.12: dependencies: argparse: 2.0.1 nearley: 2.20.1 @@ -16996,8 +16501,6 @@ snapshots: statuses@2.0.1: {} - statuses@2.0.2: {} - stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -17149,7 +16652,7 @@ snapshots: router: 2.2.0 update-notifier-cjs: 5.1.7(encoding@0.1.13) optionalDependencies: - re2: 1.22.1 + re2: 1.22.3 transitivePeerDependencies: - encoding - supports-color @@ -17352,7 +16855,7 @@ snapshots: ts-node@10.9.2(@types/node@20.19.1)(typescript@4.9.5): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 @@ -17371,7 +16874,7 @@ snapshots: ts-node@10.9.2(@types/node@20.19.1)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 + '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 @@ -17423,7 +16926,7 @@ snapshots: - tsx - yaml - tsup@8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@4.9.5)(yaml@2.8.2): + tsup@8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.0): dependencies: bundle-require: 5.1.0(esbuild@0.25.5) cac: 6.7.14 @@ -17434,35 +16937,7 @@ snapshots: fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.4.47)(tsx@4.20.3)(yaml@2.8.2) - resolve-from: 5.0.0 - rollup: 4.43.0 - source-map: 0.8.0-beta.0 - sucrase: 3.35.0 - tinyexec: 0.3.2 - tinyglobby: 0.2.14 - tree-kill: 1.2.2 - optionalDependencies: - postcss: 8.4.47 - typescript: 4.9.5 - transitivePeerDependencies: - - jiti - - supports-color - - tsx - - yaml - - tsup@8.5.0(postcss@8.4.47)(tsx@4.20.3)(typescript@5.8.3)(yaml@2.8.2): - dependencies: - bundle-require: 5.1.0(esbuild@0.25.5) - cac: 6.7.14 - chokidar: 4.0.3 - consola: 3.4.2 - debug: 4.4.1 - esbuild: 0.25.5 - fix-dts-default-cjs-exports: 1.0.1 - joycon: 3.1.1 - picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.4.47)(tsx@4.20.3)(yaml@2.8.2) + postcss-load-config: 6.0.1(postcss@8.4.47)(tsx@4.20.3)(yaml@2.8.0) resolve-from: 5.0.0 rollup: 4.43.0 source-map: 0.8.0-beta.0 @@ -17829,21 +17304,6 @@ snapshots: triple-beam: 1.4.1 winston-transport: 4.9.0 - winston@3.19.0: - dependencies: - '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.8 - async: 3.2.6 - is-stream: 2.0.1 - logform: 2.7.0 - one-time: 1.0.0 - readable-stream: 3.6.2 - safe-stable-stringify: 2.5.0 - stack-trace: 0.0.10 - triple-beam: 1.4.1 - winston-transport: 4.9.0 - optional: true - wordwrap@1.0.0: {} wrap-ansi@6.2.0: @@ -17903,8 +17363,6 @@ snapshots: yaml@2.8.0: {} - yaml@2.8.2: {} - yargs-parser@20.2.9: {} yargs-parser@21.1.1: {} @@ -17944,16 +17402,6 @@ snapshots: dependencies: zod: 3.25.67 - zod-to-json-schema@3.24.5(zod@3.25.76): - dependencies: - zod: 3.25.76 - - zod-to-json-schema@3.25.0(zod@3.25.76): - dependencies: - zod: 3.25.76 - zod@3.22.4: {} zod@3.25.67: {} - - zod@3.25.76: {} diff --git a/js/testapps/anthropic/package.json b/js/testapps/anthropic/package.json index 08e1a0d2fd..3413415bff 100644 --- a/js/testapps/anthropic/package.json +++ b/js/testapps/anthropic/package.json @@ -10,6 +10,7 @@ "start:beta": "node lib/beta/basic.js", "dev:stable": "genkit start -- npx tsx --watch src/stable/basic.ts", "dev:beta": "genkit start -- npx tsx --watch src/beta/basic.ts", + "dev:beta:files-api": "genkit start -- npx tsx --watch src/beta/files_api.ts", "dev:stable:text-plain": "genkit start -- npx tsx --watch src/stable/text-plain.ts", "dev:stable:webp": "genkit start -- npx tsx --watch src/stable/webp.ts", "dev:stable:pdf": "genkit start -- npx tsx --watch src/stable/pdf.ts", @@ -25,8 +26,10 @@ "author": "", "license": "Apache-2.0", "dependencies": { + "@genkit-ai/anthropic": "workspace:*", "genkit": "workspace:*", - "@genkit-ai/anthropic": "workspace:*" + "form-data": "^4.0.5", + "node-fetch": "^3.3.2" }, "devDependencies": { "cross-env": "^10.1.0", diff --git a/js/testapps/anthropic/src/stable/attention-first-page.pdf b/js/testapps/anthropic/src/attention-first-page.pdf similarity index 100% rename from js/testapps/anthropic/src/stable/attention-first-page.pdf rename to js/testapps/anthropic/src/attention-first-page.pdf diff --git a/js/testapps/anthropic/src/beta/files_api.ts b/js/testapps/anthropic/src/beta/files_api.ts new file mode 100644 index 0000000000..0f47100ec5 --- /dev/null +++ b/js/testapps/anthropic/src/beta/files_api.ts @@ -0,0 +1,116 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { anthropic } from '@genkit-ai/anthropic'; +import FormData from 'form-data'; +import * as fs from 'fs'; +import { genkit } from 'genkit'; +import fetch from 'node-fetch'; +import * as path from 'path'; + +// Ensure the API key is set. +const API_KEY = process.env.ANTHROPIC_API_KEY; +// If you have a file ID, you can set it here. Otherwise, the flow will upload a new PDF to Anthropic. +const FILE_ID = process.env.ANTHROPIC_FILE_ID; + +export async function uploadPdfToAnthropic() { + if (!API_KEY) throw new Error('Missing ANTHROPIC_API_KEY env variable'); + + // Path to the PDF file to upload + const pdfPath = path.join(__dirname, '../attention-first-page.pdf'); + const stream = fs.createReadStream(pdfPath); + + const form = new FormData(); + form.append('file', stream, { + filename: 'attention-first-page.pdf', + contentType: 'application/pdf', + }); + + const response = await fetch('https://api.anthropic.com/v1/files', { + method: 'POST', + headers: { + 'x-api-key': API_KEY, + 'anthropic-version': '2023-06-01', + 'anthropic-beta': 'files-api-2025-04-14', + ...form.getHeaders(), + }, + body: form, + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`Anthropic file upload failed: ${response.status} ${text}`); + } + const result = await response.json(); + return result as { id: string }; // Contains 'file_id', etc. +} + +async function main() { + const ai = genkit({ + plugins: [ + // Default all flows in this sample to the beta surface + anthropic({ + apiVersion: 'beta', + apiKey: API_KEY, + }), + ], + }); + + /** + * This flow demonstrates PDF document processing via a public data URL along with a user prompt. + * The PDF is sent as a media part with the correct contentType and a URL, not base64. + */ + ai.defineFlow('beta-pdf-url', async () => { + let fileId = FILE_ID; + + if (!fileId) { + const fileResult = await uploadPdfToAnthropic(); + if (!fileResult || !fileResult.id) { + throw new Error('File ID not found'); + } + fileId = fileResult.id; + } + + // Example: Use a (demo/test) PDF file accessible via public URL. + // Replace this with your actual PDF if needed. + const { text } = await ai.generate({ + model: anthropic.model('claude-sonnet-4-5'), + messages: [ + { + role: 'user', + content: [ + { + text: 'What are the key findings or main points in this document?', + }, + { + media: { + url: fileId, + contentType: 'file/document', + }, + }, + ], + }, + ], + }); + + return text; + }); +} + +main().catch((error) => { + console.error('Error:', error); + process.exit(1); +}); diff --git a/js/testapps/anthropic/src/stable/pdf.ts b/js/testapps/anthropic/src/stable/pdf.ts index 8953dff696..07be5f6657 100644 --- a/js/testapps/anthropic/src/stable/pdf.ts +++ b/js/testapps/anthropic/src/stable/pdf.ts @@ -29,7 +29,7 @@ const ai = genkit({ */ ai.defineFlow('stable-pdf-base64', async () => { // Read PDF file from the same directory as this source file - const pdfPath = path.join(__dirname, 'attention-first-page.pdf'); + const pdfPath = path.join(__dirname, '../attention-first-page.pdf'); const pdfBuffer = fs.readFileSync(pdfPath); const pdfBase64 = pdfBuffer.toString('base64'); From 888a4c29f983bf8dddc9e0ad8c8dc591e843af06 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 14:57:26 +0000 Subject: [PATCH 20/30] refactor(js/testapps/anthropic): remove node-fetch and form-data dev deps --- js/pnpm-lock.yaml | 6 ------ js/testapps/anthropic/package.json | 4 +--- js/testapps/anthropic/src/beta/files_api.ts | 14 ++++++-------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index ce58b1b38c..6c68183717 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -1033,15 +1033,9 @@ importers: '@genkit-ai/anthropic': specifier: workspace:* version: link:../../plugins/anthropic - form-data: - specifier: ^4.0.5 - version: 4.0.5 genkit: specifier: workspace:* version: link:../../genkit - node-fetch: - specifier: ^3.3.2 - version: 3.3.2 devDependencies: cross-env: specifier: ^10.1.0 diff --git a/js/testapps/anthropic/package.json b/js/testapps/anthropic/package.json index 3413415bff..fb96c5dca2 100644 --- a/js/testapps/anthropic/package.json +++ b/js/testapps/anthropic/package.json @@ -27,9 +27,7 @@ "license": "Apache-2.0", "dependencies": { "@genkit-ai/anthropic": "workspace:*", - "genkit": "workspace:*", - "form-data": "^4.0.5", - "node-fetch": "^3.3.2" + "genkit": "workspace:*" }, "devDependencies": { "cross-env": "^10.1.0", diff --git a/js/testapps/anthropic/src/beta/files_api.ts b/js/testapps/anthropic/src/beta/files_api.ts index 0f47100ec5..fd7dc87457 100644 --- a/js/testapps/anthropic/src/beta/files_api.ts +++ b/js/testapps/anthropic/src/beta/files_api.ts @@ -15,10 +15,8 @@ */ import { anthropic } from '@genkit-ai/anthropic'; -import FormData from 'form-data'; import * as fs from 'fs'; import { genkit } from 'genkit'; -import fetch from 'node-fetch'; import * as path from 'path'; // Ensure the API key is set. @@ -31,13 +29,14 @@ export async function uploadPdfToAnthropic() { // Path to the PDF file to upload const pdfPath = path.join(__dirname, '../attention-first-page.pdf'); - const stream = fs.createReadStream(pdfPath); + const fileBuffer = fs.readFileSync(pdfPath); const form = new FormData(); - form.append('file', stream, { - filename: 'attention-first-page.pdf', - contentType: 'application/pdf', - }); + form.append( + 'file', + new Blob([fileBuffer], { type: 'application/pdf' }), + 'attention-first-page.pdf' + ); const response = await fetch('https://api.anthropic.com/v1/files', { method: 'POST', @@ -45,7 +44,6 @@ export async function uploadPdfToAnthropic() { 'x-api-key': API_KEY, 'anthropic-version': '2023-06-01', 'anthropic-beta': 'files-api-2025-04-14', - ...form.getHeaders(), }, body: form, }); From e452ef75b84cceb4c1461faa76411e2c8aa9e2f7 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 16:23:04 +0000 Subject: [PATCH 21/30] refactor(js/plugins/anthropic): change file api discriminators slightly --- js/plugins/anthropic/src/runner/beta.ts | 4 ++-- js/testapps/anthropic/src/beta/files_api.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 3c81431f0e..54c96f7f24 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -190,7 +190,7 @@ export class BetaRunner extends BaseRunner { // Media if (part.media) { - if (part.media.contentType === 'file/document') { + if (part.media.contentType === 'anthropic/file') { return { type: 'document', source: { @@ -200,7 +200,7 @@ export class BetaRunner extends BaseRunner { }; } - if (part.media.contentType === 'file/image') { + if (part.media.contentType === 'anthropic/image') { return { type: 'image', source: { diff --git a/js/testapps/anthropic/src/beta/files_api.ts b/js/testapps/anthropic/src/beta/files_api.ts index fd7dc87457..3dd6b08d01 100644 --- a/js/testapps/anthropic/src/beta/files_api.ts +++ b/js/testapps/anthropic/src/beta/files_api.ts @@ -96,7 +96,7 @@ async function main() { { media: { url: fileId, - contentType: 'file/document', + contentType: 'anthropic/file', }, }, ], From 7cd800a9f7d2e6adf7c2b58240a29cef8c7c6665 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 16 Dec 2025 16:23:33 +0000 Subject: [PATCH 22/30] fix(anthropic): small correction --- js/plugins/anthropic/src/runner/stable.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 7ec0895774..766e0673e5 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -16,7 +16,7 @@ import { MessageStream } from '@anthropic-ai/sdk/lib/MessageStream.js'; import type { - MessageCreateParams as BetaMessageCreateParams, + MessageCreateParams, ContentBlock, DocumentBlockParam, ImageBlockParam, @@ -207,7 +207,7 @@ export class Runner extends BaseRunner { const thinkingConfig = this.toAnthropicThinkingConfig( request.config?.thinking - ) as BetaMessageCreateParams['thinking'] | undefined; + ) as MessageCreateParams['thinking'] | undefined; // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. @@ -272,7 +272,7 @@ export class Runner extends BaseRunner { const thinkingConfig = this.toAnthropicThinkingConfig( request.config?.thinking - ) as BetaMessageCreateParams['thinking'] | undefined; + ) as MessageCreateParams['thinking'] | undefined; // Need to extract topP and topK from request.config to avoid duplicate properties being added to the body // This happens because topP and topK have different property names (top_p and top_k) in the Anthropic API. From 5f5c6c201d46fcb6c76216a58cd2e7cd71bf05c7 Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Tue, 16 Dec 2025 16:36:35 +0000 Subject: [PATCH 23/30] chore: format --- js/plugins/anthropic/src/runner/stable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 766e0673e5..1496029ebd 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -16,11 +16,11 @@ import { MessageStream } from '@anthropic-ai/sdk/lib/MessageStream.js'; import type { - MessageCreateParams, ContentBlock, DocumentBlockParam, ImageBlockParam, Message, + MessageCreateParams, MessageCreateParamsNonStreaming, MessageCreateParamsStreaming, MessageParam, From ad283eb2e614dc0a2b796f96e579885b298bdadb Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 17:27:15 +0000 Subject: [PATCH 24/30] feat(js/plugins/anthropic): add support for opus 4.5 --- js/plugins/anthropic/src/models.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index 54225f2b24..9ba8129ef1 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -121,6 +121,20 @@ export const KNOWN_CLAUDE_MODELS: Record< }, } ), + 'claude-opus-4-5': commonRef( + 'claude-opus-4-5', + AnthropicThinkingConfigSchema, + { + supports: { + multiturn: true, + tools: true, + media: true, + systemRole: true, + output: ['text', 'json'], + constrained: 'all', + }, + } + ), }; /** From 0167bbd33268fcbe61b42abf6b5c49d1e96ee30c Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 16 Dec 2025 19:02:47 +0000 Subject: [PATCH 25/30] feat(js/plugins/anthropic): add structured response schema to opus 4.5 --- js/plugins/anthropic/src/models.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index f4275e9787..3b7f872179 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -119,7 +119,17 @@ export const KNOWN_CLAUDE_MODELS: Record< ), 'claude-opus-4-5': commonRef( 'claude-opus-4-5', - AnthropicThinkingConfigSchema + AnthropicThinkingConfigSchema, + { + supports: { + multiturn: true, + tools: true, + media: true, + systemRole: true, + output: ['text', 'json'], + constrained: 'all', + }, + } ), 'claude-opus-4-1': commonRef( 'claude-opus-4-1', From 3058acae73136f392aaf778d38192c66077b801a Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Thu, 18 Dec 2025 13:42:20 +0000 Subject: [PATCH 26/30] feat(anthropic): effort param and testapp --- js/plugins/anthropic/src/models.ts | 9 ++- js/plugins/anthropic/src/runner/beta.ts | 8 ++- js/testapps/anthropic/package.json | 1 + js/testapps/anthropic/src/beta/effort.ts | 79 ++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 js/testapps/anthropic/src/beta/effort.ts diff --git a/js/plugins/anthropic/src/models.ts b/js/plugins/anthropic/src/models.ts index 9ba8129ef1..d9359e01b1 100644 --- a/js/plugins/anthropic/src/models.ts +++ b/js/plugins/anthropic/src/models.ts @@ -123,7 +123,14 @@ export const KNOWN_CLAUDE_MODELS: Record< ), 'claude-opus-4-5': commonRef( 'claude-opus-4-5', - AnthropicThinkingConfigSchema, + AnthropicThinkingConfigSchema.extend({ + output_config: z + .object({ + effort: z.enum(['low', 'medium', 'high']).optional(), + }) + .passthrough() + .optional(), + }), { supports: { multiturn: true, diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 9fd7a306a1..76b07bdaac 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -84,7 +84,7 @@ const BETA_APIS = [ // 'context-management-2025-06-27', // 'model-context-window-exceeded-2025-08-26', // 'skills-2025-10-02', - // 'effort-param-2025-11-24', + 'effort-2025-11-24', // 'advanced-tool-use-2025-11-20', 'structured-outputs-2025-11-13', ]; @@ -308,6 +308,9 @@ export class BetaRunner extends BaseRunner { }; if (betaSystem !== undefined) body.system = betaSystem; + if (request.config?.output_config !== undefined) + body.output_config = request.config + .output_config as BetaMessageCreateParamsNonStreaming['output_config']; if (request.config?.stopSequences !== undefined) body.stop_sequences = request.config.stopSequences; if (request.config?.temperature !== undefined) @@ -379,6 +382,9 @@ export class BetaRunner extends BaseRunner { }; if (betaSystem !== undefined) body.system = betaSystem; + if (request.config?.output_config !== undefined) + body.output_config = request.config + .output_config as BetaMessageCreateParamsStreaming['output_config']; if (request.config?.stopSequences !== undefined) body.stop_sequences = request.config.stopSequences; if (request.config?.temperature !== undefined) diff --git a/js/testapps/anthropic/package.json b/js/testapps/anthropic/package.json index 08e1a0d2fd..cbd26f79c9 100644 --- a/js/testapps/anthropic/package.json +++ b/js/testapps/anthropic/package.json @@ -10,6 +10,7 @@ "start:beta": "node lib/beta/basic.js", "dev:stable": "genkit start -- npx tsx --watch src/stable/basic.ts", "dev:beta": "genkit start -- npx tsx --watch src/beta/basic.ts", + "dev:beta:effort": "genkit start -- npx tsx --watch src/beta/effort.ts", "dev:stable:text-plain": "genkit start -- npx tsx --watch src/stable/text-plain.ts", "dev:stable:webp": "genkit start -- npx tsx --watch src/stable/webp.ts", "dev:stable:pdf": "genkit start -- npx tsx --watch src/stable/pdf.ts", diff --git a/js/testapps/anthropic/src/beta/effort.ts b/js/testapps/anthropic/src/beta/effort.ts new file mode 100644 index 0000000000..03e83a60af --- /dev/null +++ b/js/testapps/anthropic/src/beta/effort.ts @@ -0,0 +1,79 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { anthropic } from '@genkit-ai/anthropic'; +import { genkit } from 'genkit'; + +const ai = genkit({ + plugins: [ + // Default all flows in this sample to the beta surface + anthropic({ + apiVersion: 'beta', + cacheSystemPrompt: true, + apiKey: process.env.ANTHROPIC_API_KEY, + }), + ], +}); + +const betaOpus45 = anthropic.model('claude-opus-4-5', { apiVersion: 'beta' }); + +ai.defineFlow('anthropic-beta-low-effort', async () => { + const { text } = await ai.generate({ + model: betaOpus45, + prompt: `Create me a Mathematics class using the programming language Python.`, + config: { + maxOutputTokens: 4096, + temperature: 0.6, + output_config: { + effort: 'low', + }, + }, + }); + + return text; +}); + +ai.defineFlow('anthropic-beta-medium-effort', async () => { + const { text } = await ai.generate({ + model: betaOpus45, + prompt: `Create me a Mathematics class using the programming language Python.`, + config: { + maxOutputTokens: 4096, + temperature: 0.6, + output_config: { + effort: 'medium', + }, + }, + }); + + return text; +}); + +ai.defineFlow('anthropic-beta-high-effort', async () => { + const { text } = await ai.generate({ + model: betaOpus45, + prompt: `Create me a Mathematics class using the programming language Python.`, + config: { + maxOutputTokens: 4096, + temperature: 0.6, + output_config: { + effort: 'high', + }, + }, + }); + + return text; +}); From 22dfb34d89a6c3207a9c186872ce3261ed071ed6 Mon Sep 17 00:00:00 2001 From: Darren Ackers Date: Mon, 29 Dec 2025 20:14:26 +0000 Subject: [PATCH 27/30] chore(anthropic): added effort unit tests --- .../anthropic/tests/effort_param_test.ts | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 js/plugins/anthropic/tests/effort_param_test.ts diff --git a/js/plugins/anthropic/tests/effort_param_test.ts b/js/plugins/anthropic/tests/effort_param_test.ts new file mode 100644 index 0000000000..12e67f4ed4 --- /dev/null +++ b/js/plugins/anthropic/tests/effort_param_test.ts @@ -0,0 +1,249 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type Anthropic from '@anthropic-ai/sdk'; +import * as assert from 'assert'; +import { genkit } from 'genkit'; +import { describe, test } from 'node:test'; +import { anthropic } from '../src/index.js'; +import { __testClient } from '../src/types.js'; +import { + createMockAnthropicClient, + createMockAnthropicMessage, + mockTextChunk, +} from './mocks/anthropic-client.js'; + +/** + * Options for creating a plugin with a mock client + */ +interface CreatePluginOptions { + apiVersion?: 'beta' | 'stable'; + mockClient: Anthropic; +} + +/** + * Creates an Anthropic plugin configured with a mock client for testing + */ +function createPlugin(options: CreatePluginOptions) { + return anthropic({ + apiVersion: options.apiVersion, + // @ts-ignore + [__testClient]: options.mockClient, + }); +} + +/** + * Creates a Genkit instance with the given plugin + */ +function createGenkitInstance(plugin: ReturnType) { + return genkit({ + plugins: [plugin], + }); +} + +/** + * Helper to get the proper create stub from the mock client for a given API version. + */ +function getCreateStub(mockClient: Anthropic, apiVersion: 'beta' | 'stable') { + return apiVersion === 'beta' + ? (mockClient.beta.messages.create as any) + : (mockClient.messages.create as any); +} + +/** + * Extracts the API request object from the mock for verification + * @param apiVersion - 'beta' or 'stable' to determine which API endpoint to check + */ +function getApiRequest( + mockClient: Anthropic, + apiVersion: 'beta' | 'stable', + callIndex: number = 0 +) { + const stub = getCreateStub(mockClient, apiVersion); + return stub.mock.calls[callIndex]?.arguments[0]; +} + +/** + * Verifies that the API was called the expected number of times + * @param apiVersion - 'beta' or 'stable' to determine which API endpoint to verify + */ +function verifyApiCalled( + mockClient: Anthropic, + apiVersion: 'beta' | 'stable', + expectedCalls: number = 1 +) { + const stub = getCreateStub(mockClient, apiVersion); + assert.strictEqual( + stub.mock.calls.length, + expectedCalls, + `${apiVersion === 'beta' ? 'Beta' : 'Stable'} API should be called ${expectedCalls} time(s)` + ); +} + +/** + * Tests for effort parameter functionality. + * These tests verify that output_config.effort is correctly passed to the Anthropic API + * when using the beta API with claude-opus-4-5. + */ +describe('Effort Parameter Tests', () => { + const OPUS_4_5_MODEL = 'anthropic/claude-opus-4-5'; + + test('should pass output_config.effort to API when using beta API with claude-opus-4-5', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: 'Response with high effort', + }), + }); + + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + await ai.generate({ + model: OPUS_4_5_MODEL, + prompt: 'Generate a detailed response', + config: { + output_config: { + effort: 'high', + }, + }, + }); + + verifyApiCalled(mockClient, 'beta'); + const apiRequest = getApiRequest(mockClient, 'beta'); + + assert.ok(apiRequest.output_config, 'Request should have output_config'); + assert.strictEqual( + apiRequest.output_config.effort, + 'high', + 'effort should be set to high' + ); + }); + + test('should pass output_config.effort with low value', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: 'Response with low effort', + }), + }); + + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + await ai.generate({ + model: OPUS_4_5_MODEL, + prompt: 'Generate a quick response', + config: { + output_config: { + effort: 'low', + }, + }, + }); + + verifyApiCalled(mockClient, 'beta'); + const apiRequest = getApiRequest(mockClient, 'beta'); + + assert.ok(apiRequest.output_config, 'Request should have output_config'); + assert.strictEqual( + apiRequest.output_config.effort, + 'low', + 'effort should be set to low' + ); + }); + + test('should pass output_config.effort with medium value', async () => { + const mockClient = createMockAnthropicClient({ + messageResponse: createMockAnthropicMessage({ + text: 'Response with medium effort', + }), + }); + + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + await ai.generate({ + model: OPUS_4_5_MODEL, + prompt: 'Generate a balanced response', + config: { + output_config: { + effort: 'medium', + }, + }, + }); + + verifyApiCalled(mockClient, 'beta'); + const apiRequest = getApiRequest(mockClient, 'beta'); + + assert.ok(apiRequest.output_config, 'Request should have output_config'); + assert.strictEqual( + apiRequest.output_config.effort, + 'medium', + 'effort should be set to medium' + ); + }); + + test('should pass output_config.effort in streaming requests', async () => { + const mockClient = createMockAnthropicClient({ + streamChunks: [mockTextChunk('Streaming response')], + messageResponse: createMockAnthropicMessage({ + text: 'Streaming response', + }), + }); + + const plugin = createPlugin({ + apiVersion: 'beta', + mockClient, + }); + + const ai = createGenkitInstance(plugin); + + await ai.generate({ + model: OPUS_4_5_MODEL, + prompt: 'Generate a streaming response', + config: { + output_config: { + effort: 'high', + }, + }, + streamingCallback: () => {}, + }); + + const betaStreamStub = mockClient.beta.messages.stream as any; + assert.strictEqual(betaStreamStub.mock.calls.length, 1); + const requestBody = betaStreamStub.mock.calls[0]?.arguments[0]; + + assert.ok( + requestBody.output_config, + 'Streaming request should have output_config' + ); + assert.strictEqual( + requestBody.output_config.effort, + 'high', + 'effort should be set to high in streaming request' + ); + }); +}); From 6635e6a4101d426e27cc3d42ce277a0851065948 Mon Sep 17 00:00:00 2001 From: Darren Ackers Date: Tue, 30 Dec 2025 12:30:24 +0000 Subject: [PATCH 28/30] chore(*): added fixes to execution tests --- js/plugins/anthropic/tests/execution_test.ts | 78 ++++++++++++++------ 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/js/plugins/anthropic/tests/execution_test.ts b/js/plugins/anthropic/tests/execution_test.ts index 069d2d2dcd..ae7b6a85e7 100644 --- a/js/plugins/anthropic/tests/execution_test.ts +++ b/js/plugins/anthropic/tests/execution_test.ts @@ -14,11 +14,12 @@ * limitations under the License. */ -import type { GenerateRequest, ModelAction } from '@genkit-ai/ai/model'; import * as assert from 'assert'; +import type { GenerateRequest } from 'genkit'; +import type { ModelAction } from 'genkit/model'; import { describe, mock, test } from 'node:test'; import { anthropic } from '../src/index.js'; -import { __testClient } from '../src/types.js'; +import { PluginOptions, __testClient } from '../src/types.js'; import { createMockAnthropicClient, createMockAnthropicMessage, @@ -35,11 +36,17 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); // Resolve the model action via plugin - const modelAction = plugin.resolve('model', 'claude-3-5-haiku-20241022'); - assert.ok(modelAction, 'Model should be resolved'); + const modelAction = plugin.resolve( + 'model', + 'claude-3-5-haiku-20241022' + ) as ModelAction; + assert.strictEqual( (modelAction as ModelAction).__action.name, 'anthropic/claude-3-5-haiku-20241022' @@ -55,11 +62,11 @@ describe('Model Execution Integration Tests', () => { ], }; - const response = await (modelAction as ModelAction)(request, { + const response = await modelAction(request, { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - }); + } as Parameters[1]); assert.ok(response, 'Response should be returned'); assert.ok(response.candidates, 'Response should have candidates'); @@ -86,7 +93,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); const modelAction = plugin.resolve( 'model', @@ -114,9 +124,10 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - }); + } as Parameters[1]); assert.ok(response, 'Response should be returned'); + assert.ok(response.candidates, 'Response should have candidates'); assert.strictEqual( response.candidates[0].message.content[0].text, 'The capital of France is Paris.' @@ -139,7 +150,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); const modelAction = plugin.resolve( 'model', @@ -163,7 +177,7 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - }); + } as Parameters[1]); assert.ok(response, 'Response should be returned'); @@ -197,7 +211,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); const modelAction = plugin.resolve( 'model', @@ -212,7 +229,7 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - } + } as Parameters[1] ); assert.ok(response.usage, 'Usage should be returned'); @@ -231,7 +248,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); const modelAction = plugin.resolve( 'model', @@ -246,10 +266,11 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - } + } as Parameters[1] ); assert.ok(response, 'Response should be returned'); + assert.ok(response.candidates, 'Response should have candidates'); assert.strictEqual(response.candidates[0].finishReason, 'length'); }); @@ -263,7 +284,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); // Resolve without prefix const modelAction = plugin.resolve( @@ -280,7 +304,7 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - } + } as Parameters[1] ); assert.ok(response, 'Response should be returned'); @@ -296,7 +320,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); // Resolve with prefix const modelAction = plugin.resolve( @@ -313,7 +340,7 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - } + } as Parameters[1] ); assert.ok(response, 'Response should be returned'); @@ -329,7 +356,10 @@ describe('Model Execution Integration Tests', () => { const plugin = anthropic({ apiKey: 'test-key', [__testClient]: mockClient, - }); + } as PluginOptions); + + // Verify plugin has resolve method + assert.ok(plugin.resolve, 'Plugin should have resolve method'); // Resolve unknown model (passes through to API) const modelAction = plugin.resolve( @@ -346,13 +376,15 @@ describe('Model Execution Integration Tests', () => { streamingRequested: false, sendChunk: mock.fn(), abortSignal: new AbortController().signal, - } + } as Parameters[1] ); assert.ok(response, 'Response should be returned for unknown model'); + assert.ok(response.candidates, 'Response should have candidates'); assert.strictEqual( - response.candidates[0].message.content[0].text, - 'Response from future model' + response.candidates?.[0]?.message.content[0].text, + 'Response from future model', + 'Response should have candidates' ); }); }); From 293c2c7c49f4ba2b08904dbfbb819381166a35a3 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:40:23 +0000 Subject: [PATCH 29/30] Update js/testapps/anthropic/src/beta/structured_output.ts Co-authored-by: Pavel Jbanov --- js/testapps/anthropic/src/beta/structured_output.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/testapps/anthropic/src/beta/structured_output.ts b/js/testapps/anthropic/src/beta/structured_output.ts index 725c9a0681..f454f51dfa 100644 --- a/js/testapps/anthropic/src/beta/structured_output.ts +++ b/js/testapps/anthropic/src/beta/structured_output.ts @@ -75,8 +75,8 @@ ai.defineFlow( const collected: string[] = []; for await (const chunk of stream) { if (chunk.text) { - collected.push(chunk.text); - sendChunk(chunk.text); + collected.push(chunk.output); + sendChunk(chunk.output); } } From 03486e77bd75deff99f114e8634a428cf4304daf Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:42:12 +0000 Subject: [PATCH 30/30] Update js/testapps/anthropic/src/beta/structured_output.ts --- js/testapps/anthropic/src/beta/structured_output.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/js/testapps/anthropic/src/beta/structured_output.ts b/js/testapps/anthropic/src/beta/structured_output.ts index f454f51dfa..36e8a1ee0f 100644 --- a/js/testapps/anthropic/src/beta/structured_output.ts +++ b/js/testapps/anthropic/src/beta/structured_output.ts @@ -68,7 +68,6 @@ ai.defineFlow( city: z.string(), }), format: 'json', - constrained: true, }, });