From 4d4b19e26a178dc0f65153e4894b183059851c09 Mon Sep 17 00:00:00 2001 From: David Alonso Date: Sat, 11 May 2024 14:54:35 +0200 Subject: [PATCH 1/2] move anthropic plugin to plugins monorepo --- plugins/anthropic/.gitignore | 2 + plugins/anthropic/.npmignore | 17 ++ plugins/anthropic/README.md | 38 +++ plugins/anthropic/package.json | 61 +++++ plugins/anthropic/src/claude.ts | 340 +++++++++++++++++++++++++ plugins/anthropic/src/index.ts | 86 +++++++ plugins/anthropic/tests/claude_test.ts | 178 +++++++++++++ plugins/anthropic/tsconfig.json | 4 + plugins/anthropic/tsup.config.ts | 22 ++ 9 files changed, 748 insertions(+) create mode 100644 plugins/anthropic/.gitignore create mode 100644 plugins/anthropic/.npmignore create mode 100644 plugins/anthropic/README.md create mode 100644 plugins/anthropic/package.json create mode 100644 plugins/anthropic/src/claude.ts create mode 100644 plugins/anthropic/src/index.ts create mode 100644 plugins/anthropic/tests/claude_test.ts create mode 100644 plugins/anthropic/tsconfig.json create mode 100644 plugins/anthropic/tsup.config.ts diff --git a/plugins/anthropic/.gitignore b/plugins/anthropic/.gitignore new file mode 100644 index 00000000..46f10721 --- /dev/null +++ b/plugins/anthropic/.gitignore @@ -0,0 +1,2 @@ +lib/ +node_modules/ \ No newline at end of file diff --git a/plugins/anthropic/.npmignore b/plugins/anthropic/.npmignore new file mode 100644 index 00000000..d265d4ab --- /dev/null +++ b/plugins/anthropic/.npmignore @@ -0,0 +1,17 @@ +# typescript source files +src/ +tests/ +tsconfig.json +tsup.common.ts +tsup.config.ts + +# GitHub files +.github/ +.gitignore +.npmignore +CODE_OF_CONDUCT.md +CONTRIBUTING.md + +# Developer related files +.devcontainer/ +.vscode/ diff --git a/plugins/anthropic/README.md b/plugins/anthropic/README.md new file mode 100644 index 00000000..ff03db66 --- /dev/null +++ b/plugins/anthropic/README.md @@ -0,0 +1,38 @@ +

Firebase Genkit <> Anthropic AI Plugin

+ +

Anthropic AI Community Plugin for Google Firebase Genkit

+ +
+ +`genkitx-anthropicai` is a community plugin for using Anthropic AI and all its supported models with [Firebase GenKit](https://github.com/firebase/genkit). + +## Installation + +Install the plugin in your project with your favorite package manager: + +- `npm install genkitx-anthropicai` +- `yarn add genkitx-anthropicai` + +## Usage + +> \[!WARNING\]\ +> Documentation is currently work in progress. + +## Contributing + +Want to contribute to the project? That's awesome! Head over to our [Contribution Guidelines](CONTRIBUTING.md). + +## Need support? + +> \[!NOTE\]\ +> This repository depends on Google's Firebase Genkit. For issues and questions related to GenKit, please refer to instructions available in [GenKit's repository](https://github.com/firebase/genkit). + +Reach out by opening a discussion on [Github Discussions](https://github.com/TheFireCo/genkitx-openai/discussions). + +## Credits + +This plugin is proudly maintained by the team at [**The Fire Company**](https://github.com/TheFireCo). 🔥 + +## License + +This project is licensed under the [Apache 2.0 License](https://github.com/TheFireCo/genkitx-openai/blob/main/LICENSE). \ No newline at end of file diff --git a/plugins/anthropic/package.json b/plugins/anthropic/package.json new file mode 100644 index 00000000..65949bbf --- /dev/null +++ b/plugins/anthropic/package.json @@ -0,0 +1,61 @@ +{ + "name": "genkitx-anthropicai", + "description": "Firebase Genkit AI framework plugin for Anthropic AI APIs.", + "keywords": [ + "genkit", + "genkit-plugin", + "genkit-model", + "anthropic", + "anthropicai", + "claude", + "claude-3", + "sonnet", + "haiku", + "opus", + "ai", + "genai", + "generative-ai" + ], + "version": "0.0.0", + "type": "commonjs", + "repository": { + "type": "git", + "url": "git+https://github.com/TheFireCo/genkit-plugins.git", + "directory": "plugins/anthropic" + }, + "author": "TheFireCo", + "license": "Apache-2.0", + "dependencies": { + "@genkit-ai/ai": "0.5.0-rc.8", + "@genkit-ai/core": "0.5.0-rc.8", + "@anthropic-ai/sdk": "^0.20.9", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.11.16", + "npm-run-all": "^4.1.5", + "tsup": "^8.0.2", + "tsx": "^4.7.0", + "typescript": "^4.9.5" + }, + "types": "./lib/index.d.ts", + "exports": { + ".": { + "require": "./lib/index.js", + "default": "./lib/index.js", + "import": "./lib/index.mjs", + "types": "./lib/index.d.ts" + } + }, + "files": [ + "lib" + ], + "scripts": { + "check": "tsc", + "compile": "tsup-node", + "build:clean": "rm -rf ./lib", + "build": "npm-run-all build:clean check compile", + "build:watch": "tsup-node --watch", + "test": "node --import tsx --test ./tests/*_test.ts" + } +} diff --git a/plugins/anthropic/src/claude.ts b/plugins/anthropic/src/claude.ts new file mode 100644 index 00000000..d4e0843c --- /dev/null +++ b/plugins/anthropic/src/claude.ts @@ -0,0 +1,340 @@ +/** + * Copyright 2024 The Fire Company + * + * 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 { Message } from "@genkit-ai/ai"; +import { + CandidateData, + defineModel, + GenerateRequest, + MessageData, + modelRef, + ModelReference, + Part, + Role, +} from "@genkit-ai/ai/model"; +import Anthropic from "@anthropic-ai/sdk"; +import z from "zod"; + +const MODEL_VERSION_MAP: Record = { + "claude-3-opus": "claude-3-opus-20240229", + "claude-3-sonnet": "claude-3-sonnet-20240229", + "claude-3-haiku": "claude-3-haiku-20240307", +}; + +const AnthropicConfigSchema = z.object({ + metadata: z + .object({ + user_id: z.string().optional(), + }) + .optional(), +}); + +export const claude3Haiku = modelRef({ + name: "anthropic/claude-3-haiku", + info: { + versions: ["claude-3-haiku-20240307"], + label: "Anthropic - Claude 3 Haiku", + supports: { + multiturn: true, + tools: false, + media: true, + output: ["text"], + }, + }, + configSchema: AnthropicConfigSchema, +}); + +export const claude3Sonnet = modelRef({ + name: "anthropic/claude-3-sonnet", + info: { + versions: ["claude-3-sonnet-20240229"], + label: "Anthropic - Claude 3 Sonnet", + supports: { + multiturn: true, + tools: false, + media: true, + output: ["text"], + }, + }, + configSchema: AnthropicConfigSchema, +}); + +export const claude3Opus = modelRef({ + name: "anthropic/claude-3-opus", + info: { + versions: ["claude-3-opus-20240229"], + label: "Anthropic - Claude 3 Opus", + supports: { + multiturn: true, + tools: false, + media: true, + output: ["text"], + }, + }, + configSchema: AnthropicConfigSchema, +}); + +export const SUPPORTED_CLAUDE_MODELS: Record< + string, + ModelReference +> = { + "claude-3-haiku": claude3Haiku, + "claude-3-sonnet": claude3Sonnet, + "claude-3-opus": claude3Opus, +}; + +/** + * Converts a Genkit role to the corresponding Anthropic role. + * @param role The Genkit role to convert. + * @returns The corresponding Anthropic role. + * @throws Error if the role doesn't map to an Anthropic role. + */ +function toAnthropicRole(role: Role): Anthropic.MessageParam["role"] { + switch (role) { + case "user": + return "user"; + case "model": + return "assistant"; + default: + throw new Error(`Role ${role} doesn't map to an Anthropic role.`); + } +} + +/** + * Converts a Genkit Part to the corresponding Anthropic TextBlock or ImageBlockParam. + * @param part The Genkit Part to convert. + * @returns The corresponding Anthropic TextBlock or ImageBlockParam. + * @throws Error if the part contains unsupported fields for the current message role. + */ +export function toAnthropicTextAndMedia( + part: Part +): Anthropic.TextBlock | Anthropic.ImageBlockParam { + if (part.text) { + return { + type: "text", + text: part.text, + } as Anthropic.TextBlock; + } else if (part.media) { + return { + type: "image", + source: { + type: "base64", + data: part.media.url.substring(part.media.url.indexOf(",") + 1), + media_type: + part.media.contentType || + part.media.url.substring("data:".length, part.media.url.indexOf(";")), + }, + } as Anthropic.ImageBlockParam; + } + throw Error( + `Unsupported Genkit part fields encountered. Current message role does not support the provided part structure: ${JSON.stringify( + part + )}.` + ); +} + +/** + * Converts a Genkit MessageData array to an Anthropic system message and MessageParam array. + * @param messages The Genkit MessageData array to convert. + * @returns An object containing the optional Anthropic system message and the array of Anthropic MessageParam objects. + */ +export function toAnthropicMessages(messages: MessageData[]): { + system?: string; + messages: Anthropic.Messages.MessageParam[]; +} { + let systemMessage: string | undefined; + if (messages[0]?.role === "system") { + systemMessage = messages[0].content?.[0]?.text; + } + const messagesToMap = systemMessage ? messages.slice(1) : messages; + const mappedMessages: Anthropic.Messages.MessageParam[] = []; + messagesToMap.forEach((message) => { + const msg = new Message(message); + const role = toAnthropicRole(message.role); + switch (role) { + case "assistant": + mappedMessages.push({ + role: role, + content: msg.text(), + }); + break; + case "user": + mappedMessages.push({ + role: role, + content: msg.content.map(toAnthropicTextAndMedia), + }); + break; + default: + throw new Error(`Unrecognized role: ${role}`); + } + }); + return { system: systemMessage, messages: mappedMessages }; +} + +const FINISH_REASON_MAP: Record< + NonNullable, + CandidateData["finishReason"] +> = { + end_turn: "stop", + max_tokens: "length", + stop_sequence: "stop", +}; + +/** + * Converts an Anthropic content block to a Genkit CandidateData object. + * @param choice The Anthropic content block to convert. + * @param index The index of the content block. + * @param stopReason The reason the content block generation stopped. + * @returns The converted Genkit CandidateData object. + */ +export function fromAnthropicContentBlock( + choice: Anthropic.Messages.ContentBlock, + index: number, + stopReason: Anthropic.Message["stop_reason"] +): CandidateData { + return { + finishReason: (stopReason && FINISH_REASON_MAP[stopReason]) || "other", + index, + message: { + role: "model", + content: [{ text: choice.text }], + }, + }; +} + +/** + * Converts an Anthropic message stream event to a Genkit CandidateData object. + * @param choice The Anthropic message stream event to convert. + * @returns The converted Genkit CandidateData object if the event is a content block start or delta, otherwise undefined. + */ +export function fromAnthropicContentBlockChunk( + choice: Anthropic.MessageStreamEvent +): CandidateData | undefined { + if ( + choice.type !== "content_block_delta" && + choice.type !== "content_block_start" + ) { + return; + } + return { + finishReason: "unknown", + index: choice.index, + message: { + role: "model", + content: [ + { + text: + choice.type === "content_block_start" + ? choice.content_block.text + : choice.delta.text, + }, + ], + }, + }; +} + +/** + * Converts an Anthropic request to an Anthropic API request body. + * @param modelName The name of the Anthropic model to use. + * @param request The Genkit GenerateRequest to convert. + * @param stream Whether to stream the response. + * @returns The converted Anthropic API request body. + * @throws An error if the specified model is not supported or if an unsupported output format is requested. + */ +export function toAnthropicRequestBody( + modelName: string, + request: GenerateRequest, + stream?: boolean +): Anthropic.Messages.MessageCreateParams { + const model = SUPPORTED_CLAUDE_MODELS[modelName]; + if (!model) throw new Error(`Unsupported model: ${modelName}`); + const mappedModelName = MODEL_VERSION_MAP[modelName] || modelName; + const { system, messages } = toAnthropicMessages(request.messages); + const body: Anthropic.MessageCreateParams = { + system, + messages, + max_tokens: request.config?.maxOutputTokens ?? 4096, + model: mappedModelName, + top_k: request.config?.topK, + top_p: request.config?.topP, + temperature: request.config?.temperature, + stop_sequences: request.config?.stopSequences, + stream, + ...(request.config?.custom || {}), + }; + + if (request.output?.format && request.output.format !== "text") { + throw new Error( + `Claude models currently support only the 'text' output format.` + ); + } + for (const key in body) { + if (!body[key] || (Array.isArray(body[key]) && !body[key].length)) + delete body[key]; + } + return body; +} + +/** + * Defines a Claude model with the given name and Anthropic client. + * @param name The name of the Claude model. + * @param client The Anthropic client instance. + * @returns The defined Claude model. + * @throws An error if the specified model is not supported. + */ +export function claudeModel(name: string, client: Anthropic) { + const model = SUPPORTED_CLAUDE_MODELS[name]; + if (!model) throw new Error(`Unsupported model: ${name}`); + + const modelId = `anthropic/${name}`; + + return defineModel( + { + name: modelId, + ...model.info, + configSchema: SUPPORTED_CLAUDE_MODELS[name].configSchema, + }, + async (request, streamingCallback) => { + let response: Anthropic.Message; + const body = toAnthropicRequestBody(name, request, !!streamingCallback); + if (streamingCallback) { + const stream = client.messages.stream(body); + for await (const chunk of stream) { + const c = fromAnthropicContentBlockChunk(chunk); + if (c) { + streamingCallback({ + index: c.index, + content: c.message.content, + }); + } + } + response = await stream.finalMessage(); + } else { + response = (await client.messages.create(body)) as Anthropic.Message; + } + return { + candidates: response.content.map((content, index) => + fromAnthropicContentBlock(content, index, response.stop_reason) + ), + usage: { + inputTokens: response.usage.input_tokens, + outputTokens: response.usage.output_tokens, + }, + custom: response, + }; + } + ); +} diff --git a/plugins/anthropic/src/index.ts b/plugins/anthropic/src/index.ts new file mode 100644 index 00000000..f9b1408b --- /dev/null +++ b/plugins/anthropic/src/index.ts @@ -0,0 +1,86 @@ +/** + * Copyright 2024 The Fire Company + * + * 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 { genkitPlugin, Plugin } from '@genkit-ai/core'; +import Anthropic from '@anthropic-ai/sdk'; +import { + claude3Haiku, + claude3Sonnet, + claude3Opus, + claudeModel, + SUPPORTED_CLAUDE_MODELS, +} from './claude'; + +export { + claude3Haiku, + claude3Sonnet, + claude3Opus, +}; + +export interface PluginOptions { + apiKey?: string; +} + +/** + * This module provides an interface to the Anthropic AI models through the Genkit plugin system. + * It allows users to interact with various Claude models by providing an API key and optional configuration. + * + * The main export is the `anthropic` plugin, which can be configured with an API key either directly or through + * environment variables. It initializes the Anthropic client and makes available the Claude models for use. + * + * Exports: + * - claude3Haiku: Reference to the Claude 3 Haiku model. + * - claude3Sonnet: Reference to the Claude 3 Sonnet model. + * - claude3Opus: Reference to the Claude 3 Opus model. + * - anthropic: The main plugin function to interact with the Anthropic AI. + * + * Usage: + * To use the Claude models, initialize the anthropic plugin inside `configureGenkit` and pass the configuration options. If no API key is provided in the options, the environment variable `ANTHROPIC_API_KEY` must be set. + * + * Example: + * ``` + * import anthropic from 'genkitx-anthropicai'; + * + * export default configureGenkit({ + * plugins: [ + * anthropic({ apiKey: 'your-api-key' }) + * ... // other plugins + * ] + * }); + * ``` + */ +// TODO: add support for voyage embeddings and tool use (both not documented well in docs.anthropic.com) +export const anthropic: Plugin<[PluginOptions] | []> = genkitPlugin( + 'anthropic', + async (options?: PluginOptions) => { + let apiKey = options?.apiKey || process.env.ANTHROPIC_API_KEY; + if (!apiKey) + throw new Error( + 'Please pass in the API key or set the ANTHROPIC_API_KEY environment variable' + ); + const client = new Anthropic({apiKey}); + return { + models: [ + ...Object.keys(SUPPORTED_CLAUDE_MODELS).map((name) => + claudeModel(name, client) + ), + ], + }; + } +); + +export default anthropic; + diff --git a/plugins/anthropic/tests/claude_test.ts b/plugins/anthropic/tests/claude_test.ts new file mode 100644 index 00000000..7df87ed3 --- /dev/null +++ b/plugins/anthropic/tests/claude_test.ts @@ -0,0 +1,178 @@ +import { GenerateRequest, MessageData } from '@genkit-ai/ai/model'; +import assert from 'node:assert'; +import { describe, it } from 'node:test'; +import { fromAnthropicContentBlock, fromAnthropicContentBlockChunk, toAnthropicMessages, toAnthropicRequestBody } from '../src/claude.ts'; +import { ContentBlockStartEvent, TextBlock } from '@anthropic-ai/sdk/resources/messages'; + +describe('toAnthropicMessages', () => { + it('should correctly convert simple text messages', () => { + const inputMessages: MessageData[] = [ + { role: 'user', content: [{ text: 'Hello' }] }, + { role: 'model', content: [{ text: 'Welcome!' }] } + ]; + const expected = { + messages: [ + { role: 'user', content: [{ type: 'text', text: 'Hello' }] }, + { role: 'assistant', content: 'Welcome!' } + ], + system: undefined + }; + const result = toAnthropicMessages(inputMessages); + assert.deepStrictEqual(result, expected); + }); + + it('should handle system messages and convert subsequent user message', () => { + const inputMessages: MessageData[] = [ + { role: 'system', content: [{ text: 'System initialization' }] }, + { role: 'user', content: [{ text: 'System test' }] } + ]; + const expected = { + messages: [ + { role: 'user', content: [{ type: 'text', text: 'System test' }] } + ], + system: 'System initialization' + }; + const result = toAnthropicMessages(inputMessages); + assert.deepStrictEqual(result, expected); + }); +}); + +describe('toAnthropicRequestBody', () => { + it('should create a valid request body for a simple text message', () => { + const modelName = 'claude-3-haiku'; + const genkitRequest: GenerateRequest = { + messages: [{ role: 'user', content: [{ text: 'What is AI?' }] }], + output: { format: 'text' } + }; + const expected = { + max_tokens: 4096, + messages: [ + { role: 'user', content: [{ type: 'text', text: 'What is AI?' }] } + ], + model: 'claude-3-haiku-20240307' + }; + const result = toAnthropicRequestBody(modelName, genkitRequest); + assert.deepStrictEqual(result, expected); + }); + + it('should handle custom configuration and metadata', () => { + const modelName = 'claude-3-opus'; + const genkitRequest: GenerateRequest = { + messages: [{ role: 'user', content: [{ text: 'Explain quantum computing.' }] }], + output: { format: 'text' }, + config: { + maxOutputTokens: 500, + custom: { metadata: { user_id: 'user123' } } + } + }; + const expected = { + max_tokens: 500, + messages: [ + { role: 'user', content: [{ type: 'text', text: 'Explain quantum computing.' }] } + ], + model: 'claude-3-opus-20240229', + metadata: { user_id: 'user123' } + }; + const result = toAnthropicRequestBody(modelName, genkitRequest); + assert.deepStrictEqual(result, expected); + }); +}); + +it('should handle streaming requests correctly', () => { + const modelName = 'claude-3-sonnet'; + const genkitRequest: GenerateRequest = { + messages: [{ role: 'user', content: [{ text: 'Narrate a story.' }] }], + output: { format: 'text' }, + config: { + maxOutputTokens: 1000 + } + }; + const expected = { + max_tokens: 1000, + messages: [ + { role: 'user', content: [{ type: 'text', text: 'Narrate a story.' }] } + ], + model: 'claude-3-sonnet-20240229', + stream: true + }; + const result = toAnthropicRequestBody(modelName, genkitRequest, true); + assert.deepStrictEqual(result, expected); +}); + +it('should throw an error for unsupported model names', () => { + const modelName = 'claude-3-unknown'; + const genkitRequest: GenerateRequest = { + messages: [{ role: 'user', content: [{ text: 'Hello' }] }], + output: { format: 'text' } + }; + assert.throws(() => { + toAnthropicRequestBody(modelName, genkitRequest); + }, new Error('Unsupported model: claude-3-unknown')); +}); + +describe('fromAnthropicContentBlock', () => { + it('should convert content blocks to candidate data correctly', () => { + const contentBlock = { + text: 'Sample response text', + type: 'text', + } as TextBlock; + const expected = { + finishReason: 'stop', + index: 0, + message: { + role: 'model', + content: [{ text: 'Sample response text' }] + } + }; + const result = fromAnthropicContentBlock(contentBlock, 0, "end_turn"); + assert.deepStrictEqual(result, expected); + }); + + it('should handle undefined stop reasons', () => { + const contentBlock = { + text: 'Another sample text', + type: 'text', + } as TextBlock; + const expected = { + finishReason: 'other', + index: 1, + message: { + role: 'model', + content: [{ text: 'Another sample text' }] + } + }; + const stopReason = undefined; + const result = fromAnthropicContentBlock(contentBlock, 1, stopReason as any); + assert.deepStrictEqual(result, expected); + }); +}); + +describe('fromAnthropicContentBlockChunk', () => { + it('should convert content block start events to candidate data', () => { + const event: ContentBlockStartEvent = { + type: 'content_block_start', + index: 0, + content_block: { text: 'Start of content block', type: 'text' } + }; + const expected = { + finishReason: 'unknown', + index: 0, + message: { + role: 'model', + content: [{ text: 'Start of content block' }] + } + }; + const result = fromAnthropicContentBlockChunk(event); + assert.deepStrictEqual(result, expected); + }); + + it('should return undefined for non-content block events', () => { + const event = { + type: 'non_content_event', + index: 0, + content_block: { text: 'Should not process' } + }; + const result = fromAnthropicContentBlockChunk(event as any); + assert.strictEqual(result, undefined); + }); +}); \ No newline at end of file diff --git a/plugins/anthropic/tsconfig.json b/plugins/anthropic/tsconfig.json new file mode 100644 index 00000000..674e85d9 --- /dev/null +++ b/plugins/anthropic/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src"] +} \ No newline at end of file diff --git a/plugins/anthropic/tsup.config.ts b/plugins/anthropic/tsup.config.ts new file mode 100644 index 00000000..10c67bba --- /dev/null +++ b/plugins/anthropic/tsup.config.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2024 The Fire Company + * + * 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 { defineConfig, Options } from 'tsup'; +import { defaultOptions } from '../../tsup.common'; + +export default defineConfig({ + ...(defaultOptions as Options), +}); From 3f5e2afbf0cfd72c8afd0eb4cddd42923aca5ca6 Mon Sep 17 00:00:00 2001 From: David Alonso Date: Sat, 11 May 2024 15:31:19 +0200 Subject: [PATCH 2/2] update package-lock.json --- package-lock.json | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/package-lock.json b/package-lock.json index 2c07d4d2..380be691 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,29 @@ "lerna": "^8.1.2" } }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.20.9", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.20.9.tgz", + "integrity": "sha512-Lq74+DhiEQO6F9/gdVOLmHx57pX45ebK2Q/zH14xYe1157a7QeUVknRqIp0Jz5gQI01o7NKbuv9Dag2uQsLjDg==", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + } + }, + "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { + "version": "18.19.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.33.tgz", + "integrity": "sha512-NR9+KrpSajr2qBVp/Yt5TU/rp+b5Mayi3+OlMlcg2cVCfRmcG5PWZ7S4+MG9PZ5gWBoc9Pd0BKSRViuBCRPu0A==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", @@ -6239,6 +6262,10 @@ "node": ">=14" } }, + "node_modules/genkitx-anthropicai": { + "resolved": "plugins/anthropic", + "link": true + }, "node_modules/genkitx-cohere": { "resolved": "plugins/cohere", "link": true @@ -14521,6 +14548,36 @@ "zod": "^3.23.3" } }, + "plugins/anthropic": { + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@anthropic-ai/sdk": "^0.20.9", + "@genkit-ai/ai": "0.5.0-rc.8", + "@genkit-ai/core": "0.5.0-rc.8", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.11.16", + "npm-run-all": "^4.1.5", + "tsup": "^8.0.2", + "tsx": "^4.7.0", + "typescript": "^4.9.5" + } + }, + "plugins/anthropic/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "plugins/cohere": { "name": "genkitx-cohere", "version": "0.0.8",