mirror of
https://github.com/anomalyco/opencode.git
synced 2026-09-01 05:34:33 +00:00
Merge branch 'bedrock-messages' into native-compaction
This commit is contained in:
commit
e07ae57caa
2 changed files with 87 additions and 3 deletions
|
|
@ -16,7 +16,12 @@ const Body = Schema.Struct({
|
|||
...Struct.omit(AnthropicMessages.AnthropicMessagesBody.fields, ["model", "stream"]),
|
||||
anthropic_version: Schema.Literal(VERSION),
|
||||
anthropic_beta: Schema.optional(Schema.Array(Schema.String)),
|
||||
})
|
||||
}).check(
|
||||
Schema.makeFilter(
|
||||
(body) =>
|
||||
body.messages.flatMap((message) => message.content.map(mediaIssue)).find((issue) => issue !== undefined) ?? true,
|
||||
),
|
||||
)
|
||||
const Event = Schema.Struct({
|
||||
chunk: Schema.optional(Schema.Struct({ bytes: Schema.String })),
|
||||
exception: Schema.optional(
|
||||
|
|
@ -80,6 +85,25 @@ export const protocol = Protocol.make({
|
|||
},
|
||||
})
|
||||
|
||||
function mediaIssue(
|
||||
block: AnthropicMessages.AnthropicMessagesBody["messages"][number]["content"][number],
|
||||
): string | undefined {
|
||||
if (block.type === "tool_result")
|
||||
return typeof block.content === "string"
|
||||
? undefined
|
||||
: block.content.map(mediaIssue).find((issue) => issue !== undefined)
|
||||
if (block.type !== "image" && block.type !== "document") return
|
||||
if (block.source.type === "url" || block.source.type === "file")
|
||||
return "Bedrock Messages does not support URL or file-ID media sources"
|
||||
if (
|
||||
block.type === "image" &&
|
||||
!["image/jpeg", "image/png", "image/webp", "image/gif"].includes(block.source.media_type)
|
||||
)
|
||||
return "Bedrock Messages requires a JPEG, PNG, WebP, or GIF image"
|
||||
if (block.source.type === "base64" && Encoding.decodeBase64(block.source.data)._tag === "Failure")
|
||||
return "Bedrock Messages media data must be valid base64"
|
||||
}
|
||||
|
||||
export const route = Route.make({
|
||||
id: ID,
|
||||
provider: "amazon-bedrock",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
|
|||
import { expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { LLM, LLMRequest, Message } from "../../src/index.js"
|
||||
import { LLMClient } from "../../src/route/client.js"
|
||||
import { LLMClient, compileRequest } from "../../src/route/client.js"
|
||||
import { AmazonBedrock } from "../../src/providers/index.js"
|
||||
import { testEffect } from "../lib/effect.js"
|
||||
import { it, testEffect } from "../lib/effect.js"
|
||||
import { dynamicResponse, fixedResponse } from "../lib/http.js"
|
||||
|
||||
const codec = new EventStreamCodec(toUtf8, fromUtf8)
|
||||
|
|
@ -91,3 +91,63 @@ testEffect(
|
|||
expect(error.reason.http?.status).toBe(200)
|
||||
}),
|
||||
)
|
||||
|
||||
for (const mediaType of ["image/png", "application/pdf"]) {
|
||||
for (const data of ["https://example.com/media", "invalid base64!"]) {
|
||||
for (const role of ["user", "tool"] as const) {
|
||||
it.effect(`rejects ${role} ${mediaType} with ${data}`, () =>
|
||||
Effect.gen(function* () {
|
||||
const error = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: AmazonBedrock.configure({ apiKey: "test" }).messages("claude"),
|
||||
messages:
|
||||
role === "user"
|
||||
? [Message.user({ type: "media", mediaType, data })]
|
||||
: [
|
||||
Message.tool({
|
||||
id: "call_1",
|
||||
name: "read",
|
||||
result: { type: "content", value: [{ type: "file", mime: mediaType, uri: data }] },
|
||||
}),
|
||||
],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
expect(error.reason._tag).toBe("InvalidRequest")
|
||||
expect(error.message).toContain("Bedrock Messages")
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.effect("accepts inline image and document sources", () =>
|
||||
Effect.gen(function* () {
|
||||
const prepared = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: AmazonBedrock.configure({ apiKey: "test" }).messages("claude"),
|
||||
messages: [
|
||||
Message.user([
|
||||
{ type: "media", mediaType: "image/png", data: "data:image/png;base64,AQID" },
|
||||
{ type: "media", mediaType: "application/pdf", data: "data:application/pdf;base64,AQID" },
|
||||
]),
|
||||
],
|
||||
}),
|
||||
)
|
||||
expect(prepared.body.messages[0].content.map((block: { source: { type: string } }) => block.source.type)).toEqual([
|
||||
"base64",
|
||||
"base64",
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("rejects Anthropic file IDs", () =>
|
||||
Effect.gen(function* () {
|
||||
const error = yield* compileRequest(
|
||||
LLM.request({
|
||||
model: AmazonBedrock.configure({ apiKey: "test" }).messages("claude"),
|
||||
messages: [Message.user({ type: "media", mediaType: "image/png", data: "", metadata: { file_id: "file_1" } })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
expect(error.message).toContain("file-ID")
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue