Review-Agent: Default=Approved + vollständige Tool-Boxes für Sub-Agents
Backend:
- Review-Agent: Default = Approved (analog zum Preparer Default=Forward)
Nur bei explizitem [FEEDBACK]-Tag wird Feedback zurückgespielt
Verhindert Loop wenn Review-Agent bestätigt ohne [APPROVED]-Tag
- Neues SSE-Event {agentType}_tool_end für Sub-Agent Tool-Ergebnisse
Sendet toolName, input, result, isError nach Tool-Ausführung
Frontend Streaming (stream-ui.js + chat.js):
- addReviewToolUse: Vollständige Tool-Box mit Loading-Spinner statt nur Name
- finishReviewToolBox: Befüllt Tool-Box nach tool_end mit Details (Pfad, Diff, Result)
- Event-Handler für preparer/review/finalizer_tool_end
Frontend History (history.js):
- _renderReviewGroup: Vollständige Tool-Boxes statt einfache Tool-Use-Indikatoren
- Tool-Result Look-Ahead für korrekte Zuordnung (toolCallId-Match)
- Web-Search-Sources in Review-Bubbles unterstützt
- Tool-Visibility-Filter (isToolVisible) auch für Sub-Agent-Tools
CSS:
- .review-tool-use → .review-tool-box (erbt normale Tool-Box-Styles)
This commit is contained in:
1 parent
f3b6491643
commit
1fc6889ced
5 files changed
+93
-30
No files matched your search
+35
-6
@@ -320,11 +320,8 @@ function _renderReviewGroup(tagGroup, archived) {
|
||||
text = text.replace(/^\[(Review|Preparer|Finalizer): [^\]]+\]\s*/, '');
|
||||
if (text) textParts.push(text);
|
||||
} else if (m.type === 'tool_use') {
|
||||
// Insert tool-use indicator
|
||||
var toolDiv = document.createElement('div');
|
||||
toolDiv.className = 'review-tool-use';
|
||||
toolDiv.innerHTML = '<i class="fa fa-wrench"></i> <span class="tool-name">' + esc(m.toolName) + '</span>';
|
||||
// Flush accumulated text before tool indicator
|
||||
if (!isToolVisible(m.toolName)) continue;
|
||||
// Flush accumulated text before tool box
|
||||
if (textParts.length > 0) {
|
||||
var contentDiv = document.createElement('div');
|
||||
contentDiv.className = 'review-content markdown';
|
||||
@@ -333,9 +330,41 @@ function _renderReviewGroup(tagGroup, archived) {
|
||||
bubble.appendChild(contentDiv);
|
||||
textParts = [];
|
||||
}
|
||||
// Full tool-box (same as normal tool boxes)
|
||||
var toolDiv = document.createElement('div');
|
||||
toolDiv.className = 'tool-box review-tool-box' + (archived ? ' archived' : '');
|
||||
// Look ahead for matching tool_result
|
||||
var toolResult = null;
|
||||
var toolIsError = false;
|
||||
for (var j = i + 1; j < tagGroup.length; j++) {
|
||||
if (tagGroup[j].type === 'tool_result' && tagGroup[j].toolCallId === m.toolCallId) {
|
||||
toolResult = tagGroup[j].content;
|
||||
toolIsError = tagGroup[j].isError;
|
||||
break;
|
||||
}
|
||||
}
|
||||
renderToolBoxContent(toolDiv, m.toolName, m.content, toolResult, toolIsError);
|
||||
bubble.appendChild(toolDiv);
|
||||
} else if (m.type === 'web_search_result') {
|
||||
if (!isToolVisible('web_search')) continue;
|
||||
if (textParts.length > 0) {
|
||||
var contentDiv = document.createElement('div');
|
||||
contentDiv.className = 'review-content markdown';
|
||||
contentDiv.innerHTML = renderMarkdown(textParts.join('\n\n'));
|
||||
parseFluentEmojis(contentDiv);
|
||||
bubble.appendChild(contentDiv);
|
||||
textParts = [];
|
||||
}
|
||||
var wsSources = [];
|
||||
try { wsSources = JSON.parse(m.content || '[]'); } catch(e) {}
|
||||
if (wsSources.length > 0) {
|
||||
var wsDiv = document.createElement('div');
|
||||
wsDiv.className = 'tool-box review-tool-box' + (archived ? ' archived' : '');
|
||||
renderToolBoxContent(wsDiv, 'web_search', null, null, false, wsSources);
|
||||
bubble.appendChild(wsDiv);
|
||||
}
|
||||
}
|
||||
// tool_result and web_search_result are skipped (same as streaming)
|
||||
// tool_result is consumed by tool_use look-ahead above
|
||||
}
|
||||
|
||||
// Flush remaining text
|
||||
|
||||
Reference in new issue
Block a user