genkitx-anthropic
Version:
Firebase Genkit AI framework plugin for Anthropic APIs.
505 lines • 16.3 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
var claude_exports = {};
__export(claude_exports, {
AnthropicConfigSchema: () => AnthropicConfigSchema,
SUPPORTED_CLAUDE_MODELS: () => SUPPORTED_CLAUDE_MODELS,
claude35Haiku: () => claude35Haiku,
claude35Sonnet: () => claude35Sonnet,
claude37Sonnet: () => claude37Sonnet,
claude3Haiku: () => claude3Haiku,
claude3Opus: () => claude3Opus,
claude3Sonnet: () => claude3Sonnet,
claudeModel: () => claudeModel,
claudeRunner: () => claudeRunner,
fromAnthropicContentBlockChunk: () => fromAnthropicContentBlockChunk,
fromAnthropicResponse: () => fromAnthropicResponse,
fromAnthropicStopReason: () => fromAnthropicStopReason,
toAnthropicMessageContent: () => toAnthropicMessageContent,
toAnthropicMessages: () => toAnthropicMessages,
toAnthropicRequestBody: () => toAnthropicRequestBody,
toAnthropicRole: () => toAnthropicRole,
toAnthropicTool: () => toAnthropicTool,
toAnthropicToolResponseContent: () => toAnthropicToolResponseContent
});
module.exports = __toCommonJS(claude_exports);
var import_genkit = require("genkit");
var import_genkit2 = require("genkit");
var import_model = require("genkit/model");
const AnthropicConfigSchema = import_genkit2.GenerationCommonConfigSchema.extend({
tool_choice: import_genkit.z.union([
import_genkit.z.object({
type: import_genkit.z.literal("auto")
}),
import_genkit.z.object({
type: import_genkit.z.literal("any")
}),
import_genkit.z.object({
type: import_genkit.z.literal("tool"),
name: import_genkit.z.string()
})
]).optional(),
metadata: import_genkit.z.object({
user_id: import_genkit.z.string().optional()
}).optional()
});
const claude37Sonnet = (0, import_model.modelRef)({
name: "anthropic/claude-3-7-sonnet",
info: {
versions: ["claude-3-7-sonnet-20250219", "claude-3-7-sonnet-latest"],
label: "Anthropic - Claude 3.7 Sonnet",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-7-sonnet-latest"
});
const claude35Sonnet = (0, import_model.modelRef)({
name: "anthropic/claude-3-5-sonnet",
info: {
versions: [
"claude-3-5-sonnet-20240620",
"claude-3-5-sonnet-20241022",
"claude-3-5-sonnet-latest"
],
label: "Anthropic - Claude 3.5 Sonnet",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-5-sonnet-latest"
});
const claude3Opus = (0, import_model.modelRef)({
name: "anthropic/claude-3-opus",
info: {
versions: ["claude-3-opus-20240229"],
label: "Anthropic - Claude 3 Opus",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-opus-20240229"
});
const claude3Sonnet = (0, import_model.modelRef)({
name: "anthropic/claude-3-sonnet",
info: {
versions: ["claude-3-sonnet-20240229"],
label: "Anthropic - Claude 3 Sonnet",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-sonnet-20240229"
});
const claude3Haiku = (0, import_model.modelRef)({
name: "anthropic/claude-3-haiku",
info: {
versions: ["claude-3-haiku-20240307"],
label: "Anthropic - Claude 3 Haiku",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-haiku-20240307"
});
const claude35Haiku = (0, import_model.modelRef)({
name: "anthropic/claude-3-5-haiku",
info: {
versions: ["claude-3-5-haiku-20241022", "claude-3-5-haiku-latest"],
label: "Anthropic - Claude 3.5 Haiku",
supports: {
multiturn: true,
tools: true,
media: true,
systemRole: true,
output: ["text"]
}
},
configSchema: AnthropicConfigSchema,
version: "claude-3-5-haiku-latest"
});
const SUPPORTED_CLAUDE_MODELS = {
"claude-3-7-sonnet": claude37Sonnet,
"claude-3-5-sonnet": claude35Sonnet,
"claude-3-opus": claude3Opus,
"claude-3-sonnet": claude3Sonnet,
"claude-3-haiku": claude3Haiku,
"claude-3-5-haiku": claude35Haiku
};
function toAnthropicRole(role, toolMessageType) {
switch (role) {
case "user":
return "user";
case "model":
return "assistant";
case "tool":
return toolMessageType === "tool_use" ? "assistant" : "user";
default:
throw new Error(`role ${role} doesn't map to an Anthropic role.`);
}
}
const isMediaObject = (obj) => typeof obj === "object" && obj !== null && "url" in obj && typeof obj.url === "string";
const extractDataFromBase64Url = (url) => {
const match = url.match(/^data:([^;]+);base64,(.+)$/);
return match && {
contentType: match[1],
data: match[2]
};
};
function toAnthropicToolResponseContent(part) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
if (!part.toolResponse) {
throw Error(
`Invalid genkit part provided to toAnthropicToolResponseContent: ${JSON.stringify(
part
)}.`
);
}
const isMedia = isMediaObject((_a = part.toolResponse) == null ? void 0 : _a.output);
const isString = typeof ((_b = part.toolResponse) == null ? void 0 : _b.output) === "string";
let base64Data;
if (isMedia) {
base64Data = extractDataFromBase64Url(
((_c = part.toolResponse) == null ? void 0 : _c.output).url
);
} else if (isString) {
base64Data = extractDataFromBase64Url((_d = part.toolResponse) == null ? void 0 : _d.output);
}
return base64Data ? {
type: "image",
source: {
type: "base64",
data: base64Data.data,
media_type: (_g = (_f = (_e = part.toolResponse) == null ? void 0 : _e.output) == null ? void 0 : _f.contentType) != null ? _g : base64Data.contentType
}
} : {
type: "text",
text: isString ? (_h = part.toolResponse) == null ? void 0 : _h.output : JSON.stringify((_i = part.toolResponse) == null ? void 0 : _i.output)
};
}
function toAnthropicMessageContent(part) {
var _a, _b;
if (part.text) {
return {
type: "text",
text: part.text
};
}
if (part.media) {
const { data, contentType } = (_a = extractDataFromBase64Url(part.media.url)) != null ? _a : {};
if (!data) {
throw Error(
`Invalid genkit part media provided to toAnthropicMessageContent: ${JSON.stringify(
part.media
)}.`
);
}
return {
type: "image",
source: {
type: "base64",
data,
// @ts-expect-error TODO: improve these types
media_type: (_b = part.media.contentType) != null ? _b : contentType
}
};
}
if (part.toolRequest) {
return {
type: "tool_use",
id: part.toolRequest.ref,
name: part.toolRequest.name,
input: part.toolRequest.input
};
}
if (part.toolResponse) {
return {
type: "tool_result",
tool_use_id: part.toolResponse.ref,
content: [toAnthropicToolResponseContent(part)]
};
}
throw Error(
`Unsupported genkit part fields encountered for current message role: ${JSON.stringify(
part
)}.`
);
}
function toAnthropicMessages(messages) {
var _a, _b, _c;
const system = ((_a = messages[0]) == null ? void 0 : _a.role) === "system" ? (_c = (_b = messages[0].content) == null ? void 0 : _b[0]) == null ? void 0 : _c.text : void 0;
const messagesToIterate = system ? messages.slice(1) : messages;
const anthropicMsgs = [];
for (const message of messagesToIterate) {
const msg = new import_genkit.Message(message);
const content = msg.content.map(toAnthropicMessageContent);
const toolMessageType = content.find(
(c) => c.type === "tool_use" || c.type === "tool_result"
);
const role = toAnthropicRole(message.role, toolMessageType == null ? void 0 : toolMessageType.type);
anthropicMsgs.push({
role,
content
});
}
return { system, messages: anthropicMsgs };
}
function toAnthropicTool(tool) {
return {
name: tool.name,
description: tool.description,
input_schema: tool.inputSchema
};
}
function fromAnthropicContentBlock(contentBlock) {
return contentBlock.type === "tool_use" ? {
toolRequest: {
ref: contentBlock.id,
name: contentBlock.name,
input: contentBlock.input
}
} : { text: contentBlock.text };
}
function fromAnthropicContentBlockChunk(event) {
if (event.type !== "content_block_start" && event.type !== "content_block_delta") {
return;
}
const eventField = event.type === "content_block_start" ? "content_block" : "delta";
return ["text", "text_delta"].includes(event[eventField].type) ? {
text: event[eventField].text
} : {
toolRequest: {
ref: event[eventField].id,
name: event[eventField].name,
input: event[eventField].input
}
};
}
function fromAnthropicStopReason(reason) {
switch (reason) {
case "max_tokens":
return "length";
case "end_turn":
// fall through
case "stop_sequence":
// fall through
case "tool_use":
return "stop";
case null:
return "unknown";
default:
return "other";
}
}
function fromAnthropicResponse(response) {
return {
candidates: [
{
index: 0,
finishReason: fromAnthropicStopReason(response.stop_reason),
message: {
role: "model",
content: response.content.map(fromAnthropicContentBlock)
}
}
],
usage: {
inputTokens: response.usage.input_tokens,
outputTokens: response.usage.output_tokens
},
custom: response
};
}
function toAnthropicRequestBody(modelName, request, stream, cacheSystemPrompt) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
const model = SUPPORTED_CLAUDE_MODELS[modelName];
if (!model) throw new Error(`Unsupported model: ${modelName}`);
const { system, messages } = toAnthropicMessages(request.messages);
const mappedModelName = (_c = (_b = (_a = request.config) == null ? void 0 : _a.version) != null ? _b : model.version) != null ? _c : modelName;
const body = {
system: cacheSystemPrompt ? [
{
type: "text",
text: system,
// @ts-expect-error cache_control is in beta
cache_control: { type: "ephemeral" }
}
] : system,
messages,
tools: (_d = request.tools) == null ? void 0 : _d.map(toAnthropicTool),
max_tokens: (_f = (_e = request.config) == null ? void 0 : _e.maxOutputTokens) != null ? _f : 4096,
model: mappedModelName,
top_k: (_g = request.config) == null ? void 0 : _g.topK,
top_p: (_h = request.config) == null ? void 0 : _h.topP,
temperature: (_i = request.config) == null ? void 0 : _i.temperature,
stop_sequences: (_j = request.config) == null ? void 0 : _j.stopSequences,
metadata: (_k = request.config) == null ? void 0 : _k.metadata,
tool_choice: (_l = request.config) == null ? void 0 : _l.tool_choice,
stream
};
if (((_m = request.output) == null ? void 0 : _m.format) && request.output.format !== "text") {
throw new Error(
`Only text output format is supported for Claude models currently`
);
}
for (const key in body) {
if (!body[key] || Array.isArray(body[key]) && !body[key].length)
delete body[key];
}
return body;
}
function claudeRunner(name, client, cacheSystemPrompt) {
return (request, streamingCallback) => __async(this, null, function* () {
let response;
const body = toAnthropicRequestBody(
name,
request,
!!streamingCallback,
cacheSystemPrompt
);
if (streamingCallback) {
const stream = client.messages.stream(body);
try {
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
const chunk = temp.value;
const c = fromAnthropicContentBlockChunk(chunk);
if (c) {
streamingCallback({
index: 0,
content: [c]
});
}
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && (yield temp.call(iter));
} finally {
if (error)
throw error[0];
}
}
response = yield stream.finalMessage();
} else {
response = yield client.messages.create(body);
}
return fromAnthropicResponse(response);
});
}
function claudeModel(ai, name, client, cacheSystemPrompt) {
const modelId = `anthropic/${name}`;
const model = SUPPORTED_CLAUDE_MODELS[name];
if (!model) throw new Error(`Unsupported model: ${name}`);
return ai.defineModel(
__spreadProps(__spreadValues({
name: modelId
}, model.info), {
configSchema: model.configSchema
}),
claudeRunner(name, client, cacheSystemPrompt)
);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
AnthropicConfigSchema,
SUPPORTED_CLAUDE_MODELS,
claude35Haiku,
claude35Sonnet,
claude37Sonnet,
claude3Haiku,
claude3Opus,
claude3Sonnet,
claudeModel,
claudeRunner,
fromAnthropicContentBlockChunk,
fromAnthropicResponse,
fromAnthropicStopReason,
toAnthropicMessageContent,
toAnthropicMessages,
toAnthropicRequestBody,
toAnthropicRole,
toAnthropicTool,
toAnthropicToolResponseContent
});
//# sourceMappingURL=claude.js.map