From 3b5aafc991d2de43927983c496d9e9e57ed5b8f5 Mon Sep 17 00:00:00 2001 From: Michael Suchacz <203725896+ibetitsmike@users.noreply.github.com> Date: Mon, 3 Aug 2026 15:49:20 +0000 Subject: [PATCH 1/8] =?UTF-8?q?=F0=9F=A4=96=20feat:=20expose=20sub-agent?= =?UTF-8?q?=20model=20and=20thinking=20level=20in=20task=20schedule=20and?= =?UTF-8?q?=20report?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task tool results (spawned rows, completed reports) and the sub-agent report envelope now carry the child's resolved modelString/thinkingLevel, and the TaskToolCall card plus SubagentReportMessageContent render them. --- _Generated with `mux` • Model: `anthropic:claude-fable-5` • Thinking: `xhigh`_ --- .../Messages/MessageRenderer.test.tsx | 26 ++++++++ .../Messages/SubagentReportMessageContent.tsx | 18 +++++ .../features/Tools/TaskToolCall.stories.tsx | 6 ++ src/browser/features/Tools/TaskToolCall.tsx | 66 +++++++++++++++++++ .../stories/helpers/subagentReportStory.tsx | 4 ++ src/browser/stories/mocks/messages.ts | 5 ++ .../utils/subagentReportEnvelope.test.ts | 28 ++++++++ src/common/utils/subagentReportEnvelope.ts | 12 ++++ src/common/utils/tools/toolDefinitions.ts | 13 +++- src/node/services/taskService.test.ts | 10 ++- src/node/services/taskService.ts | 47 ++++++++++++- src/node/services/tools/task.ts | 22 +++++++ 12 files changed, 250 insertions(+), 7 deletions(-) diff --git a/src/browser/features/Messages/MessageRenderer.test.tsx b/src/browser/features/Messages/MessageRenderer.test.tsx index 187bcb4cac..2e8dabe71b 100644 --- a/src/browser/features/Messages/MessageRenderer.test.tsx +++ b/src/browser/features/Messages/MessageRenderer.test.tsx @@ -288,6 +288,32 @@ Found the **message renderer** and its responsive story coverage. expect(parseSubagentReportEnvelope(formatSubagentReportEnvelope(expected))).toEqual(expected); }); + test("shows the sub-agent model and thinking level when the envelope carries them", () => { + const withMetadata = createReportMessage(` +{"taskId":"task-model","agentType":"explore","status":"completed","title":"Model exposed","reportMarkdown":"Body","model":"anthropic:claude-opus-5","thinkingLevel":"high"} +`); + + const metadataView = render( + + + + ); + expect(metadataView.getByText("Opus 5")).toBeDefined(); + expect(metadataView.getByText("thinking: high")).toBeDefined(); + metadataView.unmount(); + + const withoutMetadata = createReportMessage(` +{"taskId":"task-no-model","agentType":"explore","status":"completed","title":"No model","reportMarkdown":"Body"} +`); + + const plainView = render( + + + + ); + expect(plainView.queryByText(/thinking:/)).toBeNull(); + }); + test("normalizes multiline report titles instead of exposing the envelope", () => { const message = createReportMessage(` task-multiline-title diff --git a/src/browser/features/Messages/SubagentReportMessageContent.tsx b/src/browser/features/Messages/SubagentReportMessageContent.tsx index 106d0cfa97..dae51c7f25 100644 --- a/src/browser/features/Messages/SubagentReportMessageContent.tsx +++ b/src/browser/features/Messages/SubagentReportMessageContent.tsx @@ -2,8 +2,10 @@ import { useState, type ReactElement } from "react"; import { Bot, Braces, ChevronRight, CircleCheck, Radio } from "lucide-react"; import { cn } from "@/common/lib/utils"; +import { getThinkingOptionLabel } from "@/common/types/thinking"; import type { SubagentReportEnvelope } from "@/common/utils/subagentReportEnvelope"; import { MarkdownRenderer } from "./MarkdownRenderer"; +import { ModelDisplay } from "./ModelDisplay"; export { parseSubagentReportEnvelope } from "@/common/utils/subagentReportEnvelope"; @@ -40,6 +42,22 @@ export function SubagentReportMessageContent(
{props.report.agentType} + {props.report.model && ( + <> + + + + + + )} + {props.report.thinkingLevel != null && ( + <> + + + thinking: {getThinkingOptionLabel(props.report.thinkingLevel, props.report.model)} + + + )} = (props) => { + if (!props.modelString && props.thinkingLevel == null) { + return null; + } + return ( + + {props.modelString && } + {props.thinkingLevel != null && ( + + thinking: {getThinkingOptionLabel(props.thinkingLevel, props.modelString)} + + )} + + ); +}; + interface TaskToolOwnReport { reportMarkdown: string; title?: string; @@ -654,12 +682,14 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): ownReportsByTaskId: Map; taskGroupsByTaskId: Map; workspaceIdByTaskId: Map; + aiSettingsByTaskId: Map; } { const taskIds = new Set(); const statusByTaskId = new Map(); const ownReportsByTaskId = new Map(); const taskGroupsByTaskId = new Map(); const workspaceIdByTaskId = new Map(); + const aiSettingsByTaskId = new Map(); if (!result) { return { taskIds: [], @@ -667,6 +697,7 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): ownReportsByTaskId, taskGroupsByTaskId, workspaceIdByTaskId, + aiSettingsByTaskId, }; } @@ -699,10 +730,23 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): } }; + const rememberAiSettings = (taskId: string, settings: TaskAiSettingsInfo): void => { + const modelString = trimToNonEmptyString(settings.modelString) ?? undefined; + if (!modelString && settings.thinkingLevel == null) { + return; + } + const existing = aiSettingsByTaskId.get(taskId); + aiSettingsByTaskId.set(taskId, { + modelString: existing?.modelString ?? modelString, + thinkingLevel: existing?.thinkingLevel ?? settings.thinkingLevel, + }); + }; + const taskStatuses = "tasks" in result && Array.isArray(result.tasks) ? result.tasks : undefined; const singleTaskId = rememberTaskId(result.taskId); if (singleTaskId) { rememberWorkspace(singleTaskId, result.workspaceId); + rememberAiSettings(singleTaskId, result); } if (singleTaskId && result.status === "completed" && typeof result.reportMarkdown === "string") { ownReportsByTaskId.set(singleTaskId, { @@ -724,6 +768,7 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): statusByTaskId.set(taskId, task.status); rememberWorkspace(taskId, task.workspaceId); rememberTaskGroup(taskId, { groupKind: task.groupKind, label: task.label }); + rememberAiSettings(taskId, task); } } } @@ -740,6 +785,7 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): }); rememberWorkspace(taskId, report.workspaceId); rememberTaskGroup(taskId, { groupKind: report.groupKind, label: report.label }); + rememberAiSettings(taskId, report); } } } @@ -757,6 +803,7 @@ function collectTaskToolResultDisplayData(result: TaskToolSuccessResult | null): ownReportsByTaskId, taskGroupsByTaskId, workspaceIdByTaskId, + aiSettingsByTaskId, }; } @@ -808,6 +855,11 @@ const TaskToolCandidateCard: React.FC<{ {entry.title && ( {entry.title} )} + {canViewTranscript && (