Skip to content

Commit 870cbee

Browse files
committed
Re-implement token caching for Vercel AI SDK usage with Anthropic provider (fixes #58)
1 parent 462cff6 commit 870cbee

File tree

2 files changed

+42
-53
lines changed

2 files changed

+42
-53
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mycoder-agent": patch
3+
---
4+
5+
Re-implemented token caching for Vercel AI SDK usage with Anthropic provider to reduce token consumption during repeated API calls.

packages/agent/src/core/toolAgent.ts

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ToolResultPart,
99
ToolSet,
1010
tool as makeTool,
11+
Message
1112
} from 'ai';
1213
import chalk from 'chalk';
1314

@@ -191,62 +192,42 @@ async function executeTools(
191192
};
192193
}
193194

194-
/*
195-
// a function that takes a list of messages and returns a list of messages but with the last message having a cache_control of ephemeral
196-
function addCacheControlToTools<T>(messages: T[]): T[] {
197-
return messages.map((m, i) => ({
198-
...m,
199-
...(i === messages.length - 1
200-
? { cache_control: { type: 'ephemeral' } }
201-
: {}),
202-
}));
203-
}
204-
205-
function addCacheControlToContentBlocks(
206-
content: ContentBlockParam[],
207-
): ContentBlockParam[] {
208-
return content.map((c, i) => {
209-
if (i === content.length - 1) {
210-
if (
211-
c.type === 'text' ||
212-
c.type === 'document' ||
213-
c.type === 'image' ||
214-
c.type === 'tool_use' ||
215-
c.type === 'tool_result' ||
216-
c.type === 'thinking' ||
217-
c.type === 'redacted_thinking'
218-
) {
219-
return { ...c, cache_control: { type: 'ephemeral' } };
195+
/**
196+
* Adds cache control to the messages for token caching with the Vercel AI SDK
197+
* This marks the last two messages as ephemeral which allows the conversation up to that
198+
* point to be cached (with a ~5 minute window), reducing token usage when making multiple API calls
199+
*/
200+
function addCacheControlToMessages(messages: CoreMessage[]): CoreMessage[] {
201+
if (messages.length <= 1) return messages;
202+
203+
// Create a deep copy of the messages array to avoid mutating the original
204+
const result = JSON.parse(JSON.stringify(messages)) as CoreMessage[];
205+
206+
// Get the last two messages (if available)
207+
const lastTwoMessageIndices = [
208+
messages.length - 1,
209+
messages.length - 2
210+
];
211+
212+
// Add providerOptions with anthropic cache control to the last two messages
213+
lastTwoMessageIndices.forEach(index => {
214+
if (index >= 0) {
215+
const message = result[index];
216+
if (message) {
217+
// For the Vercel AI SDK, we need to add the providerOptions.anthropic property
218+
// with cacheControl: 'ephemeral' to enable token caching
219+
message.providerOptions = {
220+
...message.providerOptions,
221+
anthropic: {
222+
cacheControl: 'ephemeral'
223+
}
224+
};
220225
}
221226
}
222-
return c;
223227
});
228+
229+
return result;
224230
}
225-
function addCacheControlToMessages(
226-
messages: Anthropic.Messages.MessageParam[],
227-
): Anthropic.Messages.MessageParam[] {
228-
return messages.map((m, i) => {
229-
if (typeof m.content === 'string') {
230-
return {
231-
...m,
232-
content: [
233-
{
234-
type: 'text',
235-
text: m.content,
236-
cache_control: { type: 'ephemeral' },
237-
},
238-
] as ContentBlockParam[],
239-
};
240-
}
241-
return {
242-
...m,
243-
content:
244-
i >= messages.length - 2
245-
? addCacheControlToContentBlocks(m.content)
246-
: m.content,
247-
};
248-
});
249-
}*/
250231

251232
export const toolAgent = async (
252233
initialPrompt: string,
@@ -293,10 +274,13 @@ export const toolAgent = async (
293274
parameters: tool.parameters,
294275
});
295276
});
277+
// Apply cache control to messages for token caching
278+
const messagesWithCacheControl = addCacheControlToMessages(messages);
279+
296280
const generateTextProps = {
297281
model: config.model,
298282
temperature: config.temperature,
299-
messages,
283+
messages: messagesWithCacheControl,
300284
system: systemPrompt,
301285
tools: toolSet,
302286
};

0 commit comments

Comments
 (0)