tool folding

This commit is contained in:
Ian Gulliver
2026-10-16 11:26:15 -07:00
parent 4dff9b7471
commit ff7ce86cb5
5 changed files with 77 additions and 21 deletions
+34 -8
View File
@@ -66,6 +66,8 @@ type Subagent = {
type: string;
description: string;
status: HTMLElement;
body: HTMLElement;
run: Run | undefined;
};
type Ctx = {
@@ -397,12 +399,19 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
const runHead = (run: Run) => [subagentTag(run.parent, ctx), runSummary(run.calls)];
const addToRun = (el: HTMLElement, call: Call | undefined, parent: string) => {
const run = ctx.run;
if (!run || run.parent !== parent) {
ctx.run = { first: el, group: undefined, calls: call ? [call] : [], parent };
put(el);
const sub = ctx.subagents.get(parent);
if (sub) {
sub.run = extendRun(sub.run, el, call, parent, (e) => sub.body.append(e));
return;
}
ctx.run = extendRun(ctx.run, el, call, parent, put);
};
const extendRun = (run: Run | undefined, el: HTMLElement, call: Call | undefined, parent: string, place: (el: HTMLElement) => void): Run => {
if (!run || run.parent !== parent) {
place(el);
return { first: el, group: undefined, calls: call ? [call] : [], parent };
}
if (call) {
run.calls.push(call);
}
@@ -417,6 +426,7 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
}
run.group.body.append(el);
replace(run.group.summary, ...runHead(run));
return run;
};
let stream: { el: HTMLElement; text: string; timer: number } | undefined;
@@ -515,9 +525,16 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
markReview(button, r);
}
}
const sub = ctx.subagents.get(parent);
if (ev.kind === "agent.tool_call" && isSubagentCall(p)) {
const el = renderSubagent(p, ctx);
if (sub) {
sub.run = undefined;
sub.body.append(el);
continue;
}
ctx.run = undefined;
put(renderSubagent(p, ctx));
put(el);
continue;
}
if (ev.kind === "agent.tool_call") {
@@ -532,6 +549,11 @@ export function mountChat(root: HTMLElement, src: ChatSource, makeHead: (rerende
addToRun(el, undefined, parent);
continue;
}
if (sub) {
sub.run = undefined;
sub.body.append(el);
continue;
}
ctx.run = undefined;
if (ev.kind === "turn.ended") {
ctx.open = false;
@@ -907,8 +929,10 @@ function subagentTag(parent: string, ctx: Ctx): HTMLElement | null {
if (!parent) {
return null;
}
const sub = ctx.subagents.get(parent);
return h("span", { class: "subagent-tag", title: sub?.description ?? "" }, `↳ ${sub?.type ?? "subagent"}`);
if (ctx.subagents.has(parent)) {
return null;
}
return h("span", { class: "subagent-tag" }, "↳ subagent");
}
function renderToolCall(p: Record<string, unknown>, ctx: Ctx): HTMLElement {
@@ -946,14 +970,16 @@ function renderSubagent(p: Record<string, unknown>, ctx: Ctx): HTMLElement {
const description = String(input["description"] ?? "");
const status = h("span", { class: "subagent-status" }, "starting…");
const result = h("div", { class: "tool-result pending" }, "running…");
const body = h("div", { class: "subagent-body" });
const tag = subagentTag(parentOf(p), ctx);
ctx.tools.set(id, result);
ctx.subagents.set(id, { type, description, status });
ctx.subagents.set(id, { type, description, status, body, run: undefined });
return h(
"details",
{ class: "tool subagent" },
h("summary", {}, tag, h("span", { class: "tool-name" }, `${p["name"]} ${type}`), " ", h("span", { class: "tool-brief" }, description), " ", status),
markdown(String(input["prompt"] ?? ""), "text md subagent-prompt", { taskId: ctx.taskId }),
body,
result,
);
}