@genkit-ai/anthropic
Version:
Genkit AI framework plugin for Anthropic APIs.
377 lines • 11.9 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
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 beta_exports = {};
__export(beta_exports, {
BetaRunner: () => BetaRunner
});
module.exports = __toCommonJS(beta_exports);
var import_logging = require("genkit/logging");
var import_utils = require("../utils.js");
var import_base = require("./base.js");
var import_beta = require("./converters/beta.js");
var import_shared = require("./converters/shared.js");
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-2025-11-24",
// 'advanced-tool-use-2025-11-20',
"structured-outputs-2025-11-13",
"task-budgets-2026-03-13"
];
function toAnthropicSchema(schema) {
const out = structuredClone(schema);
delete out.$schema;
if (out.type === "object") {
out.additionalProperties = false;
}
for (const key in out) {
if (typeof out[key] === "object" && out[key] !== null) {
out[key] = toAnthropicSchema(out[key]);
}
}
return out;
}
class BetaRunner extends import_base.BaseRunner {
constructor(params) {
super(params);
}
/**
* Map a Genkit Part -> Anthropic beta content block param.
* Supports: text, images (base64 data URLs), PDFs (document source),
* tool_use (client tool request), tool_result (client tool response).
*/
toAnthropicMessageContent(part) {
if (part.reasoning) {
const signature = this.getThinkingSignature(part);
if (!signature) {
throw new Error(
"Anthropic thinking parts require a signature when sending back to the API. Preserve the `metadata.thoughtSignature` value from the original response."
);
}
return {
type: "thinking",
thinking: part.reasoning,
signature
};
}
const redactedThinking = this.getRedactedThinkingData(part);
if (redactedThinking !== void 0) {
return {
type: "redacted_thinking",
data: redactedThinking
};
}
if (part.text) {
return { type: "text", text: part.text };
}
if (part.custom?.anthropicDocument) {
return (0, import_beta.toBetaDocumentBlock)(
part.custom.anthropicDocument
);
}
if (part.media) {
if (part.media.contentType === "anthropic/file") {
return {
type: "document",
source: {
type: "file",
file_id: part.media.url
}
};
}
if (part.media.contentType === "anthropic/image") {
return {
type: "image",
source: {
type: "file",
file_id: part.media.url
}
};
}
if (part.media.contentType === "application/pdf") {
return {
type: "document",
source: this.toPdfDocumentSource(part.media)
};
}
const source = this.toImageSource(part.media);
if (source.kind === "base64") {
return {
type: "image",
source: {
type: "base64",
data: source.data,
media_type: source.mediaType
}
};
}
return {
type: "image",
source: {
type: "url",
url: source.url
}
};
}
if (part.toolRequest) {
if (!part.toolRequest.ref) {
throw new Error(
`Tool request ref is required for Anthropic API. Part: ${JSON.stringify(
part.toolRequest
)}`
);
}
return {
type: "tool_use",
id: part.toolRequest.ref,
name: part.toolRequest.name,
input: part.toolRequest.input
};
}
if (part.toolResponse) {
if (!part.toolResponse.ref) {
throw new Error(
`Tool response ref is required for Anthropic API. Part: ${JSON.stringify(
part.toolResponse
)}`
);
}
const betaResult = {
type: "tool_result",
tool_use_id: part.toolResponse.ref,
content: [this.toAnthropicToolResponseContent(part)]
};
return betaResult;
}
throw new Error(
`Unsupported genkit part fields encountered for current message role: ${JSON.stringify(
part
)}.`
);
}
createMessage(body, abortSignal) {
return this.client.beta.messages.create(body, { signal: abortSignal });
}
streamMessages(body, abortSignal) {
return this.client.beta.messages.stream(body, { signal: abortSignal });
}
/**
* Build non-streaming request body.
*/
toAnthropicRequestBody(modelName, request) {
const { system, messages } = this.toAnthropicMessages(request.messages);
const mappedModelName = request.config?.version ?? (0, import_utils.checkModelName)(modelName);
const thinkingConfig = this.toAnthropicThinkingConfig(
request.config?.thinking
);
const {
topP,
topK,
apiVersion: _1,
thinking: _2,
maxOutputTokens,
stopSequences,
version,
apiKey,
...restConfig
} = request.config ?? {};
const body = {
model: mappedModelName,
max_tokens: maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS,
messages,
system,
stop_sequences: stopSequences,
temperature: request.config?.temperature,
top_k: topK,
top_p: topP,
tool_choice: request.config?.tool_choice,
metadata: request.config?.metadata,
tools: request.tools?.map((tool) => this.toAnthropicTool(tool)),
thinking: thinkingConfig,
output_format: this.isStructuredOutputEnabled(request) ? {
type: "json_schema",
schema: toAnthropicSchema(request.output.schema)
} : void 0,
betas: Array.isArray(request.config?.betas) ? [...request.config?.betas ?? []] : [...BETA_APIS],
...restConfig
};
return (0, import_utils.removeUndefinedProperties)(body);
}
/**
* Build streaming request body.
*/
toAnthropicStreamingRequestBody(modelName, request) {
const { system, messages } = this.toAnthropicMessages(request.messages);
const mappedModelName = request.config?.version ?? (0, import_utils.checkModelName)(modelName);
const thinkingConfig = this.toAnthropicThinkingConfig(
request.config?.thinking
);
const {
topP,
topK,
apiVersion: _1,
thinking: _2,
maxOutputTokens,
stopSequences,
version,
apiKey,
...restConfig
} = request.config ?? {};
const body = {
model: mappedModelName,
max_tokens: maxOutputTokens ?? this.DEFAULT_MAX_OUTPUT_TOKENS,
messages,
stream: true,
system,
stop_sequences: stopSequences,
temperature: request.config?.temperature,
top_k: topK,
top_p: topP,
tool_choice: request.config?.tool_choice,
metadata: request.config?.metadata,
tools: request.tools?.map((tool) => this.toAnthropicTool(tool)),
thinking: thinkingConfig,
output_format: this.isStructuredOutputEnabled(request) ? {
type: "json_schema",
schema: toAnthropicSchema(request.output.schema)
} : void 0,
betas: Array.isArray(request.config?.betas) ? [...request.config?.betas ?? []] : [...BETA_APIS],
...restConfig
};
return (0, import_utils.removeUndefinedProperties)(body);
}
toGenkitResponse(message) {
return {
candidates: [
{
index: 0,
finishReason: this.fromBetaStopReason(message.stop_reason),
message: {
role: "model",
content: message.content.map(
(block) => this.fromBetaContentBlock(block)
)
}
}
],
usage: {
inputTokens: message.usage.input_tokens,
outputTokens: message.usage.output_tokens
},
custom: message,
raw: message
};
}
toGenkitPart(event) {
if (event.type === "content_block_start") {
return this.fromBetaContentBlock(event.content_block);
}
if (event.type === "content_block_delta") {
if (event.delta.type === "text_delta") {
return (0, import_shared.textDeltaToPart)(event.delta);
}
if (event.delta.type === "thinking_delta") {
return (0, import_shared.thinkingDeltaToPart)(event.delta);
}
if (event.delta.type === "citations_delta") {
return (0, import_shared.citationsDeltaToPart)(event.delta);
}
return void 0;
}
return void 0;
}
fromBetaContentBlock(contentBlock) {
switch (contentBlock.type) {
case "text":
return (0, import_shared.textBlockToPart)(contentBlock);
case "tool_use":
return (0, import_shared.toolUseBlockToPart)({
id: contentBlock.id,
name: contentBlock.name ?? "unknown_tool",
input: contentBlock.input
});
case "thinking":
return (0, import_shared.thinkingBlockToPart)(contentBlock);
case "redacted_thinking":
return (0, import_shared.redactedThinkingBlockToPart)(contentBlock);
case "server_tool_use":
return (0, import_beta.betaServerToolUseBlockToPart)(contentBlock);
case "web_search_tool_result":
return (0, import_shared.webSearchToolResultBlockToPart)(contentBlock);
// Unsupported beta server tool types
case "mcp_tool_use":
case "mcp_tool_result":
case "web_fetch_tool_result":
case "code_execution_tool_result":
case "bash_code_execution_tool_result":
case "text_editor_code_execution_tool_result":
case "container_upload":
case "tool_search_tool_result":
throw new Error((0, import_beta.unsupportedServerToolError)(contentBlock.type));
default: {
const unknownType = contentBlock.type;
import_logging.logger.warn(
`Unexpected Anthropic beta content block type: ${unknownType}. Returning empty text. Content block: ${JSON.stringify(contentBlock)}`
);
return { text: "" };
}
}
}
fromBetaStopReason(reason) {
switch (reason) {
case "max_tokens":
case "model_context_window_exceeded":
return "length";
case "end_turn":
case "stop_sequence":
case "tool_use":
case "pause_turn":
return "stop";
case null:
return "unknown";
case "refusal":
return "other";
default:
return "other";
}
}
isStructuredOutputEnabled(request) {
return !!(request.output?.schema && request.output.constrained && request.output.format === "json");
}
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BetaRunner
});
//# sourceMappingURL=beta.js.map