fix: show operation details in OpenCode tool records
Preserve OpenCode operation titles in main-session tool summaries, including permission waits, failures and interrupted calls. Keep title trimming and length limits aligned with subagent records. Update tool display documentation and include the activity-menu wording in UI-DESIGN.md. Validation: 132 focused tests passed; main-process typecheck and changed-file lint passed. Full-suite checks were affected by concurrent activity-menu changes and a test timeout. Release note: OpenCode main-session tool records now show file paths, commands or operation descriptions beside tool names, matching subagent records.
This commit is contained in:
@@ -2517,7 +2517,11 @@ describe("OpenCodeRuntime embedded permission mediation", () => {
|
||||
await runtime.dispose();
|
||||
});
|
||||
|
||||
it("keeps non-Task tools with Task-shaped input as generic tools", async () => {
|
||||
it.each([
|
||||
[" Custom delegate ", "Custom delegate"],
|
||||
["", "OpenCode 工具:custom_delegate"],
|
||||
["x".repeat(300), "x".repeat(240)],
|
||||
])("keeps generic tool titles bounded: %s", async (title, summary) => {
|
||||
const setup = runClient([
|
||||
{
|
||||
id: "custom-tool-completed",
|
||||
@@ -2536,7 +2540,7 @@ describe("OpenCodeRuntime embedded permission mediation", () => {
|
||||
prompt: "Inspect the complete source tree.",
|
||||
},
|
||||
output: "Custom tool result.",
|
||||
title: "Custom delegate",
|
||||
title,
|
||||
metadata: {},
|
||||
time: { start: 1, end: 2 },
|
||||
},
|
||||
@@ -2559,12 +2563,73 @@ describe("OpenCodeRuntime embedded permission mediation", () => {
|
||||
callId: "call-custom-1",
|
||||
name: "custom_delegate",
|
||||
state: "completed",
|
||||
summary,
|
||||
}),
|
||||
);
|
||||
expect(events.some((event) => event.type === "subagent")).toBe(false);
|
||||
await runtime.dispose();
|
||||
});
|
||||
|
||||
it.each(["error", "interrupted"])("retains the running tool title after %s", async (ending) => {
|
||||
const part = {
|
||||
id: "part-read-1",
|
||||
callID: "call-read-1",
|
||||
type: "tool" as const,
|
||||
tool: "read",
|
||||
};
|
||||
const setup = runClient([
|
||||
{
|
||||
id: "read-running",
|
||||
type: "message.part.updated",
|
||||
properties: {
|
||||
sessionID: "session-1",
|
||||
part: {
|
||||
...part,
|
||||
state: {
|
||||
status: "running",
|
||||
input: { filePath: "README.md" },
|
||||
title: "README.md",
|
||||
time: { start: 1 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
...(ending === "error" ? [{
|
||||
id: "read-error",
|
||||
type: "message.part.updated" as const,
|
||||
properties: {
|
||||
sessionID: "session-1",
|
||||
part: {
|
||||
...part,
|
||||
state: {
|
||||
status: "error" as const,
|
||||
input: { filePath: "README.md" },
|
||||
error: "File not found",
|
||||
time: { start: 1, end: 2 },
|
||||
},
|
||||
},
|
||||
},
|
||||
}] : []),
|
||||
]);
|
||||
const runtime = embeddedRuntime(setup.client);
|
||||
const events: RuntimeEvent[] = [];
|
||||
await expect((async () => {
|
||||
for await (const event of runtime.run({
|
||||
requestId: "3f496642-f47d-4e0a-8944-a32c77b0d6ef",
|
||||
conversationId: "conversation-1",
|
||||
prompt: "Read README.md",
|
||||
workMode: "execute",
|
||||
}, new AbortController().signal)) {
|
||||
events.push(event);
|
||||
}
|
||||
})()).rejects.toThrow();
|
||||
expect(events.filter((event) => event.type === "tool")).toEqual([
|
||||
expect.objectContaining({ state: "running", summary: "README.md" }),
|
||||
expect.objectContaining({ state: "failed", summary: "README.md" }),
|
||||
]);
|
||||
await runtime.dispose();
|
||||
});
|
||||
|
||||
it("does not impose a default wall-clock deadline on OpenCode runs", async () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user