fix(app): don't rely on metadata.summary in task tool render (#12497)

This commit is contained in:
Adam
2026-02-06 10:54:54 -06:00
committed by GitHub
parent 22353f0169
commit 9497cfdf45
2 changed files with 18 additions and 48 deletions

View File

@@ -2,7 +2,6 @@ import { Tool } from "./tool"
import DESCRIPTION from "./task.txt" import DESCRIPTION from "./task.txt"
import z from "zod" import z from "zod"
import { Session } from "../session" import { Session } from "../session"
import { Bus } from "../bus"
import { MessageV2 } from "../session/message-v2" import { MessageV2 } from "../session/message-v2"
import { Identifier } from "../id/id" import { Identifier } from "../id/id"
import { Agent } from "../agent/agent" import { Agent } from "../agent/agent"
@@ -118,28 +117,6 @@ export const TaskTool = Tool.define("task", async (ctx) => {
}) })
const messageID = Identifier.ascending("message") const messageID = Identifier.ascending("message")
const parts: Record<string, { id: string; tool: string; state: { status: string; title?: string } }> = {}
const unsub = Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
if (evt.properties.part.sessionID !== session.id) return
if (evt.properties.part.messageID === messageID) return
if (evt.properties.part.type !== "tool") return
const part = evt.properties.part
parts[part.id] = {
id: part.id,
tool: part.tool,
state: {
status: part.state.status,
title: part.state.status === "completed" ? part.state.title : undefined,
},
}
ctx.metadata({
title: params.description,
metadata: {
sessionId: session.id,
model,
},
})
})
function cancel() { function cancel() {
SessionPrompt.cancel(session.id) SessionPrompt.cancel(session.id)
@@ -163,22 +140,8 @@ export const TaskTool = Tool.define("task", async (ctx) => {
...Object.fromEntries((config.experimental?.primary_tools ?? []).map((t) => [t, false])), ...Object.fromEntries((config.experimental?.primary_tools ?? []).map((t) => [t, false])),
}, },
parts: promptParts, parts: promptParts,
}).finally(() => {
unsub()
}) })
const messages = await Session.messages({ sessionID: session.id })
const summary = messages
.filter((x) => x.info.role === "assistant")
.flatMap((msg) => msg.parts.filter((x: any) => x.type === "tool") as MessageV2.ToolPart[])
.map((part) => ({
id: part.id,
tool: part.tool,
state: {
status: part.state.status,
title: part.state.status === "completed" ? part.state.title : undefined,
},
}))
const text = result.parts.findLast((x) => x.type === "text")?.text ?? "" const text = result.parts.findLast((x) => x.type === "text")?.text ?? ""
const output = [ const output = [
@@ -192,7 +155,6 @@ export const TaskTool = Tool.define("task", async (ctx) => {
return { return {
title: params.description, title: params.description,
metadata: { metadata: {
summary,
sessionId: session.id, sessionId: session.id,
model, model,
}, },

View File

@@ -876,16 +876,18 @@ ToolRegistry.register({
render(props) { render(props) {
const data = useData() const data = useData()
const i18n = useI18n() const i18n = useI18n()
const summary = () => const childSessionId = () => props.metadata.sessionId as string | undefined
(props.metadata.summary ?? []) as { id: string; tool: string; state: { status: string; title?: string } }[] const childToolParts = createMemo(() => {
const sessionId = childSessionId()
if (!sessionId) return []
return getSessionToolParts(data.store, sessionId)
})
const autoScroll = createAutoScroll({ const autoScroll = createAutoScroll({
working: () => true, working: () => true,
overflowAnchor: "auto", overflowAnchor: "auto",
}) })
const childSessionId = () => props.metadata.sessionId as string | undefined
const childPermission = createMemo(() => { const childPermission = createMemo(() => {
const sessionId = childSessionId() const sessionId = childSessionId()
if (!sessionId) return undefined if (!sessionId) return undefined
@@ -1006,15 +1008,21 @@ ToolRegistry.register({
data-scrollable data-scrollable
> >
<div ref={autoScroll.contentRef} data-component="task-tools"> <div ref={autoScroll.contentRef} data-component="task-tools">
<For each={summary()}> <For each={childToolParts()}>
{(item) => { {(item) => {
const info = getToolInfo(item.tool) const info = createMemo(() => getToolInfo(item.tool, item.state.input))
const subtitle = createMemo(() => {
if (info().subtitle) return info().subtitle
if (item.state.status === "completed" || item.state.status === "running") {
return item.state.title
}
})
return ( return (
<div data-slot="task-tool-item"> <div data-slot="task-tool-item">
<Icon name={info.icon} size="small" /> <Icon name={info().icon} size="small" />
<span data-slot="task-tool-title">{info.title}</span> <span data-slot="task-tool-title">{info().title}</span>
<Show when={item.state.title}> <Show when={subtitle()}>
<span data-slot="task-tool-subtitle">{item.state.title}</span> <span data-slot="task-tool-subtitle">{subtitle()}</span>
</Show> </Show>
</div> </div>
) )