|
8 | 8 | ToolResultPart, |
9 | 9 | ToolSet, |
10 | 10 | tool as makeTool, |
| 11 | + Message |
11 | 12 | } from 'ai'; |
12 | 13 | import chalk from 'chalk'; |
13 | 14 |
|
@@ -191,62 +192,42 @@ async function executeTools( |
191 | 192 | }; |
192 | 193 | } |
193 | 194 |
|
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 | + }; |
220 | 225 | } |
221 | 226 | } |
222 | | - return c; |
223 | 227 | }); |
| 228 | + |
| 229 | + return result; |
224 | 230 | } |
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 | | -}*/ |
250 | 231 |
|
251 | 232 | export const toolAgent = async ( |
252 | 233 | initialPrompt: string, |
@@ -293,10 +274,13 @@ export const toolAgent = async ( |
293 | 274 | parameters: tool.parameters, |
294 | 275 | }); |
295 | 276 | }); |
| 277 | + // Apply cache control to messages for token caching |
| 278 | + const messagesWithCacheControl = addCacheControlToMessages(messages); |
| 279 | + |
296 | 280 | const generateTextProps = { |
297 | 281 | model: config.model, |
298 | 282 | temperature: config.temperature, |
299 | | - messages, |
| 283 | + messages: messagesWithCacheControl, |
300 | 284 | system: systemPrompt, |
301 | 285 | tools: toolSet, |
302 | 286 | }; |
|
0 commit comments