@coze-arch/cli 0.0.13 → 0.0.14-alpha.c52ee4

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.
Files changed (76) hide show
  1. package/lib/__templates__/expo/AGENTS.md +15 -7
  2. package/lib/__templates__/expo/README.md +15 -7
  3. package/lib/__templates__/expo/client/eslint.config.mjs +3 -0
  4. package/lib/__templates__/expo/eslint-plugins/expo/index.js +9 -0
  5. package/lib/__templates__/expo/eslint-plugins/expo/rule.js +105 -0
  6. package/lib/__templates__/expo/eslint-plugins/expo/tech.md +108 -0
  7. package/lib/__templates__/nextjs/AGENTS.md +9 -0
  8. package/lib/__templates__/nextjs/eslint.config.mjs +15 -0
  9. package/lib/__templates__/pi-agent/.coze +10 -0
  10. package/lib/__templates__/pi-agent/AGENTS.md +150 -0
  11. package/lib/__templates__/pi-agent/README.md +155 -0
  12. package/lib/__templates__/pi-agent/_gitignore +3 -0
  13. package/lib/__templates__/pi-agent/docs/project-overview.md +273 -0
  14. package/lib/__templates__/pi-agent/docs/user/getting-started.md +46 -0
  15. package/lib/__templates__/pi-agent/package.json +52 -0
  16. package/lib/__templates__/pi-agent/pnpm-lock.yaml +7840 -0
  17. package/lib/__templates__/pi-agent/scripts/dev.sh +14 -0
  18. package/lib/__templates__/pi-agent/scripts/prepare.sh +2 -0
  19. package/lib/__templates__/pi-agent/src/agent.ts +367 -0
  20. package/lib/__templates__/pi-agent/src/channels/feishu/index.ts +760 -0
  21. package/lib/__templates__/pi-agent/src/channels/feishu/streaming-card.ts +297 -0
  22. package/lib/__templates__/pi-agent/src/channels/wechat/index.ts +171 -0
  23. package/lib/__templates__/pi-agent/src/config.ts +596 -0
  24. package/lib/__templates__/pi-agent/src/core.ts +218 -0
  25. package/lib/__templates__/pi-agent/src/dashboard/api/channels.ts +148 -0
  26. package/lib/__templates__/pi-agent/src/dashboard/api/docs.ts +204 -0
  27. package/lib/__templates__/pi-agent/src/dashboard/api/models.ts +141 -0
  28. package/lib/__templates__/pi-agent/src/dashboard/api/overview.ts +33 -0
  29. package/lib/__templates__/pi-agent/src/dashboard/config-store.ts +64 -0
  30. package/lib/__templates__/pi-agent/src/dashboard/index.ts +39 -0
  31. package/lib/__templates__/pi-agent/src/dashboard/server.ts +622 -0
  32. package/lib/__templates__/pi-agent/src/dashboard/types.ts +25 -0
  33. package/lib/__templates__/pi-agent/src/dashboard/web/index.html +13 -0
  34. package/lib/__templates__/pi-agent/src/dashboard/web/postcss.config.cjs +7 -0
  35. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/app-layout.tsx +186 -0
  36. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/page-title.tsx +17 -0
  37. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/alert.tsx +22 -0
  38. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/badge.tsx +25 -0
  39. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/button.tsx +40 -0
  40. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/card.tsx +29 -0
  41. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/input.tsx +18 -0
  42. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/label.tsx +8 -0
  43. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/select.tsx +80 -0
  44. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/separator.tsx +23 -0
  45. package/lib/__templates__/pi-agent/src/dashboard/web/src/hooks/use-fetch.ts +32 -0
  46. package/lib/__templates__/pi-agent/src/dashboard/web/src/hooks/use-local-storage-state.ts +23 -0
  47. package/lib/__templates__/pi-agent/src/dashboard/web/src/main.tsx +30 -0
  48. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/channels-page.tsx +188 -0
  49. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/chat-page.tsx +451 -0
  50. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/docs-page.tsx +65 -0
  51. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/models-page.tsx +122 -0
  52. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/overview-page.tsx +134 -0
  53. package/lib/__templates__/pi-agent/src/dashboard/web/src/services/chat-ws-service.ts +167 -0
  54. package/lib/__templates__/pi-agent/src/dashboard/web/src/styles.css +294 -0
  55. package/lib/__templates__/pi-agent/src/dashboard/web/src/utils/index.ts +11 -0
  56. package/lib/__templates__/pi-agent/src/dashboard/web/tsconfig.json +13 -0
  57. package/lib/__templates__/pi-agent/src/dashboard/web/vite.config.ts +17 -0
  58. package/lib/__templates__/pi-agent/src/index.ts +123 -0
  59. package/lib/__templates__/pi-agent/src/session-store.ts +223 -0
  60. package/lib/__templates__/pi-agent/template.config.js +45 -0
  61. package/lib/__templates__/pi-agent/tests/config.test.ts +292 -0
  62. package/lib/__templates__/pi-agent/tests/dashboard-docs-api.test.ts +125 -0
  63. package/lib/__templates__/pi-agent/tests/dashboard-models-api.test.ts +171 -0
  64. package/lib/__templates__/pi-agent/tests/feishu-channel.test.ts +149 -0
  65. package/lib/__templates__/pi-agent/tests/feishu-streaming-card.test.ts +15 -0
  66. package/lib/__templates__/pi-agent/tests/session-store.test.ts +61 -0
  67. package/lib/__templates__/pi-agent/tests/smoke/run-smoke.ts +275 -0
  68. package/lib/__templates__/pi-agent/tsconfig.json +20 -0
  69. package/lib/__templates__/pi-agent/types/larksuiteoapi-node-sdk.d.ts +113 -0
  70. package/lib/__templates__/taro/pnpm-lock.yaml +24 -14
  71. package/lib/__templates__/taro/server/package.json +0 -2
  72. package/lib/__templates__/taro/src/presets/dev-debug.ts +2 -2
  73. package/lib/__templates__/templates.json +24 -0
  74. package/lib/__templates__/vite/AGENTS.md +5 -0
  75. package/lib/cli.js +1 -1
  76. package/package.json +1 -1
@@ -0,0 +1,273 @@
1
+ # Pi Bot 项目总览
2
+
3
+ ## 1. 项目定位
4
+
5
+ `pi-bot` 是一个基于 `pi-mono` / `@mariozechner/pi-coding-agent` 的 Bot 项目。
6
+
7
+ 这个目录直接承载三类能力:
8
+
9
+ - 初始化骨架
10
+ - 平台 channel 接入
11
+ - provider 扩展
12
+
13
+ 项目里的关键运行时代码集中在这里,阅读、修改和扩展都会更直接。
14
+
15
+ ## 2. 当前目录结构
16
+
17
+ ```txt
18
+ .
19
+ ├── docs
20
+ │ ├── project-overview.md
21
+ │ └── user
22
+ ├── src
23
+ │ ├── agent.ts
24
+ │ ├── config.ts
25
+ │ ├── core.ts
26
+ │ ├── session-store.ts
27
+ │ ├── dashboard
28
+ │ │ ├── config-store.ts
29
+ │ │ ├── api
30
+ │ │ │ ├── channels.ts
31
+ │ │ │ ├── models.ts
32
+ │ │ │ └── overview.ts
33
+ │ │ ├── web
34
+ │ │ │ ├── src
35
+ │ │ │ │ ├── components
36
+ │ │ │ │ │ ├── ui
37
+ │ │ │ │ │ └── app-layout.tsx
38
+ │ │ │ │ ├── pages
39
+ │ │ │ │ ├── utils
40
+ │ │ │ │ ├── main.tsx
41
+ │ │ │ │ └── styles.css
42
+ │ │ │ ├── index.html
43
+ │ │ │ ├── postcss.config.cjs
44
+ │ │ │ ├── tsconfig.json
45
+ │ │ │ └── vite.config.ts
46
+ │ │ ├── index.ts
47
+ │ │ ├── server.ts
48
+ │ │ └── types.ts
49
+ │ ├── index.ts
50
+ │ ├── channels
51
+ │ │ ├── feishu
52
+ │ │ └── wechat
53
+ ├── tests
54
+ │ ├── config.test.ts
55
+ │ └── smoke
56
+ └── types
57
+ ```
58
+
59
+ 各部分职责:
60
+
61
+ - `src/config.ts`
62
+ - 项目唯一配置入口,读取 `config.json` 并装配 agent、channel、routing 等运行配置
63
+ - `src/index.ts`
64
+ - 应用装配层,创建 channel 并把消息交给 runtime
65
+ - `src/agent.ts`
66
+ - `pi-coding-agent` runtime 封装
67
+ - `src/core.ts`
68
+ - 通用消息协议、共享类型和基础 helper
69
+ - `src/session-store.ts`
70
+ - session 持久化索引层
71
+ - 负责维护 `sessionKey -> sessionId/sessionFile` 映射,并管理 transcript header、reset 归档等文件操作
72
+ - `src/channels/feishu`
73
+ - 飞书消息接收、标准化、去重、过滤和回复发送
74
+ - `src/channels/wechat`
75
+ - 微信消息标准化和回复发送
76
+ - `src/dashboard/*`
77
+ - 本地 Dashboard(HTTP + WebSocket),用于查看运行状态、编辑配置、以及以 UI 方式调试聊天会话
78
+ - 同时提供 `Docs` 页面,直接展示项目内的快速开始文档
79
+ - 开发态通过 Vite middleware 提供前端资源;生产态直接托管 `src/dashboard/web/dist`
80
+ - `src/dashboard/config-store.ts`
81
+ - Dashboard 配置存储抽象
82
+ - 默认使用文件存储读写 `workspace/config.json`
83
+ - 也支持内存存储,便于 smoke test 或宿主注入
84
+ - `tests/smoke`
85
+ - 基础链路 smoke test
86
+ - 当前会额外覆盖 dashboard 的 models/channels 配置读写,并使用内存 `ConfigStore` 避免依赖真实配置文件
87
+ - `tests/config.test.ts`
88
+ - config 解析与模型构建测试
89
+ - `types`
90
+ - 第三方 SDK 的类型补充
91
+
92
+ ## 3. Dashboard(现状实现)
93
+
94
+ Dashboard 是一个「和 Bot 同进程」启动的本地 HTTP 服务,默认地址:
95
+
96
+ - `http://127.0.0.1:5000`
97
+ - 端口/Host 可通过环境变量覆盖:`PI_BOT_DASHBOARD_PORT`、`PI_BOT_DASHBOARD_HOST`
98
+
99
+ 服务端入口:
100
+
101
+ - [`src/dashboard/server.ts`](../src/dashboard/server.ts) 负责 Express 路由、Vite 开发中间件、以及 WebSocket(聊天流式)
102
+ - [`src/dashboard/index.ts`](../src/dashboard/index.ts) 负责把 Bot runtime 信息注入 Dashboard server
103
+ - [`src/dashboard/config-store.ts`](../src/dashboard/config-store.ts) 负责把 Dashboard 的配置读写抽象成 `ConfigStore`
104
+
105
+ ### 3.1 前端技术栈
106
+
107
+ - Vite + React + React Router
108
+ - Tailwind CSS v4(`styles.css` 里使用 `@import "tailwindcss"` / `@theme`)
109
+ - shadcn 风格组件(代码内置于 `src/dashboard/web/src/components/ui/*`)
110
+ - 暗黑模式:通过在 `documentElement` 上切换 `dark` class,并在 `styles.css` 提供 `:root` / `.dark` token
111
+
112
+ ### 3.2 页面与路由
113
+
114
+ 前端路由位于 `src/dashboard/web/src/main.tsx`,当前页面:
115
+
116
+ - `/overview`:运行状态与关键路径(workspace/agent dir 等)
117
+ - `/docs`:项目快速开始文档
118
+ - `/models`:切换默认模型
119
+ - `/channels`:编辑渠道配置
120
+ - `/chat`:调试聊天会话(含历史、reset、WebSocket 流式)
121
+
122
+ ### 3.3 HTTP API(服务端)
123
+
124
+ 当前主要接口(均在同一进程内,不做鉴权):
125
+
126
+ - `GET /api/overview`:运行状态/路径/启用渠道等
127
+ - `GET /api/docs`:读取 `docs/user/` 下的用户文档并返回当前文档内容
128
+ - `GET /api/models`:通过 `ConfigStore` 读取配置并返回默认模型与可选模型列表(用于下拉选择)
129
+ - `POST /api/models`:仅写回默认模型(请求体只包含 `defaultModel`;服务端会基于当前配置扫描列表做校验)
130
+ - `GET /api/channels`:通过 `ConfigStore` 读取配置并返回可编辑结构
131
+ - `POST /api/channels`:通过 `ConfigStore` 写回配置;默认文件存储会落回 `workspace/config.json`,保存后需要重启进程生效
132
+ - `GET /api/chat/history`:按 session identity 计算 sessionKey,并按需加载持久化 transcript 后返回消息
133
+ - `POST /api/chat/reset`:重置指定 sessionKey 的会话;会切换到新的 `sessionId/sessionFile`,旧 transcript 归档到 `archive/`
134
+ - `WS /api/chat/ws`:聊天流式(推荐的 UI 通道)
135
+
136
+ 补充说明:
137
+
138
+ - 生产/日常开发默认使用文件型 `ConfigStore`
139
+ - `createBotApp(..., { dashboardConfigStore })` 可注入自定义存储实现
140
+ - `tests/smoke/run-smoke.ts` 当前使用内存型 `ConfigStore`,直接验证 dashboard 配置的读写 API 行为
141
+
142
+ ### 3.4 模型配置页能力边界
143
+
144
+ 当前 `/models` 页面的目标,是以 UI 方式快速切换默认模型,降低直接手改 JSON 的成本。当前页面支持:
145
+
146
+ - 修改默认模型(写回 `agents.defaults.model.primary`)
147
+
148
+ 当前页面不支持:
149
+
150
+ - 编辑 Provider 配置
151
+ - 编辑模型参数
152
+ - 新增/删除 Provider 或模型条目
153
+
154
+ 因此,如果要接入新的 openai-compatible provider、修改模型定义或参数,仍然建议直接编辑默认文件存储对应的 `workspace/config.json`;补充完成后,Dashboard 会自动读取并展示这些新模型供选择。
155
+
156
+ ### 3.5 Session 持久化
157
+
158
+ 当前 `pi-bot` 已支持 session 持久化,逻辑参考 `openclaw` 的 transcript/sessionFile 模式:
159
+
160
+ - `src/core.ts` 里的 `getSessionKey()` 仍然负责根据 channel / conversation / thread 等信息生成稳定的业务会话键
161
+ - `src/session-store.ts` 负责把这个 `sessionKey` 映射到一个可落盘的 transcript 文件
162
+ - `src/agent.ts` 在创建真实 `pi-coding-agent` session 时,不再只依赖进程内 `Map`,而是通过 `SessionManager.open(sessionFile)` 绑定到固定 transcript
163
+
164
+ 默认持久化目录位于:
165
+
166
+ ```txt
167
+ <agentDir>/.pi-bot/sessions/
168
+ ├── index.json
169
+ ├── transcripts/
170
+ └── archive/
171
+ ```
172
+
173
+ 其中:
174
+
175
+ - `index.json`
176
+ - 保存 `sessionKey -> { sessionId, sessionFile, updatedAt }` 的索引
177
+ - `transcripts/`
178
+ - 保存当前活跃会话的 transcript(`.jsonl`)
179
+ - `archive/`
180
+ - 保存 reset 后被归档的旧 transcript
181
+
182
+ 补充说明:
183
+
184
+ - 持久化覆盖全部 channel:`dashboard` / `feishu` / `wechat`
185
+ - transcript 文件名不会直接使用原始 `sessionKey`,而是基于其 hash 生成,避免特殊字符和超长文件名问题
186
+ - Dashboard 重启后仍可通过 `GET /api/chat/history` 恢复已有会话消息
187
+ - Reset 不会直接覆盖旧 transcript,而是新建 session 并归档旧文件,便于排查和追溯
188
+
189
+ ### 3.6 构建方式
190
+
191
+ 前端生产构建命令:
192
+
193
+ ```bash
194
+ npm run dashboard:build
195
+ ```
196
+
197
+ 该脚本对应 Vite 配置:
198
+
199
+ - [`src/dashboard/web/vite.config.ts`](../src/dashboard/web/vite.config.ts)
200
+
201
+ 开发态(`NODE_ENV !== "production"`):
202
+
203
+ - Dashboard server 通过 Vite middleware 直接服务前端(无需单独启动 Vite dev server)
204
+
205
+ 生产态(`NODE_ENV=production`):
206
+
207
+ - Dashboard server 托管 `src/dashboard/web/dist` 的静态文件
208
+ - 如果你需要生产态可用,记得先运行 `npm run dashboard:build`
209
+
210
+ ## 4. 运行模型
211
+
212
+ 当前项目的运行链路如下:
213
+
214
+ 1. channel 接收平台事件
215
+ 2. channel 把事件转换成 `BotMessage`
216
+ 3. `src/index.ts` 调用 `runtime.run(message)`
217
+ 4. `src/agent.ts` 根据配置选择 mock 或真实 `pi-coding-agent`
218
+ 5. 真实 runtime 会先通过 `getSessionKey()` 确定业务会话,再通过 `src/session-store.ts` 找到或创建对应的持久化 transcript
219
+ 6. runtime 基于该 transcript 执行 prompt,新的 user / assistant 消息持续写入 sessionFile
220
+ 7. runtime 返回文本
221
+ 8. channel 把文本发回原平台
222
+
223
+ ## 4.1 飞书卡片与流式输出
224
+
225
+ `pi-bot` 的飞书回复有两种渲染形态:
226
+
227
+ - 普通文本:`msg_type: "text"`
228
+ - Markdown 卡片:`msg_type: "interactive"`(卡片内使用 `tag: "markdown"`)
229
+
230
+ 默认情况下会按内容自动选择是否使用卡片(与 `openclaw` 的判断一致):
231
+
232
+ - 命中代码块(```...```,流式阶段也接受仅出现 opening fence)或 Markdown 表格时,使用卡片渲染
233
+ - 其他普通文本/普通 Markdown,使用文本消息
234
+
235
+ 当启用流式回复(`onStreamMessage` + `runtime.stream()`)时,如果内容命中“使用卡片”的条件,会尝试使用 CardKit 的 streaming card API 做实时更新:
236
+
237
+ - 创建 streaming card(CardKit `cardkit/v1/cards`)
238
+ - reply 一条 `interactive` 卡片引用到原消息
239
+ - 按增量内容持续更新卡片中的 markdown 元素
240
+ - 最终关闭 streaming 模式并更新 summary
241
+
242
+ 注意:流式卡片需要飞书开放平台开通 CardKit 相关权限(例如 `cardkit:card:write`)。如果权限未开通,streaming card 创建/更新会失败并自动回退为“最终一次性回复”。
243
+
244
+ 如果 streaming card 创建失败(例如未开通 CardKit 权限、参数/租户不匹配等),会自动回退为“最终一次性回复”,不会影响正常出消息。
245
+
246
+ 补充说明:
247
+
248
+ - 进程内仍保留 `Map<string, AgentSession>` 作为热缓存,避免同一 session 在单次运行期间重复创建
249
+ - 但真正的“可恢复会话”依赖的是磁盘上的 transcript,而不是这个内存 `Map`
250
+ - 因此进程重启后,只要 `sessionKey` 不变,就可以重新打开对应 transcript 继续对话
251
+ - 飞书 thinking reaction 默认 emoji 已调整为 `OneSecond`,也可通过 `channels.feishu.thinkingReaction.emojiType` 覆盖
252
+
253
+ ## 5. 当前建议的开发顺序
254
+
255
+ 如果后续继续扩展,建议按这个顺序理解项目:
256
+
257
+ 1. 阅读根目录 `README.md`
258
+ 2. 阅读 `docs/project-overview.md`
259
+ 3. 阅读 `src/config.ts`
260
+ 4. 阅读 `src/index.ts`
261
+ 5. 阅读 `src/agent.ts`
262
+ 6. 根据需要再进入 `src/channels/*`、`src/dashboard/*` 和相关测试
263
+
264
+ ## 6. 关于 docs
265
+
266
+ `docs/` 目录中保留了两类材料:
267
+
268
+ - `docs/project-overview.md`
269
+ - 面向维护者的架构介绍
270
+ - `docs/user/getting-started.md`
271
+ - 面向项目使用者的快速开始文档,Dashboard 的 `Docs` 页面会直接读取并展示
272
+
273
+ 最贴近现状的介绍文档是这份 `docs/project-overview.md`。如果其他文档与当前目录结构冲突,应以当前源码、`README.md` 和本文件为准。
@@ -0,0 +1,46 @@
1
+ ---
2
+ title: 快速开始
3
+ ---
4
+
5
+ # 快速开始
6
+
7
+ 即使暂时没有打通外部渠道,你也可以先用 Dashboard 的 `聊天` 页面验证 Agent 行为。
8
+
9
+ ## 接入飞书机器人
10
+
11
+ 1. 打开 [渠道](/channels) 页面。
12
+ 2. 填写 `App ID` 和 `App Secret`。
13
+ 3. 按需填写 `domain`、`encryptKey`、`verificationToken`。
14
+ 4. 点击保存。
15
+ 5. 重启应用让配置生效。
16
+
17
+ ### 飞书机器人配置
18
+
19
+ 1. 在「权限管理」中配置以下权限:
20
+
21
+ ```json
22
+ {
23
+ "scopes": {
24
+ "tenant": [
25
+ "cardkit:card:write",
26
+ "docx:document:readonly",
27
+ "im:message.group_at_msg:readonly",
28
+ "im:message.p2p_msg:readonly",
29
+ "im:message.reactions:read",
30
+ "im:message.reactions:write_only",
31
+ "im:message:send_as_bot"
32
+ ],
33
+ "user": [
34
+ "docx:document:readonly"
35
+ ]
36
+ }
37
+ }
38
+ ```
39
+
40
+ 2. 在「事件与回调」中添加 `im.message.receive_v1` 事件,并将订阅方式设置为“使用长连接接收事件”。
41
+
42
+ ## 发送第一条飞书消息
43
+
44
+ 飞书接通后,你可以直接给机器人发私聊消息。
45
+
46
+ 如果当前配置开启了群聊提及限制,那么群聊里需要先 `@机器人`,消息才会进入处理链路。
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "pi-bot",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "scripts": {
8
+ "dev": "bash scripts/dev.sh",
9
+ "start": "npm run dev",
10
+ "test": "node --import tsx --test tests/**/*.test.ts",
11
+ "smoke": "node --import tsx tests/smoke/run-smoke.ts",
12
+ "typecheck": "tsc -p tsconfig.json --noEmit",
13
+ "dashboard:build": "vite build --config src/dashboard/web/vite.config.ts"
14
+ },
15
+ "dependencies": {
16
+ "@larksuiteoapi/node-sdk": "^1.60.0",
17
+ "@mariozechner/pi-agent-core": "^0.63.2",
18
+ "@mariozechner/pi-ai": "^0.63.2",
19
+ "@mariozechner/pi-coding-agent": "^0.63.2",
20
+ "@radix-ui/react-select": "^2.2.6",
21
+ "@radix-ui/react-slot": "^1.2.4",
22
+ "@streamdown/code": "^1.1.1",
23
+ "class-variance-authority": "^0.7.1",
24
+ "clsx": "^2.1.1",
25
+ "express": "^4.21.2",
26
+ "lodash-es": "^4.18.1",
27
+ "lucide-react": "^1.8.0",
28
+ "react": "^18.3.1",
29
+ "react-dom": "^18.3.1",
30
+ "react-router-dom": "^6.28.0",
31
+ "sonner": "^2.0.7",
32
+ "streamdown": "^2.5.0",
33
+ "tailwind-merge": "^3.5.0",
34
+ "ws": "^8.19.0"
35
+ },
36
+ "devDependencies": {
37
+ "@tailwindcss/postcss": "^4.2.2",
38
+ "@types/express": "^4.17.22",
39
+ "@types/lodash-es": "^4.17.12",
40
+ "@types/node": "^24.3.0",
41
+ "@types/react": "^18.3.12",
42
+ "@types/react-dom": "^18.3.1",
43
+ "@types/ws": "^8.5.10",
44
+ "@vitejs/plugin-react": "^4.3.3",
45
+ "autoprefixer": "^10.4.27",
46
+ "postcss": "^8.5.9",
47
+ "tailwindcss": "^4.2.2",
48
+ "tsx": "^4.20.3",
49
+ "typescript": "^5.9.2",
50
+ "vite": "^6.0.6"
51
+ }
52
+ }