page-agent-sdk 1.0.0
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/LICENSE +15 -0
- package/README.md +285 -0
- package/dist/chat-sdk.css +2 -0
- package/dist/chat-sdk.iife.js +303 -0
- package/dist/chat-sdk.js +17020 -0
- package/dist/chat-sdk.umd.cjs +147 -0
- package/dist/page-agent-sdk.css +2 -0
- package/package.json +81 -0
- package/types/index.d.ts +438 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chat-sdk contributors
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# chat-sdk
|
|
2
|
+
|
|
3
|
+
> 给网页一个**会改页面的 AI 助手**。一行代码挂载对话框,AI 通过工具按 schema 安全读写页面数据,实现「对话式」搭建/编辑/运维。
|
|
4
|
+
|
|
5
|
+
> **AI agent 接入**:直接看下方「[Agent 接入速查](#agent-接入速查给-ai-agent-读)」(导出 / 选项表 / 扩展点 / 内置工具 / 文件结构),架构与约定坑见 [`CLAUDE.md`](./CLAUDE.md)。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/chat-sdk)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
[](#自测)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 适合谁
|
|
14
|
+
|
|
15
|
+
**低代码 / 可视化搭建平台、表单与页面设计器、CMS、智能运维台**——凡是「页面有可结构化描述的数据,希望用自然语言驱动它变化」的场景。
|
|
16
|
+
|
|
17
|
+
核心思路一句话:**把页面数据结构(schema)声明给 Agent,它用工具按 schema 安全读写**——「改页面」从拖拽/手填变成一句话。
|
|
18
|
+
|
|
19
|
+
## 使用场景
|
|
20
|
+
|
|
21
|
+
| 场景 | 用户说 | AI 做 |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| 🏗 **低代码搭建** | 「顶部 Banner 改深色、主标题加粗、加一张新品卡」 | 按 jsonPath 增量 patch 组件树,画布实时刷新 |
|
|
24
|
+
| 📝 **表单设计器** | 「手机号加格式校验、地址改三级联动」 | 增量改字段定义,schema 校验防错 |
|
|
25
|
+
| 📰 **CMS 运营** | 「这批商品标题加『限时』前缀、低于 100 元的标红」 | JSONPath 筛选 + 沙箱脚本批量改 |
|
|
26
|
+
| 🖥 **运维配置台** | 「A 实验阈值调到 30%、关掉 B 开关」 | 白名单 + 人工确认改配置,写后读回校验 |
|
|
27
|
+
| 🤖 **AI 原生助手** | 「把这张看板的图例改成柱状」 | 对话操作产品自有数据,免做 UI |
|
|
28
|
+
|
|
29
|
+
> 仓库 `examples/nested-demo` 即低代码场景完整示例:嵌套区块树 + 人工确认 + 一键回退。
|
|
30
|
+
|
|
31
|
+
## 30 秒上手
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install page-agent-sdk zod @langchain/openai @langchain/core
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { createChatSdk } from 'page-agent-sdk'
|
|
39
|
+
import { z } from 'zod'
|
|
40
|
+
|
|
41
|
+
window.page = { title: '新品专区', theme: 'light' }
|
|
42
|
+
|
|
43
|
+
createChatSdk({
|
|
44
|
+
container: '#chat',
|
|
45
|
+
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
|
|
46
|
+
systemPrompt: '你是页面搭建助手,通过工具读写 window.page。',
|
|
47
|
+
windowProps: [
|
|
48
|
+
{ path: 'page.title', description: '页面标题', schema: z.string() },
|
|
49
|
+
{ path: 'page.theme', description: '主题', schema: z.enum(['light', 'dark']) },
|
|
50
|
+
],
|
|
51
|
+
approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // 写操作弹确认
|
|
52
|
+
checkpoint: true, // 误改一键回退
|
|
53
|
+
}).mount()
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
用户说「标题改成『夏日新品』、主题切深色」→ AI 调 `edit_window_prop` 增量改 → schema 校验 → 写前确认 → 响应式刷新。说错了?点「↩ 回退」。
|
|
57
|
+
|
|
58
|
+
CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `ChatSdk.createChatSdk({...})`。
|
|
59
|
+
|
|
60
|
+
## 它能做什么
|
|
61
|
+
|
|
62
|
+
| 能力 | 说明 | 选项 |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| 🛠 window 操作 | 读写注册属性,schema 校验 + 增量 patch + 快照回退 | `windowProps` |
|
|
65
|
+
| 🧠 ReAct harness | 可插拔中间件(8 钩子),自研不引 LangGraph | `middleware` |
|
|
66
|
+
| 📋 规划/技能/记忆 | `write_todos` / `define_skill` / AGENTS.md 指令 | `capabilities.*` |
|
|
67
|
+
| 🗄 虚拟工作区 | 内存文件系统,大结果外存不撑爆上下文 | `capabilities.vfs` |
|
|
68
|
+
| ↩️ 回退 | per-path 快照(修小错)+ 会话 checkpoint(回大错) | `checkpoint` |
|
|
69
|
+
| ✋ 人工确认 | 写前弹框 + AI 主动征询(不确定/多方案/高风险) | `approval` |
|
|
70
|
+
| ✅ 自检自纠 | 返回前 check,不通过 feedback 回灌重试 | `capabilities.verify` |
|
|
71
|
+
| 🤖 子 agent | 委派子任务,过程不占主上下文 | `subagent` |
|
|
72
|
+
| 🔌 MCP | 连远程 MCP server 动态注入工具 | `mcp` |
|
|
73
|
+
| 📦 上下文压缩 | 4 层自适应压缩,预设档位 + LLM 摘要 | `contextPreset` |
|
|
74
|
+
| 💾 持久化 | IndexedDB 多会话 + 配额淘汰 + 切换 | `storage` |
|
|
75
|
+
|
|
76
|
+
能力默认开(`verify`/`approval`/`checkpoint` 默认关;**主动征询 `humanConfirm` 默认开**——AI 遇不确定/多方案主动问你、不猜测),可经 `capabilities` 关掉无用的省 token。
|
|
77
|
+
|
|
78
|
+
## Agent 接入速查(给 AI agent 读)
|
|
79
|
+
|
|
80
|
+
> 本节是给 AI agent 的密集接入参考:导出清单 / 选项表 / 扩展点 / 内置工具 / 文件结构。深挖见 `doc/` 与 `CLAUDE.md`。
|
|
81
|
+
|
|
82
|
+
### 导出(`import { ... } from 'page-agent-sdk'`)
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// 入口与工具构造
|
|
86
|
+
createChatSdk, defineTool, defineSkill, presets, z
|
|
87
|
+
// harness 与中间件(自定义编排)
|
|
88
|
+
createAgent, createSubagentMiddleware, createSubagentsMiddleware,
|
|
89
|
+
createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
|
|
90
|
+
createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
|
|
91
|
+
createUsageHintsMiddleware, createWindowOps, createVfs, connectMcp
|
|
92
|
+
// 上下文/模型
|
|
93
|
+
resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
|
|
94
|
+
// 存储
|
|
95
|
+
createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
|
|
96
|
+
// UI(headless 自建 UI 复用)
|
|
97
|
+
ChatDialog, MessageContent, CodePreview, useChat
|
|
98
|
+
// 类型(略):ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, WindowPropSpec, AgentMessage, StreamEvent …
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `createChatSdk` 选项速查
|
|
102
|
+
|
|
103
|
+
| 分类 | 选项 | 类型 / 默认 | 说明 |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| **基础** | `container` | `string \| HTMLElement` | 挂载点(`ui:true` 必传) |
|
|
106
|
+
| | `ui` | `boolean \| 'default'` · 默认 `true` | `false` = headless(用 `agent.messages` 自建 UI) |
|
|
107
|
+
| | `llm` | `LLMConfig \| BaseChatModel` · **必传** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`;兼容 OpenAI 协议(默认 DeepSeek) |
|
|
108
|
+
| | `id` | `string` | 稳定 id(多 agent 隔离 + 持久化恢复;不传随机+warn) |
|
|
109
|
+
| | `systemPrompt` | `string` | Agent 身份(不硬编码业务,靠这注入) |
|
|
110
|
+
| **页面数据** | `windowProps` | `{path,description,schema}[]` | 注册可被工具读写的 window 属性 + zod schema 校验 |
|
|
111
|
+
| | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | 自定义工具 / 技能 / AGENTS.md 风格持久指令 |
|
|
112
|
+
| **能力开关** | `capabilities` | `{planning?,windowOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | 默认全开(`verify` 默认关);`false` 关掉省 token |
|
|
113
|
+
| | `permissions` | `PermissionRule[]` | scope 白名单(first-match-wins,默认不启用) |
|
|
114
|
+
| | `humanConfirm` | `boolean` · 默认 `true` | 主动征询(AI 不确定/多方案主动问你,不猜测) |
|
|
115
|
+
| | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝) |
|
|
116
|
+
| | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` · 默认关 | 会话级回滚(`auto` 默认 `true` 每轮存档) |
|
|
117
|
+
| | `verify` | `{check?,maxAttempts?,adversarial?}` | 需 `capabilities.verify:true`;`check` 省略用 `createWriteBackCheck` |
|
|
118
|
+
| **子 agent** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | 运行时自由委派(`spawn_agent`/`spawn_agents`) |
|
|
119
|
+
| | `subagents` | `SubagentConfig[]` | 预声明命名子 agent → 每个生成 `use_<id>` 委派工具 |
|
|
120
|
+
| **上下文** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · 默认 `auto` | 压缩预设档位 |
|
|
121
|
+
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩) |
|
|
122
|
+
| | `summaryLlm` | `BaseChatModel \| LLMConfig` | 摘要专用 LLM(不配用主 `llm`) |
|
|
123
|
+
| | `maxMemoryRounds` | `number` · 默认 `50` | 对话历史内存上限轮次(`0` 关裁剪) |
|
|
124
|
+
| | `vfs` | `{initialFiles?,maxBytes?}` · 默认 4MB | 内存工作区上限(超限 LRU 淘汰) |
|
|
125
|
+
| **持久化** | `storage` | `'indexed' \| 'session' \| 'local' \| 'memory' \| 配置 \| false` · 默认关 | 赋值开启;多 agent 靠 `id` 隔离 |
|
|
126
|
+
| | `session` | `{id?,autoResume?,title?}` | 会话控制 |
|
|
127
|
+
| | `shareContext` | `boolean` · 默认 `false` | 同 `id` 多实例共享同一 agent |
|
|
128
|
+
| **鲁棒/其他** | `maxRetries` / `maxParallelTools` / `maxToolRounds` | `number` · 2 / 1 / 10 | 模型重试 / 同轮工具并发 / 最大轮次 |
|
|
129
|
+
| | `mcp` | `McpServerConfig[]` | 远程 MCP server(http/sse/websocket) |
|
|
130
|
+
| | `middleware` | `Middleware[]` | 自定义中间件(拼到内置栈末尾) |
|
|
131
|
+
| | `streaming` / `title` / `placeholder` / `debug` | — | UI/调试 |
|
|
132
|
+
|
|
133
|
+
### 扩展点
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// ① 自定义工具
|
|
137
|
+
const myTool = defineTool({ name: 'do_x', description: '...', schema: z.object({...}), handler: (args) => 'result' })
|
|
138
|
+
createChatSdk({ tools: [myTool], /*...*/ })
|
|
139
|
+
|
|
140
|
+
// ② 自定义技能(渐进披露:用到才 load_skill 加载详情)
|
|
141
|
+
const mySkill = defineSkill({ name: 'style_guide', description: '品牌色规范', body: '主色 #1f4d3a…' })
|
|
142
|
+
createChatSdk({ skills: [mySkill], /*...*/ })
|
|
143
|
+
|
|
144
|
+
// ③ 自定义中间件(8 钩子:beforeAgent/wrapModelCall/beforeModel/afterModel/wrapToolCall/afterAgent/beforeReturn + augmentPrompt/compressInput/tools)
|
|
145
|
+
const mw: Middleware = { name: 'telemetry', afterModel: async (ctx, next) => { await next(ctx); console.log('round done') } }
|
|
146
|
+
createChatSdk({ middleware: [mw], /*...*/ })
|
|
147
|
+
|
|
148
|
+
// ④ 预声明子 agent(规划-反思-执行等固定角色)
|
|
149
|
+
createChatSdk({ subagents: [
|
|
150
|
+
{ id: 'planner', description: '创意规划', temperature: 0.9, systemPrompt: '…' },
|
|
151
|
+
{ id: 'reflector', description: '反思审查', temperature: 0.3, systemPrompt: '…' },
|
|
152
|
+
], /*...*/ })
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 内置工具(Agent 可调用)
|
|
156
|
+
|
|
157
|
+
- **window 操作**(`windowProps` 注册后):`list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop`(jsonPath 增量 patch)/ `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
|
|
158
|
+
- **window 查询**:`query_window_prop`(JSONPath)/ `search_window_prop`(模糊搜索)/ `eval_window_script`(沙箱脚本)
|
|
159
|
+
- **抓取**:`fetch_document`
|
|
160
|
+
- **vfs**:`vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
|
|
161
|
+
- **规划/技能**:`write_todos` / `define_skill` / `load_skill`
|
|
162
|
+
- **人工确认**:`request_human_confirmation`(主动征询,默认开)
|
|
163
|
+
- **子 agent**:`spawn_agent` / `spawn_agents` / `use_<id>`(预声明)
|
|
164
|
+
- **checkpoint**:`restore_last_checkpoint` / `list_checkpoints`
|
|
165
|
+
|
|
166
|
+
### 文件结构
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
src/core/
|
|
170
|
+
├── sdk/createChatSdk.ts # 命令式入口(组装 harness+工具+中间件)
|
|
171
|
+
│ sdk/defineTool.ts presets.ts contextPreset.ts
|
|
172
|
+
├── harness/ # 自研 ReAct harness(中间件驱动)
|
|
173
|
+
│ createAgent.ts middleware.ts state.ts
|
|
174
|
+
│ todos.ts skills.ts memory.ts summarization.ts retry.ts
|
|
175
|
+
│ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
|
|
176
|
+
│ permissions.ts usageHints.ts
|
|
177
|
+
├── tools/ # windowOps(注册表+增量编辑+快照)/ windowQuery / fetchDoc
|
|
178
|
+
├── backends/ # vfs(内存) / storage(IndexedDB+多后端+配额淘汰)
|
|
179
|
+
├── mcp/client.ts # MCP 远程工具接入
|
|
180
|
+
├── composables/ # useChat / useContextManager / useMarkdown
|
|
181
|
+
├── components/ # ChatDialog / MessageContent / CodePreview / DebugDrawer
|
|
182
|
+
└── types/index.ts index.ts # 类型 / 库唯一入口
|
|
183
|
+
examples/ # page-demo / nested-demo / human-confirm-demo / planner-demo / subagent-demo / mcp-demo
|
|
184
|
+
doc/ # usage-guide / architecture / context-management / architecture-files
|
|
185
|
+
CLAUDE.md # 架构要点 + 约定坑 + 编码规范(agent 必读)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 架构
|
|
189
|
+
|
|
190
|
+
```mermaid
|
|
191
|
+
flowchart TD
|
|
192
|
+
APP[集成方页面] -->|createChatSdk| SDK[createChatSdk<br/>组装 harness + 工具 + 中间件]
|
|
193
|
+
SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
|
|
194
|
+
CORE --> AGENT[createAgent<br/>ReAct 循环 + 中间件栈]
|
|
195
|
+
AGENT --> MW[中间件栈<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→用户]
|
|
196
|
+
AGENT --> TOOLS[工具集<br/>windowOps / fetchDoc / vfs / MCP / 用户]
|
|
197
|
+
TOOLS -->|零桥接| WIN[宿主页面 window<br/>直接读写注册属性]
|
|
198
|
+
AGENT --> LLM[LLM<br/>OpenAI 协议 / 任意 ChatModel]
|
|
199
|
+
SDK --> UI[ChatDialog UI<br/>Vue 打包进库 / 或 headless]
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI
|
|
203
|
+
- **provider 抽离**:`llm` 传任意 LangChain `BaseChatModel`,或 `LLMConfig`(内部构造 `ChatOpenAI`,兼容 OpenAI 协议,默认接 DeepSeek)
|
|
204
|
+
- **自研 harness**:不引 LangGraph/langchain 整包,规避浏览器打包阻塞
|
|
205
|
+
|
|
206
|
+
## 配置
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# .env(前缀 VITE_)
|
|
210
|
+
VITE_AI_API_KEY=sk-...
|
|
211
|
+
VITE_AI_BASE_URL=https://api.deepseek.com
|
|
212
|
+
VITE_AI_MODEL=deepseek-chat
|
|
213
|
+
VITE_AI_TEMPERATURE=0.3 # 结构化操作建议低温
|
|
214
|
+
# VITE_AI_MAX_TOKENS= # 不配则按模型自动取值
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
createChatSdk({
|
|
219
|
+
container: '#root',
|
|
220
|
+
llm: { apiKey, baseUrl, model },
|
|
221
|
+
id: 'my-agent', // 稳定 id(多 agent 隔离 + 持久化恢复)
|
|
222
|
+
systemPrompt: '...',
|
|
223
|
+
windowProps: [{ path, description, schema }],
|
|
224
|
+
storage: 'indexed', // 持久化(默认关)
|
|
225
|
+
streaming: true, ui: 'default',
|
|
226
|
+
capabilities: { verify: true }, // 能力开关
|
|
227
|
+
humanConfirm: true, // 主动征询(默认开;AI 不确定/多方案主动问你)
|
|
228
|
+
approval: { tools: ['set_window_prop','edit_window_prop'] }, // 被动确认白名单(默认关)
|
|
229
|
+
checkpoint: true,
|
|
230
|
+
contextPreset: 'auto', // auto/conservative/aggressive
|
|
231
|
+
summaryLlm: { ... }, // 摘要专用 LLM(不配用主 llm)
|
|
232
|
+
maxRetries: 2, maxParallelTools: 1,
|
|
233
|
+
subagent: { allowedTools: [...] },
|
|
234
|
+
middleware: [/* 自定义中间件 */],
|
|
235
|
+
}).mount()
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## 示例
|
|
239
|
+
|
|
240
|
+
`npm run dev` 后访问对应页面:
|
|
241
|
+
|
|
242
|
+
| 示例 | 入口 | 演示 |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| page-demo | `/` | 自举 demo:左 JSON 响应式页面 + 右对话框 |
|
|
245
|
+
| nested-demo | `/nested.html` | 嵌套区块树 + 人工确认 + checkpoint |
|
|
246
|
+
| human-confirm-demo | `/human-confirm.html` | AI 主动征询(多方案点选)+ 写前确认 |
|
|
247
|
+
| planner-demo | `/planner.html` | 规划-反思-执行(高温创意 planner + 低温 reflector) |
|
|
248
|
+
| subagent-demo | `/subagent.html` | 子 agent 并行编排 |
|
|
249
|
+
| mcp-demo | `/mcp.html` | MCP 远程工具(需 `npm run mcp:mock`) |
|
|
250
|
+
|
|
251
|
+
框架无关集成:`demo/plain.html`(importmap + esm.sh)。
|
|
252
|
+
|
|
253
|
+
## 文档
|
|
254
|
+
|
|
255
|
+
| 文档 | 内容 |
|
|
256
|
+
|---|---|
|
|
257
|
+
| [文档索引](./doc/README.md) | 各文档导航 + 其他信息源(规范/变更/自测) |
|
|
258
|
+
| [使用手册](./doc/usage-guide.md) | 安装 / 配置项 / 能力详解 / 自定义中间件 / FAQ |
|
|
259
|
+
| [功能架构](./doc/architecture.md) | 分层 / 控制流 / window 操作安全流 |
|
|
260
|
+
| [上下文与压缩](./doc/context-management.md) | 上下文组成 / 4 层压缩 / 流程图 |
|
|
261
|
+
| [文件全览](./doc/architecture-files.md) | 逐文件职责 / 依赖 / 数据流 |
|
|
262
|
+
| [CLAUDE.md](./CLAUDE.md) | **agent 必读** · 架构要点 / 约定坑 / 编码规范 |
|
|
263
|
+
|
|
264
|
+
## 自测
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
npm test # 341 项断言,不依赖 LLM
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## 开发
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npm install
|
|
274
|
+
npm run dev # 端口 3000(被占则 3001)
|
|
275
|
+
npm run build # ESM + UMD + IIFE + CSS
|
|
276
|
+
npm test
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 与 Deep Agents 的关系
|
|
280
|
+
|
|
281
|
+
借鉴 [Deep Agents](https://github.com/langchain-ai/deepagents) 的 harness 思路(ReAct + 中间件 + planning + skills + memory + context 管理),但自研实现:不引 LangGraph/langchain 整包;面向浏览器端(持久化用 IndexedDB 而非服务端 DB);上下文用输入压缩 + 内存裁剪 + 大结果 offload,而非每步 checkpointer 存档。详见 [上下文与压缩 - 与 Deep Agents 的差异](./doc/context-management.md#七与-deep-agents-的差异)。
|
|
282
|
+
|
|
283
|
+
## License
|
|
284
|
+
|
|
285
|
+
[ISC](./LICENSE)
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.code-preview-overlay[data-v-1e52dc9d]{z-index:9999;background:#00000080;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.code-preview-modal[data-v-1e52dc9d]{background:#fff;border-radius:12px;flex-direction:column;width:90%;max-width:900px;height:80vh;display:flex;overflow:hidden;box-shadow:0 20px 60px #0000004d}.preview-header[data-v-1e52dc9d]{color:#fff;background:#1f2937;align-items:center;gap:12px;padding:10px 16px;display:flex}.preview-title[data-v-1e52dc9d]{font-size:14px;font-weight:600}.preview-tabs[data-v-1e52dc9d]{gap:4px;margin-left:auto;display:flex}.preview-tabs button[data-v-1e52dc9d]{color:#fff;cursor:pointer;background:#ffffff1a;border:none;border-radius:6px;padding:4px 12px;font-size:13px}.preview-tabs button.active[data-v-1e52dc9d]{background:#667eea}.preview-tabs button[data-v-1e52dc9d]:disabled{opacity:.4;cursor:not-allowed}.preview-actions[data-v-1e52dc9d]{gap:4px;display:flex}.icon-btn[data-v-1e52dc9d]{color:#fff;cursor:pointer;background:#ffffff1a;border:none;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;font-size:14px;display:flex}.icon-btn[data-v-1e52dc9d]:hover{background:#ffffff40}.preview-body[data-v-1e52dc9d]{background:#f9fafb;flex:1;overflow:hidden}.preview-iframe[data-v-1e52dc9d]{background:#fff;border:none;width:100%;height:100%}.preview-source[data-v-1e52dc9d]{color:#e5e7eb;white-space:pre-wrap;word-break:break-word;background:#1f2937;height:100%;margin:0;padding:16px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px;line-height:1.5;overflow:auto}.message-md{word-break:break-word;font-size:14px;line-height:1.6}.message-md p{margin:0 0 8px}.message-md p:last-child{margin-bottom:0}.message-md ul,.message-md ol{margin:6px 0;padding-left:20px}.message-md li{margin:2px 0}.message-md h1,.message-md h2,.message-md h3{margin:10px 0 6px;font-weight:600}.message-md h1{font-size:18px}.message-md h2{font-size:16px}.message-md h3{font-size:15px}.message-md a{color:#667eea;text-decoration:underline}.message-md code:not(.hljs){color:#4338ca;background:#667eea1a;border-radius:4px;padding:1px 5px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px}.message-md .code-block{background:#1f2937;border-radius:8px;margin:10px 0;padding:0;position:relative;overflow:hidden}.message-md .code-block code{color:#e5e7eb;background:0 0;padding:12px 14px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px;line-height:1.5;display:block;overflow-x:auto}.message-md .code-toolbar{background:#00000040;border-bottom:1px solid #ffffff14;align-items:center;gap:8px;padding:6px 12px;display:flex}.message-md .code-lang{color:#9ca3af;text-transform:lowercase;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.message-md .code-action-btn{color:#e5e7eb;cursor:pointer;background:#ffffff1a;border:none;border-radius:4px;margin-left:auto;padding:3px 10px;font-size:12px;transition:background .2s}.message-md .code-action-btn:hover{background:#fff3}.message-md .code-action-btn.preview-btn{color:#fff;background:#667eea;margin-left:4px}.message-md .code-action-btn.preview-btn:hover{background:#5568d3}.message-md .hljs{color:#e5e7eb}.message-md .hljs-keyword{color:#c084fc}.message-md .hljs-string{color:#86efac}.message-md .hljs-comment{color:#6b7280;font-style:italic}.message-md .hljs-number{color:#fca5a5}.message-md .hljs-function .hljs-title,.message-md .hljs-title{color:#93c5fd}.message-md .hljs-tag{color:#fca5a5}.message-md .hljs-attr{color:#fcd34d}.message-md .hljs-built_in{color:#67e8f9}.debug-drawer[data-v-1bf2e689]{z-index:9000;pointer-events:none;position:fixed;inset:0}.drawer-mask[data-v-1bf2e689]{pointer-events:auto;background:#00000040;position:absolute;inset:0}.drawer-panel[data-v-1bf2e689]{--cs-primary:#1f4d3a;--cs-primary-rgb:31, 77, 58;pointer-events:auto;z-index:2;background:#fff;flex-direction:column;width:520px;max-width:90vw;display:flex;position:absolute;top:0;bottom:0;right:0;box-shadow:-8px 0 32px #00000026}.drawer-mask[data-v-1bf2e689]{z-index:1}.drawer-header[data-v-1bf2e689]{color:#fff;background:linear-gradient(135deg,#1f2937,#111827);justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.drawer-title[data-v-1bf2e689]{font-size:15px;font-weight:600}.tab-group[data-v-1bf2e689]{gap:4px;display:flex}.tab-btn[data-v-1bf2e689]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;padding:4px 12px;font-size:13px;transition:background .2s}.tab-btn[data-v-1bf2e689]:hover{background:#ffffff38}.tab-btn.active[data-v-1bf2e689]{background:#ffffff73;font-weight:600}.info-body[data-v-1bf2e689]{padding:4px 0}.info-section[data-v-1bf2e689]{margin-bottom:14px}.info-title[data-v-1bf2e689]{color:#2d5a47;border-bottom:1px solid #f3f4f6;margin-bottom:6px;padding-bottom:4px;font-size:12px;font-weight:600}.info-item[data-v-1bf2e689]{background:#f9fafb;border-radius:6px;margin-bottom:4px;padding:6px 8px}.info-name[data-v-1bf2e689]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:12px;font-weight:600}.info-desc[data-v-1bf2e689]{color:#6b7280;margin-top:2px;font-size:11px;line-height:1.5}.info-desc.muted[data-v-1bf2e689]{color:#9ca3af}.src-tag[data-v-1bf2e689]{vertical-align:middle;border-radius:8px;margin-left:6px;padding:0 6px;font-size:10px;font-weight:600;display:inline-block}.src-tag.builtin[data-v-1bf2e689]{color:#6b7280;background:#f3f4f6}.src-tag.mcp[data-v-1bf2e689]{color:#7c3aed;background:#f3e8ff}.src-tag.user[data-v-1bf2e689]{color:#2563eb;background:#dbeafe}.info-todo[data-v-1bf2e689]{color:#374151;background:#f9fafb;border-radius:6px;align-items:center;gap:6px;margin-bottom:4px;padding:4px 8px;font-size:12px;display:flex}.todo-tag[data-v-1bf2e689]{color:#fff;border-radius:8px;flex-shrink:0;padding:1px 6px;font-size:10px}.info-pre[data-v-1bf2e689]{color:#4b5563;white-space:pre-wrap;word-break:break-word;background:#f9fafb;border-radius:6px;max-height:200px;margin:0;padding:8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;overflow-y:auto}.header-actions[data-v-1bf2e689]{gap:4px;display:flex}.hd-btn[data-v-1bf2e689]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;width:28px;height:28px}.hd-btn[data-v-1bf2e689]:hover{background:#ffffff40}.drawer-filters[data-v-1bf2e689]{background:#fafafa;border-bottom:1px solid #f3f4f6;flex-wrap:wrap;gap:6px;padding:10px 16px;display:flex}.filter-chip[data-v-1bf2e689]{color:#6b7280;cursor:pointer;background:#fff;border:1px solid #e5e7eb;border-radius:14px;align-items:center;gap:4px;padding:4px 10px;font-size:12px;transition:all .2s;display:inline-flex}.filter-chip[data-v-1bf2e689]:hover{border-color:var(--chip-color,var(--cs-primary))}.filter-chip.active[data-v-1bf2e689]{background:var(--chip-color,var(--cs-primary));border-color:var(--chip-color,var(--cs-primary));color:#fff}.chip-count[data-v-1bf2e689]{background:#00000014;border-radius:8px;padding:0 5px;font-size:11px}.filter-chip.active .chip-count[data-v-1bf2e689]{background:#ffffff40}.drawer-body[data-v-1bf2e689]{flex:1;padding:12px;overflow-y:auto}.empty[data-v-1bf2e689]{text-align:center;color:#9ca3af;padding:40px 20px;font-size:13px}.log-item[data-v-1bf2e689]{background:#fff;border:1px solid #e5e7eb;border-radius:8px;margin-bottom:10px;overflow:hidden}.log-head[data-v-1bf2e689]{background:#f9fafb;align-items:center;gap:8px;padding:8px 10px;display:flex}.log-type[data-v-1bf2e689]{color:#fff;white-space:nowrap;border-radius:4px;padding:2px 8px;font-size:11px;font-weight:600}.log-source[data-v-1bf2e689]{color:#7c3aed;white-space:nowrap;background:#f3e8ff;border-radius:4px;padding:2px 8px;font-size:10px;font-weight:600}.log-time[data-v-1bf2e689]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.log-body[data-v-1bf2e689]{padding:10px 12px}.log-footer[data-v-1bf2e689]{border-top:1px dashed #f3f4f6;gap:8px;padding:6px 12px;display:flex}.raw-toggle[data-v-1bf2e689]{color:var(--cs-primary);cursor:pointer;background:0 0;border:none;padding:2px 4px;font-size:11px}.raw-toggle[data-v-1bf2e689]:hover{text-decoration:underline}.log-raw[data-v-1bf2e689]{color:#e5e7eb;white-space:pre-wrap;word-break:break-word;background:#1f2937;border-top:1px solid #f3f4f6;max-height:280px;margin:0;padding:10px 12px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;line-height:1.5;overflow:auto}.kv-grid[data-v-1bf2e689]{grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px;display:grid}.kv[data-v-1bf2e689]{background:#f9fafb;border-radius:6px;flex-direction:column;padding:6px 8px;display:flex}.kv .k[data-v-1bf2e689]{color:#9ca3af;text-transform:uppercase;font-size:10px}.kv .v[data-v-1bf2e689]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px;font-weight:600}.section-label[data-v-1bf2e689]{color:#6b7280;margin:10px 0 4px;font-size:11px;font-weight:600}.chip-row[data-v-1bf2e689]{flex-wrap:wrap;gap:4px;display:flex}.tool-chip[data-v-1bf2e689]{color:#2d5a47;background:#ecf5ef;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.msg-list[data-v-1bf2e689]{flex-direction:column;gap:4px;display:flex}.msg-row[data-v-1bf2e689]{background:#f9fafb;border-radius:6px;align-items:flex-start;gap:6px;padding:5px 8px;display:flex}.msg-role[data-v-1bf2e689]{color:#fff;border-radius:3px;flex-shrink:0;margin-top:1px;padding:2px 6px;font-size:9px;font-weight:700}.msg-text[data-v-1bf2e689]{color:#374151;white-space:pre-wrap;word-break:break-word;flex:1;font-size:12px;line-height:1.5}.msg-tool-hint[data-v-1bf2e689]{color:#7c3aed;flex-shrink:0;font-size:10px}.badge-row[data-v-1bf2e689]{flex-wrap:wrap;gap:6px;margin-bottom:8px;display:flex}.badge[data-v-1bf2e689]{color:#2d5a47;background:#dbeee4;border-radius:10px;padding:2px 8px;font-size:11px;font-weight:600}.badge.muted[data-v-1bf2e689]{color:#6b7280;background:#f3f4f6}.badge.warn[data-v-1bf2e689]{color:#92400e;background:#fef3c7}.resp-content[data-v-1bf2e689]{color:#1f2937;white-space:pre-wrap;word-break:break-word;background:#fffbeb;border-left:3px solid #d97706;border-radius:4px;margin-bottom:8px;padding:6px 10px;font-size:12px}.tc-list[data-v-1bf2e689]{flex-direction:column;gap:6px;display:flex}.tc-card[data-v-1bf2e689]{border:1px solid #e5e7eb;border-radius:6px;overflow:hidden}.tc-card.inline[data-v-1bf2e689]{margin-top:4px}.tc-name[data-v-1bf2e689]{color:#2d5a47;background:#ecf5ef;padding:5px 8px;font-size:12px;font-weight:600}.tc-args[data-v-1bf2e689]{color:#e5e7eb;white-space:pre-wrap;word-break:break-word;background:#1f2937;max-height:200px;margin:0;padding:8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;line-height:1.5;overflow-y:auto}.usage-row[data-v-1bf2e689]{flex-wrap:wrap;gap:6px;margin-top:8px;display:flex}.usage[data-v-1bf2e689]{color:#047857;background:#ecfdf5;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.err-box[data-v-1bf2e689]{color:#991b1b;white-space:pre-wrap;word-break:break-word;background:#fef2f2;border:1px solid #fecaca;border-radius:6px;padding:8px 10px;font-size:12px}.msg-detail[data-v-1bf2e689]{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.tc-inline[data-v-1bf2e689]{background:#f0f7f3;border:1px solid #c3dcd0;border-radius:4px;align-items:baseline;gap:4px;padding:2px 6px;font-size:11px;display:flex}.tc-inline-name[data-v-1bf2e689]{color:#2d5a47;white-space:nowrap;font-weight:600}.tc-inline-args[data-v-1bf2e689]{color:#16402f;word-break:break-all;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.tc-id[data-v-1bf2e689]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.view-toggle[data-v-1bf2e689]{color:#2d5a47;cursor:pointer;background:#ecf5ef;border:1px solid #b8d4c5;border-radius:10px;margin-left:auto;padding:2px 8px;font-size:11px}.view-toggle[data-v-1bf2e689]:hover{background:#dbeee4}.drawer-enter-active[data-v-1bf2e689],.drawer-leave-active[data-v-1bf2e689]{transition:opacity .25s}.drawer-enter-active .drawer-panel[data-v-1bf2e689],.drawer-leave-active .drawer-panel[data-v-1bf2e689]{transition:transform .25s}.drawer-enter-from[data-v-1bf2e689],.drawer-leave-to[data-v-1bf2e689]{opacity:0}.drawer-enter-from .drawer-panel[data-v-1bf2e689],.drawer-leave-to .drawer-panel[data-v-1bf2e689]{transform:translate(100%)}.flow-section[data-v-1bf2e689]{margin-bottom:14px}.flow-section-title[data-v-1bf2e689]{color:#6b7280;margin-bottom:6px;padding-left:2px;font-size:11px;font-weight:600}.flow-round[data-v-1bf2e689]{border:1px solid #e5e7eb;border-radius:8px;margin-bottom:12px;overflow:hidden}.flow-round-head[data-v-1bf2e689]{color:#fff;background:var(--cs-primary);padding:5px 10px;font-size:12px;font-weight:600}.flow-round-body[data-v-1bf2e689]{flex-direction:column;gap:3px;padding:6px;display:flex}.flow-node[data-v-1bf2e689]{border-left:3px solid var(--cs-primary);background:#f9fafb;border-radius:6px;align-items:center;gap:6px;padding:5px 8px;font-size:12px;display:flex}.flow-node.llm_request[data-v-1bf2e689]{border-left-color:#059669}.flow-node.llm_response[data-v-1bf2e689]{border-left-color:#d97706}.flow-node.tool_call[data-v-1bf2e689]{border-left-color:#7c3aed}.flow-node.tool_result[data-v-1bf2e689]{border-left-color:#2563eb}.flow-node.error[data-v-1bf2e689]{background:#fef2f2;border-left-color:#dc2626}.flow-node.middleware[data-v-1bf2e689]{border-left-color:#0891b2}.flow-ico[data-v-1bf2e689]{flex-shrink:0;font-size:13px}.flow-label[data-v-1bf2e689]{color:#374151;white-space:nowrap;flex-shrink:0;font-weight:600}.flow-detail[data-v-1bf2e689]{color:#6b7280;text-overflow:ellipsis;white-space:nowrap;flex:1;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px;overflow:hidden}.flow-time[data-v-1bf2e689]{color:#9ca3af;flex-shrink:0;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.chat-dialog[data-v-d3e4f57d]{--cs-primary:#1f4d3a;--cs-primary-rgb:31, 77, 58;--cs-bg:#fff;--cs-bubble-ai:#f3f4f6;--cs-radius:12px;border-radius:var(--cs-radius);background:var(--cs-bg);flex-direction:column;width:100%;height:100%;transition:all .3s;display:flex;overflow:hidden;box-shadow:0 8px 32px #0000001f,0 2px 8px #00000014}.chat-dialog.collapsed[data-v-d3e4f57d]{height:52px}.chat-header[data-v-d3e4f57d]{background:var(--cs-primary);color:#fff;cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.header-left[data-v-d3e4f57d]{align-items:center;gap:8px;display:flex}.header-icon[data-v-d3e4f57d]{font-size:20px}.header-title[data-v-d3e4f57d]{font-size:15px;font-weight:600}.status-dot[data-v-d3e4f57d]{background:#4ade80;border-radius:50%;width:8px;height:8px}.status-dot.pulse[data-v-d3e4f57d]{animation:1.5s infinite pulse-d3e4f57d}@keyframes pulse-d3e4f57d{0%,to{opacity:1}50%{opacity:.4}}.header-actions[data-v-d3e4f57d]{gap:4px;display:flex}.action-btn[data-v-d3e4f57d]{color:#fff;cursor:pointer;background:#ffffff26;border:none;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;transition:background .2s;display:flex}.action-btn[data-v-d3e4f57d]:hover:not(:disabled){background:#ffffff4d}.action-btn[data-v-d3e4f57d]:disabled{opacity:.4;cursor:not-allowed}.action-btn.debug-btn[data-v-d3e4f57d]{position:relative}.action-btn.debug-btn.active[data-v-d3e4f57d]{background:#ffffff73}.debug-badge[data-v-d3e4f57d]{color:#fff;background:#ef4444;border-radius:8px;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:600;line-height:16px;position:absolute;top:-2px;right:-2px}.chat-body[data-v-d3e4f57d]{scroll-behavior:smooth;flex:1;min-height:0;padding:16px;overflow-y:auto}.empty-state[data-v-d3e4f57d]{color:#9ca3af;flex-direction:column;justify-content:center;align-items:center;height:200px;display:flex}.empty-icon[data-v-d3e4f57d]{margin-bottom:12px;font-size:48px}.empty-state p[data-v-d3e4f57d]{font-size:14px}.message-row[data-v-d3e4f57d]{align-items:flex-start;gap:10px;margin-bottom:16px;display:flex}.message-row.user[data-v-d3e4f57d]{flex-direction:row-reverse}.message-avatar[data-v-d3e4f57d]{background:#f3f4f6;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;font-size:16px;display:flex}.message-row.user .message-avatar[data-v-d3e4f57d]{background:#ecf5ef}.message-content[data-v-d3e4f57d]{max-width:75%}.message-bubble[data-v-d3e4f57d]{word-break:break-word;white-space:pre-wrap;border-radius:12px;padding:10px 14px;font-size:14px;line-height:1.5}.message-row.assistant .message-bubble[data-v-d3e4f57d]{color:#1f2937;white-space:normal;background:#f3f4f6;border-bottom-left-radius:4px}.message-row.user .message-bubble[data-v-d3e4f57d]{background:var(--cs-primary);color:#fff;border-bottom-right-radius:4px}.message-row.user .message-content[data-v-d3e4f57d]{flex-direction:column;align-items:flex-end;display:flex}.message-time[data-v-d3e4f57d]{color:#9ca3af;margin-top:4px;padding:0 4px;font-size:11px}.typing[data-v-d3e4f57d]{gap:4px;padding:12px 16px;display:flex}.typing .dot[data-v-d3e4f57d]{background:#9ca3af;border-radius:50%;width:8px;height:8px;animation:1.4s ease-in-out infinite bounce-d3e4f57d}.typing .dot[data-v-d3e4f57d]:nth-child(2){animation-delay:.2s}.typing .dot[data-v-d3e4f57d]:nth-child(3){animation-delay:.4s}@keyframes bounce-d3e4f57d{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.typing-text[data-v-d3e4f57d]{color:#9ca3af;font-size:13px}.reasoning-block[data-v-d3e4f57d]{background:#f0f7f3;border:1px dashed #b8d4c5;border-radius:8px;margin-bottom:6px;overflow:hidden}.reasoning-header[data-v-d3e4f57d]{cursor:pointer;-webkit-user-select:none;user-select:none;color:#2d5a47;align-items:center;gap:6px;padding:5px 10px;font-size:12px;display:flex}.reasoning-icon[data-v-d3e4f57d]{font-size:13px}.reasoning-title[data-v-d3e4f57d]{font-weight:600}.reasoning-toggle[data-v-d3e4f57d]{margin-left:auto}.reasoning-body[data-v-d3e4f57d]{color:#16402f;white-space:pre-wrap;word-break:break-word;border-top:1px dashed #b8d4c5;max-height:240px;padding:8px 10px;font-size:12px;line-height:1.6;overflow-y:auto}.steps-block[data-v-d3e4f57d]{flex-direction:column;gap:4px;margin-bottom:6px;display:flex}.step-item[data-v-d3e4f57d]{color:#0e7490;background:#ecfeff;border:1px solid #a5f3fc;border-radius:10px;flex-direction:column;align-self:flex-start;align-items:flex-start;gap:3px;max-width:100%;padding:2px 8px;font-size:11px;display:flex}.step-head[data-v-d3e4f57d]{align-items:center;gap:5px;display:inline-flex}.step-icon[data-v-d3e4f57d]{font-size:11px}.step-name[data-v-d3e4f57d]{font-family:SF Mono,Monaco,Consolas,monospace}.step-count[data-v-d3e4f57d]{color:#0891b2;font-size:10px;font-weight:600}.step-status.running[data-v-d3e4f57d]{color:#0891b2}.step-children[data-v-d3e4f57d]{background:#faf5ff;border-left:2px solid #c4b5fd;border-radius:0 8px 8px 0;flex-direction:column;gap:3px;margin-top:4px;padding:4px 8px 4px 10px;display:flex}.step-children-label[data-v-d3e4f57d]{color:#7c3aed;letter-spacing:.3px;font-size:10px;font-weight:600}.step-child[data-v-d3e4f57d]{color:#6d28d9;background:#ede9fe;border:1px solid #ddd6fe;border-radius:8px;align-items:center;gap:5px;padding:1px 7px;font-size:10px;display:inline-flex}.step-child .step-name[data-v-d3e4f57d]{color:#6d28d9}.step-child .step-status.running[data-v-d3e4f57d]{color:#8b5cf6}.stream-cursor[data-v-d3e4f57d],.typing-cursor[data-v-d3e4f57d]{vertical-align:text-bottom;background:var(--cs-primary);width:7px;height:14px;margin-left:2px;animation:1s steps(2,end) infinite blink-d3e4f57d;display:inline-block}@keyframes blink-d3e4f57d{0%,50%{opacity:1}51%,to{opacity:0}}.error-bar[data-v-d3e4f57d]{color:#dc2626;background:#fef2f2;border-radius:8px;align-items:flex-start;gap:10px;margin-top:8px;padding:8px 12px;font-size:13px;display:flex}.error-text[data-v-d3e4f57d]{word-break:break-word;overflow-wrap:anywhere;white-space:pre-wrap;flex:1;min-width:0;max-height:120px;line-height:1.5;overflow-y:auto}.error-bar .retry-btn[data-v-d3e4f57d],.error-bar .undo-btn[data-v-d3e4f57d]{flex-shrink:0;margin-top:1px}.retry-btn[data-v-d3e4f57d]{color:#fff;cursor:pointer;background:#dc2626;border:none;border-radius:6px;flex-shrink:0;padding:3px 12px;font-size:12px;font-weight:600;transition:background .2s}.retry-btn[data-v-d3e4f57d]:hover{background:#b91c1c}.chat-footer[data-v-d3e4f57d]{background:#fafafa;border-top:1px solid #f3f4f6;align-items:flex-end;gap:8px;padding:12px 16px;display:flex}.chat-input[data-v-d3e4f57d]{resize:none;border:1px solid #e5e7eb;border-radius:8px;outline:none;flex:1;max-height:100px;padding:10px 12px;font-family:inherit;font-size:14px;line-height:1.4;transition:border-color .2s;overflow-y:auto}.chat-input[data-v-d3e4f57d]:focus{border-color:var(--cs-primary);box-shadow:0 0 0 2px rgba(var(--cs-primary-rgb), .1)}.send-btn[data-v-d3e4f57d]{background:var(--cs-primary);color:#fff;cursor:pointer;border:none;border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;width:38px;height:38px;transition:opacity .2s,transform .1s;display:flex}.send-btn[data-v-d3e4f57d]:hover:not(:disabled){opacity:.9;transform:scale(1.05)}.send-btn[data-v-d3e4f57d]:active:not(:disabled){transform:scale(.95)}.send-btn[data-v-d3e4f57d]:disabled{opacity:.4;cursor:not-allowed}.send-btn.stop-btn[data-v-d3e4f57d]{background:#9ca3af}.send-btn.stop-btn[data-v-d3e4f57d]:hover:not(:disabled){background:#6b7280;transform:none}.cap-badge[data-v-d3e4f57d]{color:#6b7280;white-space:nowrap;-webkit-user-select:none;user-select:none;background:#f9fafb;border:1px solid #e5e7eb;border-radius:14px;flex-shrink:0;align-self:center;padding:4px 10px;font-size:11px}.msg-actions[data-v-d3e4f57d]{opacity:0;gap:6px;margin-top:4px;transition:opacity .2s;display:flex}.message-row.assistant:hover .msg-actions[data-v-d3e4f57d]{opacity:1}.msg-action-btn[data-v-d3e4f57d]{color:#6b7280;cursor:pointer;background:#fff;border:1px solid #e5e7eb;border-radius:6px;padding:2px 8px;font-size:11px;transition:all .2s}.msg-action-btn[data-v-d3e4f57d]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.undo-btn[data-v-d3e4f57d]{color:#92400e;cursor:pointer;background:#fffbeb;border:1px solid #f59e0b;border-radius:6px;margin-left:6px;padding:2px 10px;font-size:11px;transition:all .2s}.undo-btn[data-v-d3e4f57d]:hover{background:#fde68a}.undo-foot-btn[data-v-d3e4f57d]{color:#6b7280;cursor:pointer;background:#f9fafb;border:1px solid #e5e7eb;border-radius:14px;flex-shrink:0;align-self:center;padding:4px 10px;font-size:11px;transition:all .2s}.undo-foot-btn[data-v-d3e4f57d]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.approval-bar[data-v-d3e4f57d]{background:#fffbeb;border:1px solid #f59e0b;border-radius:10px;margin:8px 12px;padding:10px 12px}.approval-head[data-v-d3e4f57d]{color:#92400e;align-items:center;gap:6px;font-size:13px;display:flex}.approval-icon[data-v-d3e4f57d]{font-size:15px}.approval-title code[data-v-d3e4f57d]{color:#78350f;background:#fef3c7;border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.approval-toggle[data-v-d3e4f57d]{color:#92400e;cursor:pointer;background:0 0;border:none;border-radius:4px;margin-left:auto;padding:2px 8px;font-size:12px}.approval-toggle[data-v-d3e4f57d]:hover{background:#fef3c7}.approval-args[data-v-d3e4f57d]{color:#57534e;white-space:pre-wrap;word-break:break-all;background:#fff;border:1px solid #fde68a;border-radius:6px;max-height:140px;margin:8px 0;padding:8px;font-size:12px;overflow:auto}.approval-actions[data-v-d3e4f57d]{justify-content:flex-end;gap:8px;display:flex}.approval-actions button[data-v-d3e4f57d]{cursor:pointer;border:none;border-radius:6px;padding:5px 16px;font-size:13px;transition:opacity .2s}.approval-deny[data-v-d3e4f57d]{color:#6b7280;background:#f3f4f6;border:1px solid #e5e7eb}.approval-deny[data-v-d3e4f57d]:hover{color:#374151;background:#e5e7eb}.approval-allow[data-v-d3e4f57d]{background:var(--cs-primary);color:#fff}.approval-allow[data-v-d3e4f57d]:hover{opacity:.9}.approval-question[data-v-d3e4f57d]{color:#57534e;white-space:pre-wrap;background:#fff;border:1px solid #fde68a;border-radius:6px;margin:8px 0;padding:8px 10px;font-size:13px;line-height:1.5}.approval-context[data-v-d3e4f57d]{color:#92400e;margin:4px 0 8px;font-size:12px;line-height:1.5}.approval-recommend[data-v-d3e4f57d]{color:#1f4d3a;margin:4px 0 8px;font-size:12px}.approval-opt[data-v-d3e4f57d]{border:1px solid var(--cs-primary);color:var(--cs-primary);cursor:pointer;background:#fff;border-radius:6px;padding:5px 14px;font-size:13px;transition:all .2s}.approval-opt[data-v-d3e4f57d]:hover{background:var(--cs-primary);color:#fff}
|
|
2
|
+
/*$vite$:1*/
|