page-agent-sdk 1.4.2 → 2.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/README.md CHANGED
@@ -24,9 +24,9 @@ At its core, it gives the AI a **standardized, safe JSON-operation channel**. AI
24
24
 
25
25
  | Constraint | Mechanism | Effect |
26
26
  |---|---|---|
27
- | **Scope control** | Property registry (`windowProps`) — only declared paths are writable | AI touching undeclared fields → rejected |
27
+ | **Scope control** | Property registry (`dataSlots`) — only declared paths are writable | AI touching undeclared fields → rejected |
28
28
  | **Validity check** | zod schema — `set`/`edit` validated against schema | Invalid type/enum/structure → structured error, no write |
29
- | **Incremental op** | `edit_window_prop` patches by `jsonPath` (set/remove/merge/append) | Avoid re-sending the whole large JSON; precise local edits |
29
+ | **Incremental op** | `edit_data_slot` patches by `jsonPath` (set/remove/merge/append) | Avoid re-sending the whole large JSON; precise local edits |
30
30
  | **Rollbackable** | per-path snapshots (auto-stacked) + session checkpoint | Bad edit → one-click restore to the last good state |
31
31
  | **Optimistic lock** | `expectedHash` on `set`/`edit`/`delete` + conflict human-in-the-loop | Concurrent external edits detected → suspend, user picks keep/overwrite/restore |
32
32
 
@@ -64,16 +64,16 @@ createChatSdk({
64
64
  container: '#chat',
65
65
  llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
66
66
  systemPrompt: 'You are a page-builder assistant; read/write window.page via tools.',
67
- windowProps: [
67
+ dataSlots: [
68
68
  { path: 'page.title', description: 'Page title', schema: z.string() },
69
69
  { path: 'page.theme', description: 'Theme', schema: z.enum(['light', 'dark']) },
70
70
  ],
71
- approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // confirm writes
71
+ approval: { tools: ['set_data_slot', 'edit_data_slot'] }, // confirm writes
72
72
  checkpoint: true, // one-click rollback on mistake
73
73
  }).mount()
74
74
  ```
75
75
 
76
- User says "title → 'Summer New', theme → dark" → AI calls `edit_window_prop` (incremental) → schema validation → pre-write confirm → reactive refresh. Said wrong? Click "↩ Undo".
76
+ User says "title → 'Summer New', theme → dark" → AI calls `edit_data_slot` (incremental) → schema validation → pre-write confirm → reactive refresh. Said wrong? Click "↩ Undo".
77
77
 
78
78
  CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` → `ChatSdk.createChatSdk({...})`.
79
79
 
@@ -81,7 +81,7 @@ CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` →
81
81
 
82
82
  | Capability | Description | Option |
83
83
  |---|---|---|
84
- | 🛠 window ops | Read/write registered props, schema validation + incremental patch + snapshot rollback | `windowProps` |
84
+ | 🛠 window ops | Read/write registered props, schema validation + incremental patch + snapshot rollback | `dataSlots` |
85
85
  | 🧠 ReAct harness | Pluggable middleware (8 hooks), in-house (no LangGraph) | `middleware` |
86
86
  | 📋 planning/skills/memory | `write_todos` / `define_skill` / AGENTS.md directives | `capabilities.*` |
87
87
  | 🗄 virtual workspace | In-memory file system; large results offloaded (won't blow context) | `capabilities.vfs` |
@@ -91,7 +91,7 @@ CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` →
91
91
  | 🤖 subagents | Delegate subtasks; process stays out of main context | `subagent` |
92
92
  | 🔌 MCP | Connect remote MCP servers, inject tools dynamically | `mcp` |
93
93
  | 📦 context compression | 4-layer adaptive compression, presets + LLM summary | `contextPreset` |
94
- | 🛡️ compression-safe | Live windowProps snapshot + preserved tool results in summary; write returns hint available paths; `systemPromptHelpers.reliableWriteRules` | built-in |
94
+ | 🛡️ compression-safe | Live dataSlots snapshot + preserved tool results in summary; write returns hint available paths; `systemPromptHelpers.reliableWriteRules` | built-in |
95
95
  | 💾 persistence | IndexedDB multi-session + quota eviction + switch | `storage` |
96
96
 
97
97
  Capabilities default on (`verify`/`approval`/`checkpoint` default off; **proactive `humanConfirm` default on** — AI asks when uncertain/multi-plan instead of guessing). Turn off unneeded ones via `capabilities` to save tokens.
@@ -109,14 +109,14 @@ createChatSdk, defineTool, defineSkill, presets, z
109
109
  createAgent, createSubagentMiddleware, createSubagentsMiddleware,
110
110
  createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
111
111
  createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
112
- createUsageHintsMiddleware, createWindowOps, createVfs, connectMcp
112
+ createUsageHintsMiddleware, createDataSlotOps, createVfs, connectMcp
113
113
  // context & model
114
114
  resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
115
115
  // storage
116
116
  createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
117
117
  // UI (reuse when headless)
118
118
  ChatDialog, MessageContent, CodePreview, useChat
119
- // types (omitted): ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, WindowPropSpec, AgentMessage, StreamEvent …
119
+ // types (omitted): ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, DataSlotSpec, AgentMessage, StreamEvent …
120
120
  ```
121
121
 
122
122
  ### `createChatSdk` options cheat sheet
@@ -128,9 +128,9 @@ ChatDialog, MessageContent, CodePreview, useChat
128
128
  | | `llm` | `LLMConfig \| BaseChatModel` · **required** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`; OpenAI-compatible (default DeepSeek) |
129
129
  | | `id` | `string` | Stable id (multi-agent isolation + persistence resume; random+warn if omitted) |
130
130
  | | `systemPrompt` | `string` | Agent identity (no hardcoded business; inject via this). Optional — built-in default (page assistant + `reliableWriteRules`) used if omitted; passing your own fully overrides it |
131
- | **Page data** | `windowProps` | `{path,description,schema}[]` | Register window props readable/writable by tools + zod schema |
131
+ | **Page data** | `dataSlots` | `{path,description,schema}[]` | Register data slots readable/writable by tools + zod schema |
132
132
  | | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | Custom tools / skills / AGENTS.md-style directives |
133
- | **Capability toggles** | `capabilities` | `{planning?,windowOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | Default all on (`verify` default off); `false` to turn off |
133
+ | **Capability toggles** | `capabilities` | `{planning?,dataSlotOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | Default all on (`verify` default off); `false` to turn off |
134
134
  | | `permissions` | `PermissionRule[]` | Scope whitelist (first-match-wins, default off) |
135
135
  | | `humanConfirm` | `boolean` · default `true` | Proactive inquiry (AI asks when uncertain/multi-plan) |
136
136
  | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · default off | Passive confirm whitelist (pre-write allow/deny) |
@@ -139,7 +139,7 @@ ChatDialog, MessageContent, CodePreview, useChat
139
139
  | **Subagents** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | Runtime ad-hoc delegation (`spawn_agent`/`spawn_agents`) |
140
140
  | | `subagents` | `SubagentConfig[]` | Pre-declared named subagents → each generates `use_<id>` tool |
141
141
  | **Context** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · default `auto` | Compression preset |
142
- | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | Fine params (`false` disables compression). Includes `preserveLastToolResults` (default `['describe_window_prop','list_window_props']` — keep field descriptions in compressed summary) |
142
+ | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | Fine params (`false` disables compression). Includes `preserveLastToolResults` (default `['describe_data_slot','list_data_slots']` — keep field descriptions in compressed summary) |
143
143
  | | `summaryLlm` | `BaseChatModel \| LLMConfig` | Summary-dedicated LLM (defaults to main `llm`) |
144
144
  | | `maxMemoryRounds` | `number` · default `50` | Dialog history memory round cap (`0` disables trim) |
145
145
  | | `vfs` | `{initialFiles?,maxBytes?}` · default 4MB | In-memory workspace cap (LRU evict on overflow) |
@@ -175,8 +175,8 @@ createChatSdk({ subagents: [
175
175
 
176
176
  ### Built-in tools (Agent-callable)
177
177
 
178
- - **window ops** (after `windowProps` registered): `list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop` (jsonPath incremental patch) / `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
179
- - **window query**: `query_window_prop` (JSONPath) / `search_window_prop` (fuzzy) / `eval_window_script` (sandboxed)
178
+ - **window ops** (after `dataSlots` registered): `list_data_slots` / `describe_data_slot` / `get_data_slot` / `get_slot_paths` / `set_data_slot` / `edit_data_slot` (jsonPath incremental patch) / `delete_data_slot` / `snapshot_data_slot` / `list_data_snapshots` / `restore_data_snapshot`
179
+ - **window query**: `query_data_slot` (JSONPath) / `search_data_slot` (fuzzy) / `eval_script` (sandboxed)
180
180
  - **fetch**: `fetch_document`
181
181
  - **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
182
182
  - **planning/skills**: `write_todos` / `define_skill` / `load_skill`
@@ -195,7 +195,7 @@ src/core/
195
195
  │ todos.ts skills.ts memory.ts summarization.ts retry.ts
196
196
  │ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
197
197
  │ permissions.ts usageHints.ts
198
- ├── tools/ # windowOps (registry + incremental edit + snapshot) / windowQuery / fetchDoc
198
+ ├── tools/ # dataSlotOps (registry + incremental edit + snapshot) / dataSlotQuery / fetchDoc
199
199
  ├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
200
200
  ├── mcp/client.ts # remote MCP tool integration
201
201
  ├── composables/ # useChat / useContextManager / useMarkdown
@@ -230,8 +230,8 @@ createChatSdk({ subagents: [
230
230
 
231
231
  ### Built-in tools (Agent-callable)
232
232
 
233
- - **window ops** (after `windowProps` registered): `list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop` (jsonPath incremental patch) / `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
234
- - **window query**: `query_window_prop` (JSONPath) / `search_window_prop` (fuzzy) / `eval_window_script` (sandboxed)
233
+ - **window ops** (after `dataSlots` registered): `list_data_slots` / `describe_data_slot` / `get_data_slot` / `get_slot_paths` / `set_data_slot` / `edit_data_slot` (jsonPath incremental patch) / `delete_data_slot` / `snapshot_data_slot` / `list_data_snapshots` / `restore_data_snapshot`
234
+ - **window query**: `query_data_slot` (JSONPath) / `search_data_slot` (fuzzy) / `eval_script` (sandboxed)
235
235
  - **fetch**: `fetch_document`
236
236
  - **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
237
237
  - **planning/skills**: `write_todos` / `define_skill` / `load_skill`
@@ -250,7 +250,7 @@ src/core/
250
250
  │ todos.ts skills.ts memory.ts summarization.ts retry.ts
251
251
  │ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
252
252
  │ permissions.ts usageHints.ts
253
- ├── tools/ # windowOps (registry + incremental edit + snapshot) / windowQuery / fetchDoc
253
+ ├── tools/ # dataSlotOps (registry + incremental edit + snapshot) / dataSlotQuery / fetchDoc
254
254
  ├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
255
255
  ├── mcp/client.ts # remote MCP tool integration
256
256
  ├── composables/ # useChat / useContextManager / useMarkdown
@@ -267,7 +267,7 @@ A ready-to-use Agent Skill is bundled for integrators using Claude Code / Cursor
267
267
 
268
268
  | Skill | When it triggers |
269
269
  |---|---|
270
- | `page-agent-sdk-integrate` | Embedding the SDK — choose install method, declare `windowProps` + zod schemas, configure the LLM, mount, subscribe to events (`onEvent` / `sdk.hook`), run headless, troubleshoot common pitfalls |
270
+ | `page-agent-sdk-integrate` | Embedding the SDK — choose install method, declare `dataSlots` + zod schemas, configure the LLM, mount, subscribe to events (`onEvent` / `sdk.hook`), run headless, troubleshoot common pitfalls |
271
271
 
272
272
  **Install** (pick one):
273
273
 
@@ -293,13 +293,13 @@ flowchart TD
293
293
  SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
294
294
  CORE --> AGENT[createAgent<br/>ReAct loop + middleware stack]
295
295
  AGENT --> MW[Middleware stack<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→user]
296
- AGENT --> TOOLS[Tools<br/>windowOps / fetchDoc / vfs / MCP / user]
296
+ AGENT --> TOOLS[Tools<br/>dataSlotOps / fetchDoc / vfs / MCP / user]
297
297
  TOOLS -->|zero-bridge| WIN[Host page window<br/>read/write registered props directly]
298
298
  AGENT --> LLM[LLM<br/>OpenAI-compatible / any ChatModel]
299
299
  SDK --> UI[ChatDialog UI<br/>Vue bundled in / or headless]
300
300
  ```
301
301
 
302
- - **Framework-agnostic**: Vue bundled in the lib (not a peer); host can be React/vanilla. Also supports `ui:false` headless — and runs in **Node.js** as a backend Agent (custom tools / subagents / verify; disable `windowOps`+`fetch`, use `storage:'memory'`)
302
+ - **Framework-agnostic**: Vue bundled in the lib (not a peer); host can be React/vanilla. Also supports `ui:false` headless — and runs in **Node.js** as a backend Agent (custom tools / subagents / verify; disable `dataSlotOps`+`fetch`, use `storage:'memory'`)
303
303
  - **Provider-agnostic**: `llm` accepts any LangChain `BaseChatModel`, or `LLMConfig` (builds `ChatOpenAI` internally, OpenAI-compatible, default DeepSeek)
304
304
  - **In-house harness**: no LangGraph/langchain full bundle; avoids browser bundling blockers
305
305
 
@@ -320,20 +320,20 @@ createChatSdk({
320
320
  llm: { apiKey, baseUrl, model },
321
321
  id: 'my-agent', // stable id (multi-agent isolation + persistence resume)
322
322
  systemPrompt: '...',
323
- windowProps: [{ path, description, schema }],
323
+ dataSlots: [{ path, description, schema }],
324
324
  storage: 'indexed', // persistence (default off)
325
325
  streaming: true, ui: 'default',
326
326
  capabilities: { verify: true }, // capability toggles
327
327
  humanConfirm: true, // proactive inquiry (default on)
328
- approval: { tools: ['set_window_prop','edit_window_prop'] }, // passive confirm whitelist (default off)
328
+ approval: { tools: ['set_data_slot','edit_data_slot'] }, // passive confirm whitelist (default off)
329
329
  checkpoint: true,
330
330
  contextPreset: 'auto', // auto/conservative/aggressive
331
331
  summaryLlm: { ... }, // summary-dedicated LLM (defaults to main llm)
332
332
  maxRetries: 2, maxParallelTools: 1,
333
333
  subagent: { allowedTools: [...] },
334
334
  middleware: [/* custom middleware */],
335
- onEvent(e) { // SDK event callback: subscribe to common moments (window prop change / message update / tool call / error), replaces polling
336
- if (e.type === 'window_prop_change') refreshUI()
335
+ onEvent(e) { // SDK event callback: subscribe to common moments (data slot change / message update / tool call / error), replaces polling
336
+ if (e.type === 'data_slot_change') refreshUI()
337
337
  },
338
338
  }).mount()
339
339
  ```
@@ -346,7 +346,7 @@ After `npm run dev`, visit the corresponding page:
346
346
  |---|---|---|
347
347
  | page-demo | `/` | Self-bootstrapping demo: left JSON reactive page + right chat |
348
348
  | nested-demo | `/examples/nested-demo/` | Nested block tree + human confirm + checkpoint |
349
- | dynamic-demo | `/examples/dynamic-demo/` | Lazy-loaded components with dynamic schemas (`sdk.addWindowProp`/`removeWindowProp`) |
349
+ | dynamic-demo | `/examples/dynamic-demo/` | Lazy-loaded components with dynamic schemas (`sdk.addDataSlot`/`removeDataSlot`) |
350
350
  | human-confirm-demo | `/examples/human-confirm-demo/` | AI proactive inquiry (multi-plan pick) + pre-write confirm |
351
351
  | planner-demo | `/examples/planner-demo/` | Plan-reflect-execute (high-temp creative planner + low-temp reflector) |
352
352
  | subagent-demo | `/examples/subagent-demo/` | Subagent parallel orchestration |
@@ -399,14 +399,14 @@ createChatSdk({
399
399
  container: '#root',
400
400
  llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
401
401
  systemPrompt: 'You are a page assistant; read/write window.app via tools.',
402
- windowProps: [
402
+ dataSlots: [
403
403
  { path: 'app.title', description: 'Title', schema: z.string() },
404
404
  { path: 'app.theme', description: 'Theme', schema: z.enum(['light', 'dark']) },
405
405
  ],
406
406
  }).mount()
407
407
  ```
408
408
 
409
- `npx vite` → type "change app.theme to dark" in the dialog → AI calls `set_window_prop` → `window.app.theme` becomes `dark` → verified.
409
+ `npx vite` → type "change app.theme to dark" in the dialog → AI calls `set_data_slot` → `window.app.theme` becomes `dark` → verified.
410
410
 
411
411
  > Add this test dir to `.gitignore` (local only, not in repo) to avoid committing `.env` with real keys to remotes.
412
412
 
@@ -423,7 +423,7 @@ The package ships three builds — pick by integration scenario:
423
423
  `sideEffects` is set to `["**/*.css"]` only, so bundlers can tree-shake the JS when you import named symbols. Tips to keep your bundle lean:
424
424
 
425
425
  - **Headless (`ui:false`)**: skip the built-in dialog and render `agent.messages` yourself — you can avoid importing `ChatDialog`/`CodePreview` and drop the CSS (`import 'page-agent-sdk'` without `'page-agent-sdk/style.css'`).
426
- - **Disable unused capabilities**: `capabilities:{ windowOps:false, fetch:false, planning:false, skills:false, vfs:false, summarization:false, memory:false, subagent:false }` — removes the corresponding tool schemas and middleware from the agent prompt (saves tokens, not bytes).
426
+ - **Disable unused capabilities**: `capabilities:{ dataSlotOps:false, fetch:false, planning:false, skills:false, vfs:false, summarization:false, memory:false, subagent:false }` — removes the corresponding tool schemas and middleware from the agent prompt (saves tokens, not bytes).
427
427
  - **CDN via esm.sh**: `import { createChatSdk } from 'https://esm.sh/page-agent-sdk'` — peer deps (`zod`, `@langchain/*`) are resolved and deduped by esm.sh automatically; smallest for module scenarios.
428
428
  - **IIFE only for zero-config**: the all-inlined single file is convenient but heaviest; prefer ESM when the host supports modules.
429
429
  - **MCP is an optional peer**: `@modelcontextprotocol/sdk` is dynamically imported only when `options.mcp` is passed — omit it to avoid loading the MCP runtime entirely.
package/README.zh-CN.md CHANGED
@@ -24,9 +24,9 @@
24
24
 
25
25
  | 约束 | 机制 | 作用 |
26
26
  |---|---|---|
27
- | **范围控制** | 属性注册表(`windowProps`)—— 只能动声明的 path | AI 越界改未注册字段 → 拒绝 |
27
+ | **范围控制** | 属性注册表(`dataSlots`)—— 只能动声明的 path | AI 越界改未注册字段 → 拒绝 |
28
28
  | **合法性校验** | zod schema —— `set`/`edit` 按 schema 校验 | 类型/枚举/结构不合法 → 结构化错误,不写入 |
29
- | **增量操作** | `edit_window_prop` 按 `jsonPath` 发 patch(set/remove/merge/append) | 避免重传整个大 JSON,精确改局部 |
29
+ | **增量操作** | `edit_data_slot` 按 `jsonPath` 发 patch(set/remove/merge/append) | 避免重传整个大 JSON,精确改局部 |
30
30
  | **可回滚** | per-path 快照(自动入栈)+ 会话 checkpoint | 改坏了一键回退到上次正常态 |
31
31
  | **乐观锁** | `set`/`edit`/`delete` 传 `expectedHash` + 冲突人工介入 | 检测并发外部修改 → 挂起,用户选保留/覆盖/回退 |
32
32
 
@@ -64,16 +64,16 @@ createChatSdk({
64
64
  container: '#chat',
65
65
  llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
66
66
  systemPrompt: '你是页面搭建助手,通过工具读写 window.page。',
67
- windowProps: [
67
+ dataSlots: [
68
68
  { path: 'page.title', description: '页面标题', schema: z.string() },
69
69
  { path: 'page.theme', description: '主题', schema: z.enum(['light', 'dark']) },
70
70
  ],
71
- approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // 写操作弹确认
71
+ approval: { tools: ['set_data_slot', 'edit_data_slot'] }, // 写操作弹确认
72
72
  checkpoint: true, // 误改一键回退
73
73
  }).mount()
74
74
  ```
75
75
 
76
- 用户说「标题改成『夏日新品』、主题切深色」→ AI 调 `edit_window_prop` 增量改 → schema 校验 → 写前确认 → 响应式刷新。说错了?点「↩ 回退」。
76
+ 用户说「标题改成『夏日新品』、主题切深色」→ AI 调 `edit_data_slot` 增量改 → schema 校验 → 写前确认 → 响应式刷新。说错了?点「↩ 回退」。
77
77
 
78
78
  CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `ChatSdk.createChatSdk({...})`。
79
79
 
@@ -81,7 +81,7 @@ CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `
81
81
 
82
82
  | 能力 | 说明 | 选项 |
83
83
  |---|---|---|
84
- | 🛠 window 操作 | 读写注册属性,schema 校验 + 增量 patch + 快照回退 | `windowProps` |
84
+ | 🛠 数据槽操作 | 读写注册属性,schema 校验 + 增量 patch + 快照回退 | `dataSlots` |
85
85
  | 🧠 ReAct harness | 可插拔中间件(8 钩子),自研不引 LangGraph | `middleware` |
86
86
  | 📋 规划/技能/记忆 | `write_todos` / `define_skill` / AGENTS.md 指令 | `capabilities.*` |
87
87
  | 🗄 虚拟工作区 | 内存文件系统,大结果外存不撑爆上下文 | `capabilities.vfs` |
@@ -91,7 +91,7 @@ CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `
91
91
  | 🤖 子 agent | 委派子任务,过程不占主上下文 | `subagent` |
92
92
  | 🔌 MCP | 连远程 MCP server 动态注入工具 | `mcp` |
93
93
  | 📦 上下文压缩 | 4 层自适应压缩,预设档位 + LLM 摘要 | `contextPreset` |
94
- | 🛡️ 压缩不丢信息 | 摘要内嵌当前 windowProps 快照 + 保留指定工具结果;写返回附可操作 path;`systemPromptHelpers.reliableWriteRules` | 内置 |
94
+ | 🛡️ 压缩不丢信息 | 摘要内嵌当前 dataSlots 快照 + 保留指定工具结果;写返回附可操作 path;`systemPromptHelpers.reliableWriteRules` | 内置 |
95
95
  | 💾 持久化 | IndexedDB 多会话 + 配额淘汰 + 切换 | `storage` |
96
96
 
97
97
  能力默认开(`verify`/`approval`/`checkpoint` 默认关;**主动征询 `humanConfirm` 默认开**——AI 遇不确定/多方案主动问你、不猜测),可经 `capabilities` 关掉无用的省 token。
@@ -109,14 +109,14 @@ createChatSdk, defineTool, defineSkill, presets, z
109
109
  createAgent, createSubagentMiddleware, createSubagentsMiddleware,
110
110
  createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
111
111
  createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
112
- createUsageHintsMiddleware, createWindowOps, createVfs, connectMcp
112
+ createUsageHintsMiddleware, createDataSlotOps, createVfs, connectMcp
113
113
  // 上下文/模型
114
114
  resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
115
115
  // 存储
116
116
  createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
117
117
  // UI(headless 自建 UI 复用)
118
118
  ChatDialog, MessageContent, CodePreview, useChat
119
- // 类型(略):ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, WindowPropSpec, AgentMessage, StreamEvent …
119
+ // 类型(略):ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, DataSlotSpec, AgentMessage, StreamEvent …
120
120
  ```
121
121
 
122
122
  ### `createChatSdk` 选项速查
@@ -128,9 +128,9 @@ ChatDialog, MessageContent, CodePreview, useChat
128
128
  | | `llm` | `LLMConfig \| BaseChatModel` · **必传** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`;兼容 OpenAI 协议(默认 DeepSeek) |
129
129
  | | `id` | `string` | 稳定 id(多 agent 隔离 + 持久化恢复;不传随机+warn) |
130
130
  | | `systemPrompt` | `string` | Agent 身份(不硬编码业务,靠这注入)。可选——不传用内置默认(页面操作助手 + `reliableWriteRules`);传了则完全覆盖 |
131
- | **页面数据** | `windowProps` | `{path,description,schema}[]` | 注册可被工具读写的 window 属性 + zod schema 校验 |
131
+ | **页面数据** | `dataSlots` | `{path,description,schema}[]` | 注册可被工具读写的 数据槽 + zod schema 校验 |
132
132
  | | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | 自定义工具 / 技能 / AGENTS.md 风格持久指令 |
133
- | **能力开关** | `capabilities` | `{planning?,windowOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | 默认全开(`verify` 默认关);`false` 关掉省 token |
133
+ | **能力开关** | `capabilities` | `{planning?,dataSlotOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | 默认全开(`verify` 默认关);`false` 关掉省 token |
134
134
  | | `permissions` | `PermissionRule[]` | scope 白名单(first-match-wins,默认不启用) |
135
135
  | | `humanConfirm` | `boolean` · 默认 `true` | 主动征询(AI 不确定/多方案主动问你,不猜测) |
136
136
  | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝) |
@@ -139,7 +139,7 @@ ChatDialog, MessageContent, CodePreview, useChat
139
139
  | **子 agent** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | 运行时自由委派(`spawn_agent`/`spawn_agents`) |
140
140
  | | `subagents` | `SubagentConfig[]` | 预声明命名子 agent → 每个生成 `use_<id>` 委派工具 |
141
141
  | **上下文** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · 默认 `auto` | 压缩预设档位 |
142
- | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩)。含 `preserveLastToolResults`(默认 `['describe_window_prop','list_window_props']`——压缩摘要里保留字段说明) |
142
+ | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩)。含 `preserveLastToolResults`(默认 `['describe_data_slot','list_data_slots']`——压缩摘要里保留字段说明) |
143
143
  | | `summaryLlm` | `BaseChatModel \| LLMConfig` | 摘要专用 LLM(不配用主 `llm`) |
144
144
  | | `maxMemoryRounds` | `number` · 默认 `50` | 对话历史内存上限轮次(`0` 关裁剪) |
145
145
  | | `vfs` | `{initialFiles?,maxBytes?}` · 默认 4MB | 内存工作区上限(超限 LRU 淘汰) |
@@ -175,8 +175,8 @@ createChatSdk({ subagents: [
175
175
 
176
176
  ### 内置工具(Agent 可调用)
177
177
 
178
- - **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`
179
- - **window 查询**:`query_window_prop`(JSONPath)/ `search_window_prop`(模糊搜索)/ `eval_window_script`(沙箱脚本)
178
+ - **数据槽操作**(`dataSlots` 注册后):`list_data_slots` / `describe_data_slot` / `get_data_slot` / `get_slot_paths` / `set_data_slot` / `edit_data_slot`(jsonPath 增量 patch)/ `delete_data_slot` / `snapshot_data_slot` / `list_data_snapshots` / `restore_data_snapshot`
179
+ - **window 查询**:`query_data_slot`(JSONPath)/ `search_data_slot`(模糊搜索)/ `eval_script`(沙箱脚本)
180
180
  - **抓取**:`fetch_document`
181
181
  - **vfs**:`vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
182
182
  - **规划/技能**:`write_todos` / `define_skill` / `load_skill`
@@ -195,7 +195,7 @@ src/core/
195
195
  │ todos.ts skills.ts memory.ts summarization.ts retry.ts
196
196
  │ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
197
197
  │ permissions.ts usageHints.ts
198
- ├── tools/ # windowOps(注册表+增量编辑+快照)/ windowQuery / fetchDoc
198
+ ├── tools/ # dataSlotOps(注册表+增量编辑+快照)/ dataSlotQuery / fetchDoc
199
199
  ├── backends/ # vfs(内存) / storage(IndexedDB+多后端+配额淘汰)
200
200
  ├── mcp/client.ts # MCP 远程工具接入
201
201
  ├── composables/ # useChat / useContextManager / useMarkdown
@@ -212,7 +212,7 @@ CLAUDE.md # 架构要点 + 约定坑 + 编码规范(agen
212
212
 
213
213
  | Skill | 触发场景 |
214
214
  |---|---|
215
- | `page-agent-sdk-integrate` | 集成 SDK —— 选引入方式、声明 `windowProps` + zod schema、配 LLM、挂载、订阅事件(`onEvent` / `sdk.hook`)、跑 headless、排查常见坑 |
215
+ | `page-agent-sdk-integrate` | 集成 SDK —— 选引入方式、声明 `dataSlots` + zod schema、配 LLM、挂载、订阅事件(`onEvent` / `sdk.hook`)、跑 headless、排查常见坑 |
216
216
 
217
217
  **安装**(任选其一):
218
218
 
@@ -238,13 +238,13 @@ flowchart TD
238
238
  SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
239
239
  CORE --> AGENT[createAgent<br/>ReAct 循环 + 中间件栈]
240
240
  AGENT --> MW[中间件栈<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→用户]
241
- AGENT --> TOOLS[工具集<br/>windowOps / fetchDoc / vfs / MCP / 用户]
241
+ AGENT --> TOOLS[工具集<br/>dataSlotOps / fetchDoc / vfs / MCP / 用户]
242
242
  TOOLS -->|零桥接| WIN[宿主页面 window<br/>直接读写注册属性]
243
243
  AGENT --> LLM[LLM<br/>OpenAI 协议 / 任意 ChatModel]
244
244
  SDK --> UI[ChatDialog UI<br/>Vue 打包进库 / 或 headless]
245
245
  ```
246
246
 
247
- - **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI —— 且可在 **Node.js 服务端**跑作后端 Agent(自定义工具/子 agent/自检;关 `windowOps`+`fetch`,用 `storage:'memory'`)
247
+ - **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI —— 且可在 **Node.js 服务端**跑作后端 Agent(自定义工具/子 agent/自检;关 `dataSlotOps`+`fetch`,用 `storage:'memory'`)
248
248
  - **provider 抽离**:`llm` 传任意 LangChain `BaseChatModel`,或 `LLMConfig`(内部构造 `ChatOpenAI`,兼容 OpenAI 协议,默认接 DeepSeek)
249
249
  - **自研 harness**:不引 LangGraph/langchain 整包,规避浏览器打包阻塞
250
250
 
@@ -265,20 +265,20 @@ createChatSdk({
265
265
  llm: { apiKey, baseUrl, model },
266
266
  id: 'my-agent', // 稳定 id(多 agent 隔离 + 持久化恢复)
267
267
  systemPrompt: '...',
268
- windowProps: [{ path, description, schema }],
268
+ dataSlots: [{ path, description, schema }],
269
269
  storage: 'indexed', // 持久化(默认关)
270
270
  streaming: true, ui: 'default',
271
271
  capabilities: { verify: true }, // 能力开关
272
272
  humanConfirm: true, // 主动征询(默认开;AI 不确定/多方案主动问你)
273
- approval: { tools: ['set_window_prop','edit_window_prop'] }, // 被动确认白名单(默认关)
273
+ approval: { tools: ['set_data_slot','edit_data_slot'] }, // 被动确认白名单(默认关)
274
274
  checkpoint: true,
275
275
  contextPreset: 'auto', // auto/conservative/aggressive
276
276
  summaryLlm: { ... }, // 摘要专用 LLM(不配用主 llm)
277
277
  maxRetries: 2, maxParallelTools: 1,
278
278
  subagent: { allowedTools: [...] },
279
279
  middleware: [/* 自定义中间件 */],
280
- onEvent(e) { // SDK 事件回调:订阅常用时机(window 属性变化/消息更新/工具调用/错误),替代轮询
281
- if (e.type === 'window_prop_change') refreshUI()
280
+ onEvent(e) { // SDK 事件回调:订阅常用时机(数据槽变化/消息更新/工具调用/错误),替代轮询
281
+ if (e.type === 'data_slot_change') refreshUI()
282
282
  },
283
283
  }).mount()
284
284
  ```
@@ -291,7 +291,7 @@ createChatSdk({
291
291
  |---|---|---|
292
292
  | page-demo | `/` | 自举 demo:左 JSON 响应式页面 + 右对话框 |
293
293
  | nested-demo | `/examples/nested-demo/` | 嵌套区块树 + 人工确认 + checkpoint |
294
- | dynamic-demo | `/examples/dynamic-demo/` | 懒加载组件 + 动态注册 schema(`sdk.addWindowProp`/`removeWindowProp`) |
294
+ | dynamic-demo | `/examples/dynamic-demo/` | 懒加载组件 + 动态注册 schema(`sdk.addDataSlot`/`removeDataSlot`) |
295
295
  | human-confirm-demo | `/examples/human-confirm-demo/` | AI 主动征询(多方案点选)+ 写前确认 |
296
296
  | planner-demo | `/examples/planner-demo/` | 规划-反思-执行(高温创意 planner + 低温 reflector) |
297
297
  | subagent-demo | `/examples/subagent-demo/` | 子 agent 并行编排 |
@@ -305,7 +305,7 @@ createChatSdk({
305
305
  |---|---|
306
306
  | [文档索引](./doc/README.md) | 各文档导航 + 其他信息源(规范/变更/自测) |
307
307
  | [使用手册](./doc/usage-guide.md) | 安装 / 配置项 / 能力详解 / 自定义中间件 / FAQ |
308
- | [功能架构](./doc/architecture.md) | 分层 / 控制流 / window 操作安全流 |
308
+ | [功能架构](./doc/architecture.md) | 分层 / 控制流 / 数据槽操作安全流 |
309
309
  | [上下文与压缩](./doc/context-management.md) | 上下文组成 / 4 层压缩 / 流程图 |
310
310
  | [文件全览](./doc/architecture-files.md) | 逐文件职责 / 依赖 / 数据流 |
311
311
  | [CLAUDE.md](./CLAUDE.md) | **agent 必读** · 架构要点 / 约定坑 / 编码规范 |
@@ -344,14 +344,14 @@ createChatSdk({
344
344
  container: '#root',
345
345
  llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
346
346
  systemPrompt: '你是页面助手,用工具读写 window.app。',
347
- windowProps: [
347
+ dataSlots: [
348
348
  { path: 'app.title', description: '标题', schema: z.string() },
349
349
  { path: 'app.theme', description: '主题', schema: z.enum(['light', 'dark']) },
350
350
  ],
351
351
  }).mount()
352
352
  ```
353
353
 
354
- `npx vite` → 对话框输入「把 app.theme 改成 dark」→ AI 调 `set_window_prop` → `window.app.theme` 变为 `dark` 即验证通过。
354
+ `npx vite` → 对话框输入「把 app.theme 改成 dark」→ AI 调 `set_data_slot` → `window.app.theme` 变为 `dark` 即验证通过。
355
355
 
356
356
  > 建议此测试目录加入 `.gitignore`(纯本地,不进仓库),避免把含真实 key 的 `.env` 提交到远程。
357
357
 
@@ -368,7 +368,7 @@ createChatSdk({
368
368
  `sideEffects` 仅标记 `["**/*.css"]`,打包器可对 JS 做 tree-shaking。瘦身建议:
369
369
 
370
370
  - **headless(`ui:false`)**:不渲染内置对话框,自渲染 `agent.messages` —— 可不引 `ChatDialog`/`CodePreview`,并省略 CSS(`import 'page-agent-sdk'` 不引 `'page-agent-sdk/style.css'`)。
371
- - **关闭无用能力**:`capabilities:{ windowOps:false, fetch:false, planning:false, skills:false, vfs:false, summarization:false, memory:false, subagent:false }` —— 移除对应工具 schema 与中间件(省 token,非字节)。
371
+ - **关闭无用能力**:`capabilities:{ dataSlotOps:false, fetch:false, planning:false, skills:false, vfs:false, summarization:false, memory:false, subagent:false }` —— 移除对应工具 schema 与中间件(省 token,非字节)。
372
372
  - **CDN 用 esm.sh**:`import { createChatSdk } from 'https://esm.sh/page-agent-sdk'` —— peer(`zod`、`@langchain/*`)由 esm.sh 自动解析去重,模块场景最小。
373
373
  - **IIFE 仅用于零配置**:全量单文件方便但最重,宿主支持模块时优先 ESM。
374
374
  - **MCP 为可选 peer**:`@modelcontextprotocol/sdk` 仅在传 `options.mcp` 时动态 import —— 不用 MCP 完全不加载该运行时。
@@ -1,2 +1,2 @@
1
- .code-preview-overlay[data-v-3d6e2a95]{z-index:9999;background:#00000080;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.code-preview-modal[data-v-3d6e2a95]{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-3d6e2a95]{color:#fff;background:#1f2937;align-items:center;gap:12px;padding:10px 16px;display:flex}.preview-title[data-v-3d6e2a95]{font-size:14px;font-weight:600}.preview-tabs[data-v-3d6e2a95]{gap:4px;margin-left:auto;display:flex}.preview-tabs button[data-v-3d6e2a95]{color:#fff;cursor:pointer;background:#ffffff1a;border:none;border-radius:6px;padding:4px 12px;font-size:13px}.preview-tabs button.active[data-v-3d6e2a95]{background:#667eea}.preview-tabs button[data-v-3d6e2a95]:disabled{opacity:.4;cursor:not-allowed}.preview-actions[data-v-3d6e2a95]{gap:4px;display:flex}.icon-btn[data-v-3d6e2a95]{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-3d6e2a95]:hover{background:#ffffff40}.preview-body[data-v-3d6e2a95]{background:#f9fafb;flex:1;overflow:hidden}.preview-iframe[data-v-3d6e2a95]{background:#fff;border:none;width:100%;height:100%}.preview-source[data-v-3d6e2a95]{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{overflow-wrap:anywhere;word-break:break-word;font-size:13px;line-height:1.6}.message-md p{margin:0 0 8px}.message-md p:last-child{margin-bottom:0}.message-md table{border-collapse:collapse;max-width:100%;margin:8px 0;display:block;overflow-x:auto}.message-md th,.message-md td{white-space:nowrap;border:1px solid #e5e7eb;padding:4px 8px;font-size:12px}.message-md th{background:#f9fafb}.message-md img{max-width:100%}.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-ac94546c]{z-index:9000;pointer-events:none;position:fixed;inset:0}.drawer-mask[data-v-ac94546c]{pointer-events:auto;background:#00000040;position:absolute;inset:0}.drawer-panel[data-v-ac94546c]{--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-ac94546c]{z-index:1}.drawer-header[data-v-ac94546c]{color:#fff;background:linear-gradient(135deg,#1f2937,#111827);justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.drawer-title[data-v-ac94546c]{font-size:15px;font-weight:600}.tab-group[data-v-ac94546c]{gap:4px;display:flex}.tab-btn[data-v-ac94546c]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;padding:4px 12px;font-size:13px;transition:background .2s}.tab-btn[data-v-ac94546c]:hover{background:#ffffff38}.tab-btn.active[data-v-ac94546c]{background:#ffffff73;font-weight:600}.info-body[data-v-ac94546c]{padding:4px 0}.info-section[data-v-ac94546c]{margin-bottom:14px}.info-title[data-v-ac94546c]{color:#2d5a47;border-bottom:1px solid #f3f4f6;margin-bottom:6px;padding-bottom:4px;font-size:12px;font-weight:600}.info-item[data-v-ac94546c]{background:#f9fafb;border-radius:6px;margin-bottom:4px;padding:6px 8px}.info-name[data-v-ac94546c]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:12px;font-weight:600}.info-desc[data-v-ac94546c]{color:#6b7280;margin-top:2px;font-size:11px;line-height:1.5}.info-desc.muted[data-v-ac94546c]{color:#9ca3af}.src-tag[data-v-ac94546c]{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-ac94546c]{color:#6b7280;background:#f3f4f6}.src-tag.mcp[data-v-ac94546c]{color:#7c3aed;background:#f3e8ff}.src-tag.user[data-v-ac94546c]{color:#2563eb;background:#dbeafe}.info-todo[data-v-ac94546c]{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-ac94546c]{color:#fff;border-radius:8px;flex-shrink:0;padding:1px 6px;font-size:10px}.info-pre[data-v-ac94546c]{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-ac94546c]{gap:4px;display:flex}.hd-btn[data-v-ac94546c]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;width:28px;height:28px}.hd-btn[data-v-ac94546c]:hover{background:#ffffff40}.drawer-filters[data-v-ac94546c]{background:#fafafa;border-bottom:1px solid #f3f4f6;flex-wrap:wrap;gap:6px;padding:10px 16px;display:flex}.filter-chip[data-v-ac94546c]{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-ac94546c]:hover{border-color:var(--chip-color,var(--cs-primary))}.filter-chip.active[data-v-ac94546c]{background:var(--chip-color,var(--cs-primary));border-color:var(--chip-color,var(--cs-primary));color:#fff}.chip-count[data-v-ac94546c]{background:#00000014;border-radius:8px;padding:0 5px;font-size:11px}.filter-chip.active .chip-count[data-v-ac94546c]{background:#ffffff40}.drawer-body[data-v-ac94546c]{flex:1;padding:12px;overflow-y:auto}.empty[data-v-ac94546c]{text-align:center;color:#9ca3af;padding:40px 20px;font-size:13px}.log-item[data-v-ac94546c]{background:#fff;border:1px solid #e5e7eb;border-radius:8px;margin-bottom:10px;overflow:hidden}.log-head[data-v-ac94546c]{background:#f9fafb;align-items:center;gap:8px;padding:8px 10px;display:flex}.log-type[data-v-ac94546c]{color:#fff;white-space:nowrap;border-radius:4px;padding:2px 8px;font-size:11px;font-weight:600}.log-source[data-v-ac94546c]{color:#7c3aed;white-space:nowrap;background:#f3e8ff;border-radius:4px;padding:2px 8px;font-size:10px;font-weight:600}.log-time[data-v-ac94546c]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.log-body[data-v-ac94546c]{padding:10px 12px}.log-footer[data-v-ac94546c]{border-top:1px dashed #f3f4f6;gap:8px;padding:6px 12px;display:flex}.raw-toggle[data-v-ac94546c]{color:var(--cs-primary);cursor:pointer;background:0 0;border:none;padding:2px 4px;font-size:11px}.raw-toggle[data-v-ac94546c]:hover{text-decoration:underline}.log-raw[data-v-ac94546c]{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-ac94546c]{grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px;display:grid}.kv[data-v-ac94546c]{background:#f9fafb;border-radius:6px;flex-direction:column;padding:6px 8px;display:flex}.kv .k[data-v-ac94546c]{color:#9ca3af;text-transform:uppercase;font-size:10px}.kv .v[data-v-ac94546c]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px;font-weight:600}.section-label[data-v-ac94546c]{color:#6b7280;margin:10px 0 4px;font-size:11px;font-weight:600}.chip-row[data-v-ac94546c]{flex-wrap:wrap;gap:4px;display:flex}.tool-chip[data-v-ac94546c]{color:#2d5a47;background:#ecf5ef;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.msg-list[data-v-ac94546c]{flex-direction:column;gap:4px;display:flex}.msg-row[data-v-ac94546c]{background:#f9fafb;border-radius:6px;align-items:flex-start;gap:6px;padding:5px 8px;display:flex}.msg-role[data-v-ac94546c]{color:#fff;border-radius:3px;flex-shrink:0;margin-top:1px;padding:2px 6px;font-size:9px;font-weight:700}.msg-text[data-v-ac94546c]{color:#374151;white-space:pre-wrap;word-break:break-word;flex:1;font-size:12px;line-height:1.5}.msg-tool-hint[data-v-ac94546c]{color:#7c3aed;flex-shrink:0;font-size:10px}.badge-row[data-v-ac94546c]{flex-wrap:wrap;gap:6px;margin-bottom:8px;display:flex}.badge[data-v-ac94546c]{color:#2d5a47;background:#dbeee4;border-radius:10px;padding:2px 8px;font-size:11px;font-weight:600}.badge.muted[data-v-ac94546c]{color:#6b7280;background:#f3f4f6}.badge.warn[data-v-ac94546c]{color:#92400e;background:#fef3c7}.resp-content[data-v-ac94546c]{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-ac94546c]{flex-direction:column;gap:6px;display:flex}.tc-card[data-v-ac94546c]{border:1px solid #e5e7eb;border-radius:6px;overflow:hidden}.tc-card.inline[data-v-ac94546c]{margin-top:4px}.tc-name[data-v-ac94546c]{color:#2d5a47;background:#ecf5ef;padding:5px 8px;font-size:12px;font-weight:600}.tc-args[data-v-ac94546c]{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-ac94546c]{flex-wrap:wrap;gap:6px;margin-top:8px;display:flex}.usage[data-v-ac94546c]{color:#047857;background:#ecfdf5;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.err-box[data-v-ac94546c]{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-ac94546c]{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.tc-inline[data-v-ac94546c]{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-ac94546c]{color:#2d5a47;white-space:nowrap;font-weight:600}.tc-inline-args[data-v-ac94546c]{color:#16402f;word-break:break-all;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.tc-id[data-v-ac94546c]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.view-toggle[data-v-ac94546c]{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-ac94546c]:hover{background:#dbeee4}.drawer-enter-active[data-v-ac94546c],.drawer-leave-active[data-v-ac94546c]{transition:opacity .25s}.drawer-enter-active .drawer-panel[data-v-ac94546c],.drawer-leave-active .drawer-panel[data-v-ac94546c]{transition:transform .25s}.drawer-enter-from[data-v-ac94546c],.drawer-leave-to[data-v-ac94546c]{opacity:0}.drawer-enter-from .drawer-panel[data-v-ac94546c],.drawer-leave-to .drawer-panel[data-v-ac94546c]{transform:translate(100%)}.flow-section[data-v-ac94546c]{margin-bottom:14px}.flow-section-title[data-v-ac94546c]{color:#6b7280;margin-bottom:6px;padding-left:2px;font-size:11px;font-weight:600}.flow-round[data-v-ac94546c]{border:1px solid #e5e7eb;border-radius:8px;margin-bottom:12px;overflow:hidden}.flow-round-head[data-v-ac94546c]{color:#fff;background:var(--cs-primary);padding:5px 10px;font-size:12px;font-weight:600}.flow-round-body[data-v-ac94546c]{flex-direction:column;gap:3px;padding:6px;display:flex}.flow-node[data-v-ac94546c]{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-ac94546c]{border-left-color:#059669}.flow-node.llm_response[data-v-ac94546c]{border-left-color:#d97706}.flow-node.tool_call[data-v-ac94546c]{border-left-color:#7c3aed}.flow-node.tool_result[data-v-ac94546c]{border-left-color:#2563eb}.flow-node.error[data-v-ac94546c]{background:#fef2f2;border-left-color:#dc2626}.flow-node.middleware[data-v-ac94546c]{border-left-color:#0891b2}.flow-ico[data-v-ac94546c]{flex-shrink:0;font-size:13px}.flow-label[data-v-ac94546c]{color:#374151;white-space:nowrap;flex-shrink:0;font-weight:600}.flow-detail[data-v-ac94546c]{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-ac94546c]{color:#9ca3af;flex-shrink:0;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.chat-dialog[data-v-063f5f71]{--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-063f5f71]{height:52px}.chat-header[data-v-063f5f71]{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-063f5f71]{align-items:center;gap:8px;display:flex}.header-icon[data-v-063f5f71]{font-size:20px}.header-title[data-v-063f5f71]{font-size:15px;font-weight:600}.status-dot[data-v-063f5f71]{background:#4ade80;border-radius:50%;width:8px;height:8px}.status-dot.pulse[data-v-063f5f71]{animation:1.5s infinite pulse-063f5f71}@keyframes pulse-063f5f71{0%,to{opacity:1}50%{opacity:.4}}.header-actions[data-v-063f5f71]{gap:4px;display:flex}.action-btn[data-v-063f5f71]{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-063f5f71]:hover:not(:disabled){background:#ffffff4d}.action-btn[data-v-063f5f71]:disabled{opacity:.4;cursor:not-allowed}.action-btn.debug-btn[data-v-063f5f71]{position:relative}.action-btn.debug-btn.active[data-v-063f5f71]{background:#ffffff73}.debug-badge[data-v-063f5f71]{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-063f5f71]{overscroll-behavior:contain;flex:1;min-height:0;padding:16px;overflow-y:auto}.empty-state[data-v-063f5f71]{color:#9ca3af;flex-direction:column;justify-content:center;align-items:center;height:200px;display:flex}.empty-icon[data-v-063f5f71]{margin-bottom:12px;font-size:48px}.empty-state p[data-v-063f5f71]{font-size:14px}.message-row[data-v-063f5f71]{align-items:flex-start;gap:10px;margin-bottom:16px;display:flex}.message-row.user[data-v-063f5f71]{flex-direction:row-reverse}.message-avatar[data-v-063f5f71]{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-063f5f71]{background:#ecf5ef}.message-content[data-v-063f5f71]{min-width:0;max-width:80%}.message-bubble[data-v-063f5f71]{overflow-wrap:anywhere;word-break:break-word;white-space:pre-wrap;border-radius:12px;padding:9px 13px;font-size:13px;line-height:1.6}.message-row.assistant .message-bubble[data-v-063f5f71]{color:#1f2937;white-space:normal;overflow-wrap:anywhere;background:#f3f4f6;border-bottom-left-radius:4px}.message-row.user .message-bubble[data-v-063f5f71]{background:var(--cs-primary);color:#fff;border-bottom-right-radius:4px}.message-row.user .message-content[data-v-063f5f71]{flex-direction:column;align-items:flex-end;display:flex}.message-time[data-v-063f5f71]{color:#9ca3af;margin-top:4px;padding:0 4px;font-size:11px}.typing[data-v-063f5f71]{gap:4px;padding:12px 16px;display:flex}.typing .dot[data-v-063f5f71]{background:#9ca3af;border-radius:50%;width:8px;height:8px;animation:1.4s ease-in-out infinite bounce-063f5f71}.typing .dot[data-v-063f5f71]:nth-child(2){animation-delay:.2s}.typing .dot[data-v-063f5f71]:nth-child(3){animation-delay:.4s}@keyframes bounce-063f5f71{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.typing-text[data-v-063f5f71]{color:#9ca3af;font-size:13px}.reasoning-block[data-v-063f5f71]{background:#f0f7f3;border:1px dashed #b8d4c5;border-radius:8px;margin-bottom:6px;overflow:hidden}.reasoning-header[data-v-063f5f71]{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-063f5f71]{font-size:13px}.reasoning-title[data-v-063f5f71]{font-weight:600}.reasoning-toggle[data-v-063f5f71]{margin-left:auto}.reasoning-body[data-v-063f5f71]{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-063f5f71]{flex-direction:column;gap:4px;margin-bottom:6px;display:flex}.step-item[data-v-063f5f71]{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-063f5f71]{align-items:center;gap:5px;display:inline-flex}.step-icon[data-v-063f5f71]{font-size:11px}.step-name[data-v-063f5f71]{font-family:SF Mono,Monaco,Consolas,monospace}.step-count[data-v-063f5f71]{color:#0891b2;font-size:10px;font-weight:600}.step-status.running[data-v-063f5f71]{color:#0891b2}.step-children[data-v-063f5f71]{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-063f5f71]{color:#7c3aed;letter-spacing:.3px;font-size:10px;font-weight:600}.step-child[data-v-063f5f71]{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-063f5f71]{color:#6d28d9}.step-child .step-status.running[data-v-063f5f71]{color:#8b5cf6}.stream-cursor[data-v-063f5f71],.typing-cursor[data-v-063f5f71]{vertical-align:text-bottom;background:var(--cs-primary);width:7px;height:14px;margin-left:2px;animation:1s steps(2,end) infinite blink-063f5f71;display:inline-block}@keyframes blink-063f5f71{0%,50%{opacity:1}51%,to{opacity:0}}.error-bar[data-v-063f5f71]{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-063f5f71]{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-063f5f71],.error-bar .undo-btn[data-v-063f5f71]{flex-shrink:0;margin-top:1px}.retry-btn[data-v-063f5f71]{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-063f5f71]:hover{background:#b91c1c}.chat-footer[data-v-063f5f71]{background:#fafafa;border-top:1px solid #f3f4f6;align-items:flex-end;gap:8px;padding:12px 16px;display:flex}.chat-input[data-v-063f5f71]{resize:none;overflow-wrap:anywhere;word-break:break-word;border:1px solid #e5e7eb;border-radius:8px;outline:none;flex:1;max-height:100px;padding:9px 12px;font-family:inherit;font-size:13px;line-height:1.5;transition:border-color .2s;overflow-y:auto}.chat-input[data-v-063f5f71]:focus{border-color:var(--cs-primary);box-shadow:0 0 0 2px rgba(var(--cs-primary-rgb), .1)}.send-btn[data-v-063f5f71]{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-063f5f71]:hover:not(:disabled){opacity:.9;transform:scale(1.05)}.send-btn[data-v-063f5f71]:active:not(:disabled){transform:scale(.95)}.send-btn[data-v-063f5f71]:disabled{opacity:.4;cursor:not-allowed}.send-btn.stop-btn[data-v-063f5f71]{background:#9ca3af}.send-btn.stop-btn[data-v-063f5f71]:hover:not(:disabled){background:#6b7280;transform:none}.cap-badge[data-v-063f5f71]{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-063f5f71]{opacity:0;gap:6px;margin-top:4px;transition:opacity .2s;display:flex}.message-row.assistant:hover .msg-actions[data-v-063f5f71]{opacity:1}.msg-action-btn[data-v-063f5f71]{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-063f5f71]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.undo-btn[data-v-063f5f71]{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-063f5f71]:hover{background:#fde68a}.undo-foot-btn[data-v-063f5f71]{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-063f5f71]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.approval-bar[data-v-063f5f71]{background:#fffbeb;border:1px solid #f59e0b;border-radius:10px;margin:8px 12px;padding:10px 12px}.approval-head[data-v-063f5f71]{color:#92400e;align-items:center;gap:6px;font-size:13px;display:flex}.approval-icon[data-v-063f5f71]{font-size:15px}.approval-title code[data-v-063f5f71]{color:#78350f;background:#fef3c7;border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.approval-toggle[data-v-063f5f71]{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-063f5f71]:hover{background:#fef3c7}.approval-args[data-v-063f5f71]{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-063f5f71]{justify-content:flex-end;gap:8px;display:flex}.approval-actions button[data-v-063f5f71]{cursor:pointer;border:none;border-radius:6px;padding:5px 16px;font-size:13px;transition:opacity .2s}.approval-deny[data-v-063f5f71]{color:#6b7280;background:#f3f4f6;border:1px solid #e5e7eb}.approval-deny[data-v-063f5f71]:hover{color:#374151;background:#e5e7eb}.approval-allow[data-v-063f5f71]{background:var(--cs-primary);color:#fff}.approval-allow[data-v-063f5f71]:hover{opacity:.9}.approval-question[data-v-063f5f71]{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-063f5f71]{color:#92400e;margin:4px 0 8px;font-size:12px;line-height:1.5}.approval-recommend[data-v-063f5f71]{color:#1f4d3a;margin:4px 0 8px;font-size:12px}.approval-opt[data-v-063f5f71]{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-063f5f71]:hover{background:var(--cs-primary);color:#fff}.conflict-bar[data-v-063f5f71]{background:#fef2f2;border:1px solid #dc2626;border-radius:10px;margin:8px 12px;padding:10px 12px}.conflict-head[data-v-063f5f71]{color:#991b1b;align-items:center;gap:6px;font-size:13px;display:flex}.conflict-icon[data-v-063f5f71]{font-size:15px}.conflict-title code[data-v-063f5f71]{color:#7f1d1d;background:#fee2e2;border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.conflict-detail[data-v-063f5f71]{color:#7f1d1d;margin:6px 0 8px;font-size:12px;line-height:1.5}.conflict-actions[data-v-063f5f71]{flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.conflict-actions button[data-v-063f5f71]{cursor:pointer;border:none;border-radius:6px;padding:5px 14px;font-size:13px;transition:opacity .2s}.conflict-keep[data-v-063f5f71]{color:#6b7280;background:#f3f4f6;border:1px solid #e5e7eb}.conflict-keep[data-v-063f5f71]:hover{color:#374151;background:#e5e7eb}.conflict-overwrite[data-v-063f5f71]{color:#fff;background:#dc2626}.conflict-overwrite[data-v-063f5f71]:hover{opacity:.9}.conflict-restore[data-v-063f5f71]{color:#dc2626;background:#fff;border:1px solid #dc2626}.conflict-restore[data-v-063f5f71]:hover{background:#fee2e2}.conflict-toggle[data-v-063f5f71]{color:#991b1b;cursor:pointer;background:0 0;border:none;border-radius:4px;margin:2px 0 6px;padding:2px 8px;font-size:12px}.conflict-toggle[data-v-063f5f71]:hover{background:#fee2e2}.conflict-diff[data-v-063f5f71]{gap:8px;margin:4px 0 8px;display:flex}.conflict-diff-col[data-v-063f5f71]{flex:1;min-width:0}.conflict-diff-label[data-v-063f5f71]{color:#7f1d1d;margin-bottom:2px;font-size:11px}.conflict-diff-pre[data-v-063f5f71]{color:#57534e;white-space:pre-wrap;word-break:break-all;background:#fff;border:1px solid #fecaca;border-radius:6px;max-height:140px;margin:0;padding:6px;font-size:11px;overflow:auto}
1
+ .code-preview-overlay[data-v-3d6e2a95]{z-index:9999;background:#00000080;justify-content:center;align-items:center;padding:20px;display:flex;position:fixed;inset:0}.code-preview-modal[data-v-3d6e2a95]{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-3d6e2a95]{color:#fff;background:#1f2937;align-items:center;gap:12px;padding:10px 16px;display:flex}.preview-title[data-v-3d6e2a95]{font-size:14px;font-weight:600}.preview-tabs[data-v-3d6e2a95]{gap:4px;margin-left:auto;display:flex}.preview-tabs button[data-v-3d6e2a95]{color:#fff;cursor:pointer;background:#ffffff1a;border:none;border-radius:6px;padding:4px 12px;font-size:13px}.preview-tabs button.active[data-v-3d6e2a95]{background:#667eea}.preview-tabs button[data-v-3d6e2a95]:disabled{opacity:.4;cursor:not-allowed}.preview-actions[data-v-3d6e2a95]{gap:4px;display:flex}.icon-btn[data-v-3d6e2a95]{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-3d6e2a95]:hover{background:#ffffff40}.preview-body[data-v-3d6e2a95]{background:#f9fafb;flex:1;overflow:hidden}.preview-iframe[data-v-3d6e2a95]{background:#fff;border:none;width:100%;height:100%}.preview-source[data-v-3d6e2a95]{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{overflow-wrap:anywhere;word-break:break-word;font-size:13px;line-height:1.6}.message-md p{margin:0 0 8px}.message-md p:last-child{margin-bottom:0}.message-md table{border-collapse:collapse;max-width:100%;margin:8px 0;display:block;overflow-x:auto}.message-md th,.message-md td{white-space:nowrap;border:1px solid #e5e7eb;padding:4px 8px;font-size:12px}.message-md th{background:#f9fafb}.message-md img{max-width:100%}.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-2a895152]{z-index:9000;pointer-events:none;position:fixed;inset:0}.drawer-mask[data-v-2a895152]{pointer-events:auto;background:#00000040;position:absolute;inset:0}.drawer-panel[data-v-2a895152]{--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-2a895152]{z-index:1}.drawer-header[data-v-2a895152]{color:#fff;background:linear-gradient(135deg,#1f2937,#111827);justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.drawer-title[data-v-2a895152]{font-size:15px;font-weight:600}.tab-group[data-v-2a895152]{gap:4px;display:flex}.tab-btn[data-v-2a895152]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;padding:4px 12px;font-size:13px;transition:background .2s}.tab-btn[data-v-2a895152]:hover{background:#ffffff38}.tab-btn.active[data-v-2a895152]{background:#ffffff73;font-weight:600}.info-body[data-v-2a895152]{padding:4px 0}.info-section[data-v-2a895152]{margin-bottom:14px}.info-title[data-v-2a895152]{color:#2d5a47;border-bottom:1px solid #f3f4f6;margin-bottom:6px;padding-bottom:4px;font-size:12px;font-weight:600}.info-item[data-v-2a895152]{background:#f9fafb;border-radius:6px;margin-bottom:4px;padding:6px 8px}.info-name[data-v-2a895152]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:12px;font-weight:600}.info-desc[data-v-2a895152]{color:#6b7280;margin-top:2px;font-size:11px;line-height:1.5}.info-desc.muted[data-v-2a895152]{color:#9ca3af}.src-tag[data-v-2a895152]{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-2a895152]{color:#6b7280;background:#f3f4f6}.src-tag.mcp[data-v-2a895152]{color:#7c3aed;background:#f3e8ff}.src-tag.user[data-v-2a895152]{color:#2563eb;background:#dbeafe}.info-todo[data-v-2a895152]{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-2a895152]{color:#fff;border-radius:8px;flex-shrink:0;padding:1px 6px;font-size:10px}.info-pre[data-v-2a895152]{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-2a895152]{gap:4px;display:flex}.hd-btn[data-v-2a895152]{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:6px;width:28px;height:28px}.hd-btn[data-v-2a895152]:hover{background:#ffffff40}.drawer-filters[data-v-2a895152]{background:#fafafa;border-bottom:1px solid #f3f4f6;flex-wrap:wrap;gap:6px;padding:10px 16px;display:flex}.filter-chip[data-v-2a895152]{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-2a895152]:hover{border-color:var(--chip-color,var(--cs-primary))}.filter-chip.active[data-v-2a895152]{background:var(--chip-color,var(--cs-primary));border-color:var(--chip-color,var(--cs-primary));color:#fff}.chip-count[data-v-2a895152]{background:#00000014;border-radius:8px;padding:0 5px;font-size:11px}.filter-chip.active .chip-count[data-v-2a895152]{background:#ffffff40}.drawer-body[data-v-2a895152]{flex:1;padding:12px;overflow-y:auto}.empty[data-v-2a895152]{text-align:center;color:#9ca3af;padding:40px 20px;font-size:13px}.log-item[data-v-2a895152]{background:#fff;border:1px solid #e5e7eb;border-radius:8px;margin-bottom:10px;overflow:hidden}.log-head[data-v-2a895152]{background:#f9fafb;align-items:center;gap:8px;padding:8px 10px;display:flex}.log-type[data-v-2a895152]{color:#fff;white-space:nowrap;border-radius:4px;padding:2px 8px;font-size:11px;font-weight:600}.log-source[data-v-2a895152]{color:#7c3aed;white-space:nowrap;background:#f3e8ff;border-radius:4px;padding:2px 8px;font-size:10px;font-weight:600}.log-time[data-v-2a895152]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.log-body[data-v-2a895152]{padding:10px 12px}.log-footer[data-v-2a895152]{border-top:1px dashed #f3f4f6;gap:8px;padding:6px 12px;display:flex}.raw-toggle[data-v-2a895152]{color:var(--cs-primary);cursor:pointer;background:0 0;border:none;padding:2px 4px;font-size:11px}.raw-toggle[data-v-2a895152]:hover{text-decoration:underline}.log-raw[data-v-2a895152]{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-2a895152]{grid-template-columns:1fr 1fr;gap:6px;margin-bottom:8px;display:grid}.kv[data-v-2a895152]{background:#f9fafb;border-radius:6px;flex-direction:column;padding:6px 8px;display:flex}.kv .k[data-v-2a895152]{color:#9ca3af;text-transform:uppercase;font-size:10px}.kv .v[data-v-2a895152]{color:#1f2937;font-family:SF Mono,Monaco,Consolas,monospace;font-size:13px;font-weight:600}.section-label[data-v-2a895152]{color:#6b7280;margin:10px 0 4px;font-size:11px;font-weight:600}.chip-row[data-v-2a895152]{flex-wrap:wrap;gap:4px;display:flex}.tool-chip[data-v-2a895152]{color:#2d5a47;background:#ecf5ef;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.msg-list[data-v-2a895152]{flex-direction:column;gap:4px;display:flex}.msg-row[data-v-2a895152]{background:#f9fafb;border-radius:6px;align-items:flex-start;gap:6px;padding:5px 8px;display:flex}.msg-role[data-v-2a895152]{color:#fff;border-radius:3px;flex-shrink:0;margin-top:1px;padding:2px 6px;font-size:9px;font-weight:700}.msg-text[data-v-2a895152]{color:#374151;white-space:pre-wrap;word-break:break-word;flex:1;font-size:12px;line-height:1.5}.msg-tool-hint[data-v-2a895152]{color:#7c3aed;flex-shrink:0;font-size:10px}.badge-row[data-v-2a895152]{flex-wrap:wrap;gap:6px;margin-bottom:8px;display:flex}.badge[data-v-2a895152]{color:#2d5a47;background:#dbeee4;border-radius:10px;padding:2px 8px;font-size:11px;font-weight:600}.badge.muted[data-v-2a895152]{color:#6b7280;background:#f3f4f6}.badge.warn[data-v-2a895152]{color:#92400e;background:#fef3c7}.resp-content[data-v-2a895152]{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-2a895152]{flex-direction:column;gap:6px;display:flex}.tc-card[data-v-2a895152]{border:1px solid #e5e7eb;border-radius:6px;overflow:hidden}.tc-card.inline[data-v-2a895152]{margin-top:4px}.tc-name[data-v-2a895152]{color:#2d5a47;background:#ecf5ef;padding:5px 8px;font-size:12px;font-weight:600}.tc-args[data-v-2a895152]{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-2a895152]{flex-wrap:wrap;gap:6px;margin-top:8px;display:flex}.usage[data-v-2a895152]{color:#047857;background:#ecfdf5;border-radius:10px;padding:2px 8px;font-family:SF Mono,Monaco,Consolas,monospace;font-size:11px}.err-box[data-v-2a895152]{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-2a895152]{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.tc-inline[data-v-2a895152]{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-2a895152]{color:#2d5a47;white-space:nowrap;font-weight:600}.tc-inline-args[data-v-2a895152]{color:#16402f;word-break:break-all;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.tc-id[data-v-2a895152]{color:#9ca3af;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.view-toggle[data-v-2a895152]{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-2a895152]:hover{background:#dbeee4}.drawer-enter-active[data-v-2a895152],.drawer-leave-active[data-v-2a895152]{transition:opacity .25s}.drawer-enter-active .drawer-panel[data-v-2a895152],.drawer-leave-active .drawer-panel[data-v-2a895152]{transition:transform .25s}.drawer-enter-from[data-v-2a895152],.drawer-leave-to[data-v-2a895152]{opacity:0}.drawer-enter-from .drawer-panel[data-v-2a895152],.drawer-leave-to .drawer-panel[data-v-2a895152]{transform:translate(100%)}.flow-section[data-v-2a895152]{margin-bottom:14px}.flow-section-title[data-v-2a895152]{color:#6b7280;margin-bottom:6px;padding-left:2px;font-size:11px;font-weight:600}.flow-round[data-v-2a895152]{border:1px solid #e5e7eb;border-radius:8px;margin-bottom:12px;overflow:hidden}.flow-round-head[data-v-2a895152]{color:#fff;background:var(--cs-primary);padding:5px 10px;font-size:12px;font-weight:600}.flow-round-body[data-v-2a895152]{flex-direction:column;gap:3px;padding:6px;display:flex}.flow-node[data-v-2a895152]{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-2a895152]{border-left-color:#059669}.flow-node.llm_response[data-v-2a895152]{border-left-color:#d97706}.flow-node.tool_call[data-v-2a895152]{border-left-color:#7c3aed}.flow-node.tool_result[data-v-2a895152]{border-left-color:#2563eb}.flow-node.error[data-v-2a895152]{background:#fef2f2;border-left-color:#dc2626}.flow-node.middleware[data-v-2a895152]{border-left-color:#0891b2}.flow-ico[data-v-2a895152]{flex-shrink:0;font-size:13px}.flow-label[data-v-2a895152]{color:#374151;white-space:nowrap;flex-shrink:0;font-weight:600}.flow-detail[data-v-2a895152]{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-2a895152]{color:#9ca3af;flex-shrink:0;font-family:SF Mono,Monaco,Consolas,monospace;font-size:10px}.chat-dialog[data-v-5bd12eb9]{--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-5bd12eb9]{height:52px}.chat-header[data-v-5bd12eb9]{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-5bd12eb9]{align-items:center;gap:8px;display:flex}.header-icon[data-v-5bd12eb9]{font-size:20px}.header-title[data-v-5bd12eb9]{font-size:15px;font-weight:600}.status-dot[data-v-5bd12eb9]{background:#4ade80;border-radius:50%;width:8px;height:8px}.status-dot.pulse[data-v-5bd12eb9]{animation:1.5s infinite pulse-5bd12eb9}@keyframes pulse-5bd12eb9{0%,to{opacity:1}50%{opacity:.4}}.header-actions[data-v-5bd12eb9]{gap:4px;display:flex}.action-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover:not(:disabled){background:#ffffff4d}.action-btn[data-v-5bd12eb9]:disabled{opacity:.4;cursor:not-allowed}.action-btn.debug-btn[data-v-5bd12eb9]{position:relative}.action-btn.debug-btn.active[data-v-5bd12eb9]{background:#ffffff73}.debug-badge[data-v-5bd12eb9]{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-5bd12eb9]{overscroll-behavior:contain;flex:1;min-height:0;padding:16px;overflow-y:auto}.empty-state[data-v-5bd12eb9]{color:#9ca3af;flex-direction:column;justify-content:center;align-items:center;height:200px;display:flex}.empty-icon[data-v-5bd12eb9]{margin-bottom:12px;font-size:48px}.empty-state p[data-v-5bd12eb9]{font-size:14px}.message-row[data-v-5bd12eb9]{align-items:flex-start;gap:10px;margin-bottom:16px;display:flex}.message-row.user[data-v-5bd12eb9]{flex-direction:row-reverse}.message-avatar[data-v-5bd12eb9]{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-5bd12eb9]{background:#ecf5ef}.message-content[data-v-5bd12eb9]{min-width:0;max-width:80%}.message-bubble[data-v-5bd12eb9]{overflow-wrap:anywhere;word-break:break-word;white-space:pre-wrap;border-radius:12px;padding:9px 13px;font-size:13px;line-height:1.6}.message-row.assistant .message-bubble[data-v-5bd12eb9]{color:#1f2937;white-space:normal;overflow-wrap:anywhere;background:#f3f4f6;border-bottom-left-radius:4px}.message-row.user .message-bubble[data-v-5bd12eb9]{background:var(--cs-primary);color:#fff;border-bottom-right-radius:4px}.message-row.user .message-content[data-v-5bd12eb9]{flex-direction:column;align-items:flex-end;display:flex}.message-time[data-v-5bd12eb9]{color:#9ca3af;margin-top:4px;padding:0 4px;font-size:11px}.typing[data-v-5bd12eb9]{gap:4px;padding:12px 16px;display:flex}.typing .dot[data-v-5bd12eb9]{background:#9ca3af;border-radius:50%;width:8px;height:8px;animation:1.4s ease-in-out infinite bounce-5bd12eb9}.typing .dot[data-v-5bd12eb9]:nth-child(2){animation-delay:.2s}.typing .dot[data-v-5bd12eb9]:nth-child(3){animation-delay:.4s}@keyframes bounce-5bd12eb9{0%,80%,to{transform:translateY(0)}40%{transform:translateY(-6px)}}.typing-text[data-v-5bd12eb9]{color:#9ca3af;font-size:13px}.reasoning-block[data-v-5bd12eb9]{background:#f0f7f3;border:1px dashed #b8d4c5;border-radius:8px;margin-bottom:6px;overflow:hidden}.reasoning-header[data-v-5bd12eb9]{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-5bd12eb9]{font-size:13px}.reasoning-title[data-v-5bd12eb9]{font-weight:600}.reasoning-toggle[data-v-5bd12eb9]{margin-left:auto}.reasoning-body[data-v-5bd12eb9]{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-5bd12eb9]{flex-direction:column;gap:4px;margin-bottom:6px;display:flex}.step-item[data-v-5bd12eb9]{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-5bd12eb9]{align-items:center;gap:5px;display:inline-flex}.step-icon[data-v-5bd12eb9]{font-size:11px}.step-name[data-v-5bd12eb9]{font-family:SF Mono,Monaco,Consolas,monospace}.step-count[data-v-5bd12eb9]{color:#0891b2;font-size:10px;font-weight:600}.step-status.running[data-v-5bd12eb9]{color:#0891b2}.step-children[data-v-5bd12eb9]{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-5bd12eb9]{color:#7c3aed;letter-spacing:.3px;font-size:10px;font-weight:600}.step-child[data-v-5bd12eb9]{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-5bd12eb9]{color:#6d28d9}.step-child .step-status.running[data-v-5bd12eb9]{color:#8b5cf6}.stream-cursor[data-v-5bd12eb9],.typing-cursor[data-v-5bd12eb9]{vertical-align:text-bottom;background:var(--cs-primary);width:7px;height:14px;margin-left:2px;animation:1s steps(2,end) infinite blink-5bd12eb9;display:inline-block}@keyframes blink-5bd12eb9{0%,50%{opacity:1}51%,to{opacity:0}}.error-bar[data-v-5bd12eb9]{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-5bd12eb9]{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-5bd12eb9],.error-bar .undo-btn[data-v-5bd12eb9]{flex-shrink:0;margin-top:1px}.retry-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover{background:#b91c1c}.chat-footer[data-v-5bd12eb9]{background:#fafafa;border-top:1px solid #f3f4f6;align-items:flex-end;gap:8px;padding:12px 16px;display:flex}.chat-input[data-v-5bd12eb9]{resize:none;overflow-wrap:anywhere;word-break:break-word;border:1px solid #e5e7eb;border-radius:8px;outline:none;flex:1;max-height:100px;padding:9px 12px;font-family:inherit;font-size:13px;line-height:1.5;transition:border-color .2s;overflow-y:auto}.chat-input[data-v-5bd12eb9]:focus{border-color:var(--cs-primary);box-shadow:0 0 0 2px rgba(var(--cs-primary-rgb), .1)}.send-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover:not(:disabled){opacity:.9;transform:scale(1.05)}.send-btn[data-v-5bd12eb9]:active:not(:disabled){transform:scale(.95)}.send-btn[data-v-5bd12eb9]:disabled{opacity:.4;cursor:not-allowed}.send-btn.stop-btn[data-v-5bd12eb9]{background:#9ca3af}.send-btn.stop-btn[data-v-5bd12eb9]:hover:not(:disabled){background:#6b7280;transform:none}.cap-badge[data-v-5bd12eb9]{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-5bd12eb9]{opacity:0;gap:6px;margin-top:4px;transition:opacity .2s;display:flex}.message-row.assistant:hover .msg-actions[data-v-5bd12eb9]{opacity:1}.msg-action-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.undo-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover{background:#fde68a}.undo-foot-btn[data-v-5bd12eb9]{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-5bd12eb9]:hover{border-color:var(--cs-primary);color:var(--cs-primary);background:#f0f7f3}.approval-bar[data-v-5bd12eb9]{background:#fffbeb;border:1px solid #f59e0b;border-radius:10px;margin:8px 12px;padding:10px 12px}.approval-head[data-v-5bd12eb9]{color:#92400e;align-items:center;gap:6px;font-size:13px;display:flex}.approval-icon[data-v-5bd12eb9]{font-size:15px}.approval-title code[data-v-5bd12eb9]{color:#78350f;background:#fef3c7;border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.approval-toggle[data-v-5bd12eb9]{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-5bd12eb9]:hover{background:#fef3c7}.approval-args[data-v-5bd12eb9]{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-5bd12eb9]{justify-content:flex-end;gap:8px;display:flex}.approval-actions button[data-v-5bd12eb9]{cursor:pointer;border:none;border-radius:6px;padding:5px 16px;font-size:13px;transition:opacity .2s}.approval-deny[data-v-5bd12eb9]{color:#6b7280;background:#f3f4f6;border:1px solid #e5e7eb}.approval-deny[data-v-5bd12eb9]:hover{color:#374151;background:#e5e7eb}.approval-allow[data-v-5bd12eb9]{background:var(--cs-primary);color:#fff}.approval-allow[data-v-5bd12eb9]:hover{opacity:.9}.approval-question[data-v-5bd12eb9]{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-5bd12eb9]{color:#92400e;margin:4px 0 8px;font-size:12px;line-height:1.5}.approval-recommend[data-v-5bd12eb9]{color:#1f4d3a;margin:4px 0 8px;font-size:12px}.approval-opt[data-v-5bd12eb9]{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-5bd12eb9]:hover{background:var(--cs-primary);color:#fff}.conflict-bar[data-v-5bd12eb9]{background:#fef2f2;border:1px solid #dc2626;border-radius:10px;margin:8px 12px;padding:10px 12px}.conflict-head[data-v-5bd12eb9]{color:#991b1b;align-items:center;gap:6px;font-size:13px;display:flex}.conflict-icon[data-v-5bd12eb9]{font-size:15px}.conflict-title code[data-v-5bd12eb9]{color:#7f1d1d;background:#fee2e2;border-radius:4px;padding:1px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.conflict-detail[data-v-5bd12eb9]{color:#7f1d1d;margin:6px 0 8px;font-size:12px;line-height:1.5}.conflict-actions[data-v-5bd12eb9]{flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.conflict-actions button[data-v-5bd12eb9]{cursor:pointer;border:none;border-radius:6px;padding:5px 14px;font-size:13px;transition:opacity .2s}.conflict-keep[data-v-5bd12eb9]{color:#6b7280;background:#f3f4f6;border:1px solid #e5e7eb}.conflict-keep[data-v-5bd12eb9]:hover{color:#374151;background:#e5e7eb}.conflict-overwrite[data-v-5bd12eb9]{color:#fff;background:#dc2626}.conflict-overwrite[data-v-5bd12eb9]:hover{opacity:.9}.conflict-restore[data-v-5bd12eb9]{color:#dc2626;background:#fff;border:1px solid #dc2626}.conflict-restore[data-v-5bd12eb9]:hover{background:#fee2e2}.conflict-toggle[data-v-5bd12eb9]{color:#991b1b;cursor:pointer;background:0 0;border:none;border-radius:4px;margin:2px 0 6px;padding:2px 8px;font-size:12px}.conflict-toggle[data-v-5bd12eb9]:hover{background:#fee2e2}.conflict-diff[data-v-5bd12eb9]{gap:8px;margin:4px 0 8px;display:flex}.conflict-diff-col[data-v-5bd12eb9]{flex:1;min-width:0}.conflict-diff-label[data-v-5bd12eb9]{color:#7f1d1d;margin-bottom:2px;font-size:11px}.conflict-diff-pre[data-v-5bd12eb9]{color:#57534e;white-space:pre-wrap;word-break:break-all;background:#fff;border:1px solid #fecaca;border-radius:6px;max-height:140px;margin:0;padding:6px;font-size:11px;overflow:auto}
2
2
  /*$vite$:1*/