## Backend
- Add workspace_card SSE event protocol: {id, name, props, merge}
- Add _extract_llm_text / _maybe_emit_workspace_card helpers in chat.py
- Refactor all tools to dual-output format: {llm_text, ui: {name, props}}
- kb_search → KnowledgeResultCard
- ticket_list/detail → TicketSummaryCard / TicketDetailCard
- web_search → SearchResultCard
- generate_document → DocumentResultCard
- sandbox_run → SandboxResultCard
- Update SYSTEM_PROMPT: instruct LLM not to repeat tool data (UI shows it)
## Frontend
- Three-column layout: sidebar + chat + Agent Workspace (360px right panel)
- WorkspaceSession state model with ActivityNode + WorkspaceCard
- New components/workspace/: AgentWorkspace, ActivityTimeline, WorkspaceCardRenderer
- 6 card components: Knowledge/Ticket/Search/Document/Sandbox/ErrorCard
- GeminiChat: workspace state management, SSE routing for workspace_card events
- GeminiMessage: replace TracePanel with lightweight activity summary line
- lib/api.ts: add WorkspaceSession/ActivityNode/WorkspaceCard types
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
28 lines
872 B
TypeScript
28 lines
872 B
TypeScript
"use client";
|
|
import { KnowledgeResultCard } from "./cards/KnowledgeResultCard";
|
|
import { TicketSummaryCard } from "./cards/TicketSummaryCard";
|
|
import { SearchResultCard } from "./cards/SearchResultCard";
|
|
import { DocumentResultCard } from "./cards/DocumentResultCard";
|
|
import { SandboxResultCard } from "./cards/SandboxResultCard";
|
|
import { ErrorCard } from "./cards/ErrorCard";
|
|
import type { WorkspaceCard } from "@/lib/api";
|
|
|
|
const COMPONENT_MAP: Record<string, React.ComponentType<any>> = {
|
|
KnowledgeResultCard,
|
|
TicketSummaryCard,
|
|
SearchResultCard,
|
|
DocumentResultCard,
|
|
SandboxResultCard,
|
|
ErrorCard,
|
|
};
|
|
|
|
export function WorkspaceCardRenderer({ card }: { card: WorkspaceCard }) {
|
|
const Component = COMPONENT_MAP[card.name];
|
|
if (!Component) return null;
|
|
return (
|
|
<div className="mb-3">
|
|
<Component {...(card.props as any)} />
|
|
</div>
|
|
);
|
|
}
|