Commit Graph
14 Commits
Author SHA1 Message Date
gongzhiyong f43d239e6c fix(main.tsx): cast message prop to any in LoadExternalComponent 2026-04-10 04:37:21 +08:00
gongzhiyong 8d30e0cca0 fix(main.tsx): rename UIMessage→UIMsgLocal to avoid SDK type conflict 2026-04-10 04:35:15 +08:00
gongzhiyong 4f75b65d52 fix(main.tsx): add type field to local UIMessage type 2026-04-10 04:32:06 +08:00
gongzhiyong 844aaa8dcc fix(main.tsx): resolve TypeScript errors — UIMessage type, role→type, ComponentMap cast 2026-04-10 04:28:28 +08:00
gongzhiyongandClaude Sonnet 4.6 7a3cc140b0 refactor: replace SOC system with LangGraph.js gen-ui — full cleanup
## Removed (old SOC system)
- backend/ — Python FastAPI + LangGraph Python ReAct agent
- frontend/ — Next.js Gemini-style UI
- config/, doc/ — old documentation
- .github/workflows/deploy-backend.yml
- .github/workflows/deploy-frontend.yml

## Added (new LangGraph.js system)
- langgraph/src/agent/enterprise/ — enterprise agent with 6 tools
  - kb_search → KnowledgeResultCard
  - ticket_list/detail → TicketSummaryCard / TicketDetailCard
  - web_search (Jina Search+Reader) → SearchResultCard
  - sandbox_run (Daytona REST) → SandboxResultCard
- langgraph/src/agent-uis/enterprise/ — UI card components
- .github/workflows/deploy-langgraph-ui.yml — Vite SPA → Azure Static Web App

## Azure Resources
- soc-backend webapp: DELETED
- soc-frontend Static Web App (eastasia): DELETED
- soc-langgraph-ui Static Web App (eastasia): CREATED
  URL: salmon-mushroom-0d8872e00.7.azurestaticapps.net

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:23:51 +08:00
gongzhiyongandClaude Sonnet 4.6 645f1ecaae feat(langgraph): add enterprise UI card components and implement main.tsx Chat entry
- Create 5 enterprise UI card components under src/agent-uis/enterprise/:
  knowledge-result, ticket-summary, ticket-detail, search-result, sandbox-result
- Update ComponentMap in src/agent-uis/index.tsx to replace () => null placeholders
  with real component imports
- Implement src/main.tsx with useStream + LoadExternalComponent for full Chat UI,
  connecting to LangGraph agent with VITE_LANGGRAPH_URL env var

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:23:32 +08:00
gongzhiyong b621fbae92 fix(langgraph): add missing pnpm-lock.yaml for Docker build 2026-04-10 04:04:27 +08:00
gongzhiyongandClaude Sonnet 4.6 ac388b3c07 feat: add langgraph/ — LangGraph.js gen-ui server with CI/CD to Azure Container App
## Azure Resources Created
- ACR: socsocacr.azurecr.io (Operation, southeastasia)
- Container App Environment: soc-cae (Operation, southeastasia)
- Container App: soc-langgraph (Operation, southeastasia, port 2024)
  - Scale: 0-2 replicas, 0.5 vCPU / 1GB
  - Registry: socsocacr.azurecr.io (system-assigned managed identity)
- OIDC: oidc-msi-8ac6 granted Contributor on Operation resource group

## What's included
- Full langgraphjs-gen-ui-examples codebase under langgraph/
- Dockerfile: node:20-slim + pnpm, exposes port 2024
- .dockerignore, .gitignore
- GitHub Actions: .github/workflows/deploy-langgraph.yml
  - Trigger: push to main, paths langgraph/**
  - Uses az acr build (cloud build, no local Docker needed)
  - Deploys to soc-langgraph Container App

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:01:06 +08:00
gongzhiyongandClaude Sonnet 4.6 c6ca9dc126 fix: restore workspace components accidentally dropped from git index
workspace/ files existed on disk but were not included in previous
incremental commit, causing git to record them as deleted. Re-adding
all workspace card components, AgentWorkspace, ActivityTimeline, and
WorkspaceCardRenderer to properly track them.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 03:09:41 +08:00
gongzhiyongandClaude Sonnet 4.6 47921d1a45 fix: resolve 6 gen-ui issues — timeline completeness, regen sync, localStorage persistence
## Fixes
- [#3] Status events now add/update a status ActivityNode in timeline (upsertWsStatusNode)
- [#4] Done callback adds done node; error callback adds error node + sets session.status="error"
- [#5] handleRegenerate fully synced with workspace: status/tool/card/done/error all handled
- [#1][#2] localStorage persistence: completed/error sessions auto-saved, lazy-loaded on demand
- [#1] handleSelectConversation preloads workspace sessions from localStorage for history messages
- Refactored completeWsSession to include done ActivityNode in timeline
- Added errorWsSession, upsertWsStatusNode, saveWsToStorage, loadWsFromStorage helpers

## Known limitation
- [#7] workspace_card merge:true not yet used by backend (all cards are append-only for now)
- History workspace recovery depends on localStorage (browser-local, not cross-device)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 03:08:23 +08:00
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
gongzhiyongandClaude Sonnet 4.6 1ad75a3602 fix: prevent duplicate AI message when switching conversations during stream
Two bugs caused the same AI response to appear twice:

1. handleSelectConversation would fetch conversation history even while
   a stream was in progress (isLoading). If the fetch resolved mid-stream,
   fetchConversation overwrote the conversation messages unconditionally,
   writing the server-persisted AI message (with a real UUID) alongside the
   still-streaming client-side message (with a temp ID), producing a duplicate.
   Fix: guard the fetch with !isLoading, and add a second check inside the
   .then callback so setConversations only writes history if the messages
   array is still empty (protects against slow-resolving network requests).

2. onDone in streamChat could theoretically be called a second time if the
   ReadableStream completed without a "done" SSE event. Fix: call
   reader.cancel() immediately after onDone so the while loop exits cleanly.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:58:47 +08:00
gongzhiyongandClaude Sonnet 4.6 d86d9b8b32 fix(backend): handle MCP tool output format and read_url list input
- Add _extract_output_str() to unwrap MCP ToolMessage content objects
  instead of calling str() on the raw object
- Handle read_url url param when LLM passes a list instead of a string

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 22:46:58 +08:00
gongzhiyongandClaude Sonnet 4.6 fe8c361127 feat(input): replace model selector buttons with Select dropdown
Replace the three pill buttons (Auto/Flash/Pro) in GeminiInput with a
single shadcn/ui Select component. Selection logic and onSelectedModelChange
callback are unchanged; only the UI widget is swapped.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:47:35 +08:00