test: add regression test for tool_use ids were found without tool_result blocks immediately after

This commit is contained in:
Aiden Cline 2026-04-15 11:34:27 -05:00
parent 1f279cd2c8
commit c4d804fb48

View file

@ -13,7 +13,7 @@ import { ProviderID, ModelID } from "../../src/provider/schema"
import { Filesystem } from "../../src/util/filesystem"
import { tmpdir } from "../fixture/fixture"
import type { Agent } from "../../src/agent/agent"
import type { MessageV2 } from "../../src/session/message-v2"
import { MessageV2 } from "../../src/session/message-v2"
import { SessionID, MessageID } from "../../src/session/schema"
import { AppRuntime } from "../../src/effect/app-runtime"
@ -909,6 +909,269 @@ describe("session.llm.stream", () => {
})
})
test("sends anthropic tool_use blocks with tool_result immediately after them", async () => {
const server = state.server
if (!server) {
throw new Error("Server not initialized")
}
const source = await loadFixture("anthropic", "claude-opus-4-6")
const model = source.model
const chunks = [
{
type: "message_start",
message: {
id: "msg-tool-order",
model: model.id,
usage: {
input_tokens: 3,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
},
},
},
{
type: "content_block_start",
index: 0,
content_block: { type: "text", text: "" },
},
{
type: "content_block_delta",
index: 0,
delta: { type: "text_delta", text: "ok" },
},
{ type: "content_block_stop", index: 0 },
{
type: "message_delta",
delta: { stop_reason: "end_turn", stop_sequence: null, container: null },
usage: {
input_tokens: 3,
output_tokens: 2,
cache_creation_input_tokens: null,
cache_read_input_tokens: null,
},
},
{ type: "message_stop" },
]
const request = waitRequest("/messages", createEventResponse(chunks))
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(
path.join(dir, "opencode.json"),
JSON.stringify({
$schema: "https://opencode.ai/config.json",
enabled_providers: ["anthropic"],
provider: {
anthropic: {
name: "Anthropic",
env: ["ANTHROPIC_API_KEY"],
npm: "@ai-sdk/anthropic",
api: "https://api.anthropic.com/v1",
models: {
[model.id]: model,
},
options: {
apiKey: "test-anthropic-key",
baseURL: `${server.url.origin}/v1`,
},
},
},
}),
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const resolved = await getModel(ProviderID.make("anthropic"), ModelID.make(model.id))
const sessionID = SessionID.make("session-test-anthropic-tools")
const agent = {
name: "test",
mode: "primary",
options: {},
permission: [{ permission: "*", pattern: "*", action: "allow" }],
} satisfies Agent.Info
const user = {
id: MessageID.make("user-anthropic-tools"),
sessionID,
role: "user",
time: { created: Date.now() },
agent: agent.name,
model: { providerID: ProviderID.make("anthropic"), modelID: resolved.id, variant: "max" },
} satisfies MessageV2.User
const input = [
{
info: {
id: "msg_user",
sessionID,
role: "user",
time: { created: 1 },
agent: "gentleman",
model: { providerID: "anthropic", modelID: "claude-opus-4-6", variant: "max" },
},
parts: [
{
id: "p_user",
sessionID,
messageID: "msg_user",
type: "text",
text: "Can you check whether there are any PDF files in my home directory?",
},
],
},
{
info: {
id: "msg_call",
sessionID,
parentID: "msg_user",
role: "assistant",
mode: "gentleman",
agent: "gentleman",
variant: "max",
path: { cwd: "/root", root: "/" },
cost: 0,
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
modelID: "claude-opus-4-6",
providerID: "anthropic",
time: { created: 2, completed: 3 },
finish: "tool-calls",
},
parts: [
{
id: "p_step",
sessionID,
messageID: "msg_call",
type: "step-start",
},
{
id: "p_read",
sessionID,
messageID: "msg_call",
type: "tool",
tool: "read",
callID: "toolu_01N8mDEzG8DSTs7UPHFtmgCT",
state: {
status: "completed",
input: { filePath: "/root" },
output: "<path>/root</path>",
metadata: {},
title: "root",
time: { start: 10, end: 11 },
},
},
{
id: "p_glob",
sessionID,
messageID: "msg_call",
type: "tool",
tool: "glob",
callID: "toolu_01APxrADs7VozN8uWzw9WwHr",
state: {
status: "completed",
input: { pattern: "**/*.pdf", path: "/root" },
output: "No files found",
metadata: {},
title: "root",
time: { start: 12, end: 13 },
},
},
{
id: "p_text",
sessionID,
messageID: "msg_call",
type: "text",
text: "I checked your home directory and looked for PDF files.",
time: { start: 14, end: 15 },
},
],
},
] as any[]
await drain({
user,
sessionID,
model: resolved,
agent,
system: [],
messages: await MessageV2.toModelMessages(input as any, resolved),
tools: {
read: tool({
description: "Stub read tool",
inputSchema: z.object({
filePath: z.string(),
}),
execute: async () => ({ output: "stub" }),
}),
glob: tool({
description: "Stub glob tool",
inputSchema: z.object({
pattern: z.string(),
path: z.string().optional(),
}),
execute: async () => ({ output: "stub" }),
}),
},
})
const capture = await request
const body = capture.body
expect(capture.url.pathname.endsWith("/messages")).toBe(true)
expect(body.messages).toStrictEqual([
{
role: "user",
content: [{ type: "text", text: "Can you check whether there are any PDF files in my home directory?" }],
},
{
role: "assistant",
content: [
{
type: "text",
text: "I checked your home directory and looked for PDF files.",
cache_control: {
type: "ephemeral",
},
},
{
type: "tool_use",
id: "toolu_01N8mDEzG8DSTs7UPHFtmgCT",
name: "read",
input: { filePath: "/root" },
},
{
type: "tool_use",
id: "toolu_01APxrADs7VozN8uWzw9WwHr",
name: "glob",
input: { pattern: "**/*.pdf", path: "/root" },
},
],
},
{
role: "user",
content: [
{
type: "tool_result",
tool_use_id: "toolu_01N8mDEzG8DSTs7UPHFtmgCT",
content: "<path>/root</path>",
},
{
type: "tool_result",
tool_use_id: "toolu_01APxrADs7VozN8uWzw9WwHr",
content: "No files found",
cache_control: {
type: "ephemeral",
},
},
],
},
])
},
})
})
test("sends Google API payload for Gemini models", async () => {
const server = state.server
if (!server) {