@veryfront/ext-llm-anthropic 0.1.985
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +159 -0
- package/esm/_dnt.polyfills.d.ts +50 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +37 -0
- package/esm/_dnt.shims.d.ts +12 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +68 -0
- package/esm/anthropic-provider.d.ts +26 -0
- package/esm/anthropic-provider.d.ts.map +1 -0
- package/esm/anthropic-provider.js +206 -0
- package/esm/anthropic-request-builder.d.ts +98 -0
- package/esm/anthropic-request-builder.d.ts.map +1 -0
- package/esm/anthropic-request-builder.js +403 -0
- package/esm/anthropic-stream.d.ts +12 -0
- package/esm/anthropic-stream.d.ts.map +1 -0
- package/esm/anthropic-stream.js +413 -0
- package/esm/index.d.ts +13 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/index.js +34 -0
- package/esm/package.json +3 -0
- package/package.json +63 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic provider - implements the {@link LLMProvider} contract for
|
|
3
|
+
* Anthropic's Messages API (direct + via Veryfront Cloud / Bedrock-compatible
|
|
4
|
+
* proxies).
|
|
5
|
+
*
|
|
6
|
+
* Ported from `src/provider/runtime-loader.ts` as part of PR 12.
|
|
7
|
+
*
|
|
8
|
+
* @module extensions/ext-llm-anthropic/anthropic-provider
|
|
9
|
+
*/
|
|
10
|
+
import { buildProviderError, createAnthropicRequestInit, createWarningCollector, getAnthropicMessagesUrl, isNumberArray, mergeUsage, parseRetryAfterMs, ProviderError, ProviderOverloadedError, ProviderQuotaError, ProviderRateLimitError, ProviderRequestError, readRecord, requestJson, requestStream, stringifyJsonValue, TOOL_INPUT_PENDING_THRESHOLD_MS, withToolInputStatusTransitions, } from "veryfront/provider/shared";
|
|
11
|
+
import { buildAnthropicMessagesRequest, } from "./anthropic-request-builder.js";
|
|
12
|
+
import { extractAnthropicUsage, normalizeAnthropicFinishReason, streamAnthropicCompatibleParts, } from "./anthropic-stream.js";
|
|
13
|
+
export { buildProviderError, isNumberArray, mergeUsage, parseRetryAfterMs, ProviderError, ProviderOverloadedError, ProviderQuotaError, ProviderRateLimitError, ProviderRequestError, TOOL_INPUT_PENDING_THRESHOLD_MS, withToolInputStatusTransitions, };
|
|
14
|
+
/**
|
|
15
|
+
* Best-effort camelCase normalization of a single Anthropic citation
|
|
16
|
+
* record. Handles the union of fields across web_search_result_location,
|
|
17
|
+
* web_fetch_result_location, char_location, page_location, and
|
|
18
|
+
* content_block_location citation kinds - see
|
|
19
|
+
* https://docs.claude.com/en/docs/build-with-claude/citations
|
|
20
|
+
*/
|
|
21
|
+
function normalizeAnthropicCitation(raw) {
|
|
22
|
+
const r = readRecord(raw);
|
|
23
|
+
if (!r)
|
|
24
|
+
return undefined;
|
|
25
|
+
const typeStr = typeof r.type === "string" ? r.type : undefined;
|
|
26
|
+
if (!typeStr)
|
|
27
|
+
return undefined;
|
|
28
|
+
const out = { type: typeStr };
|
|
29
|
+
if (typeof r.cited_text === "string")
|
|
30
|
+
out.citedText = r.cited_text;
|
|
31
|
+
if (typeof r.url === "string")
|
|
32
|
+
out.url = r.url;
|
|
33
|
+
if (typeof r.title === "string")
|
|
34
|
+
out.title = r.title;
|
|
35
|
+
if (typeof r.start_char_index === "number")
|
|
36
|
+
out.startCharIndex = r.start_char_index;
|
|
37
|
+
if (typeof r.end_char_index === "number")
|
|
38
|
+
out.endCharIndex = r.end_char_index;
|
|
39
|
+
if (typeof r.start_block_index === "number")
|
|
40
|
+
out.startBlockIndex = r.start_block_index;
|
|
41
|
+
if (typeof r.end_block_index === "number")
|
|
42
|
+
out.endBlockIndex = r.end_block_index;
|
|
43
|
+
if (typeof r.start_page_number === "number")
|
|
44
|
+
out.startPageNumber = r.start_page_number;
|
|
45
|
+
if (typeof r.end_page_number === "number")
|
|
46
|
+
out.endPageNumber = r.end_page_number;
|
|
47
|
+
if (typeof r.document_index === "number")
|
|
48
|
+
out.documentIndex = r.document_index;
|
|
49
|
+
if (typeof r.document_title === "string")
|
|
50
|
+
out.documentTitle = r.document_title;
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
function buildAnthropicGenerateResult(payload) {
|
|
54
|
+
const record = readRecord(payload);
|
|
55
|
+
const content = Array.isArray(record?.content) ? record.content : [];
|
|
56
|
+
const normalized = [];
|
|
57
|
+
for (const blockValue of content) {
|
|
58
|
+
const block = readRecord(blockValue);
|
|
59
|
+
const blockType = typeof block?.type === "string" ? block.type : undefined;
|
|
60
|
+
if (blockType === "text" && typeof block?.text === "string" && block.text.length > 0) {
|
|
61
|
+
const citationsRaw = Array.isArray(block.citations) ? block.citations : undefined;
|
|
62
|
+
const citations = citationsRaw
|
|
63
|
+
?.flatMap((c) => {
|
|
64
|
+
const normalizedCitation = normalizeAnthropicCitation(c);
|
|
65
|
+
return normalizedCitation ? [normalizedCitation] : [];
|
|
66
|
+
});
|
|
67
|
+
normalized.push({
|
|
68
|
+
type: "text",
|
|
69
|
+
text: block.text,
|
|
70
|
+
...(citations && citations.length > 0 ? { citations } : {}),
|
|
71
|
+
});
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// Thinking blocks carry the cleartext trace plus a signature that
|
|
75
|
+
// Anthropic uses to verify on subsequent turns. Surfacing both lets
|
|
76
|
+
// callers persist them as `reasoning` content parts and replay on
|
|
77
|
+
// the next turn so Claude can continue from the same thinking.
|
|
78
|
+
if (blockType === "thinking") {
|
|
79
|
+
normalized.push({
|
|
80
|
+
type: "reasoning",
|
|
81
|
+
...(typeof block?.thinking === "string" ? { text: block.thinking } : {}),
|
|
82
|
+
...(typeof block?.signature === "string" ? { signature: block.signature } : {}),
|
|
83
|
+
});
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// Redacted thinking blocks arrive when Claude's safety classifier
|
|
87
|
+
// hides the trace. Pass the encrypted blob through opaquely so the
|
|
88
|
+
// caller can replay it on the next turn (Anthropic still needs the
|
|
89
|
+
// blob to verify continuity even though it can't read it).
|
|
90
|
+
if (blockType === "redacted_thinking" && typeof block?.data === "string") {
|
|
91
|
+
normalized.push({
|
|
92
|
+
type: "reasoning",
|
|
93
|
+
redactedData: block.data,
|
|
94
|
+
});
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if ((blockType === "tool_use" || blockType === "server_tool_use") &&
|
|
98
|
+
typeof block?.id === "string" &&
|
|
99
|
+
typeof block?.name === "string") {
|
|
100
|
+
normalized.push({
|
|
101
|
+
type: "tool-call",
|
|
102
|
+
toolCallId: block.id,
|
|
103
|
+
toolName: block.name,
|
|
104
|
+
input: stringifyJsonValue(block.input ?? {}),
|
|
105
|
+
});
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (blockType === "web_search_tool_result" &&
|
|
109
|
+
typeof block?.tool_use_id === "string" &&
|
|
110
|
+
Array.isArray(block?.content)) {
|
|
111
|
+
normalized.push({
|
|
112
|
+
type: "tool-result",
|
|
113
|
+
toolCallId: block.tool_use_id,
|
|
114
|
+
toolName: "web_search",
|
|
115
|
+
result: block.content,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (blockType === "web_fetch_tool_result" &&
|
|
119
|
+
typeof block?.tool_use_id === "string" &&
|
|
120
|
+
readRecord(block?.content)) {
|
|
121
|
+
normalized.push({
|
|
122
|
+
type: "tool-result",
|
|
123
|
+
toolCallId: block.tool_use_id,
|
|
124
|
+
toolName: "web_fetch",
|
|
125
|
+
result: block.content,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
content: normalized,
|
|
131
|
+
finishReason: normalizeAnthropicFinishReason(record?.stop_reason),
|
|
132
|
+
usage: extractAnthropicUsage(payload),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export function createAnthropicModelRuntime(config, modelId) {
|
|
136
|
+
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
137
|
+
return {
|
|
138
|
+
provider: config.name ?? "anthropic",
|
|
139
|
+
modelId,
|
|
140
|
+
specificationVersion: "v3",
|
|
141
|
+
supportedUrls: {},
|
|
142
|
+
doGenerate(optionsForRuntime) {
|
|
143
|
+
const options = optionsForRuntime;
|
|
144
|
+
const url = getAnthropicMessagesUrl(config.baseURL);
|
|
145
|
+
const warnings = createWarningCollector();
|
|
146
|
+
const body = buildAnthropicMessagesRequest(modelId, config.name ?? "anthropic", options, false, warnings);
|
|
147
|
+
return requestJson({
|
|
148
|
+
url,
|
|
149
|
+
fetchImpl,
|
|
150
|
+
providerLabel: config.name ?? "anthropic",
|
|
151
|
+
providerKind: "anthropic",
|
|
152
|
+
init: createAnthropicRequestInit({
|
|
153
|
+
apiKey: config.apiKey,
|
|
154
|
+
authToken: config.authToken,
|
|
155
|
+
extraHeaders: options.headers,
|
|
156
|
+
body: JSON.stringify(body),
|
|
157
|
+
signal: options.abortSignal,
|
|
158
|
+
}),
|
|
159
|
+
}).then((payload) => {
|
|
160
|
+
const drained = warnings.drain();
|
|
161
|
+
return {
|
|
162
|
+
...buildAnthropicGenerateResult(payload),
|
|
163
|
+
...(drained.length > 0 ? { warnings: drained } : {}),
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
doStream(optionsForRuntime) {
|
|
168
|
+
const options = optionsForRuntime;
|
|
169
|
+
const url = getAnthropicMessagesUrl(config.baseURL);
|
|
170
|
+
const warnings = createWarningCollector();
|
|
171
|
+
const body = buildAnthropicMessagesRequest(modelId, config.name ?? "anthropic", options, true, warnings);
|
|
172
|
+
return requestStream({
|
|
173
|
+
url,
|
|
174
|
+
fetchImpl,
|
|
175
|
+
providerLabel: config.name ?? "anthropic",
|
|
176
|
+
providerKind: "anthropic",
|
|
177
|
+
init: createAnthropicRequestInit({
|
|
178
|
+
apiKey: config.apiKey,
|
|
179
|
+
authToken: config.authToken,
|
|
180
|
+
extraHeaders: options.headers,
|
|
181
|
+
enableFineGrainedToolStreaming: true,
|
|
182
|
+
body: JSON.stringify(body),
|
|
183
|
+
signal: options.abortSignal,
|
|
184
|
+
}),
|
|
185
|
+
}).then((responseStream) => {
|
|
186
|
+
const drained = warnings.drain();
|
|
187
|
+
return {
|
|
188
|
+
stream: ReadableStream.from(withToolInputStatusTransitions(streamAnthropicCompatibleParts(responseStream))),
|
|
189
|
+
...(drained.length > 0 ? { warnings: drained } : {}),
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export class AnthropicProvider {
|
|
196
|
+
id = "anthropic";
|
|
197
|
+
createModel(modelId, config) {
|
|
198
|
+
return createAnthropicModelRuntime({
|
|
199
|
+
apiKey: config.credential,
|
|
200
|
+
authToken: typeof config.authToken === "string" ? config.authToken : undefined,
|
|
201
|
+
baseURL: config.baseURL,
|
|
202
|
+
name: config.name ?? "anthropic",
|
|
203
|
+
fetch: config.fetch,
|
|
204
|
+
}, modelId);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { RuntimePromptMessage } from "veryfront/provider/shared";
|
|
2
|
+
type ProviderCacheTtl = boolean | "5m" | "1h";
|
|
3
|
+
type ProviderCacheControlOption = {
|
|
4
|
+
system?: ProviderCacheTtl;
|
|
5
|
+
tools?: ProviderCacheTtl;
|
|
6
|
+
};
|
|
7
|
+
type ProviderReasoningEffort = "low" | "medium" | "high" | "max";
|
|
8
|
+
type ProviderReasoningOption = {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
effort?: ProviderReasoningEffort;
|
|
11
|
+
budgetTokens?: number;
|
|
12
|
+
};
|
|
13
|
+
export type RuntimeToolDefinition = {
|
|
14
|
+
type: "function";
|
|
15
|
+
name: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
inputSchema: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
type: "provider";
|
|
20
|
+
name: string;
|
|
21
|
+
id: `${string}.${string}`;
|
|
22
|
+
args: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
export type OpenAICompatibleLanguageOptions = {
|
|
25
|
+
prompt: RuntimePromptMessage[];
|
|
26
|
+
maxOutputTokens?: number;
|
|
27
|
+
temperature?: number;
|
|
28
|
+
topP?: number;
|
|
29
|
+
topK?: number;
|
|
30
|
+
stopSequences?: string[];
|
|
31
|
+
tools?: RuntimeToolDefinition[];
|
|
32
|
+
toolChoice?: unknown;
|
|
33
|
+
seed?: number;
|
|
34
|
+
presencePenalty?: number;
|
|
35
|
+
frequencyPenalty?: number;
|
|
36
|
+
headers?: HeadersInit;
|
|
37
|
+
providerOptions?: Record<string, unknown>;
|
|
38
|
+
includeRawChunks?: boolean;
|
|
39
|
+
abortSignal?: AbortSignal;
|
|
40
|
+
cacheControl?: ProviderCacheControlOption;
|
|
41
|
+
reasoning?: ProviderReasoningOption;
|
|
42
|
+
userId?: string;
|
|
43
|
+
requestLabels?: Record<string, string>;
|
|
44
|
+
serviceTier?: "auto" | "default" | "flex" | "scale";
|
|
45
|
+
parallelToolCalls?: boolean;
|
|
46
|
+
responseFormat?: {
|
|
47
|
+
type: "text";
|
|
48
|
+
} | {
|
|
49
|
+
type: "json";
|
|
50
|
+
} | {
|
|
51
|
+
type: "json_schema";
|
|
52
|
+
name: string;
|
|
53
|
+
schema: unknown;
|
|
54
|
+
description?: string;
|
|
55
|
+
strict?: boolean;
|
|
56
|
+
};
|
|
57
|
+
anthropicContainer?: unknown;
|
|
58
|
+
googleCachedContent?: string;
|
|
59
|
+
googleSafetySettings?: Array<{
|
|
60
|
+
category: string;
|
|
61
|
+
threshold: string;
|
|
62
|
+
}>;
|
|
63
|
+
mcpServers?: Array<Record<string, unknown>>;
|
|
64
|
+
};
|
|
65
|
+
type WarningCollector = {
|
|
66
|
+
push(warning: {
|
|
67
|
+
type: "unsupported-setting" | "other";
|
|
68
|
+
setting?: string;
|
|
69
|
+
details?: string;
|
|
70
|
+
provider: string;
|
|
71
|
+
}): void;
|
|
72
|
+
drain(): Array<{
|
|
73
|
+
type: "unsupported-setting" | "other";
|
|
74
|
+
setting?: string;
|
|
75
|
+
details?: string;
|
|
76
|
+
provider: string;
|
|
77
|
+
}>;
|
|
78
|
+
};
|
|
79
|
+
type AnthropicCompatibleMessage = {
|
|
80
|
+
role: "user" | "assistant";
|
|
81
|
+
content: Array<Record<string, unknown>>;
|
|
82
|
+
};
|
|
83
|
+
type AnthropicCompatibleRequest = {
|
|
84
|
+
model: string;
|
|
85
|
+
messages: AnthropicCompatibleMessage[];
|
|
86
|
+
max_tokens: number;
|
|
87
|
+
stream?: boolean;
|
|
88
|
+
system?: string | Array<Record<string, unknown>>;
|
|
89
|
+
temperature?: number;
|
|
90
|
+
top_p?: number;
|
|
91
|
+
stop_sequences?: string[];
|
|
92
|
+
tools?: Array<Record<string, unknown>>;
|
|
93
|
+
tool_choice?: unknown;
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
};
|
|
96
|
+
export declare function buildAnthropicMessagesRequest(modelId: string, providerName: string, options: OpenAICompatibleLanguageOptions, stream: boolean, warnings: WarningCollector): AnthropicCompatibleRequest;
|
|
97
|
+
export {};
|
|
98
|
+
//# sourceMappingURL=anthropic-request-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-request-builder.d.ts","sourceRoot":"","sources":["../src/anthropic-request-builder.ts"],"names":[],"mappings":"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"}
|