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;
|
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[]
|
* Convert NormalizedMessage[] from the session store into ChatMessage[]
|
||||||
* that the existing UI components expect.
|
* that the existing UI components expect.
|
||||||
@@ -56,17 +98,26 @@ export function normalizedToChatMessages(messages: NormalizedMessage[]): ChatMes
|
|||||||
|
|
||||||
if (msg.role === 'user') {
|
if (msg.role === 'user') {
|
||||||
// Parse task notifications
|
// 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 taskNotif = parseTaskNotification(content);
|
||||||
const taskNotifMatch = taskNotifRegex.exec(content);
|
if (taskNotif) {
|
||||||
if (taskNotifMatch) {
|
|
||||||
converted.push({
|
converted.push({
|
||||||
type: 'assistant',
|
type: 'assistant',
|
||||||
content: taskNotifMatch[2]?.trim() || 'Background task finished',
|
content: taskNotif.summary,
|
||||||
timestamp: msg.timestamp,
|
timestamp: msg.timestamp,
|
||||||
isTaskNotification: true,
|
isTaskNotification: true,
|
||||||
taskStatus: taskNotifMatch[1]?.trim() || 'completed',
|
taskStatus: taskNotif.status,
|
||||||
...sharedMetadata,
|
...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 {
|
} else {
|
||||||
converted.push({
|
converted.push({
|
||||||
type: 'user',
|
type: 'user',
|
||||||
|
|||||||
Reference in New Issue
Block a user