Skip to content

Commit 5b7ae24

Browse files
p12ticedelauna
andauthored
chore: upgrade @anthropic-ai/sdk to 0.104.1 and @anthropic-ai/vertex-sdk to 0.17.1 (#600)
* chore: upgrade @anthropic-ai/sdk to 0.104.1 and @anthropic-ai/vertex-sdk to 0.17.1 * fix(transform): handle URL-sourced images and non-base64 blocks in format converters * test: bumping coverage * test(e2e): adding image test --------- Co-authored-by: Elliott de Launay <edelauna@gmail.com>
1 parent 4e68b59 commit 5b7ae24

24 files changed

Lines changed: 892 additions & 128 deletions

apps/vscode-e2e/fixtures/openrouter.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
{
22
"fixtures": [
3+
{
4+
"match": {
5+
"userMessage": "openrouter-image-e2e"
6+
},
7+
"response": {
8+
"toolCalls": [
9+
{
10+
"name": "attempt_completion",
11+
"arguments": "{\"result\":\"Red\"}",
12+
"id": "call_openrouter_image_001"
13+
}
14+
]
15+
}
16+
},
317
{
418
"match": {
519
"userMessage": "openrouter-identity-smoke"

apps/vscode-e2e/src/suite/providers/openrouter.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type CapturedOpenRouterRequest = {
99
xTitle: string | undefined
1010
httpReferer: string | undefined
1111
userAgent: string | undefined
12+
userMessageContent?: unknown
1213
}
1314

1415
function getRequestUrl(input: RequestInfo | URL): string {
@@ -40,10 +41,22 @@ function installOpenRouterRequestCapture(capture: CapturedOpenRouterRequest[], b
4041
if (new URL(url).origin === targetOrigin) {
4142
const xTitle = getHeaderValue(init, "X-Title") ?? getHeaderValue(init, "x-title")
4243
if (xTitle !== undefined) {
44+
let userMessageContent: unknown
45+
if (init?.body && typeof init.body === "string") {
46+
try {
47+
const body = JSON.parse(init.body)
48+
const messages: Array<{ role?: string; content?: unknown }> = body.messages ?? []
49+
const lastUser = [...messages].reverse().find((m) => m.role === "user")
50+
userMessageContent = lastUser?.content
51+
} catch {
52+
// ignore parse errors
53+
}
54+
}
4355
capture.push({
4456
xTitle,
4557
httpReferer: getHeaderValue(init, "HTTP-Referer") ?? getHeaderValue(init, "http-referer"),
4658
userAgent: getHeaderValue(init, "User-Agent") ?? getHeaderValue(init, "user-agent"),
59+
userMessageContent,
4760
})
4861
}
4962
}
@@ -82,7 +95,7 @@ suite("OpenRouter provider", function () {
8295
await globalThis.api.setConfiguration({
8396
apiProvider: "openrouter" as const,
8497
openRouterApiKey: aimockUrl && !isRecord ? "mock-key" : OPENROUTER_API_KEY!,
85-
openRouterModelId: "openai/gpt-4.1",
98+
openRouterModelId: "anthropic/claude-haiku-4-5",
8699
...(aimockUrl && { openRouterBaseUrl: `${aimockUrl}/v1` }),
87100
})
88101
})
@@ -92,6 +105,41 @@ suite("OpenRouter provider", function () {
92105
restoreFetch = undefined
93106
})
94107

108+
test("Should forward base64 images as image_url content parts in outbound request", async () => {
109+
requests.length = 0
110+
111+
// 8x8 red PNG (1x1 is too small and rejected by Anthropic's vision API)
112+
const base64Png =
113+
"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAEklEQVR4nGP4z8CAFWEXHbQSACj/P8Fu7N9hAAAAAElFTkSuQmCC"
114+
const dataUri = `data:image/png;base64,${base64Png}`
115+
116+
const api = globalThis.api
117+
const taskId = await api.startNewTask({
118+
configuration: { mode: "ask", autoApprovalEnabled: true },
119+
text: "openrouter-image-e2e: describe the image in one word.",
120+
images: [dataUri],
121+
})
122+
123+
await waitUntilCompleted({ api, taskId })
124+
125+
// Find the first request that contains the probe tag
126+
const probeRequest = requests.find((r) => {
127+
const content = r.userMessageContent
128+
return Array.isArray(content) && JSON.stringify(content).includes("openrouter-image-e2e")
129+
})
130+
131+
assert.ok(probeRequest, "Should have captured an outbound request containing the probe tag")
132+
133+
const content = probeRequest.userMessageContent as Array<{ type: string; image_url?: { url: string } }>
134+
const imagePart = content.find((p) => p.type === "image_url")
135+
assert.ok(imagePart, "User message should contain an image_url content part")
136+
assert.strictEqual(
137+
imagePart?.image_url?.url,
138+
dataUri,
139+
"image_url.url should be the original data URI passed via startNewTask",
140+
)
141+
})
142+
95143
test("Should identify as Zoo Code in outbound DEFAULT_HEADERS", async () => {
96144
requests.length = 0
97145

0 commit comments

Comments
 (0)