page-agent-sdk 2.4.0 → 2.5.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 +49 -38
- package/README.zh-CN.md +47 -36
- package/dist/page-agent-sdk.css +1 -1
- package/dist/page-agent-sdk.iife.js +117 -124
- package/dist/page-agent-sdk.js +3381 -3399
- package/dist/page-agent-sdk.umd.cjs +69 -76
- package/package.json +1 -1
- package/types/index.d.ts +52 -68
package/README.md
CHANGED
|
@@ -24,9 +24,10 @@ 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 (`
|
|
27
|
+
| **Scope control** | Property registry (`data`) — only declared paths are writable; schema shape auto-whitelist (top-level keys limit visible + writable; undeclared fields hidden/denied; whole-set becomes merge to prevent accidental deletion) | AI touching undeclared fields → `PATH_DENIED` |
|
|
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 `
|
|
29
|
+
| **Incremental op** | `write` with `patch`/`patches` (batch, atomic rollback) or advanced `edit_data` patches by `jsonPath` (set/remove/merge/append) | Avoid re-sending the whole large JSON; precise local edits; use `patches` to edit many at once |
|
|
30
|
+
| **Large-object retrieval** | `read` supports `fields` (projection) + `depth` (truncation) to shrink payload; `query_data` (JSONPath)/`search_data` (text)/`eval_script` (sandboxed JS) | Efficient retrieval + pinpoint location in large JSON |
|
|
30
31
|
| **Rollbackable** | per-path snapshots (auto-stacked) + session checkpoint | Bad edit → one-click restore to the last good state |
|
|
31
32
|
| **Optimistic lock** | `expectedHash` on `set`/`edit`/`delete` + conflict human-in-the-loop | Concurrent external edits detected → suspend, user picks keep/overwrite/restore |
|
|
32
33
|
|
|
@@ -58,16 +59,21 @@ npm install page-agent-sdk zod @langchain/openai @langchain/core
|
|
|
58
59
|
import { createChatSdk } from 'page-agent-sdk'
|
|
59
60
|
import { z } from 'zod'
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
const page = { title: 'New Products', theme: 'light' }
|
|
63
|
+
window.page = page // optional: mount to window for your page to read; SDK tools operate on `bind` directly
|
|
62
64
|
|
|
63
65
|
createChatSdk({
|
|
64
66
|
container: '#chat',
|
|
65
67
|
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
|
|
66
|
-
systemPrompt: 'You are a page-builder assistant; read/write
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
systemPrompt: 'You are a page-builder assistant; read/write the main data via tools.',
|
|
69
|
+
data: {
|
|
70
|
+
schema: z.object({
|
|
71
|
+
title: z.string().describe('Page title'),
|
|
72
|
+
theme: z.enum(['light', 'dark']).describe('Theme'),
|
|
73
|
+
}),
|
|
74
|
+
bind: page,
|
|
75
|
+
description: 'Page config',
|
|
76
|
+
},
|
|
71
77
|
approval: { tools: ['write'] }, // confirm writes
|
|
72
78
|
checkpoint: true, // one-click rollback on mistake
|
|
73
79
|
}).mount()
|
|
@@ -81,7 +87,7 @@ CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` →
|
|
|
81
87
|
|
|
82
88
|
| Capability | Description | Option |
|
|
83
89
|
|---|---|---|
|
|
84
|
-
| 🛠 window ops | Read/write registered props, schema validation + incremental patch + snapshot rollback | `
|
|
90
|
+
| 🛠 window ops | Read/write registered props, schema validation + incremental patch + snapshot rollback | `data` |
|
|
85
91
|
| 🧠 ReAct harness | Pluggable middleware (8 hooks), in-house (no LangGraph) | `middleware` |
|
|
86
92
|
| 📋 planning/skills/memory | `write_todos` / `define_skill` / AGENTS.md directives | `capabilities.*` |
|
|
87
93
|
| 🗄 virtual workspace | In-memory file system; large results offloaded (won't blow context) | `capabilities.vfs` |
|
|
@@ -91,7 +97,7 @@ CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` →
|
|
|
91
97
|
| 🤖 subagents | Delegate subtasks; process stays out of main context | `subagent` |
|
|
92
98
|
| 🔌 MCP | Connect remote MCP servers, inject tools dynamically | `mcp` |
|
|
93
99
|
| 📦 context compression | 4-layer adaptive compression, presets + LLM summary | `contextPreset` |
|
|
94
|
-
| 🛡️ compression-safe | Live
|
|
100
|
+
| 🛡️ compression-safe | Live data snapshot + preserved tool results in summary; write returns hint available paths; `systemPromptHelpers.reliableWriteRules` | built-in |
|
|
95
101
|
| 💾 persistence | IndexedDB multi-session + quota eviction + switch | `storage` |
|
|
96
102
|
|
|
97
103
|
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 +115,14 @@ createChatSdk, defineTool, defineSkill, presets, z
|
|
|
109
115
|
createAgent, createSubagentMiddleware, createSubagentsMiddleware,
|
|
110
116
|
createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
|
|
111
117
|
createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
|
|
112
|
-
createUsageHintsMiddleware,
|
|
118
|
+
createUsageHintsMiddleware, createDataOps, createVfs, connectMcp
|
|
113
119
|
// context & model
|
|
114
120
|
resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
|
|
115
121
|
// storage
|
|
116
122
|
createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
|
|
117
123
|
// UI (reuse when headless)
|
|
118
124
|
ChatDialog, MessageContent, CodePreview, useChat
|
|
119
|
-
// types (omitted): ChatSdkOptions, Middleware, SubagentConfig, SkillSpec,
|
|
125
|
+
// types (omitted): ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, DataConfig, AgentMessage, StreamEvent …
|
|
120
126
|
```
|
|
121
127
|
|
|
122
128
|
### `createChatSdk` options cheat sheet
|
|
@@ -128,9 +134,9 @@ ChatDialog, MessageContent, CodePreview, useChat
|
|
|
128
134
|
| | `llm` | `LLMConfig \| BaseChatModel` · **required** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`; OpenAI-compatible (default DeepSeek) |
|
|
129
135
|
| | `id` | `string` | Stable id (multi-agent isolation + persistence resume; random+warn if omitted) |
|
|
130
136
|
| | `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** | `
|
|
137
|
+
| **Page data** | `data` | `{path,description,schema}[]` | Register data slots readable/writable by tools + zod schema |
|
|
132
138
|
| | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | Custom tools / skills / AGENTS.md-style directives |
|
|
133
|
-
| **Capability toggles** | `capabilities` | `{planning?,
|
|
139
|
+
| **Capability toggles** | `capabilities` | `{planning?,dataOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | Default all on (`verify` default off); `false` to turn off |
|
|
134
140
|
| | `permissions` | `PermissionRule[]` | Scope whitelist (first-match-wins, default off) |
|
|
135
141
|
| | `humanConfirm` | `boolean` · default `true` | Proactive inquiry (AI asks when uncertain/multi-plan) |
|
|
136
142
|
| | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · default off | Passive confirm whitelist (pre-write allow/deny) |
|
|
@@ -139,7 +145,7 @@ ChatDialog, MessageContent, CodePreview, useChat
|
|
|
139
145
|
| **Subagents** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | Runtime ad-hoc delegation (`spawn_agent`/`spawn_agents`) |
|
|
140
146
|
| | `subagents` | `SubagentConfig[]` | Pre-declared named subagents → each generates `use_<id>` tool |
|
|
141
147
|
| **Context** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · default `auto` | Compression preset |
|
|
142
|
-
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` | Fine params (`false` disables compression). Includes `preserveLastToolResults` (default `['
|
|
148
|
+
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` | Fine params (`false` disables compression). Includes `preserveLastToolResults` (default `['describe_data','describe_data']` — keep field descriptions in compressed summary) |
|
|
143
149
|
| | `summaryLlm` | `BaseChatModel \| LLMConfig` | Summary-dedicated LLM (defaults to main `llm`) |
|
|
144
150
|
| | `maxMemoryRounds` | `number` · default `50` | Dialog history memory round cap (`0` disables trim) |
|
|
145
151
|
| | `vfs` | `{initialFiles?,maxBytes?}` · default 4MB | In-memory workspace cap (LRU evict on overflow) |
|
|
@@ -175,8 +181,8 @@ createChatSdk({ subagents: [
|
|
|
175
181
|
|
|
176
182
|
### Built-in tools (Agent-callable)
|
|
177
183
|
|
|
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 `
|
|
179
|
-
- **window query**: `
|
|
184
|
+
- **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`
|
|
185
|
+
- **window query**: `query_data` (JSONPath) / `search_data` (fuzzy) / `eval_script` (sandboxed)
|
|
180
186
|
- **fetch**: `fetch_document`
|
|
181
187
|
- **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
|
|
182
188
|
- **planning/skills**: `write_todos` / `define_skill` / `load_skill`
|
|
@@ -195,7 +201,7 @@ src/core/
|
|
|
195
201
|
│ todos.ts skills.ts memory.ts summarization.ts retry.ts
|
|
196
202
|
│ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
|
|
197
203
|
│ permissions.ts usageHints.ts
|
|
198
|
-
├── tools/ #
|
|
204
|
+
├── tools/ # dataOps (registry + incremental edit + snapshot) / dataSlotQuery / fetchDoc
|
|
199
205
|
├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
|
|
200
206
|
├── mcp/client.ts # remote MCP tool integration
|
|
201
207
|
├── composables/ # useChat / useContextManager / useMarkdown
|
|
@@ -230,8 +236,8 @@ createChatSdk({ subagents: [
|
|
|
230
236
|
|
|
231
237
|
### Built-in tools (Agent-callable)
|
|
232
238
|
|
|
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 `
|
|
234
|
-
- **window query**: `
|
|
239
|
+
- **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`
|
|
240
|
+
- **window query**: `query_data` (JSONPath) / `search_data` (fuzzy) / `eval_script` (sandboxed)
|
|
235
241
|
- **fetch**: `fetch_document`
|
|
236
242
|
- **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
|
|
237
243
|
- **planning/skills**: `write_todos` / `define_skill` / `load_skill`
|
|
@@ -250,7 +256,7 @@ src/core/
|
|
|
250
256
|
│ todos.ts skills.ts memory.ts summarization.ts retry.ts
|
|
251
257
|
│ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
|
|
252
258
|
│ permissions.ts usageHints.ts
|
|
253
|
-
├── tools/ #
|
|
259
|
+
├── tools/ # dataOps (registry + incremental edit + snapshot) / dataSlotQuery / fetchDoc
|
|
254
260
|
├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
|
|
255
261
|
├── mcp/client.ts # remote MCP tool integration
|
|
256
262
|
├── composables/ # useChat / useContextManager / useMarkdown
|
|
@@ -267,7 +273,7 @@ A ready-to-use Agent Skill is bundled for integrators using Claude Code / Cursor
|
|
|
267
273
|
|
|
268
274
|
| Skill | When it triggers |
|
|
269
275
|
|---|---|
|
|
270
|
-
| `page-agent-sdk-integrate` | Embedding the SDK — choose install method, declare `
|
|
276
|
+
| `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
277
|
|
|
272
278
|
**Install** (pick one):
|
|
273
279
|
|
|
@@ -293,13 +299,13 @@ flowchart TD
|
|
|
293
299
|
SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
|
|
294
300
|
CORE --> AGENT[createAgent<br/>ReAct loop + middleware stack]
|
|
295
301
|
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/>
|
|
302
|
+
AGENT --> TOOLS[Tools<br/>dataOps / fetchDoc / vfs / MCP / user]
|
|
297
303
|
TOOLS -->|zero-bridge| WIN[Host page window<br/>read/write registered props directly]
|
|
298
304
|
AGENT --> LLM[LLM<br/>OpenAI-compatible / any ChatModel]
|
|
299
305
|
SDK --> UI[ChatDialog UI<br/>Vue bundled in / or headless]
|
|
300
306
|
```
|
|
301
307
|
|
|
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 `
|
|
308
|
+
- **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
309
|
- **Provider-agnostic**: `llm` accepts any LangChain `BaseChatModel`, or `LLMConfig` (builds `ChatOpenAI` internally, OpenAI-compatible, default DeepSeek)
|
|
304
310
|
- **In-house harness**: no LangGraph/langchain full bundle; avoids browser bundling blockers
|
|
305
311
|
|
|
@@ -320,11 +326,11 @@ createChatSdk({
|
|
|
320
326
|
llm: { apiKey, baseUrl, model },
|
|
321
327
|
id: 'my-agent', // stable id (multi-agent isolation + persistence resume)
|
|
322
328
|
systemPrompt: '...',
|
|
323
|
-
|
|
329
|
+
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
330
|
toolMode: 'simple', // tool presentation: simple (default, promotes read/write) / advanced (all) / minimal (read/write only)
|
|
325
331
|
interceptors: { // read/write interceptors (desensitize/transform/audit/reject; input/output at agent IO entry/exit)
|
|
326
|
-
read: (
|
|
327
|
-
write: (
|
|
332
|
+
read: (value) => value,
|
|
333
|
+
write: (payload) => payload,
|
|
328
334
|
input: (msg) => msg, // preprocess at send entry
|
|
329
335
|
output: (reply) => reply, // postprocess before return
|
|
330
336
|
},
|
|
@@ -339,8 +345,8 @@ createChatSdk({
|
|
|
339
345
|
maxRetries: 2, maxParallelTools: 1,
|
|
340
346
|
subagent: { allowedTools: [...] },
|
|
341
347
|
middleware: [/* custom middleware */],
|
|
342
|
-
onEvent(e) { // SDK event callback: subscribe to common moments (data
|
|
343
|
-
if (e.type === '
|
|
348
|
+
onEvent(e) { // SDK event callback: subscribe to common moments (data change / message update / tool call / error), replaces polling
|
|
349
|
+
if (e.type === 'data_change') refreshUI()
|
|
344
350
|
},
|
|
345
351
|
}).mount()
|
|
346
352
|
```
|
|
@@ -353,7 +359,7 @@ After `npm run dev`, visit the corresponding page:
|
|
|
353
359
|
|---|---|---|
|
|
354
360
|
| page-demo | `/` | Self-bootstrapping demo: left JSON reactive page + right chat |
|
|
355
361
|
| nested-demo | `/examples/nested-demo/` | Nested block tree + human confirm + checkpoint |
|
|
356
|
-
| dynamic-demo | `/examples/dynamic-demo/` | Lazy-loaded components with dynamic schemas (`sdk.
|
|
362
|
+
| dynamic-demo | `/examples/dynamic-demo/` | Lazy-loaded components with dynamic schemas (`sdk.setData`/``) |
|
|
357
363
|
| human-confirm-demo | `/examples/human-confirm-demo/` | AI proactive inquiry (multi-plan pick) + pre-write confirm |
|
|
358
364
|
| planner-demo | `/examples/planner-demo/` | Plan-reflect-execute (high-temp creative planner + low-temp reflector) |
|
|
359
365
|
| subagent-demo | `/examples/subagent-demo/` | Subagent parallel orchestration |
|
|
@@ -400,20 +406,25 @@ npm install -D vite typescript
|
|
|
400
406
|
import { createChatSdk, z } from 'page-agent-sdk'
|
|
401
407
|
import 'page-agent-sdk/style.css'
|
|
402
408
|
|
|
403
|
-
|
|
409
|
+
const app = { title: 'Demo', theme: 'light' }
|
|
410
|
+
window.app = app // optional: mount to window for your page; tools operate on `bind` directly
|
|
404
411
|
|
|
405
412
|
createChatSdk({
|
|
406
413
|
container: '#root',
|
|
407
414
|
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
|
|
408
|
-
systemPrompt: 'You are a page assistant; read/write
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
415
|
+
systemPrompt: 'You are a page assistant; read/write the main data via tools.',
|
|
416
|
+
data: {
|
|
417
|
+
schema: z.object({
|
|
418
|
+
title: z.string().describe('Title'),
|
|
419
|
+
theme: z.enum(['light', 'dark']).describe('Theme'),
|
|
420
|
+
}),
|
|
421
|
+
bind: app,
|
|
422
|
+
description: 'App config',
|
|
423
|
+
},
|
|
413
424
|
}).mount()
|
|
414
425
|
```
|
|
415
426
|
|
|
416
|
-
`npx vite` → type "change app.theme to dark" in the dialog → AI calls `write({
|
|
427
|
+
`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
428
|
|
|
418
429
|
> Add this test dir to `.gitignore` (local only, not in repo) to avoid committing `.env` with real keys to remotes.
|
|
419
430
|
|
|
@@ -430,7 +441,7 @@ The package ships three builds — pick by integration scenario:
|
|
|
430
441
|
`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
442
|
|
|
432
443
|
- **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:{
|
|
444
|
+
- **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
445
|
- **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
446
|
- **IIFE only for zero-config**: the all-inlined single file is convenient but heaviest; prefer ESM when the host supports modules.
|
|
436
447
|
- **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,10 @@
|
|
|
24
24
|
|
|
25
25
|
| 约束 | 机制 | 作用 |
|
|
26
26
|
|---|---|---|
|
|
27
|
-
| **范围控制** |
|
|
27
|
+
| **范围控制** | schema 校验(`data`)—— 只能改 schema 允许的值;schema 形状自动白名单(顶层 key 限制可见 + 可写,未声明字段隐藏/拒改/整体 set 转 merge 防误删) | AI 传非法值 → 拒绝;非声明字段 → `PATH_DENIED` |
|
|
28
28
|
| **合法性校验** | zod schema —— `write`/`set`/`edit` 按 schema 校验 | 类型/枚举/结构不合法 → 结构化错误,不写入 |
|
|
29
|
-
| **增量操作** | `write` 的 `patch`(或 advanced `
|
|
29
|
+
| **增量操作** | `write` 的 `patch`/`patches`(批量,原子回滚)或 advanced `edit_data` 按 `jsonPath` 发 patch(set/remove/merge/append) | 避免重传整个大 JSON,精确改局部;一次改多处用 `patches` |
|
|
30
|
+
| **大对象检索** | `read` 支持 `fields`(字段裁剪)+ `depth`(深度截断)减体积;`query_data`(JSONPath)/`search_data`(文本)/`eval_script`(沙箱 JS) | 大 JSON 高效检索 + 局部定位 |
|
|
30
31
|
| **可回滚** | per-path 快照(自动入栈)+ 会话 checkpoint | 改坏了一键回退到上次正常态 |
|
|
31
32
|
| **乐观锁** | `set`/`edit`/`delete` 传 `expectedHash` + 冲突人工介入 | 检测并发外部修改 → 挂起,用户选保留/覆盖/回退 |
|
|
32
33
|
|
|
@@ -58,16 +59,21 @@ npm install page-agent-sdk zod @langchain/openai @langchain/core
|
|
|
58
59
|
import { createChatSdk } from 'page-agent-sdk'
|
|
59
60
|
import { z } from 'zod'
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
const page = { title: '新品专区', theme: 'light' }
|
|
63
|
+
window.page = page // 可选:挂到 window 供页面读取;SDK 工具直接读写 bind
|
|
62
64
|
|
|
63
65
|
createChatSdk({
|
|
64
66
|
container: '#chat',
|
|
65
67
|
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
|
|
66
|
-
systemPrompt: '
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
systemPrompt: '你是页面搭建助手,通过工具读写主数据。',
|
|
69
|
+
data: {
|
|
70
|
+
schema: z.object({
|
|
71
|
+
title: z.string().describe('页面标题'),
|
|
72
|
+
theme: z.enum(['light', 'dark']).describe('主题'),
|
|
73
|
+
}),
|
|
74
|
+
bind: page,
|
|
75
|
+
description: '页面配置',
|
|
76
|
+
},
|
|
71
77
|
approval: { tools: ['write'] }, // 写操作弹确认
|
|
72
78
|
checkpoint: true, // 误改一键回退
|
|
73
79
|
}).mount()
|
|
@@ -81,7 +87,7 @@ CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `
|
|
|
81
87
|
|
|
82
88
|
| 能力 | 说明 | 选项 |
|
|
83
89
|
|---|---|---|
|
|
84
|
-
| 🛠
|
|
90
|
+
| 🛠 数据操作 | 读写注册属性,schema 校验 + 增量 patch + 快照回退 | `data` |
|
|
85
91
|
| 🧠 ReAct harness | 可插拔中间件(8 钩子),自研不引 LangGraph | `middleware` |
|
|
86
92
|
| 📋 规划/技能/记忆 | `write_todos` / `define_skill` / AGENTS.md 指令 | `capabilities.*` |
|
|
87
93
|
| 🗄 虚拟工作区 | 内存文件系统,大结果外存不撑爆上下文 | `capabilities.vfs` |
|
|
@@ -91,7 +97,7 @@ CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `
|
|
|
91
97
|
| 🤖 子 agent | 委派子任务,过程不占主上下文 | `subagent` |
|
|
92
98
|
| 🔌 MCP | 连远程 MCP server 动态注入工具 | `mcp` |
|
|
93
99
|
| 📦 上下文压缩 | 4 层自适应压缩,预设档位 + LLM 摘要 | `contextPreset` |
|
|
94
|
-
| 🛡️ 压缩不丢信息 | 摘要内嵌当前
|
|
100
|
+
| 🛡️ 压缩不丢信息 | 摘要内嵌当前 data 快照 + 保留指定工具结果;写返回附可操作 path;`systemPromptHelpers.reliableWriteRules` | 内置 |
|
|
95
101
|
| 💾 持久化 | IndexedDB 多会话 + 配额淘汰 + 切换 | `storage` |
|
|
96
102
|
|
|
97
103
|
能力默认开(`verify`/`approval`/`checkpoint` 默认关;**主动征询 `humanConfirm` 默认开**——AI 遇不确定/多方案主动问你、不猜测),可经 `capabilities` 关掉无用的省 token。
|
|
@@ -109,14 +115,14 @@ createChatSdk, defineTool, defineSkill, presets, z
|
|
|
109
115
|
createAgent, createSubagentMiddleware, createSubagentsMiddleware,
|
|
110
116
|
createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
|
|
111
117
|
createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
|
|
112
|
-
createUsageHintsMiddleware,
|
|
118
|
+
createUsageHintsMiddleware, createDataOps, createVfs, connectMcp
|
|
113
119
|
// 上下文/模型
|
|
114
120
|
resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
|
|
115
121
|
// 存储
|
|
116
122
|
createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
|
|
117
123
|
// UI(headless 自建 UI 复用)
|
|
118
124
|
ChatDialog, MessageContent, CodePreview, useChat
|
|
119
|
-
// 类型(略):ChatSdkOptions, Middleware, SubagentConfig, SkillSpec,
|
|
125
|
+
// 类型(略):ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, DataConfig, AgentMessage, StreamEvent …
|
|
120
126
|
```
|
|
121
127
|
|
|
122
128
|
### `createChatSdk` 选项速查
|
|
@@ -128,9 +134,9 @@ ChatDialog, MessageContent, CodePreview, useChat
|
|
|
128
134
|
| | `llm` | `LLMConfig \| BaseChatModel` · **必传** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`;兼容 OpenAI 协议(默认 DeepSeek) |
|
|
129
135
|
| | `id` | `string` | 稳定 id(多 agent 隔离 + 持久化恢复;不传随机+warn) |
|
|
130
136
|
| | `systemPrompt` | `string` | Agent 身份(不硬编码业务,靠这注入)。可选——不传用内置默认(页面操作助手 + `reliableWriteRules`);传了则完全覆盖 |
|
|
131
|
-
| **页面数据** | `
|
|
137
|
+
| **页面数据** | `data` | `{path,description,schema}[]` | 注册可被工具读写的 数据槽 + zod schema 校验 |
|
|
132
138
|
| | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | 自定义工具 / 技能 / AGENTS.md 风格持久指令 |
|
|
133
|
-
| **能力开关** | `capabilities` | `{planning?,
|
|
139
|
+
| **能力开关** | `capabilities` | `{planning?,dataOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | 默认全开(`verify` 默认关);`false` 关掉省 token |
|
|
134
140
|
| | `permissions` | `PermissionRule[]` | scope 白名单(first-match-wins,默认不启用) |
|
|
135
141
|
| | `humanConfirm` | `boolean` · 默认 `true` | 主动征询(AI 不确定/多方案主动问你,不猜测) |
|
|
136
142
|
| | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝) |
|
|
@@ -139,7 +145,7 @@ ChatDialog, MessageContent, CodePreview, useChat
|
|
|
139
145
|
| **子 agent** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | 运行时自由委派(`spawn_agent`/`spawn_agents`) |
|
|
140
146
|
| | `subagents` | `SubagentConfig[]` | 预声明命名子 agent → 每个生成 `use_<id>` 委派工具 |
|
|
141
147
|
| **上下文** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · 默认 `auto` | 压缩预设档位 |
|
|
142
|
-
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩)。含 `preserveLastToolResults`(默认 `['
|
|
148
|
+
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩)。含 `preserveLastToolResults`(默认 `['describe_data','describe_data']`——压缩摘要里保留字段说明) |
|
|
143
149
|
| | `summaryLlm` | `BaseChatModel \| LLMConfig` | 摘要专用 LLM(不配用主 `llm`) |
|
|
144
150
|
| | `maxMemoryRounds` | `number` · 默认 `50` | 对话历史内存上限轮次(`0` 关裁剪) |
|
|
145
151
|
| | `vfs` | `{initialFiles?,maxBytes?}` · 默认 4MB | 内存工作区上限(超限 LRU 淘汰) |
|
|
@@ -175,8 +181,8 @@ createChatSdk({ subagents: [
|
|
|
175
181
|
|
|
176
182
|
### 内置工具(Agent 可调用)
|
|
177
183
|
|
|
178
|
-
-
|
|
179
|
-
- **window 查询**:`
|
|
184
|
+
- **数据操作**(默认 `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`
|
|
185
|
+
- **window 查询**:`query_data`(JSONPath)/ `search_data`(模糊搜索)/ `eval_script`(沙箱脚本)
|
|
180
186
|
- **抓取**:`fetch_document`
|
|
181
187
|
- **vfs**:`vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
|
|
182
188
|
- **规划/技能**:`write_todos` / `define_skill` / `load_skill`
|
|
@@ -195,7 +201,7 @@ src/core/
|
|
|
195
201
|
│ todos.ts skills.ts memory.ts summarization.ts retry.ts
|
|
196
202
|
│ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
|
|
197
203
|
│ permissions.ts usageHints.ts
|
|
198
|
-
├── tools/ #
|
|
204
|
+
├── tools/ # dataOps(注册表+增量编辑+快照)/ dataSlotQuery / fetchDoc
|
|
199
205
|
├── backends/ # vfs(内存) / storage(IndexedDB+多后端+配额淘汰)
|
|
200
206
|
├── mcp/client.ts # MCP 远程工具接入
|
|
201
207
|
├── composables/ # useChat / useContextManager / useMarkdown
|
|
@@ -212,7 +218,7 @@ CLAUDE.md # 架构要点 + 约定坑 + 编码规范(agen
|
|
|
212
218
|
|
|
213
219
|
| Skill | 触发场景 |
|
|
214
220
|
|---|---|
|
|
215
|
-
| `page-agent-sdk-integrate` | 集成 SDK —— 选引入方式、声明 `
|
|
221
|
+
| `page-agent-sdk-integrate` | 集成 SDK —— 选引入方式、声明 `data` + zod schema、配 LLM、挂载、订阅事件(`onEvent` / `sdk.hook`)、跑 headless、排查常见坑 |
|
|
216
222
|
|
|
217
223
|
**安装**(任选其一):
|
|
218
224
|
|
|
@@ -238,13 +244,13 @@ flowchart TD
|
|
|
238
244
|
SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
|
|
239
245
|
CORE --> AGENT[createAgent<br/>ReAct 循环 + 中间件栈]
|
|
240
246
|
AGENT --> MW[中间件栈<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→用户]
|
|
241
|
-
AGENT --> TOOLS[工具集<br/>
|
|
247
|
+
AGENT --> TOOLS[工具集<br/>dataOps / fetchDoc / vfs / MCP / 用户]
|
|
242
248
|
TOOLS -->|零桥接| WIN[宿主页面 window<br/>直接读写注册属性]
|
|
243
249
|
AGENT --> LLM[LLM<br/>OpenAI 协议 / 任意 ChatModel]
|
|
244
250
|
SDK --> UI[ChatDialog UI<br/>Vue 打包进库 / 或 headless]
|
|
245
251
|
```
|
|
246
252
|
|
|
247
|
-
- **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI —— 且可在 **Node.js 服务端**跑作后端 Agent(自定义工具/子 agent/自检;关 `
|
|
253
|
+
- **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI —— 且可在 **Node.js 服务端**跑作后端 Agent(自定义工具/子 agent/自检;关 `dataOps`+`fetch`,用 `storage:'memory'`)
|
|
248
254
|
- **provider 抽离**:`llm` 传任意 LangChain `BaseChatModel`,或 `LLMConfig`(内部构造 `ChatOpenAI`,兼容 OpenAI 协议,默认接 DeepSeek)
|
|
249
255
|
- **自研 harness**:不引 LangGraph/langchain 整包,规避浏览器打包阻塞
|
|
250
256
|
|
|
@@ -265,11 +271,11 @@ createChatSdk({
|
|
|
265
271
|
llm: { apiKey, baseUrl, model },
|
|
266
272
|
id: 'my-agent', // 稳定 id(多 agent 隔离 + 持久化恢复)
|
|
267
273
|
systemPrompt: '...',
|
|
268
|
-
|
|
274
|
+
data: { schema, bind, description? }, // 单主对象:bind 直连 reactive/普通对象(工具直接读写 bind,不自动挂 window);schema 字段 .describe() 自动注入 systemPrompt「可操作数据」段
|
|
269
275
|
toolMode: 'simple', // 工具呈现:simple(默认,主推 read/write)/ advanced(全暴露)/ minimal(只 read/write)
|
|
270
276
|
interceptors: { // 读写拦截器(脱敏/转换/审计/拒绝 LLM 读写;input/output 在 agent IO 入口/出口)
|
|
271
|
-
read: (
|
|
272
|
-
write: (
|
|
277
|
+
read: (value) => value,
|
|
278
|
+
write: (payload) => payload,
|
|
273
279
|
input: (msg) => msg, // send 入口预处理
|
|
274
280
|
output: (reply) => reply, // 返回前 postprocess
|
|
275
281
|
},
|
|
@@ -284,8 +290,8 @@ createChatSdk({
|
|
|
284
290
|
maxRetries: 2, maxParallelTools: 1,
|
|
285
291
|
subagent: { allowedTools: [...] },
|
|
286
292
|
middleware: [/* 自定义中间件 */],
|
|
287
|
-
onEvent(e) { // SDK 事件回调:订阅常用时机(
|
|
288
|
-
if (e.type === '
|
|
293
|
+
onEvent(e) { // SDK 事件回调:订阅常用时机(主数据变化/消息更新/工具调用/错误),替代轮询
|
|
294
|
+
if (e.type === 'data_change') refreshUI()
|
|
289
295
|
},
|
|
290
296
|
}).mount()
|
|
291
297
|
```
|
|
@@ -298,7 +304,7 @@ createChatSdk({
|
|
|
298
304
|
|---|---|---|
|
|
299
305
|
| page-demo | `/` | 自举 demo:左 JSON 响应式页面 + 右对话框 |
|
|
300
306
|
| nested-demo | `/examples/nested-demo/` | 嵌套区块树 + 人工确认 + checkpoint |
|
|
301
|
-
| dynamic-demo | `/examples/dynamic-demo/` | 懒加载组件 + 动态注册 schema(`sdk.
|
|
307
|
+
| dynamic-demo | `/examples/dynamic-demo/` | 懒加载组件 + 动态注册 schema(`sdk.setData`/``) |
|
|
302
308
|
| human-confirm-demo | `/examples/human-confirm-demo/` | AI 主动征询(多方案点选)+ 写前确认 |
|
|
303
309
|
| planner-demo | `/examples/planner-demo/` | 规划-反思-执行(高温创意 planner + 低温 reflector) |
|
|
304
310
|
| subagent-demo | `/examples/subagent-demo/` | 子 agent 并行编排 |
|
|
@@ -312,7 +318,7 @@ createChatSdk({
|
|
|
312
318
|
|---|---|
|
|
313
319
|
| [文档索引](./doc/README.md) | 各文档导航 + 其他信息源(规范/变更/自测) |
|
|
314
320
|
| [使用手册](./doc/usage-guide.md) | 安装 / 配置项 / 能力详解 / 自定义中间件 / FAQ |
|
|
315
|
-
| [功能架构](./doc/architecture.md) | 分层 / 控制流 /
|
|
321
|
+
| [功能架构](./doc/architecture.md) | 分层 / 控制流 / 数据操作安全流 |
|
|
316
322
|
| [上下文与压缩](./doc/context-management.md) | 上下文组成 / 4 层压缩 / 流程图 |
|
|
317
323
|
| [文件全览](./doc/architecture-files.md) | 逐文件职责 / 依赖 / 数据流 |
|
|
318
324
|
| [CLAUDE.md](./CLAUDE.md) | **agent 必读** · 架构要点 / 约定坑 / 编码规范 |
|
|
@@ -345,20 +351,25 @@ npm install -D vite typescript
|
|
|
345
351
|
import { createChatSdk, z } from 'page-agent-sdk'
|
|
346
352
|
import 'page-agent-sdk/style.css'
|
|
347
353
|
|
|
348
|
-
|
|
354
|
+
const app = { title: '示例', theme: 'light' }
|
|
355
|
+
window.app = app // 可选:挂到 window 供页面读取;工具直接读写 bind
|
|
349
356
|
|
|
350
357
|
createChatSdk({
|
|
351
358
|
container: '#root',
|
|
352
359
|
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
|
|
353
|
-
systemPrompt: '
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
360
|
+
systemPrompt: '你是页面助手,用工具读写主数据。',
|
|
361
|
+
data: {
|
|
362
|
+
schema: z.object({
|
|
363
|
+
title: z.string().describe('标题'),
|
|
364
|
+
theme: z.enum(['light', 'dark']).describe('主题'),
|
|
365
|
+
}),
|
|
366
|
+
bind: app,
|
|
367
|
+
description: '应用配置',
|
|
368
|
+
},
|
|
358
369
|
}).mount()
|
|
359
370
|
```
|
|
360
371
|
|
|
361
|
-
`npx vite` → 对话框输入「把 app.theme 改成 dark」→ AI 调 `write({
|
|
372
|
+
`npx vite` → 对话框输入「把 app.theme 改成 dark」→ AI 调 `write({ value:{ theme:"dark" }, patch:{ op:"merge" } })` → `app.theme` 变为 `dark` 即验证通过。
|
|
362
373
|
|
|
363
374
|
> 建议此测试目录加入 `.gitignore`(纯本地,不进仓库),避免把含真实 key 的 `.env` 提交到远程。
|
|
364
375
|
|
|
@@ -375,7 +386,7 @@ createChatSdk({
|
|
|
375
386
|
`sideEffects` 仅标记 `["**/*.css"]`,打包器可对 JS 做 tree-shaking。瘦身建议:
|
|
376
387
|
|
|
377
388
|
- **headless(`ui:false`)**:不渲染内置对话框,自渲染 `agent.messages` —— 可不引 `ChatDialog`/`CodePreview`,并省略 CSS(`import 'page-agent-sdk'` 不引 `'page-agent-sdk/style.css'`)。
|
|
378
|
-
- **关闭无用能力**:`capabilities:{
|
|
389
|
+
- **关闭无用能力**:`capabilities:{ dataOps:false, fetch:false, planning:false, skills:false, vfs:false, summarization:false, memory:false, subagent:false }` —— 移除对应工具 schema 与中间件(省 token,非字节)。
|
|
379
390
|
- **CDN 用 esm.sh**:`import { createChatSdk } from 'https://esm.sh/page-agent-sdk'` —— peer(`zod`、`@langchain/*`)由 esm.sh 自动解析去重,模块场景最小。
|
|
380
391
|
- **IIFE 仅用于零配置**:全量单文件方便但最重,宿主支持模块时优先 ESM。
|
|
381
392
|
- **MCP 为可选 peer**:`@modelcontextprotocol/sdk` 仅在传 `options.mcp` 时动态 import —— 不用 MCP 完全不加载该运行时。
|
package/dist/page-agent-sdk.css
CHANGED
|
@@ -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*/
|