agentstudio 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cc-sessions/ppt-editor/session_1756253549429_uau1hm6lh.json +665 -0
- package/.cc-sessions/ppt-editor/session_1756257240855_v0wa26mde.json +394 -0
- package/dist/routes/agents.js +3 -3
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/projects.js +2 -2
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/settings.js +1 -1
- package/dist/routes/settings.js.map +1 -1
- package/docs/chat-clean-1.svg +1 -0
- package/docs/chat-clean.md +60 -0
- package/docs/chat-comprehensive-1.svg +1 -0
- package/docs/chat-comprehensive.md +166 -0
- package/docs/chat_api_sequence_diagram.md +58 -0
- package/docs/command-detection-logic.md +306 -0
- package/docs/command-detection-sequence.md +186 -0
- package/package.json +5 -3
- package/scripts/README.md +76 -0
- package/scripts/fix-project-names.js +113 -0
- package/scripts/migrate-projects.js +159 -0
- package/src/bin/agentstudio.ts +130 -0
- package/src/index.ts +183 -0
- package/src/middleware/auth.ts +26 -0
- package/src/routes/agents.ts +884 -0
- package/src/routes/auth.ts +73 -0
- package/src/routes/commands.ts +441 -0
- package/src/routes/files.ts +352 -0
- package/src/routes/mcp.ts +751 -0
- package/src/routes/media.ts +140 -0
- package/src/routes/projects.ts +601 -0
- package/src/routes/sessions.ts +809 -0
- package/src/routes/settings.ts +718 -0
- package/src/routes/slides.ts +170 -0
- package/src/routes/subagents.ts +364 -0
- package/src/services/claudeSession.ts +293 -0
- package/src/services/messageQueue.ts +71 -0
- package/src/services/sessionManager.ts +532 -0
- package/src/utils/jwt.ts +36 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# 后端 /chat 接口时序图
|
|
2
|
+
|
|
3
|
+
```mermaid
|
|
4
|
+
sequenceDiagram
|
|
5
|
+
participant Client
|
|
6
|
+
participant Router
|
|
7
|
+
participant Storage
|
|
8
|
+
participant SessionMgr
|
|
9
|
+
participant Session
|
|
10
|
+
participant Queue
|
|
11
|
+
participant SDK
|
|
12
|
+
participant FS
|
|
13
|
+
|
|
14
|
+
Client->>Router: POST /chat
|
|
15
|
+
Router->>Storage: Get agent config
|
|
16
|
+
Storage-->>Router: Agent config
|
|
17
|
+
|
|
18
|
+
Router->>SessionMgr: Get or create session
|
|
19
|
+
SessionMgr->>Session: Create session
|
|
20
|
+
Session->>Queue: Create message queue
|
|
21
|
+
Session->>SDK: Initialize stream
|
|
22
|
+
|
|
23
|
+
Router->>Session: Send message
|
|
24
|
+
Session->>Queue: Push message
|
|
25
|
+
SDK->>Queue: Get message
|
|
26
|
+
|
|
27
|
+
SDK->>Session: Response stream
|
|
28
|
+
Session->>Router: Forward response
|
|
29
|
+
Router->>Client: SSE data
|
|
30
|
+
|
|
31
|
+
SDK->>FS: Save history
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 时序图说明
|
|
35
|
+
|
|
36
|
+
这个时序图展示了后端 `/chat` 接口的核心流程:
|
|
37
|
+
|
|
38
|
+
### 主要参与者
|
|
39
|
+
- **Client**: 前端客户端
|
|
40
|
+
- **Router**: 聊天路由处理器 (agents.ts)
|
|
41
|
+
- **Storage**: Agent配置存储
|
|
42
|
+
- **SessionMgr**: 会话管理器
|
|
43
|
+
- **Session**: Claude会话实例
|
|
44
|
+
- **Queue**: 消息队列
|
|
45
|
+
- **SDK**: Claude Code SDK
|
|
46
|
+
- **FS**: 文件系统
|
|
47
|
+
|
|
48
|
+
### 关键流程
|
|
49
|
+
1. 客户端发送聊天请求
|
|
50
|
+
2. 路由器获取Agent配置
|
|
51
|
+
3. 会话管理器创建或获取会话
|
|
52
|
+
4. 初始化消息队列和SDK流
|
|
53
|
+
5. 处理消息并返回流式响应
|
|
54
|
+
6. 自动保存会话历史
|
|
55
|
+
|
|
56
|
+
### 技术特点
|
|
57
|
+
- 使用Streaming Input Mode
|
|
58
|
+
- SSE实时响应
|
|
59
|
+
- 会话持久化
|
|
60
|
+
- 资源自动管理
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="my-svg" width="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="max-width: 2184px; background-color: white;" viewBox="-50 -10 2184 4157" role="graphics-document document" aria-roledescription="sequence"><g><rect x="1934" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="FS" rx="3" ry="3" class="actor actor-bottom"/><text x="2009" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="2009" dy="0">FS</tspan></text></g><g><rect x="1734" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="MCP" rx="3" ry="3" class="actor actor-bottom"/><text x="1809" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1809" dy="0">MCP</tspan></text></g><g><rect x="1473" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="SDK" rx="3" ry="3" class="actor actor-bottom"/><text x="1548" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1548" dy="0">SDK</tspan></text></g><g><rect x="1207" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="Queue" rx="3" ry="3" class="actor actor-bottom"/><text x="1282" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1282" dy="0">Queue</tspan></text></g><g><rect x="937" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="Session" rx="3" ry="3" class="actor actor-bottom"/><text x="1012" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1012" dy="0">Session</tspan></text></g><g><rect x="653" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="SessionMgr" rx="3" ry="3" class="actor actor-bottom"/><text x="728" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="728" dy="0">SessionMgr</tspan></text></g><g><rect x="453" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="Storage" rx="3" ry="3" class="actor actor-bottom"/><text x="528" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="528" dy="0">Storage</tspan></text></g><g><rect x="231" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="Router" rx="3" ry="3" class="actor actor-bottom"/><text x="306" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="306" dy="0">Router</tspan></text></g><g><rect x="0" y="4071" fill="#eaeaea" stroke="#666" width="150" height="65" name="Client" rx="3" ry="3" class="actor actor-bottom"/><text x="75" y="4103.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="75" dy="0">Client</tspan></text></g><g><line id="actor8" x1="2009" y1="65" x2="2009" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="FS"/><g id="root-8"><rect x="1934" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="FS" rx="3" ry="3" class="actor actor-top"/><text x="2009" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="2009" dy="0">FS</tspan></text></g></g><g><line id="actor7" x1="1809" y1="65" x2="1809" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="MCP"/><g id="root-7"><rect x="1734" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="MCP" rx="3" ry="3" class="actor actor-top"/><text x="1809" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1809" dy="0">MCP</tspan></text></g></g><g><line id="actor6" x1="1548" y1="65" x2="1548" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="SDK"/><g id="root-6"><rect x="1473" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="SDK" rx="3" ry="3" class="actor actor-top"/><text x="1548" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1548" dy="0">SDK</tspan></text></g></g><g><line id="actor5" x1="1282" y1="65" x2="1282" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="Queue"/><g id="root-5"><rect x="1207" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="Queue" rx="3" ry="3" class="actor actor-top"/><text x="1282" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1282" dy="0">Queue</tspan></text></g></g><g><line id="actor4" x1="1012" y1="65" x2="1012" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="Session"/><g id="root-4"><rect x="937" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="Session" rx="3" ry="3" class="actor actor-top"/><text x="1012" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="1012" dy="0">Session</tspan></text></g></g><g><line id="actor3" x1="728" y1="65" x2="728" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="SessionMgr"/><g id="root-3"><rect x="653" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="SessionMgr" rx="3" ry="3" class="actor actor-top"/><text x="728" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="728" dy="0">SessionMgr</tspan></text></g></g><g><line id="actor2" x1="528" y1="65" x2="528" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="Storage"/><g id="root-2"><rect x="453" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="Storage" rx="3" ry="3" class="actor actor-top"/><text x="528" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="528" dy="0">Storage</tspan></text></g></g><g><line id="actor1" x1="306" y1="65" x2="306" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="Router"/><g id="root-1"><rect x="231" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="Router" rx="3" ry="3" class="actor actor-top"/><text x="306" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="306" dy="0">Router</tspan></text></g></g><g><line id="actor0" x1="75" y1="65" x2="75" y2="4071" class="actor-line 200" stroke-width="0.5px" stroke="#999" name="Client"/><g id="root-0"><rect x="0" y="0" fill="#eaeaea" stroke="#666" width="150" height="65" name="Client" rx="3" ry="3" class="actor actor-top"/><text x="75" y="32.5" dominant-baseline="central" alignment-baseline="central" class="actor actor-box" style="text-anchor: middle; font-size: 16px; font-weight: 400;"><tspan x="75" dy="0">Client</tspan></text></g></g><style>#my-svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:#552222;}#my-svg .error-text{fill:#552222;stroke:#552222;}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:#333333;stroke:#333333;}#my-svg .marker.cross{stroke:#333333;}#my-svg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#my-svg p{margin:0;}#my-svg .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#my-svg text.actor>tspan{fill:black;stroke:none;}#my-svg .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#my-svg .innerArc{stroke-width:1.5;stroke-dasharray:none;}#my-svg .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#my-svg .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#my-svg #arrowhead path{fill:#333;stroke:#333;}#my-svg .sequenceNumber{fill:white;}#my-svg #sequencenumber{fill:#333;}#my-svg #crosshead path{fill:#333;stroke:#333;}#my-svg .messageText{fill:#333;stroke:none;}#my-svg .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#my-svg .labelText,#my-svg .labelText>tspan{fill:black;stroke:none;}#my-svg .loopText,#my-svg .loopText>tspan{fill:black;stroke:none;}#my-svg .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#my-svg .note{stroke:#aaaa33;fill:#fff5ad;}#my-svg .noteText,#my-svg .noteText>tspan{fill:black;stroke:none;}#my-svg .activation0{fill:#f4f4f4;stroke:#666;}#my-svg .activation1{fill:#f4f4f4;stroke:#666;}#my-svg .activation2{fill:#f4f4f4;stroke:#666;}#my-svg .actorPopupMenu{position:absolute;}#my-svg .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#my-svg .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#my-svg .actor-man circle,#my-svg line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#my-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g/><defs><symbol id="computer" width="24" height="24"><path transform="scale(.5)" d="M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z"/></symbol></defs><defs><symbol id="database" fill-rule="evenodd" clip-rule="evenodd"><path transform="scale(.5)" d="M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z"/></symbol></defs><defs><symbol id="clock" width="24" height="24"><path transform="scale(.5)" d="M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z"/></symbol></defs><defs><marker id="arrowhead" refX="7.9" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto-start-reverse"><path d="M -1 0 L 10 5 L 0 10 z"/></marker></defs><defs><marker id="crosshead" markerWidth="15" markerHeight="8" orient="auto" refX="4" refY="4.5"><path fill="none" stroke="#000000" stroke-width="1pt" d="M 1,2 L 6,7 M 6,2 L 1,7" style="stroke-dasharray: 0, 0;"/></marker></defs><defs><marker id="filled-head" refX="15.5" refY="7" markerWidth="20" markerHeight="28" orient="auto"><path d="M 18,7 L9,13 L14,7 L9,1 Z"/></marker></defs><defs><marker id="sequencenumber" refX="15" refY="15" markerWidth="60" markerHeight="40" orient="auto"><circle cx="15" cy="15" r="6"/></marker></defs><g><line x1="64" y1="237" x2="539" y2="237" class="loopLine"/><line x1="539" y1="237" x2="539" y2="696" class="loopLine"/><line x1="64" y1="696" x2="539" y2="696" class="loopLine"/><line x1="64" y1="237" x2="64" y2="696" class="loopLine"/><line x1="64" y1="375" x2="539" y2="375" class="loopLine" style="stroke-dasharray: 3, 3;"/><line x1="64" y1="508" x2="539" y2="508" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="64,237 114,237 114,250 105.6,257 64,257" class="labelBox"/><text x="89" y="250" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="326.5" y="255" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="326.5">[Agent not found]</tspan></text><text x="301.5" y="393" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[Agent disabled]</text><text x="301.5" y="526" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[Agent valid]</text></g><g><line x1="221.5" y1="706" x2="2020" y2="706" class="loopLine"/><line x1="2020" y1="706" x2="2020" y2="1062" class="loopLine"/><line x1="221.5" y1="1062" x2="2020" y2="1062" class="loopLine"/><line x1="221.5" y1="706" x2="221.5" y2="1062" class="loopLine"/><line x1="221.5" y1="918" x2="2020" y2="918" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="221.5,706 271.5,706 271.5,719 263.1,726 221.5,726" class="labelBox"/><text x="247" y="719" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1145.75" y="724" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1145.75">[MCP tools provided]</tspan></text><text x="1120.75" y="936" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[No MCP tools]</text></g><g><line x1="717" y1="1457" x2="2020" y2="1457" class="loopLine"/><line x1="2020" y1="1457" x2="2020" y2="1901" class="loopLine"/><line x1="717" y1="1901" x2="2020" y2="1901" class="loopLine"/><line x1="717" y1="1457" x2="717" y2="1901" class="loopLine"/><line x1="717" y1="1669" x2="2020" y2="1669" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="717,1457 767,1457 767,1470 758.6,1477 717,1477" class="labelBox"/><text x="742" y="1470" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1393.5" y="1475" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1393.5">[Session history exists]</tspan></text><text x="1368.5" y="1687" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[No session history]</text></g><g><line x1="222" y1="1161" x2="2030" y2="1161" class="loopLine"/><line x1="2030" y1="1161" x2="2030" y2="1911" class="loopLine"/><line x1="222" y1="1911" x2="2030" y2="1911" class="loopLine"/><line x1="222" y1="1161" x2="222" y2="1911" class="loopLine"/><line x1="222" y1="1329" x2="2030" y2="1329" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="222,1161 272,1161 272,1174 263.6,1181 222,1181" class="labelBox"/><text x="247" y="1174" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1151" y="1179" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1151">[Session exists in memory]</tspan></text><text x="1126" y="1347" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[Session not in memory]</text></g><g><line x1="212" y1="1072" x2="2040" y2="1072" class="loopLine"/><line x1="2040" y1="1072" x2="2040" y2="2114" class="loopLine"/><line x1="212" y1="2114" x2="2040" y2="2114" class="loopLine"/><line x1="212" y1="1072" x2="212" y2="2114" class="loopLine"/><line x1="212" y1="1926" x2="2040" y2="1926" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="212,1072 262,1072 262,1085 253.6,1092 212,1092" class="labelBox"/><text x="237" y="1085" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1151" y="1090" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1151">[sessionId provided]</tspan></text><text x="1126" y="1944" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[No sessionId provided]</text></g><g><line x1="910" y1="2212" x2="2020" y2="2212" class="loopLine"/><line x1="2020" y1="2212" x2="2020" y2="2568" class="loopLine"/><line x1="910" y1="2568" x2="2020" y2="2568" class="loopLine"/><line x1="910" y1="2212" x2="910" y2="2568" class="loopLine"/><line x1="910" y1="2424" x2="2020" y2="2424" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="910,2212 960,2212 960,2225 951.6,2232 910,2232" class="labelBox"/><text x="935" y="2225" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1490" y="2230" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1490">[Resume existing session]</tspan></text><text x="1465" y="2442" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[New session]</text></g><g><line x1="1438" y1="3020" x2="1820" y2="3020" class="loopLine"/><line x1="1820" y1="3020" x2="1820" y2="3376" class="loopLine"/><line x1="1438" y1="3376" x2="1820" y2="3376" class="loopLine"/><line x1="1438" y1="3020" x2="1438" y2="3376" class="loopLine"/><line x1="1438" y1="3232" x2="1820" y2="3232" class="loopLine" style="stroke-dasharray: 3, 3;"/><polygon points="1438,3020 1488,3020 1488,3033 1479.6,3040 1438,3040" class="labelBox"/><text x="1463" y="3033" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="1654" y="3038" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="1654">[MCP tools configured]</tspan></text><text x="1629" y="3250" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;">[No MCP tools]</text></g><g><line x1="644" y1="3666" x2="1099" y2="3666" class="loopLine"/><line x1="1099" y1="3666" x2="1099" y2="3933" class="loopLine"/><line x1="644" y1="3933" x2="1099" y2="3933" class="loopLine"/><line x1="644" y1="3666" x2="644" y2="3933" class="loopLine"/><polygon points="644,3666 694,3666 694,3679 685.6,3686 644,3686" class="labelBox"/><text x="669" y="3679" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="labelText" style="font-size: 16px; font-weight: 400;">alt</text><text x="896.5" y="3684" text-anchor="middle" class="loopText" style="font-size: 16px; font-weight: 400;"><tspan x="896.5">[Response contains sessionId]</tspan></text></g><text x="189" y="80" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">POST /chat with params</text><line x1="76" y1="109" x2="302" y2="109" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="307" y="124" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Validate request parameters</text><path d="M 307,153 C 367,143 367,183 307,173" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="416" y="198" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Get agent configuration</text><line x1="307" y1="227" x2="524" y2="227" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="419" y="287" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">null</text><line x1="527" y1="316" x2="310" y2="316" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="192" y="331" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">404 Agent not found</text><line x1="305" y1="360" x2="79" y2="360" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="419" y="420" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">disabled agent</text><line x1="527" y1="449" x2="310" y2="449" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="192" y="464" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">403 Agent disabled</text><line x1="305" y1="493" x2="79" y2="493" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="419" y="553" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">valid agent config</text><line x1="527" y1="582" x2="310" y2="582" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="307" y="597" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Build system prompt</text><path d="M 307,626 C 367,616 367,656 307,646" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1156" y="756" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Read MCP configuration file</text><line x1="307" y1="785" x2="2005" y2="785" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1159" y="800" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">MCP server settings</text><line x1="2008" y1="829" x2="310" y2="829" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="307" y="844" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Configure MCP servers</text><path d="M 307,873 C 367,863 367,903 307,893" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="307" y="963" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Skip MCP setup</text><path d="M 307,992 C 367,982 367,1022 307,1012" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="516" y="1122" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Get session by sessionId</text><line x1="307" y1="1151" x2="724" y2="1151" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="519" y="1211" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Return active session</text><line x1="727" y1="1240" x2="310" y2="1240" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="307" y="1255" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Reuse existing session</text><path d="M 307,1284 C 367,1274 367,1314 307,1304" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="519" y="1374" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Session not found</text><line x1="727" y1="1403" x2="310" y2="1403" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="1367" y="1418" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Check session history file</text><line x1="729" y1="1447" x2="2005" y2="1447" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1370" y="1507" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">History file found</text><line x1="2008" y1="1536" x2="732" y2="1536" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="869" y="1551" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Create session with resume mode</text><line x1="729" y1="1580" x2="1008" y2="1580" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="1595" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Set resumeSessionId</text><path d="M 1013,1624 C 1073,1614 1073,1654 1013,1644" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1370" y="1714" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">No history file</text><line x1="2008" y1="1743" x2="732" y2="1743" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="869" y="1758" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Create new session</text><line x1="729" y1="1787" x2="1008" y2="1787" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="1802" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Generate new session</text><path d="M 1013,1831 C 1073,1821 1073,1861 1013,1851" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="869" y="1971" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Create completely new session</text><line x1="729" y1="2000" x2="1008" y2="2000" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="729" y="2015" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Store with temporary key</text><path d="M 729,2044 C 789,2034 789,2074 729,2064" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1146" y="2129" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Create MessageQueue instance</text><line x1="1013" y1="2158" x2="1278" y2="2158" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1279" y="2173" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Initialize query stream with options</text><line x1="1013" y1="2202" x2="1544" y2="2202" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1777" y="2262" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Load conversation history</text><line x1="1549" y1="2291" x2="2005" y2="2291" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1780" y="2306" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Historical message data</text><line x1="2008" y1="2335" x2="1552" y2="2335" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="1013" y="2350" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Restore conversation context</text><path d="M 1013,2379 C 1073,2369 1073,2409 1013,2399" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="2469" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Start fresh conversation</text><path d="M 1013,2498 C 1073,2488 1073,2528 1013,2518" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1282" y="2583" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Return async generator stream</text><line x1="1547" y1="2612" x2="1016" y2="2612" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="1013" y="2627" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Start background response handler</text><path d="M 1013,2656 C 1073,2646 1073,2686 1013,2676" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="307" y="2701" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Build message content with text and images</text><path d="M 307,2730 C 367,2720 367,2760 307,2750" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="658" y="2775" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Send message with response callback</text><line x1="307" y1="2804" x2="1008" y2="2804" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="2819" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Generate unique request ID</text><path d="M 1013,2848 C 1073,2838 1073,2878 1013,2868" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1146" y="2893" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Push message to async queue</text><line x1="1013" y1="2922" x2="1278" y2="2922" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1417" y="2937" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Get message via async iterator</text><line x1="1547" y1="2966" x2="1286" y2="2966" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1414" y="2981" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Yield user message to SDK</text><line x1="1283" y1="3010" x2="1544" y2="3010" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="1677" y="3070" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Start MCP server connections</text><line x1="1549" y1="3099" x2="1805" y2="3099" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1680" y="3114" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Initialize tool capabilities</text><line x1="1808" y1="3143" x2="1552" y2="3143" class="messageLine1" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="stroke-dasharray: 3, 3; fill: none;"/><text x="1549" y="3158" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">MCP tools ready for use</text><path d="M 1549,3187 C 1609,3177 1609,3217 1549,3207" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1549" y="3277" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Continue without external tools</text><path d="M 1549,3306 C 1609,3296 1609,3336 1549,3326" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1282" y="3391" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Start streaming responses</text><line x1="1547" y1="3420" x2="1016" y2="3420" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="3435" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Handle response in background</text><path d="M 1013,3464 C 1073,3454 1073,3494 1013,3484" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="661" y="3509" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Forward response with metadata</text><line x1="1011" y1="3538" x2="310" y2="3538" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="307" y="3553" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Add agentId and timestamp</text><path d="M 307,3582 C 367,3572 367,3612 307,3602" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="192" y="3627" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Send SSE streaming data</text><line x1="305" y1="3656" x2="79" y2="3656" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1013" y="3716" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Save Claude session ID</text><path d="M 1013,3745 C 1073,3735 1073,3775 1013,3765" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="872" y="3790" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Confirm session mapping</text><line x1="1011" y1="3819" x2="732" y2="3819" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="729" y="3834" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Update session indexes</text><path d="M 729,3863 C 789,3853 789,3893 729,3883" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="1777" y="3948" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Auto-save conversation to claude directory</text><line x1="1549" y1="3977" x2="2005" y2="3977" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/><text x="729" y="3992" text-anchor="middle" dominant-baseline="middle" alignment-baseline="middle" class="messageText" dy="1em" style="font-size: 16px; font-weight: 400;">Update session activity timestamp</text><path d="M 729,4021 C 789,4011 789,4051 729,4041" class="messageLine0" stroke-width="2" stroke="none" marker-end="url(#arrowhead)" style="fill: none;"/></svg>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# 后端 /chat 接口完整时序图
|
|
2
|
+
|
|
3
|
+
```mermaid
|
|
4
|
+
sequenceDiagram
|
|
5
|
+
participant Client
|
|
6
|
+
participant Router
|
|
7
|
+
participant Storage
|
|
8
|
+
participant SessionMgr
|
|
9
|
+
participant Session
|
|
10
|
+
participant Queue
|
|
11
|
+
participant SDK
|
|
12
|
+
participant MCP
|
|
13
|
+
participant FS
|
|
14
|
+
|
|
15
|
+
%% 请求处理阶段
|
|
16
|
+
Client->>Router: POST /chat with params
|
|
17
|
+
Router->>Router: Validate request parameters
|
|
18
|
+
|
|
19
|
+
%% Agent验证分支
|
|
20
|
+
Router->>Storage: Get agent configuration
|
|
21
|
+
alt Agent not found
|
|
22
|
+
Storage-->>Router: null
|
|
23
|
+
Router->>Client: 404 Agent not found
|
|
24
|
+
else Agent disabled
|
|
25
|
+
Storage-->>Router: disabled agent
|
|
26
|
+
Router->>Client: 403 Agent disabled
|
|
27
|
+
else Agent valid
|
|
28
|
+
Storage-->>Router: valid agent config
|
|
29
|
+
Router->>Router: Build system prompt
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
%% MCP工具配置分支
|
|
33
|
+
alt MCP tools provided
|
|
34
|
+
Router->>FS: Read MCP configuration file
|
|
35
|
+
FS-->>Router: MCP server settings
|
|
36
|
+
Router->>Router: Configure MCP servers
|
|
37
|
+
else No MCP tools
|
|
38
|
+
Router->>Router: Skip MCP setup
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
%% 会话管理分支 - 关键业务逻辑
|
|
42
|
+
alt sessionId provided
|
|
43
|
+
Router->>SessionMgr: Get session by sessionId
|
|
44
|
+
|
|
45
|
+
alt Session exists in memory
|
|
46
|
+
SessionMgr-->>Router: Return active session
|
|
47
|
+
Router->>Router: Reuse existing session
|
|
48
|
+
else Session not in memory
|
|
49
|
+
SessionMgr-->>Router: Session not found
|
|
50
|
+
SessionMgr->>FS: Check session history file
|
|
51
|
+
|
|
52
|
+
alt Session history exists
|
|
53
|
+
FS-->>SessionMgr: History file found
|
|
54
|
+
SessionMgr->>Session: Create session with resume mode
|
|
55
|
+
Session->>Session: Set resumeSessionId
|
|
56
|
+
else No session history
|
|
57
|
+
FS-->>SessionMgr: No history file
|
|
58
|
+
SessionMgr->>Session: Create new session
|
|
59
|
+
Session->>Session: Generate new session
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
else No sessionId provided
|
|
63
|
+
SessionMgr->>Session: Create completely new session
|
|
64
|
+
SessionMgr->>SessionMgr: Store with temporary key
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
%% Claude SDK初始化
|
|
68
|
+
Session->>Queue: Create MessageQueue instance
|
|
69
|
+
Session->>SDK: Initialize query stream with options
|
|
70
|
+
|
|
71
|
+
alt Resume existing session
|
|
72
|
+
SDK->>FS: Load conversation history
|
|
73
|
+
FS-->>SDK: Historical message data
|
|
74
|
+
Session->>Session: Restore conversation context
|
|
75
|
+
else New session
|
|
76
|
+
Session->>Session: Start fresh conversation
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
SDK-->>Session: Return async generator stream
|
|
80
|
+
Session->>Session: Start background response handler
|
|
81
|
+
|
|
82
|
+
%% 消息处理流程
|
|
83
|
+
Router->>Router: Build message content with text and images
|
|
84
|
+
Router->>Session: Send message with response callback
|
|
85
|
+
Session->>Session: Generate unique request ID
|
|
86
|
+
Session->>Queue: Push message to async queue
|
|
87
|
+
SDK->>Queue: Get message via async iterator
|
|
88
|
+
Queue-->>SDK: Yield user message to SDK
|
|
89
|
+
|
|
90
|
+
%% MCP工具连接
|
|
91
|
+
alt MCP tools configured
|
|
92
|
+
SDK->>MCP: Start MCP server connections
|
|
93
|
+
MCP-->>SDK: Initialize tool capabilities
|
|
94
|
+
SDK->>SDK: MCP tools ready for use
|
|
95
|
+
else No MCP tools
|
|
96
|
+
SDK->>SDK: Continue without external tools
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
%% 响应流处理
|
|
100
|
+
SDK->>Session: Start streaming responses
|
|
101
|
+
Session->>Session: Handle response in background
|
|
102
|
+
Session->>Router: Forward response with metadata
|
|
103
|
+
Router->>Router: Add agentId and timestamp
|
|
104
|
+
Router->>Client: Send SSE streaming data
|
|
105
|
+
|
|
106
|
+
%% 会话确认逻辑
|
|
107
|
+
alt Response contains sessionId
|
|
108
|
+
Session->>Session: Save Claude session ID
|
|
109
|
+
Session->>SessionMgr: Confirm session mapping
|
|
110
|
+
SessionMgr->>SessionMgr: Update session indexes
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
%% 数据持久化
|
|
114
|
+
SDK->>FS: Auto-save conversation to claude directory
|
|
115
|
+
SessionMgr->>SessionMgr: Update session activity timestamp
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## 完整业务场景分析
|
|
119
|
+
|
|
120
|
+
### 🎯 核心执行路径详解
|
|
121
|
+
|
|
122
|
+
#### 路径1: 全新用户首次对话
|
|
123
|
+
```
|
|
124
|
+
无sessionId → 创建新会话 → 初始化SDK → 处理消息 → 确认sessionId → 保存历史
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### 路径2: 用户继续现有对话
|
|
128
|
+
```
|
|
129
|
+
有sessionId且在内存 → 复用会话 → 直接处理 → 更新历史
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### 路径3: 用户恢复中断会话
|
|
133
|
+
```
|
|
134
|
+
有sessionId但不在内存 → 检查历史 → 恢复会话上下文 → 处理新消息
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### 路径4: 使用外部工具的对话
|
|
138
|
+
```
|
|
139
|
+
检测MCP工具 → 读取配置 → 连接服务器 → 工具调用可用 → 处理带工具的对话
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### 路径5: 错误和异常情况
|
|
143
|
+
```
|
|
144
|
+
Agent验证失败 → 立即返回错误
|
|
145
|
+
会话创建失败 → 错误响应
|
|
146
|
+
SDK处理异常 → 错误事件推送
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 🔧 技术架构特性
|
|
150
|
+
|
|
151
|
+
#### 会话生命周期管理
|
|
152
|
+
- **三级查找策略**: 内存缓存 → 文件历史 → 新建会话
|
|
153
|
+
- **状态同步机制**: 内存索引与文件系统双重保障
|
|
154
|
+
- **自动清理策略**: 定期清理空闲和过期会话
|
|
155
|
+
|
|
156
|
+
#### 流式处理架构
|
|
157
|
+
- **Streaming Input Mode**: 一次构造query,持续接收输入
|
|
158
|
+
- **异步消息队列**: 解耦用户输入和AI处理逻辑
|
|
159
|
+
- **Server-Sent Events**: 实时推送响应数据到前端
|
|
160
|
+
|
|
161
|
+
#### 外部工具集成
|
|
162
|
+
- **MCP协议支持**: 动态加载和管理外部工具服务器
|
|
163
|
+
- **工具生命周期**: 按需连接,自动管理连接状态
|
|
164
|
+
- **错误隔离机制**: 工具错误不影响核心对话流程
|
|
165
|
+
|
|
166
|
+
这个版本完整展示了后端chat接口的所有主要业务分支和技术实现细节!
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# /chat API Sequence Diagram
|
|
2
|
+
|
|
3
|
+
```mermaid
|
|
4
|
+
sequenceDiagram
|
|
5
|
+
participant Client as 客户端 (Frontend)
|
|
6
|
+
participant Router as 后端路由 (Express)
|
|
7
|
+
participant ChatHandler as Chat 请求处理器
|
|
8
|
+
participant SessionManager as 会话管理器
|
|
9
|
+
participant ClaudeSDK as Claude Code SDK
|
|
10
|
+
participant AIModel as Claude AI 模型
|
|
11
|
+
|
|
12
|
+
Client->>+Router: POST /api/agents/chat (含 message, agentId, sessionId?)
|
|
13
|
+
Router->>+ChatHandler: 处理请求
|
|
14
|
+
|
|
15
|
+
Note over ChatHandler: 1. 验证请求参数 (Zod)
|
|
16
|
+
ChatHandler-->>-Router: 若验证失败, 返回 400 错误
|
|
17
|
+
Router-->>-Client: 响应 400 错误
|
|
18
|
+
|
|
19
|
+
Note over ChatHandler: 2. 获取 Agent 配置
|
|
20
|
+
ChatHandler-->>-Router: 若 Agent 不存在或禁用, 返回 404/403 错误
|
|
21
|
+
Router-->>-Client: 响应 404/403 错误
|
|
22
|
+
|
|
23
|
+
Note over ChatHandler: 3. 准备 SDK 配置 (Options)
|
|
24
|
+
|
|
25
|
+
Note over ChatHandler: 4. 会话 (Session) 管理
|
|
26
|
+
opt 提供 sessionId
|
|
27
|
+
Note over SessionManager: 尝试在内存或历史记录中复用 Session
|
|
28
|
+
ChatHandler->>+SessionManager: getSession(sessionId) / resume
|
|
29
|
+
SessionManager-->>-ChatHandler: 返回现有或恢复的 Session
|
|
30
|
+
end
|
|
31
|
+
opt 未提供 sessionId
|
|
32
|
+
Note over SessionManager: 创建一个全新的 Session
|
|
33
|
+
ChatHandler->>+SessionManager: createNewSession()
|
|
34
|
+
SessionManager-->>-ChatHandler: 返回全新 Session 实例
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Note over ChatHandler: 5. 构造用户消息 (含文本和图片)
|
|
38
|
+
|
|
39
|
+
Note over ChatHandler: 6. 调用 Claude SDK
|
|
40
|
+
ChatHandler->>+ClaudeSDK: query({ prompt, options, resume? })
|
|
41
|
+
ClaudeSDK->>+AIModel: 发送格式化后的请求
|
|
42
|
+
AIModel-->>-ClaudeSDK: 返回响应流 (Stream)
|
|
43
|
+
ClaudeSDK-->>-ChatHandler: 返回 SDK 消息流
|
|
44
|
+
|
|
45
|
+
Note over ChatHandler: 7. 处理响应流并返回给客户端
|
|
46
|
+
ChatHandler->>Client: 设置 SSE 响应头 (text/event-stream)
|
|
47
|
+
loop 遍历 SDK 消息流
|
|
48
|
+
ChatHandler->>ChatHandler: 格式化消息 (JSON)
|
|
49
|
+
opt 收到 'init' 消息 (新会话)
|
|
50
|
+
ChatHandler->>SessionManager: 确认并保存新 Session ID
|
|
51
|
+
end
|
|
52
|
+
ChatHandler-->>Client: res.write(data: JSON_message)
|
|
53
|
+
opt 收到 'result' 消息
|
|
54
|
+
ChatHandler-->>Client: res.end() (结束连接)
|
|
55
|
+
break
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
```
|