refactor(llm): colocate per-type factories on their namespaces (#26799)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Redactor } from "@opencode-ai/http-recorder"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { LLM, LLMError } from "../../src"
|
||||
import { LLM, LLMError, Message, ToolCallPart } from "../../src"
|
||||
import { LLMClient } from "../../src/route"
|
||||
import * as AnthropicMessages from "../../src/protocols/anthropic-messages"
|
||||
import { weatherToolName } from "../recorded-scenarios"
|
||||
@@ -16,12 +16,12 @@ const malformedToolOrderRequest = LLM.request({
|
||||
id: "recorded_anthropic_malformed_tool_order",
|
||||
model,
|
||||
messages: [
|
||||
LLM.assistant([
|
||||
LLM.toolCall({ id: "call_1", name: weatherToolName, input: { city: "Paris" } }),
|
||||
Message.assistant([
|
||||
ToolCallPart.make({ id: "call_1", name: weatherToolName, input: { city: "Paris" } }),
|
||||
{ type: "text", text: "I will check the weather." },
|
||||
]),
|
||||
LLM.toolMessage({ id: "call_1", name: weatherToolName, result: { temperature: "72F" } }),
|
||||
LLM.user("Use that result to answer briefly."),
|
||||
Message.tool({ id: "call_1", name: weatherToolName, result: { temperature: "72F" } }),
|
||||
Message.user("Use that result to answer briefly."),
|
||||
],
|
||||
tools: [{ name: weatherToolName, description: "Get weather", inputSchema: { type: "object", properties: {} } }],
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { CacheHint, LLM, LLMError, Usage } from "../../src"
|
||||
import { CacheHint, LLM, LLMError, Message, ToolCallPart, Usage } from "../../src"
|
||||
import { LLMClient } from "../../src/route"
|
||||
import * as AnthropicMessages from "../../src/protocols/anthropic-messages"
|
||||
import { it } from "../lib/effect"
|
||||
@@ -47,9 +47,9 @@ describe("Anthropic Messages route", () => {
|
||||
id: "req_tool_result",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user("What is the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.user("What is the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
cache: "none",
|
||||
}),
|
||||
@@ -77,7 +77,7 @@ describe("Anthropic Messages route", () => {
|
||||
LLM.request({
|
||||
model,
|
||||
messages: [
|
||||
LLM.assistant([
|
||||
Message.assistant([
|
||||
{ type: "reasoning", text: "thinking", providerMetadata: { anthropic: { signature: "sig_1" } } },
|
||||
]),
|
||||
],
|
||||
@@ -304,8 +304,8 @@ describe("Anthropic Messages route", () => {
|
||||
id: "req_round_trip",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user("Search for something."),
|
||||
LLM.assistant([
|
||||
Message.user("Search for something."),
|
||||
Message.assistant([
|
||||
{
|
||||
type: "tool-call",
|
||||
id: "srvtoolu_abc",
|
||||
@@ -322,7 +322,7 @@ describe("Anthropic Messages route", () => {
|
||||
},
|
||||
{ type: "text", text: "Found it." },
|
||||
]),
|
||||
LLM.user("Thanks."),
|
||||
Message.user("Thanks."),
|
||||
],
|
||||
}),
|
||||
)
|
||||
@@ -355,7 +355,7 @@ describe("Anthropic Messages route", () => {
|
||||
id: "req_unknown_server_tool",
|
||||
model,
|
||||
messages: [
|
||||
LLM.assistant([
|
||||
Message.assistant([
|
||||
{
|
||||
type: "tool-result",
|
||||
id: "srvtoolu_abc",
|
||||
@@ -378,7 +378,7 @@ describe("Anthropic Messages route", () => {
|
||||
LLM.request({
|
||||
id: "req_media",
|
||||
model,
|
||||
messages: [LLM.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
messages: [Message.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
@@ -416,9 +416,9 @@ describe("Anthropic Messages route", () => {
|
||||
},
|
||||
],
|
||||
messages: [
|
||||
LLM.user("What's the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: {} })]),
|
||||
LLM.toolMessage({
|
||||
Message.user("What's the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({
|
||||
id: "call_1",
|
||||
name: "lookup",
|
||||
result: { temp: 72 },
|
||||
@@ -501,7 +501,7 @@ describe("Anthropic Messages route", () => {
|
||||
},
|
||||
],
|
||||
system: [{ type: "text", text: "system-tail", cache: hint }],
|
||||
messages: [LLM.user([{ type: "text", text: "message-tail", cache: hint }])],
|
||||
messages: [Message.user([{ type: "text", text: "message-tail", cache: hint }])],
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { EventStreamCodec } from "@smithy/eventstream-codec"
|
||||
import { fromUtf8, toUtf8 } from "@smithy/util-utf8"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { CacheHint, LLM } from "../../src"
|
||||
import { CacheHint, LLM, Message, ToolCallPart, ToolChoice } from "../../src"
|
||||
import { LLMClient } from "../../src/route"
|
||||
import * as BedrockConverse from "../../src/protocols/bedrock-converse"
|
||||
import { it } from "../lib/effect"
|
||||
@@ -94,7 +94,7 @@ describe("Bedrock Converse route", () => {
|
||||
inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
|
||||
},
|
||||
],
|
||||
toolChoice: LLM.toolChoice({ type: "required" }),
|
||||
toolChoice: ToolChoice.make({ type: "required" }),
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -124,9 +124,9 @@ describe("Bedrock Converse route", () => {
|
||||
id: "req_history",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user("What is the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "tool_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "tool_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.user("What is the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "tool_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "tool_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
cache: "none",
|
||||
}),
|
||||
@@ -294,8 +294,8 @@ describe("Bedrock Converse route", () => {
|
||||
model,
|
||||
system: [{ type: "text", text: "System prefix.", cache }],
|
||||
messages: [
|
||||
LLM.user([{ type: "text", text: "User prefix.", cache }]),
|
||||
LLM.assistant([{ type: "text", text: "Assistant prefix.", cache }]),
|
||||
Message.user([{ type: "text", text: "User prefix.", cache }]),
|
||||
Message.assistant([{ type: "text", text: "Assistant prefix.", cache }]),
|
||||
],
|
||||
generation: { maxTokens: 16, temperature: 0 },
|
||||
}),
|
||||
@@ -335,7 +335,7 @@ describe("Bedrock Converse route", () => {
|
||||
id: "req_image",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user([
|
||||
Message.user([
|
||||
{ type: "text", text: "What is in this image?" },
|
||||
{ type: "media", mediaType: "image/png", data: "AAAA" },
|
||||
{ type: "media", mediaType: "image/jpeg", data: "BBBB" },
|
||||
@@ -371,7 +371,7 @@ describe("Bedrock Converse route", () => {
|
||||
LLM.request({
|
||||
id: "req_image_bytes",
|
||||
model,
|
||||
messages: [LLM.user([{ type: "media", mediaType: "image/png", data: new Uint8Array([1, 2, 3, 4, 5]) }])],
|
||||
messages: [Message.user([{ type: "media", mediaType: "image/png", data: new Uint8Array([1, 2, 3, 4, 5]) }])],
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -394,7 +394,7 @@ describe("Bedrock Converse route", () => {
|
||||
id: "req_doc",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user([
|
||||
Message.user([
|
||||
{ type: "media", mediaType: "application/pdf", data: "PDFDATA", filename: "report.pdf" },
|
||||
{ type: "media", mediaType: "text/csv", data: "CSVDATA" },
|
||||
]),
|
||||
@@ -424,7 +424,7 @@ describe("Bedrock Converse route", () => {
|
||||
LLM.request({
|
||||
id: "req_bad_image",
|
||||
model,
|
||||
messages: [LLM.user([{ type: "media", mediaType: "image/svg+xml", data: "x" }])],
|
||||
messages: [Message.user([{ type: "media", mediaType: "image/svg+xml", data: "x" }])],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
@@ -438,7 +438,7 @@ describe("Bedrock Converse route", () => {
|
||||
LLM.request({
|
||||
id: "req_bad_doc",
|
||||
model,
|
||||
messages: [LLM.user([{ type: "media", mediaType: "application/x-tar", data: "x", filename: "a.tar" }])],
|
||||
messages: [Message.user([{ type: "media", mediaType: "application/x-tar", data: "x", filename: "a.tar" }])],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
@@ -471,9 +471,9 @@ describe("Bedrock Converse route", () => {
|
||||
model,
|
||||
tools: [{ name: "lookup", description: "lookup", inputSchema: { type: "object", properties: {} }, cache }],
|
||||
messages: [
|
||||
LLM.user("What's the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: {} })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { temp: 72 }, cache }),
|
||||
Message.user("What's the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: {} })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { temp: 72 }, cache }),
|
||||
],
|
||||
cache: "none",
|
||||
}),
|
||||
@@ -583,7 +583,7 @@ describe("Bedrock Converse recorded", () => {
|
||||
system: "Call tools exactly as requested.",
|
||||
prompt: "Call get_weather with city exactly Paris.",
|
||||
tools: [weatherTool],
|
||||
toolChoice: LLM.toolChoice(weatherTool),
|
||||
toolChoice: ToolChoice.make(weatherTool),
|
||||
cache: "none",
|
||||
generation: { maxTokens: 80, temperature: 0 },
|
||||
}),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { LLM, LLMError, Usage } from "../../src"
|
||||
import { LLM, LLMError, Message, ToolCallPart, Usage } from "../../src"
|
||||
import { LLMClient } from "../../src/route"
|
||||
import * as Gemini from "../../src/protocols/gemini"
|
||||
import { it } from "../lib/effect"
|
||||
@@ -49,12 +49,12 @@ describe("Gemini route", () => {
|
||||
],
|
||||
toolChoice: { type: "tool", name: "lookup" },
|
||||
messages: [
|
||||
LLM.user([
|
||||
Message.user([
|
||||
{ type: "text", text: "What is in this image?" },
|
||||
{ type: "media", mediaType: "image/png", data: "AAECAw==" },
|
||||
]),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
}),
|
||||
)
|
||||
@@ -353,7 +353,7 @@ describe("Gemini route", () => {
|
||||
LLM.request({
|
||||
id: "req_media",
|
||||
model,
|
||||
messages: [LLM.assistant({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
messages: [Message.assistant({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Schema, Stream } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM, LLMError, Usage } from "../../src"
|
||||
import { LLM, LLMError, Message, ToolCallPart, Usage } from "../../src"
|
||||
import * as Azure from "../../src/providers/azure"
|
||||
import * as OpenAI from "../../src/providers/openai"
|
||||
import * as OpenAIChat from "../../src/protocols/openai-chat"
|
||||
@@ -149,9 +149,9 @@ describe("OpenAI Chat route", () => {
|
||||
id: "req_tool_result",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user("What is the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.user("What is the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
}),
|
||||
)
|
||||
@@ -185,7 +185,7 @@ describe("OpenAI Chat route", () => {
|
||||
LLM.request({
|
||||
id: "req_media",
|
||||
model,
|
||||
messages: [LLM.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
messages: [Message.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
@@ -199,7 +199,7 @@ describe("OpenAI Chat route", () => {
|
||||
LLM.request({
|
||||
id: "req_reasoning",
|
||||
model,
|
||||
messages: [LLM.assistant({ type: "reasoning", text: "hidden" })],
|
||||
messages: [Message.assistant({ type: "reasoning", text: "hidden" })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM } from "../../src"
|
||||
import { LLM, Message, ToolCallPart } from "../../src"
|
||||
import { LLMClient } from "../../src/route"
|
||||
import * as OpenAICompatible from "../../src/providers/openai-compatible"
|
||||
import * as OpenAICompatibleChat from "../../src/protocols/openai-compatible-chat"
|
||||
@@ -157,9 +157,9 @@ describe("OpenAI-compatible Chat route", () => {
|
||||
],
|
||||
toolChoice: "lookup",
|
||||
messages: [
|
||||
LLM.user("What is the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.user("What is the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect } from "bun:test"
|
||||
import { ConfigProvider, Effect, Layer, Stream } from "effect"
|
||||
import { Headers, HttpClientRequest } from "effect/unstable/http"
|
||||
import { LLM, LLMError, Usage } from "../../src"
|
||||
import { LLM, LLMError, Message, ToolCallPart, Usage } from "../../src"
|
||||
import { Auth, LLMClient, RequestExecutor, WebSocketExecutor } from "../../src/route"
|
||||
import * as Azure from "../../src/providers/azure"
|
||||
import * as OpenAI from "../../src/providers/openai"
|
||||
@@ -251,9 +251,9 @@ describe("OpenAI Responses route", () => {
|
||||
id: "req_tool_result",
|
||||
model,
|
||||
messages: [
|
||||
LLM.user("What is the weather?"),
|
||||
LLM.assistant([LLM.toolCall({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
LLM.toolMessage({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
Message.user("What is the weather?"),
|
||||
Message.assistant([ToolCallPart.make({ id: "call_1", name: "lookup", input: { query: "weather" } })]),
|
||||
Message.tool({ id: "call_1", name: "lookup", result: { forecast: "sunny" } }),
|
||||
],
|
||||
}),
|
||||
)
|
||||
@@ -508,7 +508,7 @@ describe("OpenAI Responses route", () => {
|
||||
LLM.request({
|
||||
id: "req_media",
|
||||
model,
|
||||
messages: [LLM.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
messages: [Message.user({ type: "media", mediaType: "image/png", data: "AAECAw==" })],
|
||||
}),
|
||||
).pipe(Effect.flip)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user