|
1 | 1 | import type { ModelMessage } from "ai" |
2 | 2 | import { unique } from "remeda" |
3 | 3 |
|
| 4 | + |
4 | 5 | export namespace ProviderTransform { |
5 | | - export function message(msgs: ModelMessage[], providerID: string, modelID: string) { |
6 | | - if (providerID === "anthropic" || modelID.includes("anthropic") || modelID.includes("claude")) { |
7 | | - const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) |
8 | | - const final = msgs.filter((msg) => msg.role !== "system").slice(-2) |
9 | | - |
10 | | - const providerOptions = { |
11 | | - anthropic: { |
12 | | - cacheControl: { type: "ephemeral" }, |
13 | | - }, |
14 | | - openrouter: { |
15 | | - cache_control: { type: "ephemeral" }, |
16 | | - }, |
17 | | - bedrock: { |
18 | | - cachePoint: { type: "ephemeral" }, |
19 | | - }, |
20 | | - openaiCompatible: { |
21 | | - cache_control: { type: "ephemeral" }, |
22 | | - }, |
| 6 | + function normalizeToolCallIds(msgs: ModelMessage[]): ModelMessage[] { |
| 7 | + return msgs.map((msg) => { |
| 8 | + if ((msg.role === "assistant" || msg.role === "tool") && Array.isArray(msg.content)) { |
| 9 | + msg.content = msg.content.map((part) => { |
| 10 | + if ((part.type === "tool-call" || part.type === "tool-result") && "toolCallId" in part) { |
| 11 | + return { |
| 12 | + ...part, |
| 13 | + toolCallId: part.toolCallId.replace(/[^a-zA-Z0-9_-]/g, '_') |
| 14 | + } |
| 15 | + } |
| 16 | + return part |
| 17 | + }) |
23 | 18 | } |
| 19 | + return msg |
| 20 | + }) |
| 21 | + } |
24 | 22 |
|
25 | | - for (const msg of unique([...system, ...final])) { |
26 | | - const shouldUseContentOptions = |
27 | | - providerID !== "anthropic" && Array.isArray(msg.content) && msg.content.length > 0 |
| 23 | + function applyCaching(msgs: ModelMessage[], providerID: string): ModelMessage[] { |
| 24 | + const system = msgs.filter((msg) => msg.role === "system").slice(0, 2) |
| 25 | + const final = msgs.filter((msg) => msg.role !== "system").slice(-2) |
28 | 26 |
|
29 | | - if (shouldUseContentOptions) { |
30 | | - const lastContent = msg.content[msg.content.length - 1] |
31 | | - if (lastContent && typeof lastContent === "object") { |
32 | | - lastContent.providerOptions = { |
33 | | - ...lastContent.providerOptions, |
34 | | - ...providerOptions, |
35 | | - } |
36 | | - continue |
| 27 | + const providerOptions = { |
| 28 | + anthropic: { |
| 29 | + cacheControl: { type: "ephemeral" }, |
| 30 | + }, |
| 31 | + openrouter: { |
| 32 | + cache_control: { type: "ephemeral" }, |
| 33 | + }, |
| 34 | + bedrock: { |
| 35 | + cachePoint: { type: "ephemeral" }, |
| 36 | + }, |
| 37 | + openaiCompatible: { |
| 38 | + cache_control: { type: "ephemeral" }, |
| 39 | + }, |
| 40 | + } |
| 41 | + |
| 42 | + for (const msg of unique([...system, ...final])) { |
| 43 | + const shouldUseContentOptions = |
| 44 | + providerID !== "anthropic" && Array.isArray(msg.content) && msg.content.length > 0 |
| 45 | + |
| 46 | + if (shouldUseContentOptions) { |
| 47 | + const lastContent = msg.content[msg.content.length - 1] |
| 48 | + if (lastContent && typeof lastContent === "object") { |
| 49 | + lastContent.providerOptions = { |
| 50 | + ...lastContent.providerOptions, |
| 51 | + ...providerOptions, |
37 | 52 | } |
| 53 | + continue |
38 | 54 | } |
| 55 | + } |
39 | 56 |
|
40 | | - msg.providerOptions = { |
41 | | - ...msg.providerOptions, |
42 | | - ...providerOptions, |
43 | | - } |
| 57 | + msg.providerOptions = { |
| 58 | + ...msg.providerOptions, |
| 59 | + ...providerOptions, |
44 | 60 | } |
45 | 61 | } |
| 62 | + |
| 63 | + return msgs |
| 64 | + } |
| 65 | + |
| 66 | + export function message(msgs: ModelMessage[], providerID: string, modelID: string) { |
| 67 | + if (modelID.includes("claude")) { |
| 68 | + msgs = normalizeToolCallIds(msgs) |
| 69 | + } |
| 70 | + if (providerID === "anthropic" || modelID.includes("anthropic") || modelID.includes("claude")) { |
| 71 | + msgs = applyCaching(msgs, providerID) |
| 72 | + } |
| 73 | + |
46 | 74 | return msgs |
47 | 75 | } |
48 | 76 |
|
49 | 77 | export function temperature(_providerID: string, modelID: string) { |
50 | 78 | if (modelID.toLowerCase().includes("qwen")) return 0.55 |
51 | 79 | return 0 |
52 | 80 | } |
53 | | - |
54 | | - export function topP(_providerID: string, modelID: string) { |
55 | | - if (modelID.toLowerCase().includes("qwen")) return 1 |
56 | | - return undefined |
57 | | - } |
58 | 81 | } |
0 commit comments