Files
socaichat/frontend/components/workspace/WorkspaceCardRenderer.tsx
T
gongzhiyongandClaude Sonnet 4.6 0a2b339550 feat: implement Generative UI — Agent Workspace + workspace_card SSE protocol
## 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>
2026-04-10 02:57:09 +08:00

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>
);
}