page-agent-sdk 2.4.0 → 2.4.1

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