@aigne/anthropic 0.14.16-beta.2 → 0.14.16-beta.3
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.14.16-beta.3](https://github.com/AIGNE-io/aigne-framework/compare/anthropic-v0.14.16-beta.2...anthropic-v0.14.16-beta.3) (2025-12-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add prompt caching for OpenAI/Gemini/Anthropic and cache token display ([#838](https://github.com/AIGNE-io/aigne-framework/issues/838)) ([46c628f](https://github.com/AIGNE-io/aigne-framework/commit/46c628f180572ea1b955d1a9888aad6145204842))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @aigne/core bumped to 1.72.0-beta.3
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @aigne/test-utils bumped to 0.5.69-beta.3
|
|
18
|
+
|
|
3
19
|
## [0.14.16-beta.2](https://github.com/AIGNE-io/aigne-framework/compare/anthropic-v0.14.16-beta.1...anthropic-v0.14.16-beta.2) (2025-12-19)
|
|
4
20
|
|
|
5
21
|
|
|
@@ -124,6 +124,9 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
124
124
|
reasoningEffort?: number | "minimal" | "low" | "medium" | "high" | {
|
|
125
125
|
$get: string;
|
|
126
126
|
} | undefined;
|
|
127
|
+
cacheConfig?: import("@aigne/core").CacheConfig | {
|
|
128
|
+
$get: string;
|
|
129
|
+
} | undefined;
|
|
127
130
|
}> | undefined;
|
|
128
131
|
get credential(): {
|
|
129
132
|
apiKey: string | undefined;
|
|
@@ -166,10 +166,12 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
166
166
|
model = chunk.message.model;
|
|
167
167
|
controller.enqueue({ delta: { json: { model } } });
|
|
168
168
|
}
|
|
169
|
-
const { input_tokens, output_tokens } = chunk.message.usage;
|
|
169
|
+
const { input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens, } = chunk.message.usage;
|
|
170
170
|
usage = {
|
|
171
171
|
inputTokens: input_tokens,
|
|
172
172
|
outputTokens: output_tokens,
|
|
173
|
+
cacheCreationInputTokens: cache_creation_input_tokens ?? undefined,
|
|
174
|
+
cacheReadInputTokens: cache_read_input_tokens ?? undefined,
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
if (chunk.type === "message_delta" && usage) {
|
|
@@ -261,14 +263,40 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
261
263
|
}
|
|
262
264
|
}
|
|
263
265
|
exports.AnthropicChatModel = AnthropicChatModel;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Parse cache configuration from model options
|
|
268
|
+
*/
|
|
269
|
+
function parseCacheConfig(modelOptions) {
|
|
270
|
+
const cacheConfig = modelOptions?.cacheConfig || {};
|
|
271
|
+
const shouldCache = cacheConfig.enabled !== false; // Default: enabled
|
|
272
|
+
const ttl = cacheConfig.ttl === "1h" ? "1h" : "5m"; // Default: 5m
|
|
273
|
+
const strategy = cacheConfig.strategy || "auto"; // Default: auto
|
|
274
|
+
const autoBreakpoints = {
|
|
275
|
+
tools: cacheConfig.autoBreakpoints?.tools !== false, // Default: true
|
|
276
|
+
system: cacheConfig.autoBreakpoints?.system !== false, // Default: true
|
|
277
|
+
lastMessage: cacheConfig.autoBreakpoints?.lastMessage === true, // Default: false
|
|
278
|
+
};
|
|
279
|
+
return {
|
|
280
|
+
shouldCache,
|
|
281
|
+
ttl,
|
|
282
|
+
strategy,
|
|
283
|
+
autoBreakpoints,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
async function convertMessages({ messages, responseFormat, tools, modelOptions, }) {
|
|
287
|
+
const systemBlocks = [];
|
|
266
288
|
const msgs = [];
|
|
289
|
+
// Extract cache configuration with defaults
|
|
290
|
+
const { shouldCache, ttl, strategy, autoBreakpoints } = parseCacheConfig(modelOptions);
|
|
267
291
|
for (const msg of messages) {
|
|
268
292
|
if (msg.role === "system") {
|
|
269
293
|
if (typeof msg.content !== "string")
|
|
270
294
|
throw new Error("System message must have content");
|
|
271
|
-
|
|
295
|
+
const block = {
|
|
296
|
+
type: "text",
|
|
297
|
+
text: msg.content,
|
|
298
|
+
};
|
|
299
|
+
systemBlocks.push(block);
|
|
272
300
|
}
|
|
273
301
|
else if (msg.role === "tool") {
|
|
274
302
|
if (!msg.toolCallId)
|
|
@@ -314,16 +342,48 @@ async function convertMessages({ messages, responseFormat, tools }) {
|
|
|
314
342
|
// If there are tools and responseFormat is json_schema, we need to add a system message
|
|
315
343
|
// to inform the model about the expected json schema, then trying to parse the response as json
|
|
316
344
|
if (tools?.length && responseFormat?.type === "json_schema") {
|
|
317
|
-
|
|
345
|
+
systemBlocks.push({
|
|
346
|
+
type: "text",
|
|
347
|
+
text: `You should provide a json response with schema: ${JSON.stringify(responseFormat.jsonSchema.schema)}`,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
// Apply cache_control to the last system block if auto strategy is enabled
|
|
351
|
+
if (shouldCache && strategy === "auto" && autoBreakpoints.system && systemBlocks.length > 0) {
|
|
352
|
+
const lastBlock = systemBlocks[systemBlocks.length - 1];
|
|
353
|
+
if (lastBlock) {
|
|
354
|
+
lastBlock.cache_control = { type: "ephemeral" };
|
|
355
|
+
if (ttl === "1h") {
|
|
356
|
+
lastBlock.cache_control = { type: "ephemeral", ttl: "1h" };
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Manual cache control: apply user-specified cacheControl from system messages
|
|
361
|
+
if (shouldCache && strategy === "manual") {
|
|
362
|
+
for (const [index, msg] of messages.entries()) {
|
|
363
|
+
const msgWithCache = msg;
|
|
364
|
+
if (msg.role === "system" && msgWithCache.cacheControl) {
|
|
365
|
+
const block = systemBlocks[index];
|
|
366
|
+
if (block) {
|
|
367
|
+
block.cache_control = {
|
|
368
|
+
type: msgWithCache.cacheControl.type,
|
|
369
|
+
...(msgWithCache.cacheControl.ttl && { ttl: msgWithCache.cacheControl.ttl }),
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
318
374
|
}
|
|
319
|
-
const system = systemMessages.join("\n").trim() || undefined;
|
|
320
375
|
// Claude requires at least one message, so we add a system message if there are no messages
|
|
321
376
|
if (msgs.length === 0) {
|
|
322
|
-
if (
|
|
377
|
+
if (systemBlocks.length === 0)
|
|
323
378
|
throw new Error("No messages provided");
|
|
324
|
-
|
|
379
|
+
// Convert system blocks to a single user message
|
|
380
|
+
const systemText = systemBlocks.map((b) => b.text).join("\n");
|
|
381
|
+
return { messages: [{ role: "user", content: systemText }] };
|
|
325
382
|
}
|
|
326
|
-
return {
|
|
383
|
+
return {
|
|
384
|
+
messages: msgs,
|
|
385
|
+
system: systemBlocks.length > 0 ? systemBlocks : undefined,
|
|
386
|
+
};
|
|
327
387
|
}
|
|
328
388
|
async function convertContent(content) {
|
|
329
389
|
if (typeof content === "string")
|
|
@@ -348,7 +408,7 @@ async function convertContent(content) {
|
|
|
348
408
|
}
|
|
349
409
|
throw new Error("Invalid chat message content");
|
|
350
410
|
}
|
|
351
|
-
function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
411
|
+
function convertTools({ tools, toolChoice, disableParallelToolUse, modelOptions, }) {
|
|
352
412
|
let choice;
|
|
353
413
|
if (typeof toolChoice === "object" && "type" in toolChoice && toolChoice.type === "function") {
|
|
354
414
|
choice = {
|
|
@@ -369,15 +429,38 @@ function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
|
369
429
|
else if (toolChoice === "none") {
|
|
370
430
|
choice = { type: "none" };
|
|
371
431
|
}
|
|
432
|
+
// Extract cache configuration with defaults
|
|
433
|
+
const { shouldCache, ttl, strategy, autoBreakpoints } = parseCacheConfig(modelOptions);
|
|
434
|
+
const shouldCacheTools = shouldCache && strategy === "auto" && autoBreakpoints.tools;
|
|
372
435
|
return {
|
|
373
436
|
tools: tools?.length
|
|
374
|
-
? tools.map((i) =>
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
437
|
+
? tools.map((i, index, arr) => {
|
|
438
|
+
const tool = {
|
|
439
|
+
name: i.function.name,
|
|
440
|
+
description: i.function.description,
|
|
441
|
+
input_schema: (0, type_utils_js_1.isEmpty)(i.function.parameters)
|
|
442
|
+
? { type: "object" }
|
|
443
|
+
: i.function.parameters,
|
|
444
|
+
};
|
|
445
|
+
// Auto mode: add cache_control to the last tool
|
|
446
|
+
if (shouldCacheTools && index === arr.length - 1) {
|
|
447
|
+
tool.cache_control = { type: "ephemeral" };
|
|
448
|
+
if (ttl === "1h") {
|
|
449
|
+
tool.cache_control = { type: "ephemeral", ttl: "1h" };
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// Manual mode: use tool-specific cacheControl if provided
|
|
453
|
+
else if (shouldCache && strategy === "manual") {
|
|
454
|
+
const toolWithCache = i;
|
|
455
|
+
if (toolWithCache.cacheControl) {
|
|
456
|
+
tool.cache_control = {
|
|
457
|
+
type: toolWithCache.cacheControl.type,
|
|
458
|
+
...(toolWithCache.cacheControl.ttl && { ttl: toolWithCache.cacheControl.ttl }),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return tool;
|
|
463
|
+
})
|
|
381
464
|
: undefined,
|
|
382
465
|
tool_choice: choice,
|
|
383
466
|
};
|
|
@@ -124,6 +124,9 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
124
124
|
reasoningEffort?: number | "minimal" | "low" | "medium" | "high" | {
|
|
125
125
|
$get: string;
|
|
126
126
|
} | undefined;
|
|
127
|
+
cacheConfig?: import("@aigne/core").CacheConfig | {
|
|
128
|
+
$get: string;
|
|
129
|
+
} | undefined;
|
|
127
130
|
}> | undefined;
|
|
128
131
|
get credential(): {
|
|
129
132
|
apiKey: string | undefined;
|
|
@@ -124,6 +124,9 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
124
124
|
reasoningEffort?: number | "minimal" | "low" | "medium" | "high" | {
|
|
125
125
|
$get: string;
|
|
126
126
|
} | undefined;
|
|
127
|
+
cacheConfig?: import("@aigne/core").CacheConfig | {
|
|
128
|
+
$get: string;
|
|
129
|
+
} | undefined;
|
|
127
130
|
}> | undefined;
|
|
128
131
|
get credential(): {
|
|
129
132
|
apiKey: string | undefined;
|
|
@@ -160,10 +160,12 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
160
160
|
model = chunk.message.model;
|
|
161
161
|
controller.enqueue({ delta: { json: { model } } });
|
|
162
162
|
}
|
|
163
|
-
const { input_tokens, output_tokens } = chunk.message.usage;
|
|
163
|
+
const { input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens, } = chunk.message.usage;
|
|
164
164
|
usage = {
|
|
165
165
|
inputTokens: input_tokens,
|
|
166
166
|
outputTokens: output_tokens,
|
|
167
|
+
cacheCreationInputTokens: cache_creation_input_tokens ?? undefined,
|
|
168
|
+
cacheReadInputTokens: cache_read_input_tokens ?? undefined,
|
|
167
169
|
};
|
|
168
170
|
}
|
|
169
171
|
if (chunk.type === "message_delta" && usage) {
|
|
@@ -254,14 +256,40 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
254
256
|
};
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Parse cache configuration from model options
|
|
261
|
+
*/
|
|
262
|
+
function parseCacheConfig(modelOptions) {
|
|
263
|
+
const cacheConfig = modelOptions?.cacheConfig || {};
|
|
264
|
+
const shouldCache = cacheConfig.enabled !== false; // Default: enabled
|
|
265
|
+
const ttl = cacheConfig.ttl === "1h" ? "1h" : "5m"; // Default: 5m
|
|
266
|
+
const strategy = cacheConfig.strategy || "auto"; // Default: auto
|
|
267
|
+
const autoBreakpoints = {
|
|
268
|
+
tools: cacheConfig.autoBreakpoints?.tools !== false, // Default: true
|
|
269
|
+
system: cacheConfig.autoBreakpoints?.system !== false, // Default: true
|
|
270
|
+
lastMessage: cacheConfig.autoBreakpoints?.lastMessage === true, // Default: false
|
|
271
|
+
};
|
|
272
|
+
return {
|
|
273
|
+
shouldCache,
|
|
274
|
+
ttl,
|
|
275
|
+
strategy,
|
|
276
|
+
autoBreakpoints,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
async function convertMessages({ messages, responseFormat, tools, modelOptions, }) {
|
|
280
|
+
const systemBlocks = [];
|
|
259
281
|
const msgs = [];
|
|
282
|
+
// Extract cache configuration with defaults
|
|
283
|
+
const { shouldCache, ttl, strategy, autoBreakpoints } = parseCacheConfig(modelOptions);
|
|
260
284
|
for (const msg of messages) {
|
|
261
285
|
if (msg.role === "system") {
|
|
262
286
|
if (typeof msg.content !== "string")
|
|
263
287
|
throw new Error("System message must have content");
|
|
264
|
-
|
|
288
|
+
const block = {
|
|
289
|
+
type: "text",
|
|
290
|
+
text: msg.content,
|
|
291
|
+
};
|
|
292
|
+
systemBlocks.push(block);
|
|
265
293
|
}
|
|
266
294
|
else if (msg.role === "tool") {
|
|
267
295
|
if (!msg.toolCallId)
|
|
@@ -307,16 +335,48 @@ async function convertMessages({ messages, responseFormat, tools }) {
|
|
|
307
335
|
// If there are tools and responseFormat is json_schema, we need to add a system message
|
|
308
336
|
// to inform the model about the expected json schema, then trying to parse the response as json
|
|
309
337
|
if (tools?.length && responseFormat?.type === "json_schema") {
|
|
310
|
-
|
|
338
|
+
systemBlocks.push({
|
|
339
|
+
type: "text",
|
|
340
|
+
text: `You should provide a json response with schema: ${JSON.stringify(responseFormat.jsonSchema.schema)}`,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
// Apply cache_control to the last system block if auto strategy is enabled
|
|
344
|
+
if (shouldCache && strategy === "auto" && autoBreakpoints.system && systemBlocks.length > 0) {
|
|
345
|
+
const lastBlock = systemBlocks[systemBlocks.length - 1];
|
|
346
|
+
if (lastBlock) {
|
|
347
|
+
lastBlock.cache_control = { type: "ephemeral" };
|
|
348
|
+
if (ttl === "1h") {
|
|
349
|
+
lastBlock.cache_control = { type: "ephemeral", ttl: "1h" };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// Manual cache control: apply user-specified cacheControl from system messages
|
|
354
|
+
if (shouldCache && strategy === "manual") {
|
|
355
|
+
for (const [index, msg] of messages.entries()) {
|
|
356
|
+
const msgWithCache = msg;
|
|
357
|
+
if (msg.role === "system" && msgWithCache.cacheControl) {
|
|
358
|
+
const block = systemBlocks[index];
|
|
359
|
+
if (block) {
|
|
360
|
+
block.cache_control = {
|
|
361
|
+
type: msgWithCache.cacheControl.type,
|
|
362
|
+
...(msgWithCache.cacheControl.ttl && { ttl: msgWithCache.cacheControl.ttl }),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
311
367
|
}
|
|
312
|
-
const system = systemMessages.join("\n").trim() || undefined;
|
|
313
368
|
// Claude requires at least one message, so we add a system message if there are no messages
|
|
314
369
|
if (msgs.length === 0) {
|
|
315
|
-
if (
|
|
370
|
+
if (systemBlocks.length === 0)
|
|
316
371
|
throw new Error("No messages provided");
|
|
317
|
-
|
|
372
|
+
// Convert system blocks to a single user message
|
|
373
|
+
const systemText = systemBlocks.map((b) => b.text).join("\n");
|
|
374
|
+
return { messages: [{ role: "user", content: systemText }] };
|
|
318
375
|
}
|
|
319
|
-
return {
|
|
376
|
+
return {
|
|
377
|
+
messages: msgs,
|
|
378
|
+
system: systemBlocks.length > 0 ? systemBlocks : undefined,
|
|
379
|
+
};
|
|
320
380
|
}
|
|
321
381
|
async function convertContent(content) {
|
|
322
382
|
if (typeof content === "string")
|
|
@@ -341,7 +401,7 @@ async function convertContent(content) {
|
|
|
341
401
|
}
|
|
342
402
|
throw new Error("Invalid chat message content");
|
|
343
403
|
}
|
|
344
|
-
function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
404
|
+
function convertTools({ tools, toolChoice, disableParallelToolUse, modelOptions, }) {
|
|
345
405
|
let choice;
|
|
346
406
|
if (typeof toolChoice === "object" && "type" in toolChoice && toolChoice.type === "function") {
|
|
347
407
|
choice = {
|
|
@@ -362,15 +422,38 @@ function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
|
362
422
|
else if (toolChoice === "none") {
|
|
363
423
|
choice = { type: "none" };
|
|
364
424
|
}
|
|
425
|
+
// Extract cache configuration with defaults
|
|
426
|
+
const { shouldCache, ttl, strategy, autoBreakpoints } = parseCacheConfig(modelOptions);
|
|
427
|
+
const shouldCacheTools = shouldCache && strategy === "auto" && autoBreakpoints.tools;
|
|
365
428
|
return {
|
|
366
429
|
tools: tools?.length
|
|
367
|
-
? tools.map((i) =>
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
430
|
+
? tools.map((i, index, arr) => {
|
|
431
|
+
const tool = {
|
|
432
|
+
name: i.function.name,
|
|
433
|
+
description: i.function.description,
|
|
434
|
+
input_schema: isEmpty(i.function.parameters)
|
|
435
|
+
? { type: "object" }
|
|
436
|
+
: i.function.parameters,
|
|
437
|
+
};
|
|
438
|
+
// Auto mode: add cache_control to the last tool
|
|
439
|
+
if (shouldCacheTools && index === arr.length - 1) {
|
|
440
|
+
tool.cache_control = { type: "ephemeral" };
|
|
441
|
+
if (ttl === "1h") {
|
|
442
|
+
tool.cache_control = { type: "ephemeral", ttl: "1h" };
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// Manual mode: use tool-specific cacheControl if provided
|
|
446
|
+
else if (shouldCache && strategy === "manual") {
|
|
447
|
+
const toolWithCache = i;
|
|
448
|
+
if (toolWithCache.cacheControl) {
|
|
449
|
+
tool.cache_control = {
|
|
450
|
+
type: toolWithCache.cacheControl.type,
|
|
451
|
+
...(toolWithCache.cacheControl.ttl && { ttl: toolWithCache.cacheControl.ttl }),
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return tool;
|
|
456
|
+
})
|
|
374
457
|
: undefined,
|
|
375
458
|
tool_choice: choice,
|
|
376
459
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/anthropic",
|
|
3
|
-
"version": "0.14.16-beta.
|
|
3
|
+
"version": "0.14.16-beta.3",
|
|
4
4
|
"description": "AIGNE Anthropic SDK for integrating with Claude AI models",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@anthropic-ai/sdk": "^0.63.0",
|
|
39
39
|
"zod": "^3.25.67",
|
|
40
|
-
"@aigne/core": "^1.72.0-beta.
|
|
40
|
+
"@aigne/core": "^1.72.0-beta.3",
|
|
41
41
|
"@aigne/platform-helpers": "^0.6.7-beta"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"npm-run-all": "^4.1.5",
|
|
47
47
|
"rimraf": "^6.0.1",
|
|
48
48
|
"typescript": "^5.9.2",
|
|
49
|
-
"@aigne/test-utils": "^0.5.69-beta.
|
|
49
|
+
"@aigne/test-utils": "^0.5.69-beta.3"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"lint": "tsc --noEmit",
|