feat: Finalizer-Agent – dritter Agent der nach Worker + Review einschreitet
Backend:
- SessionRecord + DB-Migration: finalizer_agent_id auf sessions
- ChatContext.FinalizerContext (Model, SystemPrompt, Tools, Workspace)
- ChatService: FinalizerContext aufbauen (analog zu ReviewContext)
- AnthropicService: RunFinalizer() nach Review-Phase (oder direkt nach Worker)
- RunReviewAgentChat() refactored zu generischem RunAgentChat()
mit agentType-Parameter ('review' | 'finalizer') für SSE-Events und DB-Tags
- SSE-Events: finalizer_start, finalizer_text, finalizer_tool_use, finalizer_done
Frontend:
- Session-Page: Finalizer-Agent-Picker (im 'Weitere Einstellungen' Bereich)
- Chat: SSE-Events für Finalizer-Phase verarbeiten
- UI: addReviewBubble/finalizeReviewBubble unterstützen agentType 'finalizer'
mit eigener Farbe (success-green) und Flag-Checkered-Icon
- renderMarkdown: [Finalizer: AgentName] Tags parsen
- History: Finalizer-Messages als .finalizer-bubble rendern
- Shared-Page: Finalizer-Messages korrekt erkennen und stylen
- Dashboard: Finalizer-Badge (flag-checkered) auf Session-Cards
This commit is contained in:
1 parent
a3f2aa38c1
commit
4bec740765
14 files changed
+228
-46
No files matched your search
@@ -157,8 +157,8 @@ function _mergeConsecutiveAssistantTexts(msgs) {
|
||||
for (const msg of msgs) {
|
||||
if (msg.type === 'text' && msg.role === 'assistant') {
|
||||
const prev = result[result.length - 1];
|
||||
const isReview = msg.content && msg.content.startsWith('[Review:');
|
||||
const prevIsReview = prev && prev.content && prev.content.startsWith('[Review:');
|
||||
const isReview = msg.content && (msg.content.startsWith('[Review:') || msg.content.startsWith('[Finalizer:'));
|
||||
const prevIsReview = prev && prev.content && (prev.content.startsWith('[Review:') || prev.content.startsWith('[Finalizer:'));
|
||||
if (prev && prev.type === 'text' && prev.role === 'assistant'
|
||||
&& prev.iteration === msg.iteration && !isReview && !prevIsReview) {
|
||||
// Gleiche Iteration: nahtlos zusammenfügen (Web-Search-Fragmente etc.)
|
||||
@@ -181,7 +181,7 @@ function _renderMessagesIntoFragment(fragment, msgs, imageMessageIds) {
|
||||
const div = document.createElement('div');
|
||||
switch (msg.type) {
|
||||
case 'text': {
|
||||
const isReviewMsg = msg.content && (msg.content.startsWith('[Review:') || msg.content.startsWith('[Review-Feedback'));
|
||||
const isReviewMsg = msg.content && (msg.content.startsWith('[Review:') || msg.content.startsWith('[Review-Feedback') || msg.content.startsWith('[Finalizer:'));
|
||||
if (msg.role === 'user' && !isReviewMsg) {
|
||||
div.className = 'msg user markdown' + (msg.isMarked ? ' marked' : '');
|
||||
if (msg.deletedOn) div.classList.add(isDeletedVisible() ? 'msg-deleted' : 'msg-deleted-hidden');
|
||||
@@ -290,7 +290,7 @@ function renderMessages(msgs, addToConversation) {
|
||||
}
|
||||
}
|
||||
} else if (msg.role === 'assistant') {
|
||||
if (msg.content && msg.content.startsWith('[Review:')) {
|
||||
if (msg.content && (msg.content.startsWith('[Review:') || msg.content.startsWith('[Finalizer:'))) {
|
||||
addReviewBubbleStatic(msg.content, msg.createdAt, msg.id, msg.isMarked, msg.deletedOn);
|
||||
} else {
|
||||
addAssistantBubble(msg.content, msg.createdAt, msg.id, msg.isMarked, msg.deletedOn);
|
||||
|
||||
Reference in new issue
Block a user