diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..a8de724
Binary files /dev/null and b/.DS_Store differ
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..eb15b1f
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,53 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Overview
+
+This is a 1:1 pixel-perfect clone of the Google Gemini chat interface, built with Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS 4, and shadcn/ui. It was generated via [v0.app](https://v0.app/chat/lx6pc6oofZh) and auto-synced to this repo. Deployed on Vercel.
+
+## Commands
+
+```bash
+npm install # Install dependencies
+npm run dev # Start dev server (localhost:3000)
+npm run build # Build for production
+npm run lint # Run ESLint
+npm start # Start production server
+```
+
+## Architecture
+
+### Entry Point
+- `app/page.tsx` — renders `` only; all logic lives in components
+
+### Core Component: `components/gemini/GeminiChat.tsx`
+The root stateful component. Owns all state: sidebar open/close, active conversation, message list, typing indicator. Composes all other Gemini components.
+
+### Gemini Component Breakdown
+
+| Component | Purpose |
+|---|---|
+| `GeminiSidebar.tsx` | Left sidebar — logo, new chat button, conversation history list, bottom nav (Help/Activity/Extensions), user avatar |
+| `GeminiTopbar.tsx` | Top bar — hamburger toggle, model selector dropdown (Gemini 2.0 Flash etc.), settings + avatar |
+| `GeminiWelcome.tsx` | Empty state — gradient greeting, 4 suggestion cards |
+| `GeminiMessage.tsx` | Single message — user bubble (right-aligned, bg pill) vs AI response (left-aligned, ◆ icon, no bubble, markdown-like rendering) |
+| `GeminiInput.tsx` | Bottom input — rounded container, attachment icon, auto-resize textarea, mic + send button |
+| `GeminiTypingIndicator.tsx` | Animated dots shown while AI is "responding" |
+| `ExtensionsPanel.tsx` | Extensions panel UI |
+
+### Styling
+- Tailwind CSS 4 with `@tailwindcss/postcss`
+- Dark theme only — hardcoded color palette:
+ - Page bg: `#131314`, Sidebar: `#1e1e1e`, Hover/card: `#2a2a2a`, Border: `#3a3a3a`
+ - Primary text: `#e3e3e3`, Muted: `#9aa0a6`
+ - Accent gradient: `from-[#4285f4] to-[#a855f7]`
+- `components/ui/` — standard shadcn/ui primitives (do not modify directly)
+
+### Key Patterns
+- All components use `"use client"` — no server components beyond the page shell
+- `cn()` from `@/lib/utils` for conditional class merging
+- No external API calls — all data is mock/local state in `GeminiChat.tsx`
+
+## Sync Workflow
+This repo is auto-synced from v0.app. Changes made on v0.app are pushed here automatically, then deployed to Vercel. Manual edits here may be overwritten on the next v0 sync.
diff --git a/EXTERNAL_SERVICES.md b/EXTERNAL_SERVICES.md
new file mode 100644
index 0000000..a26b689
--- /dev/null
+++ b/EXTERNAL_SERVICES.md
@@ -0,0 +1,151 @@
+# 外部服务接入配置
+
+> **使用说明**:此文档用于记录外部服务的接入方式、环境变量和调用示例,便于开发、联调与排障。
+>
+> 当前服务按“代码已支持 + 部署环境变量由 Azure Web App 提供”的口径记录为已接入;实际运行效果仍以部署环境变量是否正确配置为准。
+>
+> 已接入的服务会标注 ✅。
+
+---
+
+## 1. LLM 大语言模型 ✅ 已接入
+
+> 当前使用 Azure OpenAI,已在后端 graph.py / main.py 中集成。
+
+### 环境变量(已配置)
+```
+AZURE_OPENAI_ENDPOINT=https://ai-gzy0016231ai975636166896.cognitiveservices.azure.com/openai/responses?api-version=2025-04-01-preview/
+AZURE_OPENAI_API_KEY=DlsBBFJ0RgMGdKxsdBWnlYj6IRdULzflGsKFCXnMBzqs4ZVHMtqZJQQJ99CCACHYHv6XJ3w3AAAAACOG45do
+AZURE_OPENAI_API_VERSION=2025-04-01-preview
+AZURE_OPENAI_DEPLOYMENT=gpt-5.4
+```
+
+### 请求示例
+```bash
+curl -X POST "${AZURE_OPENAI_ENDPOINT}/openai/deployments/${AZURE_OPENAI_DEPLOYMENT}/chat/completions?api-version=${AZURE_OPENAI_API_VERSION}" \
+ -H "Content-Type: application/json" \
+ -H "api-key: ${AZURE_OPENAI_API_KEY}" \
+ -d '{
+ "messages": [{"role": "user", "content": "你好"}],
+ "max_tokens": 1000
+ }'
+```
+
+---
+
+## 2. 内部知识库检索 ✅ 已接入
+
+> 当前通过 agnetdoc Function App 调用 Azure AI Search。
+
+### 环境变量(已配置)
+```
+KB_AGENT_URL=https://agnetdoc-cve0guf5h8eggmej.southeastasia-01.azurewebsites.net
+KB_AGENT_API_KEY=LdyzZlS3Nn1xFejqPsHn1nW-zsj9FLpC5KCbopCkQWKCAzFuLEUU4w==
+KB_AGENT_SEARCH_PATH=/api/v1/search
+KB_AGENT_SEARCH_TIMEOUT_SEC=15
+```
+
+### 请求示例
+```bash
+curl -X POST "${KB_AGENT_URL}/api/v1/search" \
+ -H "Content-Type: application/json" \
+ -H "api-key: ${KB_AGENT_API_KEY}" \
+ -d '{
+ "query": "Taiji Agent 产品规划",
+ "top": 8,
+ "search_mode": "hybrid"
+ }'
+```
+
+### 响应格式
+```json
+{
+ "results": [
+ {
+ "id": "xxx",
+ "title": "文档标题",
+ "content": "文档内容...",
+ "category": "分类",
+ "score": 0.85,
+ "url": "https://...",
+ "tags": ["tag1"],
+ "project": "项目名"
+ }
+ ]
+}
+```
+
+---
+
+## 3. 外部 AI 搜索 ✅ 已接入
+目前外部搜索采用https://mcp.jina.ai/sse 或者 /v1 可优先测试
+jina_e26dc30420a44a1e859216528065b203TkMRmsoz-FgMDQC5FZX9jr5oF2CI
+要求使用搜索和读取两个工具,并且要结合重排模型使用。
+满足企业级的搜索准确度,包括不限于图片和视频
+按照深度和快速来定义搜索内容和搜索的质量,还需要满足前端的展示。
+
+
+
+---
+
+## 4. 沙盒代码执行 ✅ 已接入
+沙盒采用现成的解决方案。https://docs.langchain.com/oss/python/integrations/sandboxes/daytona
+
+https://app.daytona.io/api
+dtn_066b83f57f0337c96fae2ef1f5c8456477a39dfbd5fc615456263fd4947108c2
+依然要满足前端输出要求。
+
+
+## 5. 文档生成 Agent ✅ 已接入
+http://doc-creator-agent-b0d02105-a557fe.taijiagnet.com
+sk-t5R8jkEp6IA7_ghJ6Hy1rQ
+http://agnetdoc.taijiaicloud.com/node/019cd223-9d13-7566-a2ea-52ee67645463
+
+
+## 6. 工单系统 ✅ 已接入
+
+> gongdan 工单系统,只读集成。
+
+### 环境变量(已配置)
+```
+GONGDAN_API_BASE=https://gongdan-b5fzbtgteqd5gzfb.eastasia-01.azurewebsites.net
+GONGDAN_API_KEY=gd_live_a28b3db84385be75d1d3b6b6023784c27200d045
+```
+
+### 请求示例
+```bash
+# 工单列表
+curl -X GET "${GONGDAN_API_BASE}/api/tickets?page=1&pageSize=20" \
+ -H "X-Api-Key: ${GONGDAN_API_KEY}"
+
+# 工单详情
+curl -X GET "${GONGDAN_API_BASE}/api/tickets/{ticketId}" \
+ -H "X-Api-Key: ${GONGDAN_API_KEY}"
+```
+
+---
+
+## 7. 数据库 ✅ 已接入(可选)
+
+> 当前代码支持 `DATABASE_URL` 持久化;未配置时会回退到内存模式。
+
+### 当前代码侧现状
+- `persistence.py` 已支持 PostgreSQL
+- 线程 / 分支等数据可持久化
+- 文档 workspace 元数据、sandbox 运行记录等也有数据库侧支持
+- 若未配置 `DATABASE_URL`,系统仍可运行,但持久化能力会受限
+
+### 当前示例
+```
+DATABASE_URL=postgresql://USER:PASSWORD@:5432/yydn?sslmode=require
+```
+dataope.postgres.database.azure.com
+azuredb:h13nYoFJX6QrfLzB8bdipEUCjsZq2P7W
+
+### 说明
+- 如果后续要迁移数据库主机,请单独更新部署环境变量与运维文档
+
+
+
+---
+
diff --git a/claudehd.md b/claudehd.md
new file mode 100644
index 0000000..cc869c0
--- /dev/null
+++ b/claudehd.md
@@ -0,0 +1,106 @@
+# claudehd.md — so-c-chat-clone 后端功能方案
+
+**前端代码未经明确指定不允许修改。**
+
+---
+
+## 功能一:基础对话
+
+**做什么:** 用户发送消息,后端调用 LLM 生成回复,返回 Markdown 文本给前端渲染。
+
+**用什么:**
+- **FastAPI**(Python)— 提供 `POST /chat` 接口,接收 `message` + `thread_id` + `model`
+- **Azure OpenAI SDK(异步)** — 调用 gpt-5.4 部署,返回文本内容
+- **内存字典** — 按 `thread_id` 存储多轮对话历史,拼入每次请求的 messages 数组实现上下文连续
+
+**模型行为:**
+- `model=flash` → `max_tokens=500`,`temperature=0.2`,快速简洁
+- `model=pro` → `max_tokens=4096`,`temperature=0.3`,深度详细
+
+---
+
+## 功能二:内部知识库检索
+
+**做什么:** 用户在输入框激活"内部知识库"工具后,发送消息前先检索企业知识库,将相关文档片段注入 LLM prompt,让回复基于内部知识。
+
+**用什么:**
+- **httpx(异步)** — 调用 KB Agent REST API(Azure AI Search 代理)
+- 检索参数:`search_mode=hybrid`,`top=5`
+- 检索结果格式化为背景材料追加到 system prompt,LLM 基于此生成回复
+
+---
+
+## 功能三:外部 AI 搜索
+
+**做什么:** 用户激活"搜索"工具后,后端联网检索实时信息(含图片、视频),经重排后注入 LLM,回复引用真实来源。
+
+**用什么:**
+- **Jina Search API** (`https://s.jina.ai/`) — 搜索网页,返回标题+摘要+URL
+- **Jina Reader API** (`https://r.jina.ai/{url}`) — 读取搜索结果全文
+- **Jina Rerank API** (`jina-reranker-v2-base-multilingual`) — 对结果按相关性重排,提升准确度
+- **httpx(异步)** — 并发调用以上三个接口
+
+**按模型深度区分:**
+- `flash` → 搜索 top=3,timeout=8s,跳过重排,追求速度
+- `pro` → 搜索 top=10,timeout=20s,Rerank 取 top=5,追求准确
+
+---
+
+## 功能四:沙盒代码执行
+
+**做什么:** 用户激活"沙盒"工具并提出编程需求时,后端在隔离环境中执行代码,将 stdout/stderr 格式化为 Markdown 代码块注入回复。
+
+**用什么:**
+- **Daytona API** (`https://app.daytona.io/api`) — 创建隔离 workspace → 上传代码 → 执行 → 获取输出 → 销毁 workspace
+- **httpx(异步)** — 调用 Daytona REST API
+- 执行结果以 Markdown 代码块形式追加到 LLM 最终回复
+
+---
+
+## 功能五:文档生成
+
+**做什么:** 用户激活"文档生成"工具并描述需求时,后端调用 Doc Creator Agent 生成 Word/PPT/表格文件,将下载链接追加到回复末尾。
+
+**用什么:**
+- **Doc Creator Agent** (`http://doc-creator-agent-b0d02105-a557fe.taijiagnet.com`) — 传入 prompt,返回生成文件的 URL
+- **httpx(异步)** — 调用 Agent REST API
+- 输出类型自动识别:含 ppt/slides → PPT;含 table/excel → 表格;其余 → Word
+
+---
+
+## 功能六:工单数据接入
+
+**做什么:** 前端 ExtensionsPanel 连接工单系统后,展示真实工单列表(P0-P3 优先级、状态)。后端作为代理拉取 Gongdan 工单数据。
+
+**用什么:**
+- **FastAPI** — 提供 `GET /tickets` 接口,支持 `page` / `pageSize` 分页参数
+- **httpx(异步)** — 代理调用 Gongdan API,透传工单数据
+- 返回字段严格对齐前端 `TicketData` 类型:`id / title / status / priority / createdAt`
+
+---
+
+## 功能七:多轮对话持久化
+
+**做什么:** 对话历史在服务重启后不丢失,支持恢复历史对话上下文。
+
+**用什么:**
+- **PostgreSQL**(Azure,`dataope.postgres.database.azure.com`)— 存储 thread 和 message 记录
+- **asyncpg** — 异步数据库驱动,不阻塞事件循环
+- 未配置 `DATABASE_URL` 时自动降级为内存字典(开发模式)
+
+---
+
+## 技术栈总览
+
+| 层 | 技术 |
+|----|------|
+| Web 框架 | FastAPI + Uvicorn |
+| LLM | Azure OpenAI SDK (AsyncAzureOpenAI) |
+| HTTP 客户端 | httpx(全异步) |
+| 外部搜索 | Jina Search / Reader / Rerank |
+| 知识库 | KB Agent (Azure AI Search 代理) |
+| 沙盒 | Daytona API |
+| 文档生成 | Doc Creator Agent |
+| 工单 | Gongdan API(只读代理) |
+| 数据库 | PostgreSQL / asyncpg(可选) |
+| 部署 | Azure Web App (Python 3.11) |
diff --git a/README.md b/frontend/README.md
similarity index 100%
rename from README.md
rename to frontend/README.md
diff --git a/app/globals.css b/frontend/app/globals.css
similarity index 100%
rename from app/globals.css
rename to frontend/app/globals.css
diff --git a/app/layout.tsx b/frontend/app/layout.tsx
similarity index 100%
rename from app/layout.tsx
rename to frontend/app/layout.tsx
diff --git a/app/page.tsx b/frontend/app/page.tsx
similarity index 100%
rename from app/page.tsx
rename to frontend/app/page.tsx
diff --git a/components.json b/frontend/components.json
similarity index 100%
rename from components.json
rename to frontend/components.json
diff --git a/components/gemini/ExtensionsPanel.tsx b/frontend/components/gemini/ExtensionsPanel.tsx
similarity index 100%
rename from components/gemini/ExtensionsPanel.tsx
rename to frontend/components/gemini/ExtensionsPanel.tsx
diff --git a/components/gemini/GeminiChat.tsx b/frontend/components/gemini/GeminiChat.tsx
similarity index 100%
rename from components/gemini/GeminiChat.tsx
rename to frontend/components/gemini/GeminiChat.tsx
diff --git a/components/gemini/GeminiInput.tsx b/frontend/components/gemini/GeminiInput.tsx
similarity index 100%
rename from components/gemini/GeminiInput.tsx
rename to frontend/components/gemini/GeminiInput.tsx
diff --git a/components/gemini/GeminiMessage.tsx b/frontend/components/gemini/GeminiMessage.tsx
similarity index 100%
rename from components/gemini/GeminiMessage.tsx
rename to frontend/components/gemini/GeminiMessage.tsx
diff --git a/components/gemini/GeminiSidebar.tsx b/frontend/components/gemini/GeminiSidebar.tsx
similarity index 100%
rename from components/gemini/GeminiSidebar.tsx
rename to frontend/components/gemini/GeminiSidebar.tsx
diff --git a/components/gemini/GeminiTopbar.tsx b/frontend/components/gemini/GeminiTopbar.tsx
similarity index 100%
rename from components/gemini/GeminiTopbar.tsx
rename to frontend/components/gemini/GeminiTopbar.tsx
diff --git a/components/gemini/GeminiTypingIndicator.tsx b/frontend/components/gemini/GeminiTypingIndicator.tsx
similarity index 100%
rename from components/gemini/GeminiTypingIndicator.tsx
rename to frontend/components/gemini/GeminiTypingIndicator.tsx
diff --git a/components/gemini/GeminiWelcome.tsx b/frontend/components/gemini/GeminiWelcome.tsx
similarity index 100%
rename from components/gemini/GeminiWelcome.tsx
rename to frontend/components/gemini/GeminiWelcome.tsx
diff --git a/components/theme-provider.tsx b/frontend/components/theme-provider.tsx
similarity index 100%
rename from components/theme-provider.tsx
rename to frontend/components/theme-provider.tsx
diff --git a/components/ui/accordion.tsx b/frontend/components/ui/accordion.tsx
similarity index 100%
rename from components/ui/accordion.tsx
rename to frontend/components/ui/accordion.tsx
diff --git a/components/ui/alert-dialog.tsx b/frontend/components/ui/alert-dialog.tsx
similarity index 100%
rename from components/ui/alert-dialog.tsx
rename to frontend/components/ui/alert-dialog.tsx
diff --git a/components/ui/alert.tsx b/frontend/components/ui/alert.tsx
similarity index 100%
rename from components/ui/alert.tsx
rename to frontend/components/ui/alert.tsx
diff --git a/components/ui/aspect-ratio.tsx b/frontend/components/ui/aspect-ratio.tsx
similarity index 100%
rename from components/ui/aspect-ratio.tsx
rename to frontend/components/ui/aspect-ratio.tsx
diff --git a/components/ui/avatar.tsx b/frontend/components/ui/avatar.tsx
similarity index 100%
rename from components/ui/avatar.tsx
rename to frontend/components/ui/avatar.tsx
diff --git a/components/ui/badge.tsx b/frontend/components/ui/badge.tsx
similarity index 100%
rename from components/ui/badge.tsx
rename to frontend/components/ui/badge.tsx
diff --git a/components/ui/breadcrumb.tsx b/frontend/components/ui/breadcrumb.tsx
similarity index 100%
rename from components/ui/breadcrumb.tsx
rename to frontend/components/ui/breadcrumb.tsx
diff --git a/components/ui/button-group.tsx b/frontend/components/ui/button-group.tsx
similarity index 100%
rename from components/ui/button-group.tsx
rename to frontend/components/ui/button-group.tsx
diff --git a/components/ui/button.tsx b/frontend/components/ui/button.tsx
similarity index 100%
rename from components/ui/button.tsx
rename to frontend/components/ui/button.tsx
diff --git a/components/ui/calendar.tsx b/frontend/components/ui/calendar.tsx
similarity index 100%
rename from components/ui/calendar.tsx
rename to frontend/components/ui/calendar.tsx
diff --git a/components/ui/card.tsx b/frontend/components/ui/card.tsx
similarity index 100%
rename from components/ui/card.tsx
rename to frontend/components/ui/card.tsx
diff --git a/components/ui/carousel.tsx b/frontend/components/ui/carousel.tsx
similarity index 100%
rename from components/ui/carousel.tsx
rename to frontend/components/ui/carousel.tsx
diff --git a/components/ui/chart.tsx b/frontend/components/ui/chart.tsx
similarity index 100%
rename from components/ui/chart.tsx
rename to frontend/components/ui/chart.tsx
diff --git a/components/ui/checkbox.tsx b/frontend/components/ui/checkbox.tsx
similarity index 100%
rename from components/ui/checkbox.tsx
rename to frontend/components/ui/checkbox.tsx
diff --git a/components/ui/collapsible.tsx b/frontend/components/ui/collapsible.tsx
similarity index 100%
rename from components/ui/collapsible.tsx
rename to frontend/components/ui/collapsible.tsx
diff --git a/components/ui/command.tsx b/frontend/components/ui/command.tsx
similarity index 100%
rename from components/ui/command.tsx
rename to frontend/components/ui/command.tsx
diff --git a/components/ui/context-menu.tsx b/frontend/components/ui/context-menu.tsx
similarity index 100%
rename from components/ui/context-menu.tsx
rename to frontend/components/ui/context-menu.tsx
diff --git a/components/ui/dialog.tsx b/frontend/components/ui/dialog.tsx
similarity index 100%
rename from components/ui/dialog.tsx
rename to frontend/components/ui/dialog.tsx
diff --git a/components/ui/drawer.tsx b/frontend/components/ui/drawer.tsx
similarity index 100%
rename from components/ui/drawer.tsx
rename to frontend/components/ui/drawer.tsx
diff --git a/components/ui/dropdown-menu.tsx b/frontend/components/ui/dropdown-menu.tsx
similarity index 100%
rename from components/ui/dropdown-menu.tsx
rename to frontend/components/ui/dropdown-menu.tsx
diff --git a/components/ui/empty.tsx b/frontend/components/ui/empty.tsx
similarity index 100%
rename from components/ui/empty.tsx
rename to frontend/components/ui/empty.tsx
diff --git a/components/ui/field.tsx b/frontend/components/ui/field.tsx
similarity index 100%
rename from components/ui/field.tsx
rename to frontend/components/ui/field.tsx
diff --git a/components/ui/form.tsx b/frontend/components/ui/form.tsx
similarity index 100%
rename from components/ui/form.tsx
rename to frontend/components/ui/form.tsx
diff --git a/components/ui/hover-card.tsx b/frontend/components/ui/hover-card.tsx
similarity index 100%
rename from components/ui/hover-card.tsx
rename to frontend/components/ui/hover-card.tsx
diff --git a/components/ui/input-group.tsx b/frontend/components/ui/input-group.tsx
similarity index 100%
rename from components/ui/input-group.tsx
rename to frontend/components/ui/input-group.tsx
diff --git a/components/ui/input-otp.tsx b/frontend/components/ui/input-otp.tsx
similarity index 100%
rename from components/ui/input-otp.tsx
rename to frontend/components/ui/input-otp.tsx
diff --git a/components/ui/input.tsx b/frontend/components/ui/input.tsx
similarity index 100%
rename from components/ui/input.tsx
rename to frontend/components/ui/input.tsx
diff --git a/components/ui/item.tsx b/frontend/components/ui/item.tsx
similarity index 100%
rename from components/ui/item.tsx
rename to frontend/components/ui/item.tsx
diff --git a/components/ui/kbd.tsx b/frontend/components/ui/kbd.tsx
similarity index 100%
rename from components/ui/kbd.tsx
rename to frontend/components/ui/kbd.tsx
diff --git a/components/ui/label.tsx b/frontend/components/ui/label.tsx
similarity index 100%
rename from components/ui/label.tsx
rename to frontend/components/ui/label.tsx
diff --git a/components/ui/menubar.tsx b/frontend/components/ui/menubar.tsx
similarity index 100%
rename from components/ui/menubar.tsx
rename to frontend/components/ui/menubar.tsx
diff --git a/components/ui/navigation-menu.tsx b/frontend/components/ui/navigation-menu.tsx
similarity index 100%
rename from components/ui/navigation-menu.tsx
rename to frontend/components/ui/navigation-menu.tsx
diff --git a/components/ui/pagination.tsx b/frontend/components/ui/pagination.tsx
similarity index 100%
rename from components/ui/pagination.tsx
rename to frontend/components/ui/pagination.tsx
diff --git a/components/ui/popover.tsx b/frontend/components/ui/popover.tsx
similarity index 100%
rename from components/ui/popover.tsx
rename to frontend/components/ui/popover.tsx
diff --git a/components/ui/progress.tsx b/frontend/components/ui/progress.tsx
similarity index 100%
rename from components/ui/progress.tsx
rename to frontend/components/ui/progress.tsx
diff --git a/components/ui/radio-group.tsx b/frontend/components/ui/radio-group.tsx
similarity index 100%
rename from components/ui/radio-group.tsx
rename to frontend/components/ui/radio-group.tsx
diff --git a/components/ui/resizable.tsx b/frontend/components/ui/resizable.tsx
similarity index 100%
rename from components/ui/resizable.tsx
rename to frontend/components/ui/resizable.tsx
diff --git a/components/ui/scroll-area.tsx b/frontend/components/ui/scroll-area.tsx
similarity index 100%
rename from components/ui/scroll-area.tsx
rename to frontend/components/ui/scroll-area.tsx
diff --git a/components/ui/select.tsx b/frontend/components/ui/select.tsx
similarity index 100%
rename from components/ui/select.tsx
rename to frontend/components/ui/select.tsx
diff --git a/components/ui/separator.tsx b/frontend/components/ui/separator.tsx
similarity index 100%
rename from components/ui/separator.tsx
rename to frontend/components/ui/separator.tsx
diff --git a/components/ui/sheet.tsx b/frontend/components/ui/sheet.tsx
similarity index 100%
rename from components/ui/sheet.tsx
rename to frontend/components/ui/sheet.tsx
diff --git a/components/ui/sidebar.tsx b/frontend/components/ui/sidebar.tsx
similarity index 100%
rename from components/ui/sidebar.tsx
rename to frontend/components/ui/sidebar.tsx
diff --git a/components/ui/skeleton.tsx b/frontend/components/ui/skeleton.tsx
similarity index 100%
rename from components/ui/skeleton.tsx
rename to frontend/components/ui/skeleton.tsx
diff --git a/components/ui/slider.tsx b/frontend/components/ui/slider.tsx
similarity index 100%
rename from components/ui/slider.tsx
rename to frontend/components/ui/slider.tsx
diff --git a/components/ui/sonner.tsx b/frontend/components/ui/sonner.tsx
similarity index 100%
rename from components/ui/sonner.tsx
rename to frontend/components/ui/sonner.tsx
diff --git a/components/ui/spinner.tsx b/frontend/components/ui/spinner.tsx
similarity index 100%
rename from components/ui/spinner.tsx
rename to frontend/components/ui/spinner.tsx
diff --git a/components/ui/switch.tsx b/frontend/components/ui/switch.tsx
similarity index 100%
rename from components/ui/switch.tsx
rename to frontend/components/ui/switch.tsx
diff --git a/components/ui/table.tsx b/frontend/components/ui/table.tsx
similarity index 100%
rename from components/ui/table.tsx
rename to frontend/components/ui/table.tsx
diff --git a/components/ui/tabs.tsx b/frontend/components/ui/tabs.tsx
similarity index 100%
rename from components/ui/tabs.tsx
rename to frontend/components/ui/tabs.tsx
diff --git a/components/ui/textarea.tsx b/frontend/components/ui/textarea.tsx
similarity index 100%
rename from components/ui/textarea.tsx
rename to frontend/components/ui/textarea.tsx
diff --git a/components/ui/toast.tsx b/frontend/components/ui/toast.tsx
similarity index 100%
rename from components/ui/toast.tsx
rename to frontend/components/ui/toast.tsx
diff --git a/components/ui/toaster.tsx b/frontend/components/ui/toaster.tsx
similarity index 100%
rename from components/ui/toaster.tsx
rename to frontend/components/ui/toaster.tsx
diff --git a/components/ui/toggle-group.tsx b/frontend/components/ui/toggle-group.tsx
similarity index 100%
rename from components/ui/toggle-group.tsx
rename to frontend/components/ui/toggle-group.tsx
diff --git a/components/ui/toggle.tsx b/frontend/components/ui/toggle.tsx
similarity index 100%
rename from components/ui/toggle.tsx
rename to frontend/components/ui/toggle.tsx
diff --git a/components/ui/tooltip.tsx b/frontend/components/ui/tooltip.tsx
similarity index 100%
rename from components/ui/tooltip.tsx
rename to frontend/components/ui/tooltip.tsx
diff --git a/components/ui/use-mobile.tsx b/frontend/components/ui/use-mobile.tsx
similarity index 100%
rename from components/ui/use-mobile.tsx
rename to frontend/components/ui/use-mobile.tsx
diff --git a/components/ui/use-toast.ts b/frontend/components/ui/use-toast.ts
similarity index 100%
rename from components/ui/use-toast.ts
rename to frontend/components/ui/use-toast.ts
diff --git a/hooks/use-mobile.ts b/frontend/hooks/use-mobile.ts
similarity index 100%
rename from hooks/use-mobile.ts
rename to frontend/hooks/use-mobile.ts
diff --git a/hooks/use-toast.ts b/frontend/hooks/use-toast.ts
similarity index 100%
rename from hooks/use-toast.ts
rename to frontend/hooks/use-toast.ts
diff --git a/lib/utils.ts b/frontend/lib/utils.ts
similarity index 100%
rename from lib/utils.ts
rename to frontend/lib/utils.ts
diff --git a/next.config.mjs b/frontend/next.config.mjs
similarity index 100%
rename from next.config.mjs
rename to frontend/next.config.mjs
diff --git a/package.json b/frontend/package.json
similarity index 100%
rename from package.json
rename to frontend/package.json
diff --git a/postcss.config.mjs b/frontend/postcss.config.mjs
similarity index 100%
rename from postcss.config.mjs
rename to frontend/postcss.config.mjs
diff --git a/public/apple-icon.png b/frontend/public/apple-icon.png
similarity index 100%
rename from public/apple-icon.png
rename to frontend/public/apple-icon.png
diff --git a/public/icon-dark-32x32.png b/frontend/public/icon-dark-32x32.png
similarity index 100%
rename from public/icon-dark-32x32.png
rename to frontend/public/icon-dark-32x32.png
diff --git a/public/icon-light-32x32.png b/frontend/public/icon-light-32x32.png
similarity index 100%
rename from public/icon-light-32x32.png
rename to frontend/public/icon-light-32x32.png
diff --git a/public/icon.svg b/frontend/public/icon.svg
similarity index 100%
rename from public/icon.svg
rename to frontend/public/icon.svg
diff --git a/public/placeholder-logo.png b/frontend/public/placeholder-logo.png
similarity index 100%
rename from public/placeholder-logo.png
rename to frontend/public/placeholder-logo.png
diff --git a/public/placeholder-logo.svg b/frontend/public/placeholder-logo.svg
similarity index 100%
rename from public/placeholder-logo.svg
rename to frontend/public/placeholder-logo.svg
diff --git a/public/placeholder-user.jpg b/frontend/public/placeholder-user.jpg
similarity index 100%
rename from public/placeholder-user.jpg
rename to frontend/public/placeholder-user.jpg
diff --git a/public/placeholder.jpg b/frontend/public/placeholder.jpg
similarity index 100%
rename from public/placeholder.jpg
rename to frontend/public/placeholder.jpg
diff --git a/public/placeholder.svg b/frontend/public/placeholder.svg
similarity index 100%
rename from public/placeholder.svg
rename to frontend/public/placeholder.svg
diff --git a/styles/globals.css b/frontend/styles/globals.css
similarity index 100%
rename from styles/globals.css
rename to frontend/styles/globals.css
diff --git a/tsconfig.json b/frontend/tsconfig.json
similarity index 100%
rename from tsconfig.json
rename to frontend/tsconfig.json
diff --git a/gpthd.md b/gpthd.md
new file mode 100644
index 0000000..4fdb024
--- /dev/null
+++ b/gpthd.md
@@ -0,0 +1,433 @@
+# SOC 项目后端功能方案(按功能拆解)
+
+> 约束:在未获得明确允许前,不修改前端交互,只补后端能力、接口和数据层。
+> 目标:严格围绕当前 `~/go/soc` 这个 Gemini 风格前端,为每一个功能明确说明“用什么技术,完成什么功能,怎么落地”。
+
+---
+
+## 1. 对话流式回复
+
+### 要完成什么功能
+- 用户在当前聊天输入框发送消息
+- 后端实时返回回答内容
+- 支持“思考中 / 检索中 / 生成中”的流式状态
+- 不改变现有前端交互,只替换当前前端 `simulateAIResponse()`
+
+### 用什么技术
+- **FastAPI**:提供聊天接口
+- **SSE(Server-Sent Events)**:把大模型回答流式推给前端
+- **Azure OpenAI**:生成最终回答
+- **PostgreSQL**:保存消息记录和会话记录
+
+### 怎么落地
+- 新增接口:`POST /api/chat/stream`
+- 前端发送用户消息到后端
+- 后端先写入用户消息
+- 再调用 Azure OpenAI 流式生成
+- 将生成过程通过 SSE 持续返回给前端
+- 最终把 assistant 回复保存入库
+
+### 输出结果
+- 前端保持当前 Gemini 风格交互不变
+- 用户发送后能看到真实流式回答
+- 替换掉前端 mock 返回逻辑
+
+---
+
+## 2. 会话管理
+
+### 要完成什么功能
+- 左侧历史会话列表从真实数据读取
+- 支持新建会话
+- 支持切换会话
+- 支持删除会话
+- 支持自动生成会话标题
+
+### 用什么技术
+- **FastAPI**:提供 REST API
+- **PostgreSQL**:保存 conversation 和 message
+- **SQLAlchemy / SQLModel**:管理数据表和查询
+
+### 怎么落地
+- 新增接口:
+ - `GET /api/conversations`
+ - `POST /api/conversations`
+ - `GET /api/conversations/{id}`
+ - `PATCH /api/conversations/{id}`
+ - `DELETE /api/conversations/{id}`
+- 用户首次发送消息时自动创建会话
+- 默认用首条消息前 20~30 字生成标题
+- 前端左侧栏改为读取真实会话数据
+
+### 输出结果
+- 当前左侧 mock 会话列表替换成数据库真实数据
+- 用户聊天记录可恢复
+
+---
+
+## 3. 内部知识库检索
+
+### 要完成什么功能
+- 当用户提问产品、方案、配置、内部资料时
+- 后端优先查询内部知识库
+- 再把知识库结果交给大模型总结回答
+- 回答中带来源信息
+
+### 用什么技术
+- **KB_AGENT 接口**:调用内部知识库搜索
+- **FastAPI service layer**:封装知识库调用
+- **Azure OpenAI**:对检索结果总结与生成回答
+
+### 怎么落地
+- 新增服务模块:`kb_agent.py`
+- 根据 `EXTERNAL_SERVICES.md` 中的:
+ - `KB_AGENT_URL`
+ - `KB_AGENT_API_KEY`
+ - `KB_AGENT_SEARCH_PATH`
+- 后端在识别为内部知识问题时:
+ 1. 请求知识库搜索
+ 2. 获取 top-k 文档片段
+ 3. 做摘要裁剪
+ 4. 将结果作为上下文交给 Azure OpenAI
+- 前端不改交互,只在回答里附带引用来源块
+
+### 输出结果
+- 当前产品类问题不再纯靠大模型空想
+- 回答能基于内部知识库
+- 更适合售前、售后、研发支持场景
+
+---
+
+## 4. 外部 AI 搜索
+
+### 要完成什么功能
+- 当用户问实时互联网信息、行业动态、外部资料时
+- 后端自动执行外部搜索
+- 支持网页搜索、内容读取、结果重排
+- 满足快速模式和深度模式
+- 后续支持图片和视频结果展示
+
+### 用什么技术
+- **Jina Search API**:做外部搜索
+- **Jina Reader**:读取网页正文
+- **Rerank 模型**:对结果重排
+- **Azure OpenAI**:基于外部资料生成答案
+
+### 怎么落地
+- 新增模块:
+ - `jina_search.py`
+ - `jina_reader.py`
+ - `reranker.py`
+- 固定流程:
+ - Search -> Read -> Rerank -> LLM
+- 提供三种模式:
+ - `fast`:低延迟,少量搜索
+ - `deep`:高质量,多轮检索
+ - `auto`:后端自动判断
+- 前端仍保持原有聊天区交互,只增加来源区块展示
+
+### 输出结果
+- 外部问题可获得更准确结果
+- 不再只依赖大模型参数知识
+- 满足企业级搜索准确度要求
+
+---
+
+## 5. 工单系统只读接入
+
+### 要完成什么功能
+- 支持查询工单列表
+- 支持查询工单详情
+- 支持汇总最近高优先级工单
+- 支持在聊天中回答“最近有什么 P0/P1 工单”“某类问题集中在哪里”
+- 支持首页/聊天区展示工单摘要数据
+
+### 用什么技术
+- **Gongdan HTTP API**:工单数据来源
+- **FastAPI**:对前端提供统一工单接口
+- **PostgreSQL(可选缓存)**:保存摘要缓存或查询记录
+- **Azure OpenAI**:对工单数据做归纳总结
+
+### 怎么落地
+- 新增模块:`gongdan_client.py`
+- 新增接口:
+ - `GET /api/tickets/summary`
+ - `GET /api/tickets`
+ - `GET /api/tickets/{id}`
+- 对话场景下:
+ - 用户问工单问题
+ - 后端查询 gongdan
+ - 将结果整理后交给大模型总结
+- 非对话场景下:
+ - 前端通过 summary 接口读取摘要
+
+### 输出结果
+- 当前前端 mock 工单摘要可替换为真实工单数据
+- 用户能直接在聊天里分析工单问题
+
+---
+
+## 6. 文档生成
+
+### 要完成什么功能
+- 用户在聊天中要求生成方案、汇报、纪要、总结
+- 后端把需求提交给文档生成 Agent
+- 返回任务状态
+- 文档完成后可返回下载地址或结果卡片
+
+### 用什么技术
+- **Doc Creator Agent HTTP API**:生成正式文档
+- **FastAPI BackgroundTasks / 异步任务机制**:管理任务状态
+- **PostgreSQL**:保存文档任务记录
+- **Azure OpenAI**:前置整理文档提纲或结构
+
+### 怎么落地
+- 新增接口:
+ - `POST /api/documents/generate`
+ - `GET /api/documents/{task_id}`
+- 对话中识别“生成文档”类意图
+- 后端创建任务记录
+- 调用 doc creator agent
+- 前端保持当前聊天交互,后续只在消息中增加文档结果卡片
+
+### 输出结果
+- 用户可从聊天直接发起正式文档生成
+- 满足销售、售前、汇报场景
+
+---
+
+## 7. 沙盒代码执行
+
+### 要完成什么功能
+- 处理表格、JSON、日志、数据分析类任务
+- 允许后端在安全沙盒中执行代码
+- 返回执行结果、图表、文件
+- 不直接改前端交互,只把结果作为消息内容或附件返回
+
+### 用什么技术
+- **Daytona Sandbox**:安全执行环境
+- **FastAPI**:封装沙盒执行入口
+- **Python 工具链**:pandas / matplotlib / json / csv 等
+- **PostgreSQL**:记录执行任务
+
+### 怎么落地
+- 新增接口:`POST /api/sandbox/run`
+- 第一阶段不开放任意代码执行
+- 先封装几类固定能力:
+ - CSV 汇总
+ - JSON 转换
+ - 数据统计
+ - 图表生成
+- 对话编排层按意图决定是否调用 sandbox
+
+### 输出结果
+- 数据分析、表格处理能力可真正执行
+- 后端具备“算”的能力,而不只是“说”的能力
+
+---
+
+## 8. 附件上传与解析
+
+### 要完成什么功能
+- 用户上传文件后,后端能接收附件
+- 保存附件元数据
+- 提取文本内容供知识理解、搜索或分析使用
+- 后续支持文档总结、数据分析、代码执行
+
+### 用什么技术
+- **FastAPI UploadFile**:接收文件
+- **对象存储/本地文件存储**:保存附件
+- **文本解析库**:PDF、DOCX、TXT、CSV 解析
+- **PostgreSQL**:保存附件元数据
+
+### 怎么落地
+- 新增接口:
+ - `POST /api/attachments`
+ - `GET /api/attachments/{id}`
+- 后端保存文件路径与文件类型
+- 针对不同格式做解析
+- 将解析文本挂到对应消息上下文里
+
+### 输出结果
+- 后续聊天可真正支持“基于附件分析”
+- 为文档生成、沙盒分析、知识问答提供基础能力
+
+---
+
+## 9. 工具编排层
+
+### 要完成什么功能
+- 判断用户问题该调用哪个能力
+- 决定先查 KB、还是先查工单、还是先外部搜索
+- 决定是否进入文档生成或沙盒执行
+- 把多个工具结果统一整理成大模型上下文
+
+### 用什么技术
+- **Python Orchestrator**:自定义编排逻辑
+- **Azure OpenAI**:辅助做工具选择与结果总结
+- **FastAPI service layer**:承接 API 和工具层
+
+### 怎么落地
+- 新增模块:
+ - `planner.py`
+ - `chat_orchestrator.py`
+ - `context_builder.py`
+- 第一阶段可以先做规则驱动:
+ - 问产品/项目 -> KB
+ - 问实时外部信息 -> Search
+ - 问工单 -> Tickets
+ - 问生成汇报 -> Documents
+ - 问数据处理 -> Sandbox
+- 第二阶段再逐步引入 LLM 辅助路由
+
+### 输出结果
+- 后端从“多个孤立接口”升级成“统一智能后端”
+- 前端仍然只需要一个对话入口
+
+---
+
+## 10. 数据持久化
+
+### 要完成什么功能
+- 保存历史会话
+- 保存聊天消息
+- 保存工具调用记录
+- 保存附件记录
+- 保存文档任务记录
+
+### 用什么技术
+- **PostgreSQL**:主数据库
+- **SQLAlchemy / SQLModel**:ORM
+- **Alembic**:数据库迁移
+
+### 怎么落地
+- 至少建立以下表:
+ - `conversations`
+ - `messages`
+ - `tool_runs`
+ - `attachments`
+ - `document_tasks`
+- 以后如需多租户,再增加:
+ - `users`
+ - `organizations`
+ - `memberships`
+ - `audit_logs`
+
+### 输出结果
+- 数据不丢失
+- 会话可追溯
+- 工具调用过程可排查
+
+---
+
+## 11. 接口层总表
+
+### 第一阶段建议建设的接口
+
+#### 基础接口
+- `GET /health`
+
+#### 会话接口
+- `GET /api/conversations`
+- `POST /api/conversations`
+- `GET /api/conversations/{id}`
+- `PATCH /api/conversations/{id}`
+- `DELETE /api/conversations/{id}`
+
+#### 聊天接口
+- `POST /api/chat/stream`
+
+#### 工单接口
+- `GET /api/tickets/summary`
+- `GET /api/tickets`
+- `GET /api/tickets/{id}`
+
+#### 搜索接口
+- `POST /api/search/internal`
+- `POST /api/search/external`
+
+#### 文档接口
+- `POST /api/documents/generate`
+- `GET /api/documents/{task_id}`
+
+#### 附件接口
+- `POST /api/attachments`
+- `GET /api/attachments/{id}`
+
+#### 沙盒接口
+- `POST /api/sandbox/run`
+
+---
+
+## 12. 推荐技术组合总结
+
+### 基础后端框架
+- **FastAPI**:API 服务
+- **Uvicorn / Gunicorn**:服务运行
+
+### 数据层
+- **PostgreSQL**:数据持久化
+- **SQLAlchemy / SQLModel**:ORM
+- **Alembic**:迁移管理
+
+### AI 与搜索
+- **Azure OpenAI**:LLM 生成与总结
+- **KB_AGENT**:内部知识库检索
+- **Jina Search / Reader / Rerank**:外部搜索链路
+
+### 外部业务系统
+- **Gongdan API**:工单只读
+- **Doc Creator Agent**:文档生成
+- **Daytona Sandbox**:受控代码执行
+
+### 交互协议
+- **SSE**:流式输出
+- **REST API**:管理类接口
+
+---
+
+## 13. 第一阶段开发顺序
+
+### 第一步
+先完成:
+- FastAPI 基础框架
+- PostgreSQL 接入
+- conversations/messages 表
+- `/api/chat/stream`
+- `/api/conversations`
+
+### 第二步
+接入:
+- Azure OpenAI
+- KB_AGENT
+- 工单系统
+
+### 第三步
+接入:
+- Jina 外部搜索
+- 来源引用
+- 工具状态流式事件
+
+### 第四步
+接入:
+- 文档生成任务
+- 附件解析
+- Sandbox
+
+---
+
+## 14. 最终结论
+
+这个项目当前最合适的后端建设方式,不是泛泛而谈“做一个 AI 平台后端”,而是严格按功能拆:
+
+- 用 **FastAPI + SSE** 完成真实聊天流式回复
+- 用 **PostgreSQL** 完成会话和消息持久化
+- 用 **Azure OpenAI** 完成回答生成
+- 用 **KB_AGENT** 完成内部知识检索
+- 用 **Jina Search/Reader/Rerank** 完成外部搜索
+- 用 **Gongdan API** 完成工单只读分析
+- 用 **Doc Creator Agent** 完成正式文档生成
+- 用 **Daytona Sandbox** 完成安全数据处理与代码执行
+
+而且整个过程中:
+**前端交互不改,只替换数据来源和后端能力。**