mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-07-08 06:32:44 +08:00
fix: show agent subtask
This commit is contained in:
@@ -13,6 +13,48 @@ function formatToolResultContent(content: unknown): string {
|
||||
return toolUseErrorMatch ? toolUseErrorMatch[1] : text;
|
||||
}
|
||||
|
||||
type ParsedTaskNotification = {
|
||||
status: string;
|
||||
summary: string;
|
||||
result: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a background-agent `<task-notification>` block.
|
||||
*
|
||||
* The harness injects these as user-role messages when a background task stops.
|
||||
* Newer notifications carry extra fields (`<tool-use-id>`, `<note>`, `<usage>`,
|
||||
* and a `<result>` markdown payload) that the previous single-shot regex could
|
||||
* not match, so the whole raw XML block leaked through as plain user text.
|
||||
* Fields are extracted independently so the block renders as an assistant
|
||||
* notification plus, when present, the agent's markdown result.
|
||||
*/
|
||||
function parseTaskNotification(content: string): ParsedTaskNotification | null {
|
||||
if (!content.trimStart().startsWith('<task-notification>')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const statusMatch = /<status>([\s\S]*?)<\/status>/.exec(content);
|
||||
const summaryMatch = /<summary>([\s\S]*?)<\/summary>/.exec(content);
|
||||
|
||||
let result = '';
|
||||
const resultOpen = content.indexOf('<result>');
|
||||
if (resultOpen !== -1) {
|
||||
const afterOpen = content.slice(resultOpen + '<result>'.length);
|
||||
const closeIndex = afterOpen.indexOf('</result>');
|
||||
result =
|
||||
closeIndex === -1
|
||||
? afterOpen.replace(/<\/task-notification>\s*$/, '').trim()
|
||||
: afterOpen.slice(0, closeIndex).trim();
|
||||
}
|
||||
|
||||
return {
|
||||
status: statusMatch?.[1]?.trim() || 'completed',
|
||||
summary: summaryMatch?.[1]?.trim() || 'Background task finished',
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert NormalizedMessage[] from the session store into ChatMessage[]
|
||||
* that the existing UI components expect.
|
||||
@@ -56,17 +98,26 @@ export function normalizedToChatMessages(messages: NormalizedMessage[]): ChatMes
|
||||
|
||||
if (msg.role === 'user') {
|
||||
// Parse task notifications
|
||||
const taskNotifRegex = /<task-notification>\s*<task-id>[^<]*<\/task-id>\s*<output-file>[^<]*<\/output-file>\s*<status>([^<]*)<\/status>\s*<summary>([^<]*)<\/summary>\s*<\/task-notification>/g;
|
||||
const taskNotifMatch = taskNotifRegex.exec(content);
|
||||
if (taskNotifMatch) {
|
||||
const taskNotif = parseTaskNotification(content);
|
||||
if (taskNotif) {
|
||||
converted.push({
|
||||
type: 'assistant',
|
||||
content: taskNotifMatch[2]?.trim() || 'Background task finished',
|
||||
content: taskNotif.summary,
|
||||
timestamp: msg.timestamp,
|
||||
isTaskNotification: true,
|
||||
taskStatus: taskNotifMatch[1]?.trim() || 'completed',
|
||||
taskStatus: taskNotif.status,
|
||||
...sharedMetadata,
|
||||
});
|
||||
// Render the agent's result as a normal assistant message so its
|
||||
// markdown displays correctly instead of leaking raw XML.
|
||||
if (taskNotif.result) {
|
||||
converted.push({
|
||||
type: 'assistant',
|
||||
content: formatUsageLimitText(unescapeWithMathProtection(decodeHtmlEntities(taskNotif.result))),
|
||||
timestamp: msg.timestamp,
|
||||
...sharedMetadata,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
converted.push({
|
||||
type: 'user',
|
||||
|
||||
Reference in New Issue
Block a user