page-agent-sdk 1.1.1 → 1.1.3

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
@@ -257,26 +257,27 @@ CLAUDE.md # architecture + gotchas + coding conventions (a
257
257
 
258
258
  ## Skills for AI tools (for integrators)
259
259
 
260
- Two ready-to-use Agent Skills are bundled for integrators using Claude Code / Cursor (or any agent harness that loads `.claude/skills/` / `~/.claude/skills/`). They teach the AI how to use **this SDK** in your project:
260
+ A ready-to-use Agent Skill is bundled for integrators using Claude Code / Cursor (or any agent harness that loads `.claude/skills/` / `~/.claude/skills/`). It teaches the AI how to use **this SDK** in your project:
261
261
 
262
262
  | Skill | When it triggers |
263
263
  |---|---|
264
264
  | `page-agent-sdk-integrate` | Embedding the SDK — choose install method, declare `windowProps` + zod schemas, configure the LLM, mount, subscribe to events (`onEvent` / `sdk.hook`), run headless, troubleshoot common pitfalls |
265
- | `page-agent-sdk-release` | Releasing a new version (bump → build → test → push gitee/github → npm publish → verify) — for maintainers |
266
265
 
267
266
  **Install** (pick one):
268
267
 
269
268
  ```bash
270
269
  # Option A — copy from the installed npm package
271
270
  npm i page-agent-sdk
272
- cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-* ~/.claude/skills/
271
+ cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-integrate ~/.claude/skills/
273
272
 
274
273
  # Option B — download from the repo (no install needed)
275
- curl -L https://github.com/whyymj/chat-sdk/tarball/master | tar xz --strip-components=1 --wildcards '*/skills/page-agent-sdk-*'
276
- mv skills/page-agent-sdk-* ~/.claude/skills/
274
+ curl -L https://github.com/whyymj/chat-sdk/tarball/master | tar xz --strip-components=1 --wildcards '*/skills/page-agent-sdk-integrate'
275
+ mv skills/page-agent-sdk-integrate ~/.claude/skills/
277
276
  ```
278
277
 
279
- After install, restart your AI tool; the skills auto-trigger when you ask things like "add page-agent-sdk to my page" or "publish a new version".
278
+ After install, restart your AI tool; the skill auto-triggers when you ask things like "add page-agent-sdk to my page".
279
+
280
+ > A second skill `page-agent-sdk-release` (release workflow for maintainers) is kept in the repo's `.claude/skills/` for project maintainers only and is **not** distributed via the npm package.
280
281
 
281
282
  ## Architecture
282
283
 
package/README.zh-CN.md CHANGED
@@ -202,26 +202,27 @@ CLAUDE.md # 架构要点 + 约定坑 + 编码规范(agen
202
202
 
203
203
  ## 给 AI 工具使用者的 Skills(集成方安装)
204
204
 
205
- 内置两个开箱即用的 Agent Skill,供使用 Claude Code / Cursor(或任何加载 `.claude/skills/` / `~/.claude/skills/` 的 agent 工具)的集成方使用。它们教 AI 如何在**你的项目**中使用本 SDK:
205
+ 内置一个开箱即用的 Agent Skill,供使用 Claude Code / Cursor(或任何加载 `.claude/skills/` / `~/.claude/skills/` 的 agent 工具)的集成方使用。它教 AI 如何在**你的项目**中使用本 SDK:
206
206
 
207
207
  | Skill | 触发场景 |
208
208
  |---|---|
209
209
  | `page-agent-sdk-integrate` | 集成 SDK —— 选引入方式、声明 `windowProps` + zod schema、配 LLM、挂载、订阅事件(`onEvent` / `sdk.hook`)、跑 headless、排查常见坑 |
210
- | `page-agent-sdk-release` | 发布新版本(bump → 构建 → 测试 → 推 gitee/github → 发 npm → 验证)—— 面向维护者 |
211
210
 
212
211
  **安装**(任选其一):
213
212
 
214
213
  ```bash
215
214
  # 方式 A —— 从已安装的 npm 包复制
216
215
  npm i page-agent-sdk
217
- cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-* ~/.claude/skills/
216
+ cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-integrate ~/.claude/skills/
218
217
 
219
218
  # 方式 B —— 从仓库下载(无需安装)
220
- curl -L https://github.com/whyymj/chat-sdk/tarball/master | tar xz --strip-components=1 --wildcards '*/skills/page-agent-sdk-*'
221
- mv skills/page-agent-sdk-* ~/.claude/skills/
219
+ curl -L https://github.com/whyymj/chat-sdk/tarball/master | tar xz --strip-components=1 --wildcards '*/skills/page-agent-sdk-integrate'
220
+ mv skills/page-agent-sdk-integrate ~/.claude/skills/
222
221
  ```
223
222
 
224
- 安装后重启 AI 工具;当你说「把 page-agent-sdk 加到我的页面」「发布新版本」等时 skill 自动触发。
223
+ 安装后重启 AI 工具;当你说「把 page-agent-sdk 加到我的页面」等时 skill 自动触发。
224
+
225
+ > 另有 `page-agent-sdk-release`(维护者发布工作流)skill 仅保留在仓库 `.claude/skills/` 供项目维护者自用,**不**通过 npm 包公开分发。
225
226
 
226
227
  ## 架构
227
228
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "page-agent-sdk",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "description": "框架无关的页面内 Agent JS SDK —— 以对话框形态挂载到任意网页,通过自定义 tool 读写宿主 window 属性(GET 抓文档),具备 planning/skills/虚拟工作区/快照回退/context 管理能力。Vue 打包进库,使用者无需安装 Vue。",
6
6
  "main": "./dist/page-agent-sdk.umd.cjs",
@@ -79,7 +79,15 @@ Event types: `window_prop_change` / `message_update` / `tool_call` / `tool_resul
79
79
 
80
80
  ## References (read as needed)
81
81
 
82
- - `doc/usage-guide.md` (zh) / `doc/usage-guide.en.md`full options reference (onEvent/hook/server-side/checkpoint/approval/verify/subagent/MCP)
82
+ Detailed docs live in this skill's `references/` folder load the one matching the user's question:
83
+
84
+ - **[references/quickstart.md](references/quickstart.md)** — progressive setup from 5-line CDN to full-featured (Stages 0→6). Read when the user wants a step-by-step "from simple to complete" walkthrough.
85
+ - **[references/options.md](references/options.md)** — every `createChatSdk` option: type, default, purpose & when to use. Read when the user asks "what does option X do" or needs to tune behavior.
86
+ - **[references/api.md](references/api.md)** — instance methods (`mount`/`send`/`stream`/`inspect`/`switchSession`/`hook`/checkpoints), `defineTool`/`defineSkill`/`presets`, built-in window tools, and the full `SdkEvent` type table. Read when the user asks about APIs, tools, or events.
87
+ - **[references/use-cases.md](references/use-cases.md)** — 9 end-to-end scenarios (low-code builder / form designer / CMS batch / ops console / AI-native / research / server-side / multi-agent / MCP). Read when the user wants a concrete pattern for their use case.
88
+
89
+ Project-level docs (in the repo, not bundled in this skill):
90
+ - `doc/usage-guide.md` (zh) / `doc/usage-guide.en.md` — full options reference
83
91
  - `examples/<demo>/` — runnable demos (page-demo, nested-demo, subagent-demo, mcp-demo, planner-demo, toolsets-demo, human-confirm-demo)
84
92
  - `demo/plain.html` — framework-agnostic CDN integration
85
93
  - `CLAUDE.md` — internal dev guide (architecture, conventions)
@@ -0,0 +1,119 @@
1
+ # API reference — instance methods, tool/skill definition, window tools, events
2
+
3
+ ## ChatSdk instance (`createChatSdk(...)` return)
4
+
5
+ | Method / field | Signature | Purpose |
6
+ |---|---|---|
7
+ | `mount()` | `() => Promise<void>` | Initialize & render. Await before `send` in headless. |
8
+ | `unmount()` | `() => void` | Tear down UI, listeners, flush storage. |
9
+ | `messages` | `AgentMessage[]` (reactive) | The conversation. Headless reads this to render. UI shares the same array (single source). |
10
+ | `send(message)` | `(msg: string) => Promise<string>` | Send a user message (invoke mode, no stream events). Returns final content. |
11
+ | `stream` | `(messages, onEvent, signal?) => Promise<string>` | Low-level stream. UI uses this internally; headless can call directly for streaming. |
12
+ | `inspect()` | `() => AgentInfo` | Inspect agent: tools/skills/windowProps/middleware/todos/mcp.servers (each tool's `source`: `builtin`/`mcp:<name>`/`user`). DebugDrawer uses this. |
13
+ | `switchSession(id?)` | `(id?: string) => Promise<string>` | Switch session context (load or create by id). Requires `storage` enabled. |
14
+ | `hook(handler)` | `(h: SdkEventHandler) => () => void` | Runtime event subscription (multi-listener, returns unsubscribe). Complements `onEvent`. |
15
+ | `restoreLastCheckpoint()` | `() => boolean` | Restore last good checkpoint (needs `checkpoint` enabled). |
16
+ | `listCheckpoints()` | `() => CheckpointMeta[]` | List available checkpoints. |
17
+
18
+ ## defineTool (custom tools)
19
+
20
+ ```ts
21
+ import { defineTool, z } from 'page-agent-sdk'
22
+
23
+ const addTool = defineTool({
24
+ name: 'add',
25
+ description: 'Add two numbers',
26
+ schema: z.object({ a: z.number(), b: z.number() }),
27
+ handler: async ({ a, b }) => `sum: ${a + b}`,
28
+ })
29
+
30
+ createChatSdk({ tools: [addTool], /* llm, ... */ }).mount()
31
+ ```
32
+
33
+ `handler` receives validated args; return a string (or structured result stringified). Errors via `toolError({ path, code, message })`.
34
+
35
+ ## defineSkill (progressive disclosure)
36
+
37
+ ```ts
38
+ import { defineSkill } from 'page-agent-sdk'
39
+
40
+ const apiSkill = defineSkill({
41
+ name: 'api-design',
42
+ description: 'REST API design conventions for this project',
43
+ prompt: 'Use kebab-case URLs; version under /v1; ...',
44
+ })
45
+
46
+ createChatSdk({ skills: [apiSkill], /* ... */ }).mount()
47
+ ```
48
+
49
+ Skills are loaded on demand by the agent (not always in context) — saves tokens.
50
+
51
+ ## presets (scenario bundles)
52
+
53
+ ```ts
54
+ import { createChatSdk, presets } from 'page-agent-sdk'
55
+
56
+ createChatSdk({ ...presets.pageBuilder, llm, container }).mount()
57
+ // or presets.researcher / presets.minimal
58
+ ```
59
+
60
+ Spread into options for common scenarios.
61
+
62
+ ## Built-in window tools (auto-injected when `capabilities.windowOps`)
63
+
64
+ | Tool | Purpose |
65
+ |---|---|
66
+ | `list_window_props` | List declared paths + descriptions |
67
+ | `describe_window_prop` | Show a path's schema |
68
+ | `get_window_prop` | Read a path (or ancestor/descendant sub-paths of registered props) |
69
+ | `get_window_paths` | Batch-read multiple paths |
70
+ | `set_window_prop` | Write a whole path (schema-validated, scoped to registry) |
71
+ | `edit_window_prop` | Patch by `jsonPath` (set/remove/merge/append) — avoids re-sending large JSON |
72
+ | `delete_window_prop` | Delete a path |
73
+ | `snapshot_window_prop` | Manual snapshot |
74
+ | `list_window_snapshots` | List snapshots |
75
+ | `restore_window_snapshot` | Restore (no id = most recent) |
76
+ | `query_window_prop` / `search_window_prop` | JSONPath query / full-text search |
77
+ | `eval_window_script` | Sandboxed script on data (for batch ops) |
78
+
79
+ **Key rule**: `set`/`edit`/`delete` only affect **declared** `windowProps` paths. Invalid schema → structured error, no write. `edit` writes in-place (preserves Vue reactive refs).
80
+
81
+ ### jsonPath edit operations
82
+
83
+ `edit_window_prop({ path, jsonPath, op, value })`:
84
+ - `set` — set a sub-path
85
+ - `remove` — remove a sub-path / array element
86
+ - `merge` — shallow-merge an object
87
+ - `append` — append to an array
88
+
89
+ Example: `edit_window_prop({ path: 'app.items', jsonPath: '0.price', op: 'set', value: 9.9 })` — precise local edit, no full re-send.
90
+
91
+ ## Built-in fetch tools (`capabilities.fetch`)
92
+
93
+ `fetch_document` — GET a URL, return cleaned text (HTML→markdown, truncated, offloaded to vfs if large).
94
+
95
+ ## SdkEvent types (for `onEvent` / `sdk.hook`)
96
+
97
+ | `type` | Payload | When |
98
+ |---|---|---|
99
+ | `round_start` | `round` | Each agent round begins |
100
+ | `reasoning` | `delta` | Reasoning token (models that emit it) |
101
+ | `text` | `delta` | Streamed text delta (stream mode only) |
102
+ | `tool_call` | `name, args` | A tool is invoked |
103
+ | `tool_result` | `name, result, status` | Tool returns (`status`: `done`/`error`) |
104
+ | `subagent` | `taskId, label, kind, name, args?, result?, status?` | Subagent tool progress (forwarded to UI, NOT into main LLM context) |
105
+ | `done` | `content` | Agent round completes |
106
+ | `window_prop_change` | `path, operation, value?` | A window prop was written (`operation`: `set`/`edit`/`delete`/`restore`) |
107
+ | `message_update` | `count` | The `messages` array changed |
108
+ | `error` | `message` | An error occurred (abort excluded) |
109
+
110
+ `approval_request` is **NOT** forwarded via `onEvent`/`hook` (UI handles it; headless integrators use a custom approval middleware listener).
111
+
112
+ ## Exported building blocks (for custom UIs)
113
+
114
+ - `ChatDialog`, `MessageContent`, `CodePreview` — Vue components
115
+ - `useChat(opts)` — composable (streaming/retry/stop/regenerate logic)
116
+ - `createAgent(options)` — the raw harness (if you bypass `createChatSdk`)
117
+ - Middleware factories: `createApprovalMiddleware`, `createVerifyMiddleware`, `createWriteBackCheck`, `createSubagentMiddleware`, `createCheckpointMiddleware`, `createUsageHintsMiddleware`
118
+ - Storage: `createSessionStore`, `createMemoryBackend`, `createWebStorageBackend`, `isQuotaError`
119
+ - JSON helpers: `jpEval`, `searchJson`, `runSandboxedScript`, `toolError`, `zodError`
@@ -0,0 +1,124 @@
1
+ # createChatSdk options — what each does & when to use
2
+
3
+ Full reference for `createChatSdk(options)`. Grouped by purpose. Required: `llm`. Everything else is optional with sane defaults.
4
+
5
+ ## LLM & identity
6
+
7
+ | Option | Type | Default | Purpose / when |
8
+ |---|---|---|---|
9
+ | `llm` | `LLMConfig \| BaseChatModel` | — (required) | The model. `LLMConfig = { apiKey, baseUrl, model, temperature?, maxTokens? }` (OpenAI-compatible; DeepSeek default). Or pass any LangChain `BaseChatModel` (e.g. `ChatAnthropic`, install its peerDep). |
10
+ | `systemPrompt` | `string` | generic page assistant | Agent identity/instructions. Inject here, not hardcoded. Keep single-line in `.env` (`VITE_AI_SYSTEM_PROMPT`). |
11
+ | `id` | `string` | random + warn | Stable agent id for multi-agent isolation & persistence. **Must pass a stable value** if you use `storage` or run multiple agents on one page. |
12
+ | `title` / `placeholder` | `string` | — | Dialog title / input placeholder (cosmetic). |
13
+
14
+ ## UI & mounting
15
+
16
+ | Option | Type | Default | Purpose / when |
17
+ |---|---|---|---|
18
+ | `container` | `string \| HTMLElement` | — | Where the built-in dialog mounts. Required when `ui !== false`. |
19
+ | `ui` | `boolean \| 'default'` | `true` | `false` = headless (no built-in dialog; you build UI from `sdk.messages` + `sdk.send`). `'default'` = built-in `ChatDialog`. |
20
+ | `streaming` | `boolean` | `true` | Stream tokens live. `false` = wait for full reply. Headless `sdk.send` always uses invoke (no stream events, but window/message/error still fire). |
21
+
22
+ ## window operation (the core)
23
+
24
+ | Option | Type | Default | Purpose / when |
25
+ |---|---|---|---|
26
+ | `windowProps` | `WindowPropSpec[]` | `[]` | Declare writable `window` paths + zod schemas. The agent can ONLY touch declared paths; `set`/`edit` are schema-validated. **This is the key integration step.** |
27
+ | `maxSnapshots` | `number` | 20 | Per-path snapshot stack depth for `restore_window_snapshot`. |
28
+ | `permissions` | `PermissionRule[]` | off | Scope whitelist (first-match-wins) for fine-grained per-path/tool rules. Default off (all declared paths writable). |
29
+
30
+ `WindowPropSpec = { path: string; description: string; schema?: z.ZodType }`. `description` is shown to the AI — write it clearly so the agent knows what each path means.
31
+
32
+ ## Tools, skills, memory
33
+
34
+ | Option | Type | Default | Purpose / when |
35
+ |---|---|---|---|
36
+ | `tools` | `Tool[]` | `[]` | Custom tools beyond built-ins. Use `defineTool({ name, description, schema, handler })`. |
37
+ | `skills` | `SkillSpec[]` | `[]` | Progressive-disclosure skills (`defineSkill({ name, description, prompt }`) loaded on demand by the agent. |
38
+ | `memory` | `string` | — | AGENTS.md-style persistent instructions injected into every prompt (project conventions, hard rules). |
39
+ | `middleware` | `Middleware[]` | `[]` | Custom middleware appended after built-ins. 8 hooks: `beforeAgent`/`wrapModelCall`/`beforeModel`/`afterModel`/`wrapToolCall`/`afterAgent`/`beforeReturn` + `augmentPrompt`/`compressInput`/`tools`. For interception, instrumentation, prompt enhancement. |
40
+
41
+ ## Capabilities (turn built-ins on/off)
42
+
43
+ `capabilities: { ... }` — default all `true` except `verify`. Set `false` to drop unused built-ins (saves tokens/size).
44
+
45
+ | Flag | Off when... |
46
+ |---|---|
47
+ | `windowOps` | Pure research agent, no page edits (also drops window tools from subagents). |
48
+ | `fetch` | No web fetching needed. ⚠️ turning off `windowOps` also strips subagent window tools. |
49
+ | `planning` | Don't want `write_todos` planning. |
50
+ | `skills` | Don't want progressive skill loading. |
51
+ | `vfs` | No in-memory workspace; ⚠️ large tool results then truncate instead of offloading. |
52
+ | `summarization` | No context compression; ⚠️ long sessions grow unbounded. |
53
+ | `memory` | No persistent instructions. |
54
+ | `subagent` | No `spawn_agent`/`spawn_agents` delegation. |
55
+ | `verify` (reverse) | **Off by default**; `true` enables write-back self-check before the agent returns (costs tokens). |
56
+
57
+ ## Robustness & limits
58
+
59
+ | Option | Type | Default | Purpose / when |
60
+ |---|---|---|---|
61
+ | `maxRetries` | `number` | 2 | Model call retries on network/429/5xx (exponential backoff). 4xx & abort don't retry. |
62
+ | `maxParallelTools` | `number` | 1 | Same-round tool concurrency. `>1` is faster but watch stateful middleware (todos counts). |
63
+ | `maxToolRounds` | `number` | — | Cap agent tool rounds (safety against loops). |
64
+ | `maxMemoryRounds` | `number` | 50 | In-memory dialog rounds cap; oldest compressed to a summary system message (OOM guard). `0` disables. |
65
+ | `contextWindow` / `maxOutputTokens` | `number` | by model name | Override model context/output token limits (affects offload threshold & compression trigger). |
66
+ | `debug` | `boolean` | `false` | Verbose logging / DebugDrawer. |
67
+
68
+ ## Context compression
69
+
70
+ | Option | Type | Default | Purpose / when |
71
+ |---|---|---|---|
72
+ | `contextPreset` | `'auto'\|'conservative'\|'aggressive'` | `auto` | `conservative` = save cost; `aggressive` = save context. `contextOptions` fine-tunes further. |
73
+ | `contextOptions` | `object` | — | Detailed compression params (overrides preset). `false` disables compression. |
74
+ | `summaryLlm` | `BaseChatModel \| LLMConfig` | main `llm` | Use a cheaper/faster model for summarization. |
75
+ | `summaryTemperature` | `number` | 0.3 | Summary model temperature. |
76
+ | `summaryMaxTokens` | `number` | 1024 | Summary output cap. |
77
+ | `summaryTimeoutMs` | `number` | 15000 | On timeout, fall back to index-based summary (no failure). |
78
+
79
+ ## Subagent (delegation)
80
+
81
+ | Option | Type | Default | Purpose / when |
82
+ |---|---|---|---|
83
+ | `subagent` | `object` | enabled | `{ enabled?, allowedTools?, systemPrompt?, temperature?, maxTokens?, skills?, llm?, maxDepth?, maxParallel? }`. `maxDepth` (1) physically cuts recursion. Subagents get a read-only tool subset (no spawn). |
84
+ | `subagents` | `SubagentConfig[]` | `[]` | Pre-declared named subagents → each auto-generates a `use_<id>({ task })` delegation tool (Claude-Code style). Fixed roles (research/review) vs ad-hoc `spawn_agent`. |
85
+
86
+ ## Verify (self-check before return)
87
+
88
+ `capabilities.verify: true` enables. `verify: { check?, maxAttempts?, adversarial? }`:
89
+ - `check` omitted → default `createWriteBackCheck()` (scans all writes, reads back + schema-validates; skips legitimately-rejected writes).
90
+ - custom `check: async ({ messages, state }) => ({ ok, feedback? })` — return **actionable** feedback.
91
+ - `adversarial: true` → after check passes, spawn a read-only "refuter" subagent (costs extra rounds; for semantically complex cases).
92
+ - `maxAttempts` (default 2) caps self-correction loops.
93
+
94
+ ## Approval (human-in-the-loop)
95
+
96
+ `approval: { tools?, confirm?, ... }` — human confirms before tool execution. Default off; passing `approval` enables. Headless integrators listen for `approval_request` (NOT forwarded via `onEvent`/`hook`) to build their own confirm UI.
97
+
98
+ ## Checkpoint (session rollback)
99
+
100
+ `checkpoint: true \| { maxCheckpoints?, auto? }` — per-round snapshot of (messages + window props + vfs + todos). `restoreLastCheckpoint()` / LLM tool `restore_last_checkpoint` / UI button. Distinct from windowOps per-path snapshots (checkpoint = whole-session rollback).
101
+
102
+ ## Persistence (storage)
103
+
104
+ | Option | Type | Default | Purpose / when |
105
+ |---|---|---|---|
106
+ | `storage` | `'indexed'\|'session'\|'local'\|'memory'\| StorageConfig \| false` | `false` (off) | Off by default; assign to enable. Persists messages/vfs/todos/memory (NOT window snapshots). Auto-degrades to memory if backend unavailable (private mode / quota). |
107
+ | `session` | `SessionOptions` | — | Session control (resume by id, etc.). |
108
+ | `shareContext` | `boolean` | `false` | `true` → multiple `createChatSdk` with same `id` share one `AgentCore` (same agent, multiple dialog views on a page). |
109
+
110
+ ## MCP (external tools)
111
+
112
+ `mcp: [{ transport: 'http'\|'sse'\|'websocket', url, name?, requestInit? }]` — connect remote MCP servers, dynamically inject their tools (`Promise.allSettled` fault-isolated). Browser only supports remote transports (no stdio). `@modelcontextprotocol/sdk` is an optional peerDep, dynamically imported only when used.
113
+
114
+ ## Events
115
+
116
+ | Option | Type | Default | Purpose / when |
117
+ |---|---|---|---|
118
+ | `onEvent` | `(e: SdkEvent) => void` | — | Constructor-time event subscription (single). Replaces polling for host-page reactivity. See [api.md](api.md) for event types. |
119
+
120
+ Runtime subscription via `sdk.hook(handler) => () => void` (multi-listener, cancellable) — see [api.md](api.md).
121
+
122
+ ## vfs (in-memory workspace)
123
+
124
+ `vfs: { initialFiles?, maxBytes? }` — `maxBytes` default 4MB; LRU-evicts oldest files on overflow. Tool results > 6000 chars auto-offload to vfs (only preview + `vfs_read`/`vfs_grep` reference kept). Disabling `capabilities.vfs` degrades to truncation.
@@ -0,0 +1,122 @@
1
+ # Quickstart (progressive)
2
+
3
+ From the smallest working setup to a full-featured integration. Read top-down; stop wherever your needs are met.
4
+
5
+ ## Stage 0 — Prerequisites
6
+
7
+ - An OpenAI-compatible LLM endpoint (DeepSeek works out of the box). Get an API key.
8
+ - Page data you want the AI to edit, placed on `window` (e.g. `window.app = { ... }`).
9
+
10
+ ## Stage 1 — Minimal (5 lines, CDN, no build)
11
+
12
+ Drop into any HTML page. The built-in dialog mounts itself.
13
+
14
+ ```html
15
+ <div id="root"></div>
16
+ <script src="https://unpkg.com/page-agent-sdk"></script>
17
+ <script>
18
+ window.app = { title: 'Hello', theme: 'light' }
19
+ ChatSdk.createChatSdk({
20
+ container: '#root',
21
+ llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
22
+ systemPrompt: 'You are a page assistant. Read/write window.app via tools.',
23
+ windowProps: [
24
+ { path: 'app.title', description: '标题', schema: ChatSdk.z.string() },
25
+ { path: 'app.theme', description: '主题', schema: ChatSdk.z.enum(['light','dark']) },
26
+ ],
27
+ }).mount()
28
+ </script>
29
+ ```
30
+
31
+ Talk to it: "change theme to dark" → AI calls `set_window_prop` → `window.app.theme === 'dark'`.
32
+
33
+ ## Stage 2 — npm + module project
34
+
35
+ ```bash
36
+ npm i page-agent-sdk zod @langchain/openai @langchain/core
37
+ ```
38
+
39
+ ```ts
40
+ import { createChatSdk, z } from 'page-agent-sdk'
41
+ import 'page-agent-sdk/style.css'
42
+
43
+ window.app = { title: 'Hello', theme: 'light', items: [] }
44
+
45
+ const sdk = createChatSdk({
46
+ container: '#root',
47
+ llm: { apiKey: import.meta.env.VITE_AI_API_KEY, baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
48
+ systemPrompt: 'You are a page assistant. Read/write window.app via tools.',
49
+ windowProps: [
50
+ { path: 'app.title', description: '标题', schema: z.string() },
51
+ { path: 'app.theme', description: '主题', schema: z.enum(['light','dark']) },
52
+ { path: 'app.items', description: '列表项', schema: z.array(z.object({ name: z.string(), price: z.number() })) },
53
+ ],
54
+ }).mount()
55
+ ```
56
+
57
+ ## Stage 3 — React to changes (replace polling)
58
+
59
+ Subscribe via `onEvent` (constructor) or `sdk.hook` (runtime, multi-listener, cancellable):
60
+
61
+ ```ts
62
+ const sdk = createChatSdk({
63
+ onEvent(e) {
64
+ if (e.type === 'window_prop_change') renderUI() // host page reactive refresh
65
+ if (e.type === 'error') console.error(e.message)
66
+ },
67
+ // ...llm, windowProps...
68
+ }).mount()
69
+
70
+ // runtime listener (e.g. analytics), cancellable
71
+ const off = sdk.hook((e) => { if (e.type === 'tool_call') track(e.name) })
72
+ // off()
73
+ ```
74
+
75
+ ## Stage 4 — Headless (custom UI, framework-agnostic)
76
+
77
+ No built-in dialog; drive the reactive `messages` array yourself.
78
+
79
+ ```ts
80
+ const sdk = createChatSdk({
81
+ ui: false, // headless
82
+ llm: { ... }, systemPrompt: '...', windowProps: [...],
83
+ }).mount()
84
+
85
+ // your own UI reads sdk.messages (reactive) and calls sdk.send
86
+ await sdk.send('add a new item: name=Pen, price=3')
87
+ ```
88
+
89
+ Reusable `ChatDialog` / `MessageContent` / `CodePreview` components + `useChat` composable are also exported if you want to assemble a custom UI from existing parts.
90
+
91
+ ## Stage 5 — Tune capabilities & safety
92
+
93
+ ```ts
94
+ createChatSdk({
95
+ // ...llm, windowProps...
96
+ capabilities: { verify: true }, // write-back self-check before agent returns
97
+ verify: { maxAttempts: 2 }, // auto-correct on failure (default check = write-back read + schema)
98
+ approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // human-confirm before writes
99
+ checkpoint: true, // session-level rollback on bad edits
100
+ maxParallelTools: 1, // serial tool calls (safe for stateful middleware)
101
+ contextPreset: 'conservative', // save cost on long sessions
102
+ }).mount()
103
+ ```
104
+
105
+ ## Stage 6 — Persist across refresh / multi-session
106
+
107
+ ```ts
108
+ createChatSdk({
109
+ id: 'my-page-agent', // STABLE id (multi-agent isolation); omit = random + warn
110
+ storage: 'indexed', // persist messages/vfs/todos/memory to IndexedDB
111
+ // ...llm, windowProps...
112
+ }).mount()
113
+
114
+ // later, switch session:
115
+ await sdk.switchSession('session-abc') // load or create
116
+ ```
117
+
118
+ ## Next
119
+
120
+ - All options: see [options.md](options.md)
121
+ - Instance API + tool/skill definition: see [api.md](api.md)
122
+ - End-to-end scenarios: see [use-cases.md](use-cases.md)
@@ -0,0 +1,200 @@
1
+ # Use cases — end-to-end scenarios
2
+
3
+ Concrete integration patterns for common scenarios. Each shows the key `windowProps` + options that matter. Adapt the LLM config to your provider.
4
+
5
+ ## 1. Low-code page builder
6
+
7
+ A visual builder where the page is a component tree; the AI edits the tree via jsonPath patches and the canvas re-renders live.
8
+
9
+ ```ts
10
+ window.page = {
11
+ components: [
12
+ { id: 'banner', type: 'banner', props: { title: 'Welcome', bg: '#1f4d3a' } },
13
+ { id: 'card1', type: 'card', props: { title: '新品', price: 99 } },
14
+ ],
15
+ }
16
+
17
+ createChatSdk({
18
+ container: '#chat',
19
+ llm: { apiKey, baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat', temperature: 0.3 },
20
+ systemPrompt: '你是页面搭建助手。用 edit_window_prop 按 jsonPath 增量改 components,不要重传整树。',
21
+ windowProps: [
22
+ { path: 'page.components', description: '组件树',
23
+ schema: z.array(z.object({
24
+ id: z.string(), type: z.string(),
25
+ props: z.record(z.any()),
26
+ })) },
27
+ ],
28
+ onEvent(e) { if (e.type === 'window_prop_change') renderCanvas() }, // canvas reactive refresh
29
+ checkpoint: true, // bad edit → one-click rollback
30
+ approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // confirm writes
31
+ }).mount()
32
+ ```
33
+
34
+ User: "顶部 Banner 改深色、主标题加粗、加一张新品卡" → AI calls `edit_window_prop` per component.
35
+
36
+ ## 2. Form designer
37
+
38
+ Form schema as data; AI edits field definitions, schema validation prevents malformed forms.
39
+
40
+ ```ts
41
+ window.form = {
42
+ fields: [
43
+ { name: 'phone', label: '手机号', type: 'text', required: true, validation: 'none' },
44
+ { name: 'address', label: '地址', type: 'text', required: false, cascade: false },
45
+ ],
46
+ }
47
+
48
+ createChatSdk({
49
+ container: '#chat', llm: { ... },
50
+ systemPrompt: '你是表单设计助手。改 form.fields 的字段定义,保持 schema 合法。',
51
+ windowProps: [
52
+ { path: 'form.fields', description: '字段定义数组',
53
+ schema: z.array(z.object({
54
+ name: z.string(), label: z.string(),
55
+ type: z.enum(['text','number','select','date']),
56
+ required: z.boolean(),
57
+ validation: z.enum(['none','phone','email','idcard']),
58
+ cascade: z.boolean().optional(),
59
+ })) },
60
+ ],
61
+ onEvent(e) { if (e.type === 'window_prop_change') renderForm() },
62
+ }).mount()
63
+ ```
64
+
65
+ User: "手机号加格式校验、地址改三级联动" → AI patches `form.fields[0].validation='phone'`, `form.fields[1].cascade=true`.
66
+
67
+ ## 3. CMS batch operation
68
+
69
+ Bulk-edit a product list; use `eval_window_script` or `search_window_prop` + `edit_window_prop` for batch ops.
70
+
71
+ ```ts
72
+ window.products = [
73
+ { id: 1, title: '商品A', price: 99, highlight: false },
74
+ { id: 2, title: '商品B', price: 150, highlight: false },
75
+ // ...hundreds
76
+ ]
77
+
78
+ createChatSdk({
79
+ container: '#chat', llm: { ... },
80
+ systemPrompt: '你是运营助手。批量改 products;标题加前缀用 eval_window_script,按条件筛选用 search_window_prop。',
81
+ windowProps: [
82
+ { path: 'products', description: '商品列表',
83
+ schema: z.array(z.object({
84
+ id: z.number(), title: z.string(), price: z.number(), highlight: z.boolean(),
85
+ })) },
86
+ ],
87
+ onEvent(e) { if (e.type === 'window_prop_change') renderTable() },
88
+ }).mount()
89
+ ```
90
+
91
+ User: "标题加『限时』前缀、低于 100 元的标红" → AI uses `eval_window_script` for the prefix loop + `search_window_prop` to find `<100` then `edit_window_prop` to set `highlight`.
92
+
93
+ ## 4. Ops config console
94
+
95
+ Edit experiment thresholds / feature flags with human confirmation.
96
+
97
+ ```ts
98
+ window.config = {
99
+ expA: { threshold: 0.5, enabled: true },
100
+ featureB: { enabled: false },
101
+ }
102
+
103
+ createChatSdk({
104
+ container: '#chat', llm: { ... },
105
+ systemPrompt: '你是运维助手。改 config 前必须经用户确认。',
106
+ windowProps: [
107
+ { path: 'config.expA', description: '实验A',
108
+ schema: z.object({ threshold: z.number().min(0).max(1), enabled: z.boolean() }) },
109
+ { path: 'config.featureB', description: 'B开关',
110
+ schema: z.object({ enabled: z.boolean() }) },
111
+ ],
112
+ approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // human-in-the-loop
113
+ checkpoint: true,
114
+ capabilities: { verify: true }, // write-back read + schema check
115
+ }).mount()
116
+ ```
117
+
118
+ User: "A 实验阈值调到 30%、关掉 B 开关" → AI proposes writes → user confirms → verify reads back.
119
+
120
+ ## 5. AI-native assistant (no page data, custom tools)
121
+
122
+ The agent drives your product's own API via custom tools (no windowOps).
123
+
124
+ ```ts
125
+ const lookupTool = defineTool({
126
+ name: 'lookup_order',
127
+ description: '查询订单',
128
+ schema: z.object({ orderId: z.string() }),
129
+ handler: async ({ orderId }) => JSON.stringify(await api.getOrder(orderId)),
130
+ })
131
+
132
+ createChatSdk({
133
+ container: '#chat',
134
+ llm: { ... },
135
+ systemPrompt: '你是订单助手。用 lookup_order 查询。',
136
+ tools: [lookupTool],
137
+ capabilities: { windowOps: false, fetch: false }, // pure custom-tool agent
138
+ }).mount()
139
+ ```
140
+
141
+ ## 6. Research agent (fetch + subagents, no writes)
142
+
143
+ Pure research: fetch docs, parallel subagents for multi-source investigation.
144
+
145
+ ```ts
146
+ createChatSdk({
147
+ container: '#chat', llm: { ... },
148
+ systemPrompt: '你是调研助手。多源对比用 spawn_agents 并行委派。',
149
+ capabilities: { windowOps: false }, // read-only, no page edits
150
+ subagent: { allowedTools: ['fetch_document'] },
151
+ contextPreset: 'conservative', // long research sessions
152
+ }).mount()
153
+ ```
154
+
155
+ ## 7. Headless server-side (Node.js)
156
+
157
+ Run the agent in Node (no browser). Provide `globalThis.window` only if you enable windowOps.
158
+
159
+ ```ts
160
+ // node mjs
161
+ import { createChatSdk, z } from 'page-agent-sdk'
162
+
163
+ const sdk = createChatSdk({
164
+ ui: false,
165
+ storage: 'memory',
166
+ llm: { apiKey, baseUrl, model },
167
+ systemPrompt: '...',
168
+ capabilities: { windowOps: false, fetch: false },
169
+ tools: [/* your tools */],
170
+ })
171
+ await sdk.mount()
172
+ const reply = await sdk.send('do something')
173
+ console.log(reply)
174
+ sdk.unmount()
175
+ ```
176
+
177
+ ## 8. Multi-agent on one page (shared context)
178
+
179
+ Two dialogs backed by one agent brain.
180
+
181
+ ```ts
182
+ const a = createChatSdk({ id: 'shared', container: '#dlg-a', llm: {...}, shareContext: true, windowProps }).mount()
183
+ const b = createChatSdk({ id: 'shared', container: '#dlg-b', llm: {...}, shareContext: true, windowProps }).mount()
184
+ // a & b share messages/agent/vfs/todos/memory — two views of one agent
185
+ ```
186
+
187
+ ## 9. MCP integration (external tool servers)
188
+
189
+ ```ts
190
+ createChatSdk({
191
+ container: '#chat', llm: { ... },
192
+ mcp: [
193
+ { transport: 'http', url: 'https://my-mcp-server/mcp' },
194
+ { transport: 'sse', url: 'https://another/sse' },
195
+ ],
196
+ // MCP tools auto-injected; fault-isolated (one server down doesn't break others)
197
+ }).mount()
198
+ ```
199
+
200
+ > Note: `@modelcontextprotocol/sdk` is an optional peerDep — install it only if you use `mcp`. Browser supports only remote transports (http/sse/websocket), not stdio.
@@ -1,44 +0,0 @@
1
- ---
2
- name: page-agent-sdk-release
3
- description: Release a new version of the page-agent-sdk npm package and push to its two git remotes (Gitee + GitHub). Use when the user wants to publish/ship a new version, bump the version, build + test before release, push to gitee/github, or follow the project's release checklist. Covers the full flow: code changes → sync zh/en docs → bump semver → build + self-test → commit → push Gitee → push GitHub → npm publish → verify.
4
- ---
5
-
6
- # Release page-agent-sdk
7
-
8
- Execute the project's release checklist end-to-end. The authoritative, detailed checklist lives in `CLAUDE.md` → "发布流程 checklist"; read that section first, then follow the steps below.
9
-
10
- ## Two remotes (do NOT mix them up)
11
-
12
- | remote | URL | role |
13
- |---|---|---|
14
- | `origin` | gitee.com/whyymj/**chat-agent**.git | daily storage, keeps all granular commits |
15
- | `github` | github.com/whyymj/**chat-sdk**.git | official open-source, receives curated commits |
16
-
17
- Personal notes (`doc/待确认问题.md`) are gitignored — Gitee only, never GitHub.
18
-
19
- ## Release checklist (in order)
20
-
21
- 1. **Code**: edit `src/`, sync `types/index.d.ts` (hand-maintained), update exports in `src/core/index.ts`.
22
- 2. **Docs (sync zh + en, never single-side)**:
23
- - `README.md` (en) / `README.zh-CN.md` (zh) — features, usage, scenarios
24
- - `doc/README.md` (zh) / `doc/README.en.md` (en) — doc index
25
- - `doc/usage-guide.md` (zh) / `doc/usage-guide.en.md` (en) — usage guide
26
- - `CLAUDE.md` — internal dev guide/architecture
27
- - Keep language toggle links bidirectional.
28
- 3. **Bump version**: `npm version patch|minor|major --no-git-tag-version` (semver: minor for new API, major for breaking, patch for fix). Never republish the same version.
29
- 4. **Build + self-test**: `npm run build` (= `build:lib` + `build:iife`) then `npm test` (341 assertions must pass). Run `npm pack --dry-run` to confirm the tarball excludes `.env` / `src` / `examples` / notes.
30
- 5. **Commit**: `git add -A && git commit -m "feat/fix/docs: ..."` (conventional style).
31
- 6. **Push Gitee** (daily storage): `git push origin master`. If you just rebased and rewrote history → `git push --force-with-lease origin master` (personal repo, safe).
32
- 7. **Push GitHub** (official): `git push github master`. If rejected as `non-fast-forward` → `git fetch github master && git pull --rebase github master` then push again.
33
- 8. **Publish to npm**: `npm publish` (`publishConfig.registry` is locked to the official npm registry, unaffected by the machine's default private registry).
34
- 9. **Verify**: `npm view page-agent-sdk version` (confirm latest) + a temp dir `npm i page-agent-sdk` to confirm it installs + imports.
35
-
36
- ## npm credentials gotchas
37
-
38
- - Account `whyymj` has 2FA enabled. Use an **Automation Access Token** (npmjs.com → Access Tokens → Classic → Automation, bypasses OTP); write to user-level `~/.npmrc` via `npm config set //registry.npmjs.org/:_authToken <token> --location=user`. Revoke after use. Never commit tokens or store them in the project dir.
39
- - `npm login` / `npm whoami` require `--registry=https://registry.npmjs.org/` (machine default may be a private registry).
40
-
41
- ## References
42
-
43
- - `CLAUDE.md` → "发布流程 checklist" / "双远程仓库与发布约定" / "npm 发布约定" — authoritative details.
44
- - `package.json` → `publishConfig`, `exports`, `files`, `peerDependencies`.