mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-23 10:45:33 -04:00
137 lines
3.8 KiB
TypeScript
137 lines
3.8 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { normalizeTool, toolInlineInfo, toolOutputText, toolPath, toolScroll } from "../../src/mini/tool"
|
|
import { canonicalToolPart } from "./fixture/tool-part"
|
|
|
|
describe("Mini tool presentation", () => {
|
|
test("uses V2 shell output without the model-facing status", () => {
|
|
expect(
|
|
toolOutputText("shell", [
|
|
{ type: "text", text: "mini-output\n" },
|
|
{ type: "text", text: "Command exited with code 0." },
|
|
]),
|
|
).toBe("mini-output\n")
|
|
|
|
expect(
|
|
toolOutputText("shell", [
|
|
{ type: "text", text: "" },
|
|
{ type: "text", text: "Command exited with code 0." },
|
|
]),
|
|
).toBe("")
|
|
})
|
|
|
|
test("normalizes only persisted tool aliases into current fields", () => {
|
|
expect(
|
|
normalizeTool({
|
|
type: "tool",
|
|
id: "call-patch",
|
|
name: "apply_patch",
|
|
state: {
|
|
status: "completed",
|
|
input: { patchText: "*** Begin Patch\n*** End Patch" },
|
|
structured: {
|
|
files: [
|
|
{
|
|
type: "update",
|
|
filePath: "/tmp/project/src/a.ts",
|
|
relativePath: "src/a.ts",
|
|
patch: "@@ -1 +1 @@\n-old\n+new",
|
|
},
|
|
],
|
|
},
|
|
content: [{ type: "text", text: "patched" }],
|
|
},
|
|
time: { created: 1, ran: 1, completed: 2 },
|
|
}),
|
|
).toMatchObject({
|
|
name: "patch",
|
|
state: {
|
|
structured: {
|
|
files: [
|
|
{
|
|
status: "modified",
|
|
file: "src/a.ts",
|
|
patch: "@@ -1 +1 @@\n-old\n+new",
|
|
},
|
|
],
|
|
},
|
|
content: [{ type: "text", text: "patched" }],
|
|
},
|
|
})
|
|
|
|
expect(
|
|
normalizeTool({
|
|
type: "tool",
|
|
id: "call-subagent",
|
|
name: "task",
|
|
state: {
|
|
status: "running",
|
|
input: { subagent_type: "explore", description: "Inspect" },
|
|
structured: {},
|
|
content: [],
|
|
},
|
|
time: { created: 1, ran: 1 },
|
|
}),
|
|
).toMatchObject({ name: "subagent", state: { input: { agent: "explore" } } })
|
|
})
|
|
|
|
test("renders the skill name from structured metadata with the input id as fallback", () => {
|
|
const skill = (structured: { name?: string }) => ({
|
|
type: "tool" as const,
|
|
id: "call-skill",
|
|
name: "skill",
|
|
state: {
|
|
status: "completed" as const,
|
|
input: { id: "tigerstyle" },
|
|
structured,
|
|
content: [],
|
|
},
|
|
time: { created: 1, ran: 1, completed: 2 },
|
|
})
|
|
|
|
expect(toolInlineInfo(skill({ name: "effect" })).title).toBe('Skill "effect"')
|
|
expect(toolInlineInfo(skill({})).title).toBe('Skill "tigerstyle"')
|
|
expect(
|
|
toolScroll("start", {
|
|
directory: "/work/project",
|
|
raw: "",
|
|
name: "skill",
|
|
input: { id: "tigerstyle" },
|
|
meta: { name: "effect" },
|
|
state: {},
|
|
status: "completed",
|
|
error: "",
|
|
output: "",
|
|
time: {},
|
|
}),
|
|
).toBe('→ Skill "effect"')
|
|
})
|
|
|
|
test("renders compact search metadata", () => {
|
|
expect(
|
|
toolInlineInfo(
|
|
canonicalToolPart("glob", {
|
|
status: "completed",
|
|
input: { pattern: "*.ts" },
|
|
structured: { count: 3 },
|
|
content: [],
|
|
}),
|
|
).description,
|
|
).toBe("3 matches")
|
|
expect(
|
|
toolInlineInfo(
|
|
canonicalToolPart("grep", {
|
|
status: "completed",
|
|
input: { pattern: "needle" },
|
|
structured: { matches: 1 },
|
|
content: [],
|
|
}),
|
|
).description,
|
|
).toBe("1 match")
|
|
})
|
|
|
|
test("keeps segment-safe contained tool paths relative", () => {
|
|
expect(toolPath("..cache/result.txt", { directory: "/work/project" })).toBe("..cache/result.txt")
|
|
expect(toolPath("../shared/result.txt", { directory: "/work/project" })).toBe("/work/shared/result.txt")
|
|
})
|
|
})
|