Skip to content

Commit 54fab33

Browse files
committed
test: add empty-content guard tests for message() pipeline
Covers empty string content, empty array content, all-empty text parts, mixed valid/invalid messages, and provider-agnostic behavior. Ref anomalyco#23260
1 parent 64b7f9b commit 54fab33

1 file changed

Lines changed: 129 additions & 0 deletions

File tree

‎packages/opencode/test/provider/transform.test.ts‎

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4502,3 +4502,132 @@ describe("ProviderTransform.providerOptions - ai-gateway-provider", () => {
45024502
expect(result).toEqual({ openaiCompatible: { reasoningEffort: "high" } })
45034503
})
45044504
})
4505+
4506+
4507+
describe("ProviderTransform.message - empty content filtering", () => {
4508+
const deepseekModel = {
4509+
id: ModelV2.ID.make("deepseek/deepseek-chat"),
4510+
providerID: ProviderV2.ID.make("deepseek"),
4511+
api: {
4512+
id: "deepseek-chat",
4513+
url: "https://api.deepseek.com",
4514+
npm: "@ai-sdk/openai-compatible",
4515+
},
4516+
name: "DeepSeek Chat",
4517+
capabilities: {
4518+
temperature: true,
4519+
reasoning: true,
4520+
attachment: false,
4521+
toolcall: true,
4522+
input: { text: true, audio: false, image: false, video: false, pdf: false },
4523+
output: { text: true, audio: false, image: false, video: false, pdf: false },
4524+
interleaved: {
4525+
field: "reasoning_content",
4526+
},
4527+
},
4528+
cost: { input: 0.001, output: 0.002, cache: { read: 0.0001, write: 0.0002 } },
4529+
limit: { context: 128000, output: 8192 },
4530+
status: "active",
4531+
options: {},
4532+
headers: {},
4533+
release_date: "2023-04-01",
4534+
}
4535+
4536+
test("filters out messages with empty string content", () => {
4537+
const msgs = [
4538+
{ role: "user", content: "" },
4539+
{ role: "user", content: "valid message" },
4540+
{ role: "assistant", content: "" },
4541+
] as any[]
4542+
const result = ProviderTransform.message(msgs, deepseekModel, {})
4543+
expect(result).toHaveLength(1)
4544+
expect(result[0].content).toBe("valid message")
4545+
})
4546+
4547+
test("filters out messages with empty array content", () => {
4548+
const msgs = [
4549+
{ role: "assistant", content: [] },
4550+
{ role: "user", content: "valid" },
4551+
] as any[]
4552+
const result = ProviderTransform.message(msgs, deepseekModel, {})
4553+
expect(result).toHaveLength(1)
4554+
expect(result[0].content).toBe("valid")
4555+
})
4556+
4557+
test("filters out messages where all text parts are empty", () => {
4558+
const msgs = [
4559+
{
4560+
role: "assistant",
4561+
content: [
4562+
{ type: "text", text: "" },
4563+
{ type: "reasoning", text: "" },
4564+
],
4565+
},
4566+
{ role: "user", content: "valid" },
4567+
] as any[]
4568+
const result = ProviderTransform.message(msgs, deepseekModel, {})
4569+
expect(result).toHaveLength(1)
4570+
expect(result[0].content).toBe("valid")
4571+
})
4572+
4573+
test("preserves non-empty messages in mixed context", () => {
4574+
const msgs = [
4575+
{ role: "system", content: "system prompt" },
4576+
{ role: "user", content: "hello" },
4577+
{ role: "assistant", content: "" },
4578+
{ role: "user", content: "follow up" },
4579+
{
4580+
role: "assistant",
4581+
content: [{ type: "text", text: "reply" }],
4582+
},
4583+
{
4584+
role: "assistant",
4585+
content: [
4586+
{ type: "text", text: "" },
4587+
{ type: "reasoning", text: " " },
4588+
],
4589+
},
4590+
] as any[]
4591+
const result = ProviderTransform.message(msgs, deepseekModel, {}) as any[]
4592+
expect(result).toHaveLength(4)
4593+
expect(result[0].content).toBe("system prompt")
4594+
expect(result[1].content).toBe("hello")
4595+
expect(result[2].content).toBe("follow up")
4596+
expect(result[3].content[0].text).toBe("reply")
4597+
})
4598+
4599+
test("applies empty-content guard regardless of provider", () => {
4600+
// The guard is provider-agnostic — verify it works for a non-DeepSeek model too
4601+
const openaiModel = {
4602+
id: ModelV2.ID.make("openai/gpt-4"),
4603+
providerID: ProviderV2.ID.make("openai"),
4604+
api: { id: "gpt-4", url: "https://api.openai.com", npm: "@ai-sdk/openai" },
4605+
name: "GPT-4",
4606+
capabilities: {
4607+
temperature: true,
4608+
reasoning: false,
4609+
attachment: true,
4610+
toolcall: true,
4611+
input: { text: true, audio: false, image: true, video: false, pdf: true },
4612+
output: { text: true, audio: false, image: false, video: false, pdf: false },
4613+
interleaved: false,
4614+
},
4615+
cost: { input: 1, output: 1, cache: { read: 0, write: 0 } },
4616+
limit: { context: 128000, output: 4096 },
4617+
status: "active",
4618+
options: {},
4619+
headers: {},
4620+
release_date: "2023-03-14",
4621+
}
4622+
4623+
const msgs = [
4624+
{ role: "user", content: "" },
4625+
{ role: "assistant", content: [] },
4626+
{ role: "user", content: "only valid message" },
4627+
] as any[]
4628+
const result = ProviderTransform.message(msgs, openaiModel, {})
4629+
expect(result).toHaveLength(1)
4630+
expect(result[0].content).toBe("only valid message")
4631+
})
4632+
})
4633+

0 commit comments

Comments
 (0)