opencode/packages/opencode/test/session/truncation.test.ts
Aiden Cline ece719dc77 wip
2026-01-07 12:54:13 -06:00

120 lines
4.7 KiB
TypeScript

import { describe, test, expect } from "bun:test"
import { Truncate } from "../../src/session/truncation"
import path from "path"
const FIXTURES_DIR = path.join(import.meta.dir, "fixtures")
describe("Truncate", () => {
describe("output", () => {
test("truncates large json file by bytes", async () => {
const content = await Bun.file(path.join(FIXTURES_DIR, "models-api.json")).text()
const result = await Truncate.output(content)
expect(result.truncated).toBe(true)
expect(result.content).toContain("truncated...")
expect(result.outputPath).toBeDefined()
})
test("returns content unchanged when under limits", async () => {
const content = "line1\nline2\nline3"
const result = await Truncate.output(content)
expect(result.truncated).toBe(false)
expect(result.content).toBe(content)
})
test("truncates by line count", async () => {
const lines = Array.from({ length: 100 }, (_, i) => `line${i}`).join("\n")
const result = await Truncate.output(lines, { maxLines: 10 })
expect(result.truncated).toBe(true)
expect(result.content).toContain("...90 lines truncated...")
})
test("truncates by byte count", async () => {
const content = "a".repeat(1000)
const result = await Truncate.output(content, { maxBytes: 100 })
expect(result.truncated).toBe(true)
expect(result.content).toContain("truncated...")
})
test("truncates from head by default", async () => {
const lines = Array.from({ length: 10 }, (_, i) => `line${i}`).join("\n")
const result = await Truncate.output(lines, { maxLines: 3 })
expect(result.truncated).toBe(true)
expect(result.content).toContain("line0")
expect(result.content).toContain("line1")
expect(result.content).toContain("line2")
expect(result.content).not.toContain("line9")
})
test("truncates from tail when direction is tail", async () => {
const lines = Array.from({ length: 10 }, (_, i) => `line${i}`).join("\n")
const result = await Truncate.output(lines, { maxLines: 3, direction: "tail" })
expect(result.truncated).toBe(true)
expect(result.content).toContain("line7")
expect(result.content).toContain("line8")
expect(result.content).toContain("line9")
expect(result.content).not.toContain("line0")
})
test("uses default MAX_LINES and MAX_BYTES", () => {
expect(Truncate.MAX_LINES).toBe(2000)
expect(Truncate.MAX_BYTES).toBe(50 * 1024)
})
test("large single-line file truncates with byte message", async () => {
const content = await Bun.file(path.join(FIXTURES_DIR, "models-api.json")).text()
const result = await Truncate.output(content)
expect(result.truncated).toBe(true)
expect(result.content).toContain("chars truncated...")
expect(Buffer.byteLength(content, "utf-8")).toBeGreaterThan(Truncate.MAX_BYTES)
})
test("writes full output to file when truncated", async () => {
const lines = Array.from({ length: 100 }, (_, i) => `line${i}`).join("\n")
const result = await Truncate.output(lines, { maxLines: 10 })
expect(result.truncated).toBe(true)
expect(result.outputPath).toBeDefined()
expect(result.outputPath).toContain("tool_")
expect(result.content).toContain("Full output written to:")
expect(result.content).toContain("Grep")
const written = await Bun.file(result.outputPath!).text()
expect(written).toBe(lines)
})
test("suggests Task tool when agent has task permission", async () => {
const lines = Array.from({ length: 100 }, (_, i) => `line${i}`).join("\n")
const agent = { permission: [{ permission: "task", pattern: "*", action: "allow" as const }] }
const result = await Truncate.output(lines, { maxLines: 10 }, agent as any)
expect(result.truncated).toBe(true)
expect(result.content).toContain("Grep")
expect(result.content).toContain("Task tool")
})
test("omits Task tool hint when agent lacks task permission", async () => {
const lines = Array.from({ length: 100 }, (_, i) => `line${i}`).join("\n")
const agent = { permission: [{ permission: "task", pattern: "*", action: "deny" as const }] }
const result = await Truncate.output(lines, { maxLines: 10 }, agent as any)
expect(result.truncated).toBe(true)
expect(result.content).toContain("Grep")
expect(result.content).not.toContain("Task tool")
})
test("does not write file when not truncated", async () => {
const content = "short content"
const result = await Truncate.output(content)
expect(result.truncated).toBe(false)
expect(result.outputPath).toBeUndefined()
})
})
})