refactor: improve agent notification types and fix activity curator

- Convert agent notifications to discriminated union (session/permission/status)
- Fix activity curator to properly handle typed session updates
- Serialize Date objects in AgentInfo for JSON compatibility
- Use activity curator for title generation context
- Reduce console.error to console.warn for non-critical WebSocket errors
- Improve spacing in agent stream views
- Delay title generation until 15+ updates available
```
This commit is contained in:
Mohamed Boudra
2025-10-23 09:01:38 +02:00
parent c6cdc09a0b
commit 0893a9dc33
11 changed files with 319 additions and 229 deletions
@@ -2,6 +2,7 @@ import { generateObject } from "ai";
import { createOpenAI } from "@ai-sdk/openai";
import { z } from "zod";
import type { AgentUpdate } from "../server/acp/types.js";
import { curateAgentActivity } from "../server/acp/activity-curator.js";
let openai: ReturnType<typeof createOpenAI> | null = null;
@@ -14,48 +15,6 @@ export function isTitleGeneratorInitialized(): boolean {
return openai !== null;
}
/**
* Extract text context from agent updates for title generation
*/
function extractActivityContext(updates: AgentUpdate[]): string {
const lines: string[] = [];
for (const update of updates.slice(0, 10)) { // Only use first 10 updates for context
const notification = update.notification as any;
if (notification?.update?.sessionUpdate) {
const sessionUpdate = notification.update.sessionUpdate;
// Extract user messages
if (sessionUpdate.userMessage?.text) {
lines.push(`User: ${sessionUpdate.userMessage.text}`);
}
// Extract assistant messages
if (sessionUpdate.assistantMessage?.text) {
lines.push(`Assistant: ${sessionUpdate.assistantMessage.text}`);
}
// Extract tool calls (showing what actions were taken)
if (sessionUpdate.toolCall) {
const toolCall = sessionUpdate.toolCall;
lines.push(`Tool: ${toolCall.toolName || 'unknown'}`);
}
// Extract plan entries
if (sessionUpdate.plan?.entries) {
for (const entry of sessionUpdate.plan.entries.slice(0, 3)) {
if (entry.content) {
lines.push(`Plan: ${entry.content}`);
}
}
}
}
}
return lines.join('\n');
}
/**
* Generate a concise title for an agent based on its activity
* Returns a 3-5 word title similar to ChatGPT/Claude.ai
@@ -72,9 +31,9 @@ export async function generateAgentTitle(
return "New Agent";
}
const activityContext = extractActivityContext(agentUpdates);
const activityContext = curateAgentActivity(agentUpdates);
if (!activityContext.trim()) {
if (!activityContext.trim() || activityContext === "No activity to display.") {
return "New Agent";
}