page-agent-sdk 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,34 +1,49 @@
1
1
  # page-agent-sdk
2
2
 
3
- > 给网页一个**会改页面的 AI 助手**。一行代码挂载对话框,AI 通过工具按 schema 安全读写页面数据,实现「对话式」搭建/编辑/运维。
3
+ > **[English](./README.md)** · **[中文](./README.zh-CN.md)**
4
4
 
5
- > **AI agent 接入**:直接看下方「[Agent 接入速查](#agent-接入速查给-ai-agent-读)」(导出 / 选项表 / 扩展点 / 内置工具 / 文件结构),架构与约定坑见 [`CLAUDE.md`](./CLAUDE.md)。
5
+ > Give your web page an **AI assistant that edits the page itself**. Mount a chat dialog in one line; the AI reads/writes page data safely via schema-validated tools — "conversational" building/editing/ops.
6
+
7
+ > **AI agent integration**: see [Agent Integration Cheat Sheet](#agent-integration-cheat-sheet-for-ai-agents) below (exports / options / extension points / built-in tools / file structure). Architecture & gotchas in [`CLAUDE.md`](./CLAUDE.md).
6
8
 
7
9
  [![npm](https://img.shields.io/npm/v/page-agent-sdk.svg)](https://www.npmjs.com/package/page-agent-sdk)
8
10
  [![license](https://img.shields.io/badge/license-ISC-blue.svg)](./LICENSE)
9
- [![tests](https://img.shields.io/badge/self%20tests-341%20asserts-brightgreen.svg)](#自测)
11
+ [![tests](https://img.shields.io/badge/self%20tests-341%20asserts-brightgreen.svg)](#self-tests)
10
12
 
11
13
  ---
12
14
 
13
- ## 适合谁
15
+ ## Who is it for
16
+
17
+ **Low-code / visual builders, form & page designers, CMS, ops consoles** — anywhere "page data is structured, and you want natural language to drive it".
18
+
19
+ One-line gist: **declare the page data structure (schema) to the Agent; it reads/writes via tools, validated by schema** — "editing the page" goes from drag/fill to a single sentence.
20
+
21
+ ### What it is: a standardized JSON-operation Agent
14
22
 
15
- **低代码 / 可视化搭建平台、表单与页面设计器、CMS、智能运维台**——凡是「页面有可结构化描述的数据,希望用自然语言驱动它变化」的场景。
23
+ At its core, it gives the AI a **standardized, safe JSON-operation channel**. AI editing JSON is no longer "generate a blob of text and stuff it back" (uncontrolled), but a structured operation under four constraints:
16
24
 
17
- 核心思路一句话:**把页面数据结构(schema)声明给 Agent,它用工具按 schema 安全读写**——「改页面」从拖拽/手填变成一句话。
25
+ | Constraint | Mechanism | Effect |
26
+ |---|---|---|
27
+ | **Scope control** | Property registry (`windowProps`) — only declared paths are writable | AI touching undeclared fields → rejected |
28
+ | **Validity check** | zod schema — `set`/`edit` validated against schema | Invalid type/enum/structure → structured error, no write |
29
+ | **Incremental op** | `edit_window_prop` patches by `jsonPath` (set/remove/merge/append) | Avoid re-sending the whole large JSON; precise local edits |
30
+ | **Rollbackable** | per-path snapshots (auto-stacked) + session checkpoint | Bad edit → one-click restore to the last good state |
31
+
32
+ "Editing JSON" moves from free-form LLM text generation to **structured, validatable, auditable, rollbackable** tool operations. This is the fundamental difference from "let the AI output a JSON string directly".
18
33
 
19
- ## 使用场景
34
+ ## Use cases
20
35
 
21
- | 场景 | 用户说 | AI |
36
+ | Scenario | User says | AI does |
22
37
  |---|---|---|
23
- | 🏗 **低代码搭建** | 「顶部 Banner 改深色、主标题加粗、加一张新品卡」 | jsonPath 增量 patch 组件树,画布实时刷新 |
24
- | 📝 **表单设计器** | 「手机号加格式校验、地址改三级联动」 | 增量改字段定义,schema 校验防错 |
25
- | 📰 **CMS 运营** | 「这批商品标题加『限时』前缀、低于 100 元的标红」 | JSONPath 筛选 + 沙箱脚本批量改 |
26
- | 🖥 **运维配置台** | A 实验阈值调到 30%、关掉 B 开关」 | 白名单 + 人工确认改配置,写后读回校验 |
27
- | 🤖 **AI 原生助手** | 「把这张看板的图例改成柱状」 | 对话操作产品自有数据,免做 UI |
38
+ | 🏗 **Low-code builder** | "Top banner dark, bold the title, add a new-product card" | Incremental patch the component tree via jsonPath; canvas refreshes live |
39
+ | 📝 **Form designer** | "Add phone format validation, address → 3-level cascade" | Incremental field-definition edits, schema-validated |
40
+ | 📰 **CMS ops** | "Prefix these products with 'Limited', mark under ¥100 red" | JSONPath filter + sandbox script batch edit |
41
+ | 🖥 **Ops console** | "Raise A's threshold to 30%, turn off switch B" | Whitelist + human-confirm to edit config, read-back verify |
42
+ | 🤖 **AI-native assistant** | "Change this chart's legend to bars" | Conversational ops on product data, no UI needed |
28
43
 
29
- > 仓库 `examples/nested-demo` 即低代码场景完整示例:嵌套区块树 + 人工确认 + 一键回退。
44
+ > `examples/nested-demo` is a full low-code example: nested block tree + human confirm + one-click rollback.
30
45
 
31
- ## 30 秒上手
46
+ ## 30-second quickstart
32
47
 
33
48
  ```bash
34
49
  npm install page-agent-sdk zod @langchain/openai @langchain/core
@@ -38,247 +53,343 @@ npm install page-agent-sdk zod @langchain/openai @langchain/core
38
53
  import { createChatSdk } from 'page-agent-sdk'
39
54
  import { z } from 'zod'
40
55
 
41
- window.page = { title: '新品专区', theme: 'light' }
56
+ window.page = { title: 'New Products', theme: 'light' }
42
57
 
43
58
  createChatSdk({
44
59
  container: '#chat',
45
60
  llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com', model: 'deepseek-chat' },
46
- systemPrompt: '你是页面搭建助手,通过工具读写 window.page',
61
+ systemPrompt: 'You are a page-builder assistant; read/write window.page via tools.',
47
62
  windowProps: [
48
- { path: 'page.title', description: '页面标题', schema: z.string() },
49
- { path: 'page.theme', description: '主题', schema: z.enum(['light', 'dark']) },
63
+ { path: 'page.title', description: 'Page title', schema: z.string() },
64
+ { path: 'page.theme', description: 'Theme', schema: z.enum(['light', 'dark']) },
50
65
  ],
51
- approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // 写操作弹确认
52
- checkpoint: true, // 误改一键回退
66
+ approval: { tools: ['set_window_prop', 'edit_window_prop'] }, // confirm writes
67
+ checkpoint: true, // one-click rollback on mistake
53
68
  }).mount()
54
69
  ```
55
70
 
56
- 用户说「标题改成『夏日新品』、主题切深色」→ AI `edit_window_prop` 增量改 → schema 校验写前确认响应式刷新。说错了?点「↩ 回退」。
71
+ User says "title → 'Summer New', theme → dark" → AI calls `edit_window_prop` (incremental) → schema validationpre-write confirm reactive refresh. Said wrong? Click "↩ Undo".
57
72
 
58
- CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `ChatSdk.createChatSdk({...})`。
73
+ CDN zero-config: `<script src="https://unpkg.com/page-agent-sdk"></script>` → `ChatSdk.createChatSdk({...})`.
59
74
 
60
- ## 它能做什么
75
+ ## Capabilities
61
76
 
62
- | 能力 | 说明 | 选项 |
77
+ | Capability | Description | Option |
63
78
  |---|---|---|
64
- | 🛠 window 操作 | 读写注册属性,schema 校验 + 增量 patch + 快照回退 | `windowProps` |
65
- | 🧠 ReAct harness | 可插拔中间件(8 钩子),自研不引 LangGraph | `middleware` |
66
- | 📋 规划/技能/记忆 | `write_todos` / `define_skill` / AGENTS.md 指令 | `capabilities.*` |
67
- | 🗄 虚拟工作区 | 内存文件系统,大结果外存不撑爆上下文 | `capabilities.vfs` |
68
- | ↩️ 回退 | per-path 快照(修小错)+ 会话 checkpoint(回大错) | `checkpoint` |
69
- | ✋ 人工确认 | 写前弹框 + AI 主动征询(不确定/多方案/高风险) | `approval` |
70
- | ✅ 自检自纠 | 返回前 check,不通过 feedback 回灌重试 | `capabilities.verify` |
71
- | 🤖 agent | 委派子任务,过程不占主上下文 | `subagent` |
72
- | 🔌 MCP | 连远程 MCP server 动态注入工具 | `mcp` |
73
- | 📦 上下文压缩 | 4 层自适应压缩,预设档位 + LLM 摘要 | `contextPreset` |
74
- | 💾 持久化 | IndexedDB 多会话 + 配额淘汰 + 切换 | `storage` |
79
+ | 🛠 window ops | Read/write registered props, schema validation + incremental patch + snapshot rollback | `windowProps` |
80
+ | 🧠 ReAct harness | Pluggable middleware (8 hooks), in-house (no LangGraph) | `middleware` |
81
+ | 📋 planning/skills/memory | `write_todos` / `define_skill` / AGENTS.md directives | `capabilities.*` |
82
+ | 🗄 virtual workspace | In-memory file system; large results offloaded (won't blow context) | `capabilities.vfs` |
83
+ | ↩️ rollback | per-path snapshots (small fixes) + session checkpoint (big fixes) | `checkpoint` |
84
+ | ✋ human confirm | Pre-write dialog + AI proactive inquiry (uncertain/multi-plan/high-risk) | `approval` |
85
+ | ✅ self-verify | Run `check` before return; on fail, feedback re-injects to self-correct | `capabilities.verify` |
86
+ | 🤖 subagents | Delegate subtasks; process stays out of main context | `subagent` |
87
+ | 🔌 MCP | Connect remote MCP servers, inject tools dynamically | `mcp` |
88
+ | 📦 context compression | 4-layer adaptive compression, presets + LLM summary | `contextPreset` |
89
+ | 💾 persistence | IndexedDB multi-session + quota eviction + switch | `storage` |
75
90
 
76
- 能力默认开(`verify`/`approval`/`checkpoint` 默认关;**主动征询 `humanConfirm` 默认开**——AI 遇不确定/多方案主动问你、不猜测),可经 `capabilities` 关掉无用的省 token。
91
+ 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.
77
92
 
78
- ## Agent 接入速查(给 AI agent 读)
93
+ ## Agent Integration Cheat Sheet (for AI agents)
79
94
 
80
- > 本节是给 AI agent 的密集接入参考:导出清单 / 选项表 / 扩展点 / 内置工具 / 文件结构。深挖见 `doc/` `CLAUDE.md`。
95
+ > Dense integration reference for AI agents: exports / options / extension points / built-in tools / file structure. Deep dive in `doc/` and `CLAUDE.md`.
81
96
 
82
- ### 导出(`import { ... } from 'page-agent-sdk'`)
97
+ ### Exports (`import { ... } from 'page-agent-sdk'`)
83
98
 
84
99
  ```ts
85
- // 入口与工具构造
100
+ // entry & tool construction
86
101
  createChatSdk, defineTool, defineSkill, presets, z
87
- // harness 与中间件(自定义编排)
102
+ // harness & middleware (custom orchestration)
88
103
  createAgent, createSubagentMiddleware, createSubagentsMiddleware,
89
104
  createVerifyMiddleware, createWriteBackCheck, createApprovalMiddleware,
90
105
  createHumanConfirmMiddleware, createHumanConfirmTool, createCheckpointMiddleware, createCheckpointManager,
91
106
  createUsageHintsMiddleware, createWindowOps, createVfs, connectMcp
92
- // 上下文/模型
107
+ // context & model
93
108
  resolveContextOptions, CONTEXT_PRESETS, resolveModelCaps, estimateTokens
94
- // 存储
109
+ // storage
95
110
  createSessionStore, createMemoryBackend, createWebStorageBackend, isQuotaError
96
- // UI(headless 自建 UI 复用)
111
+ // UI (reuse when headless)
97
112
  ChatDialog, MessageContent, CodePreview, useChat
98
- // 类型():ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, WindowPropSpec, AgentMessage, StreamEvent …
113
+ // types (omitted): ChatSdkOptions, Middleware, SubagentConfig, SkillSpec, WindowPropSpec, AgentMessage, StreamEvent …
99
114
  ```
100
115
 
101
- ### `createChatSdk` 选项速查
116
+ ### `createChatSdk` options cheat sheet
102
117
 
103
- | 分类 | 选项 | 类型 / 默认 | 说明 |
118
+ | Group | Option | Type / Default | Description |
104
119
  |---|---|---|---|
105
- | **基础** | `container` | `string \| HTMLElement` | 挂载点(`ui:true` 必传) |
106
- | | `ui` | `boolean \| 'default'` · 默认 `true` | `false` = headless(用 `agent.messages` 自建 UI) |
107
- | | `llm` | `LLMConfig \| BaseChatModel` · **必传** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`;兼容 OpenAI 协议(默认 DeepSeek |
108
- | | `id` | `string` | 稳定 id(多 agent 隔离 + 持久化恢复;不传随机+warn |
109
- | | `systemPrompt` | `string` | Agent 身份(不硬编码业务,靠这注入) |
110
- | **页面数据** | `windowProps` | `{path,description,schema}[]` | 注册可被工具读写的 window 属性 + zod schema 校验 |
111
- | | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | 自定义工具 / 技能 / AGENTS.md 风格持久指令 |
112
- | **能力开关** | `capabilities` | `{planning?,windowOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | 默认全开(`verify` 默认关);`false` 关掉省 token |
113
- | | `permissions` | `PermissionRule[]` | scope 白名单(first-match-wins,默认不启用) |
114
- | | `humanConfirm` | `boolean` · 默认 `true` | 主动征询(AI 不确定/多方案主动问你,不猜测) |
115
- | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝) |
116
- | | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` · 默认关 | 会话级回滚(`auto` 默认 `true` 每轮存档) |
117
- | | `verify` | `{check?,maxAttempts?,adversarial?}` | `capabilities.verify:true`;`check` 省略用 `createWriteBackCheck` |
118
- | **子 agent** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | 运行时自由委派(`spawn_agent`/`spawn_agents`) |
119
- | | `subagents` | `SubagentConfig[]` | 预声明命名子 agent每个生成 `use_<id>` 委派工具 |
120
- | **上下文** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · 默认 `auto` | 压缩预设档位 |
121
- | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | 细参覆盖(`false` 关压缩) |
122
- | | `summaryLlm` | `BaseChatModel \| LLMConfig` | 摘要专用 LLM(不配用主 `llm`) |
123
- | | `maxMemoryRounds` | `number` · 默认 `50` | 对话历史内存上限轮次(`0` 关裁剪) |
124
- | | `vfs` | `{initialFiles?,maxBytes?}` · 默认 4MB | 内存工作区上限(超限 LRU 淘汰) |
125
- | **持久化** | `storage` | `'indexed' \| 'session' \| 'local' \| 'memory' \| 配置 \| false` · 默认关 | 赋值开启;多 agent `id` 隔离 |
126
- | | `session` | `{id?,autoResume?,title?}` | 会话控制 |
127
- | | `shareContext` | `boolean` · 默认 `false` | `id` 多实例共享同一 agent |
128
- | **鲁棒/其他** | `maxRetries` / `maxParallelTools` / `maxToolRounds` | `number` · 2 / 1 / 10 | 模型重试 / 同轮工具并发 / 最大轮次 |
129
- | | `mcp` | `McpServerConfig[]` | 远程 MCP server(http/sse/websocket |
130
- | | `middleware` | `Middleware[]` | 自定义中间件(拼到内置栈末尾) |
131
- | | `streaming` / `title` / `placeholder` / `debug` | — | UI/调试 |
132
-
133
- ### 扩展点
120
+ | **Basics** | `container` | `string \| HTMLElement` | Mount point (`ui:true` required) |
121
+ | | `ui` | `boolean \| 'default'` · default `true` | `false` = headless (build UI with `agent.messages`) |
122
+ | | `llm` | `LLMConfig \| BaseChatModel` · **required** | `LLMConfig={apiKey,baseUrl?,model?,temperature?,maxTokens?}`; OpenAI-compatible (default DeepSeek) |
123
+ | | `id` | `string` | Stable id (multi-agent isolation + persistence resume; random+warn if omitted) |
124
+ | | `systemPrompt` | `string` | Agent identity (no hardcoded business; inject via this) |
125
+ | **Page data** | `windowProps` | `{path,description,schema}[]` | Register window props readable/writable by tools + zod schema |
126
+ | | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` | Custom tools / skills / AGENTS.md-style directives |
127
+ | **Capability toggles** | `capabilities` | `{planning?,windowOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?}` | Default all on (`verify` default off); `false` to turn off |
128
+ | | `permissions` | `PermissionRule[]` | Scope whitelist (first-match-wins, default off) |
129
+ | | `humanConfirm` | `boolean` · default `true` | Proactive inquiry (AI asks when uncertain/multi-plan) |
130
+ | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · default off | Passive confirm whitelist (pre-write allow/deny) |
131
+ | | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` · default off | Session-level rollback (`auto` default `true`) |
132
+ | | `verify` | `{check?,maxAttempts?,adversarial?}` | Needs `capabilities.verify:true`; `check` omitted `createWriteBackCheck` |
133
+ | **Subagents** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | Runtime ad-hoc delegation (`spawn_agent`/`spawn_agents`) |
134
+ | | `subagents` | `SubagentConfig[]` | Pre-declared named subagents each generates `use_<id>` tool |
135
+ | **Context** | `contextPreset` | `'auto' \| 'conservative' \| 'aggressive'` · default `auto` | Compression preset |
136
+ | | `contextOptions` | `Partial<ContextManagerOptions> \| false` | Fine params (`false` disables compression) |
137
+ | | `summaryLlm` | `BaseChatModel \| LLMConfig` | Summary-dedicated LLM (defaults to main `llm`) |
138
+ | | `maxMemoryRounds` | `number` · default `50` | Dialog history memory round cap (`0` disables trim) |
139
+ | | `vfs` | `{initialFiles?,maxBytes?}` · default 4MB | In-memory workspace cap (LRU evict on overflow) |
140
+ | **Persistence** | `storage` | `'indexed' \| 'session' \| 'local' \| 'memory' \| config \| false` · default off | Assign to enable; multi-agent isolated by `id` |
141
+ | | `session` | `{id?,autoResume?,title?}` | Session control |
142
+ | | `shareContext` | `boolean` · default `false` | Same `id` instances share one agent |
143
+ | **Robustness/other** | `maxRetries` / `maxParallelTools` / `maxToolRounds` | `number` · 2 / 1 / 10 | Model retries / per-round tool concurrency / max rounds |
144
+ | | `mcp` | `McpServerConfig[]` | Remote MCP servers (http/sse/websocket) |
145
+ | | `middleware` | `Middleware[]` | Custom middleware (appended to built-in stack) |
146
+ | | `streaming` / `title` / `placeholder` / `debug` | — | UI/debug |
147
+
148
+ ### Extension points
134
149
 
135
150
  ```ts
136
- // ① 自定义工具
151
+ // ① Custom tool
137
152
  const myTool = defineTool({ name: 'do_x', description: '...', schema: z.object({...}), handler: (args) => 'result' })
138
153
  createChatSdk({ tools: [myTool], /*...*/ })
139
154
 
140
- // ② 自定义技能(渐进披露:用到才 load_skill 加载详情)
141
- const mySkill = defineSkill({ name: 'style_guide', description: '品牌色规范', body: '主色 #1f4d3a…' })
155
+ // ② Custom skill (progressive disclosure: load_skill fetches details on demand)
156
+ const mySkill = defineSkill({ name: 'style_guide', description: 'Brand color spec', body: 'Primary #1f4d3a…' })
142
157
  createChatSdk({ skills: [mySkill], /*...*/ })
143
158
 
144
- // ③ 自定义中间件(8 钩子:beforeAgent/wrapModelCall/beforeModel/afterModel/wrapToolCall/afterAgent/beforeReturn + augmentPrompt/compressInput/tools)
159
+ // ③ Custom middleware (8 hooks: beforeAgent/wrapModelCall/beforeModel/afterModel/wrapToolCall/afterAgent/beforeReturn + augmentPrompt/compressInput/tools)
145
160
  const mw: Middleware = { name: 'telemetry', afterModel: async (ctx, next) => { await next(ctx); console.log('round done') } }
146
161
  createChatSdk({ middleware: [mw], /*...*/ })
147
162
 
148
- // ④ 预声明子 agent(规划-反思-执行等固定角色)
163
+ // ④ Pre-declared subagents (planner-reflector-executor fixed roles)
149
164
  createChatSdk({ subagents: [
150
- { id: 'planner', description: '创意规划', temperature: 0.9, systemPrompt: '…' },
151
- { id: 'reflector', description: '反思审查', temperature: 0.3, systemPrompt: '…' },
165
+ { id: 'planner', description: 'Creative planner', temperature: 0.9, systemPrompt: '…' },
166
+ { id: 'reflector', description: 'Reflective reviewer', temperature: 0.3, systemPrompt: '…' },
152
167
  ], /*...*/ })
153
168
  ```
154
169
 
155
- ### 内置工具(Agent 可调用)
170
+ ### Built-in tools (Agent-callable)
156
171
 
157
- - **window 操作**(`windowProps` 注册后):`list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop`(jsonPath 增量 patch)/ `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
158
- - **window 查询**:`query_window_prop`(JSONPath)/ `search_window_prop`(模糊搜索)/ `eval_window_script`(沙箱脚本)
159
- - **抓取**:`fetch_document`
160
- - **vfs**:`vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
161
- - **规划/技能**:`write_todos` / `define_skill` / `load_skill`
162
- - **人工确认**:`request_human_confirmation`(主动征询,默认开)
163
- - **子 agent**:`spawn_agent` / `spawn_agents` / `use_<id>`(预声明)
164
- - **checkpoint**:`restore_last_checkpoint` / `list_checkpoints`
172
+ - **window ops** (after `windowProps` registered): `list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop` (jsonPath incremental patch) / `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
173
+ - **window query**: `query_window_prop` (JSONPath) / `search_window_prop` (fuzzy) / `eval_window_script` (sandboxed)
174
+ - **fetch**: `fetch_document`
175
+ - **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
176
+ - **planning/skills**: `write_todos` / `define_skill` / `load_skill`
177
+ - **human confirm**: `request_human_confirmation` (proactive inquiry, default on)
178
+ - **subagents**: `spawn_agent` / `spawn_agents` / `use_<id>` (pre-declared)
179
+ - **checkpoint**: `restore_last_checkpoint` / `list_checkpoints`
165
180
 
166
- ### 文件结构
181
+ ### File structure
167
182
 
168
183
  ```
169
184
  src/core/
170
- ├── sdk/createChatSdk.ts # 命令式入口(组装 harness+工具+中间件)
185
+ ├── sdk/createChatSdk.ts # imperative entry (assembles harness + tools + middleware)
171
186
  │ sdk/defineTool.ts presets.ts contextPreset.ts
172
- ├── harness/ # 自研 ReAct harness(中间件驱动)
187
+ ├── harness/ # in-house ReAct harness (middleware-driven)
173
188
  │ createAgent.ts middleware.ts state.ts
174
189
  │ todos.ts skills.ts memory.ts summarization.ts retry.ts
175
190
  │ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
176
191
  │ permissions.ts usageHints.ts
177
- ├── tools/ # windowOps(注册表+增量编辑+快照)/ windowQuery / fetchDoc
178
- ├── backends/ # vfs(内存) / storage(IndexedDB+多后端+配额淘汰)
179
- ├── mcp/client.ts # MCP 远程工具接入
192
+ ├── tools/ # windowOps (registry + incremental edit + snapshot) / windowQuery / fetchDoc
193
+ ├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
194
+ ├── mcp/client.ts # remote MCP tool integration
180
195
  ├── composables/ # useChat / useContextManager / useMarkdown
181
196
  ├── components/ # ChatDialog / MessageContent / CodePreview / DebugDrawer
182
- └── types/index.ts index.ts # 类型 / 库唯一入口
197
+ └── types/index.ts index.ts # types / sole library entry
183
198
  examples/ # page-demo / nested-demo / human-confirm-demo / planner-demo / subagent-demo / mcp-demo
184
199
  doc/ # usage-guide / architecture / context-management / architecture-files
185
- CLAUDE.md # 架构要点 + 约定坑 + 编码规范(agent 必读)
200
+ CLAUDE.md # architecture + gotchas + coding conventions (agent must-read)
186
201
  ```
187
202
 
188
- ## 架构
203
+ ### Extension points
204
+
205
+ ```ts
206
+ // ① Custom tool
207
+ const myTool = defineTool({ name: 'do_x', description: '...', schema: z.object({...}), handler: (args) => 'result' })
208
+ createChatSdk({ tools: [myTool], /*...*/ })
209
+
210
+ // ② Custom skill (progressive disclosure: load_skill fetches details on demand)
211
+ const mySkill = defineSkill({ name: 'style_guide', description: 'Brand color spec', body: 'Primary #1f4d3a…' })
212
+ createChatSdk({ skills: [mySkill], /*...*/ })
213
+
214
+ // ③ Custom middleware (8 hooks: beforeAgent/wrapModelCall/beforeModel/afterModel/wrapToolCall/afterAgent/beforeReturn + augmentPrompt/compressInput/tools)
215
+ const mw: Middleware = { name: 'telemetry', afterModel: async (ctx, next) => { await next(ctx); console.log('round done') } }
216
+ createChatSdk({ middleware: [mw], /*...*/ })
217
+
218
+ // ④ Pre-declared subagents (planner-reflector-executor fixed roles)
219
+ createChatSdk({ subagents: [
220
+ { id: 'planner', description: 'Creative planner', temperature: 0.9, systemPrompt: '…' },
221
+ { id: 'reflector', description: 'Reflective reviewer', temperature: 0.3, systemPrompt: '…' },
222
+ ], /*...*/ })
223
+ ```
224
+
225
+ ### Built-in tools (Agent-callable)
226
+
227
+ - **window ops** (after `windowProps` registered): `list_window_props` / `describe_window_prop` / `get_window_prop` / `get_window_paths` / `set_window_prop` / `edit_window_prop` (jsonPath incremental patch) / `delete_window_prop` / `snapshot_window_prop` / `list_window_snapshots` / `restore_window_snapshot`
228
+ - **window query**: `query_window_prop` (JSONPath) / `search_window_prop` (fuzzy) / `eval_window_script` (sandboxed)
229
+ - **fetch**: `fetch_document`
230
+ - **vfs**: `vfs_read` / `vfs_write` / `vfs_edit` / `vfs_ls` / `vfs_glob` / `vfs_grep`
231
+ - **planning/skills**: `write_todos` / `define_skill` / `load_skill`
232
+ - **human confirm**: `request_human_confirmation` (proactive inquiry, default on)
233
+ - **subagents**: `spawn_agent` / `spawn_agents` / `use_<id>` (pre-declared)
234
+ - **checkpoint**: `restore_last_checkpoint` / `list_checkpoints`
235
+
236
+ ### File structure
237
+
238
+ ```
239
+ src/core/
240
+ ├── sdk/createChatSdk.ts # imperative entry (assembles harness + tools + middleware)
241
+ │ sdk/defineTool.ts presets.ts contextPreset.ts
242
+ ├── harness/ # in-house ReAct harness (middleware-driven)
243
+ │ createAgent.ts middleware.ts state.ts
244
+ │ todos.ts skills.ts memory.ts summarization.ts retry.ts
245
+ │ subagent.ts verify.ts approval.ts humanConfirm.ts checkpoint.ts
246
+ │ permissions.ts usageHints.ts
247
+ ├── tools/ # windowOps (registry + incremental edit + snapshot) / windowQuery / fetchDoc
248
+ ├── backends/ # vfs (memory) / storage (IndexedDB + multi-backend + quota eviction)
249
+ ├── mcp/client.ts # remote MCP tool integration
250
+ ├── composables/ # useChat / useContextManager / useMarkdown
251
+ ├── components/ # ChatDialog / MessageContent / CodePreview / DebugDrawer
252
+ └── types/index.ts index.ts # types / sole library entry
253
+ examples/ # page-demo / nested-demo / human-confirm-demo / planner-demo / subagent-demo / mcp-demo
254
+ doc/ # usage-guide / architecture / context-management / architecture-files
255
+ CLAUDE.md # architecture + gotchas + coding conventions (agent must-read)
256
+ ```
257
+
258
+ ## Architecture
189
259
 
190
260
  ```mermaid
191
261
  flowchart TD
192
- APP[集成方页面] -->|createChatSdk| SDK[createChatSdk<br/>组装 harness + 工具 + 中间件]
262
+ APP[Host page] -->|createChatSdk| SDK[createChatSdk<br/>assembles harness + tools + middleware]
193
263
  SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
194
- CORE --> AGENT[createAgent<br/>ReAct 循环 + 中间件栈]
195
- AGENT --> MW[中间件栈<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→用户]
196
- AGENT --> TOOLS[工具集<br/>windowOps / fetchDoc / vfs / MCP / 用户]
197
- TOOLS -->|零桥接| WIN[宿主页面 window<br/>直接读写注册属性]
198
- AGENT --> LLM[LLM<br/>OpenAI 协议 / 任意 ChatModel]
199
- SDK --> UI[ChatDialog UI<br/>Vue 打包进库 / headless]
264
+ CORE --> AGENT[createAgent<br/>ReAct loop + middleware stack]
265
+ AGENT --> MW[Middleware stack<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→user]
266
+ AGENT --> TOOLS[Tools<br/>windowOps / fetchDoc / vfs / MCP / user]
267
+ TOOLS -->|zero-bridge| WIN[Host page window<br/>read/write registered props directly]
268
+ AGENT --> LLM[LLM<br/>OpenAI-compatible / any ChatModel]
269
+ SDK --> UI[ChatDialog UI<br/>Vue bundled in / or headless]
200
270
  ```
201
271
 
202
- - **框架无关**:Vue 打包进库(非 peer),宿主用 React/原生都行;也支持 `ui:false` headless 自建 UI
203
- - **provider 抽离**:`llm` 传任意 LangChain `BaseChatModel`,或 `LLMConfig`(内部构造 `ChatOpenAI`,兼容 OpenAI 协议,默认接 DeepSeek
204
- - **自研 harness**:不引 LangGraph/langchain 整包,规避浏览器打包阻塞
272
+ - **Framework-agnostic**: Vue bundled in the lib (not a peer); host can be React/vanilla. Also supports `ui:false` headless and runs in **Node.js** as a backend Agent (custom tools / subagents / verify; disable `windowOps`+`fetch`, use `storage:'memory'`)
273
+ - **Provider-agnostic**: `llm` accepts any LangChain `BaseChatModel`, or `LLMConfig` (builds `ChatOpenAI` internally, OpenAI-compatible, default DeepSeek)
274
+ - **In-house harness**: no LangGraph/langchain full bundle; avoids browser bundling blockers
205
275
 
206
- ## 配置
276
+ ## Configuration
207
277
 
208
278
  ```bash
209
- # .env(前缀 VITE_
279
+ # .env (VITE_ prefix)
210
280
  VITE_AI_API_KEY=sk-...
211
281
  VITE_AI_BASE_URL=https://api.deepseek.com
212
282
  VITE_AI_MODEL=deepseek-chat
213
- VITE_AI_TEMPERATURE=0.3 # 结构化操作建议低温
214
- # VITE_AI_MAX_TOKENS= # 不配则按模型自动取值
283
+ VITE_AI_TEMPERATURE=0.3 # low temp recommended for structured ops
284
+ # VITE_AI_MAX_TOKENS= # omit → model default
215
285
  ```
216
286
 
217
287
  ```ts
218
288
  createChatSdk({
219
289
  container: '#root',
220
290
  llm: { apiKey, baseUrl, model },
221
- id: 'my-agent', // 稳定 id(多 agent 隔离 + 持久化恢复)
291
+ id: 'my-agent', // stable id (multi-agent isolation + persistence resume)
222
292
  systemPrompt: '...',
223
293
  windowProps: [{ path, description, schema }],
224
- storage: 'indexed', // 持久化(默认关)
294
+ storage: 'indexed', // persistence (default off)
225
295
  streaming: true, ui: 'default',
226
- capabilities: { verify: true }, // 能力开关
227
- humanConfirm: true, // 主动征询(默认开;AI 不确定/多方案主动问你)
228
- approval: { tools: ['set_window_prop','edit_window_prop'] }, // 被动确认白名单(默认关)
296
+ capabilities: { verify: true }, // capability toggles
297
+ humanConfirm: true, // proactive inquiry (default on)
298
+ approval: { tools: ['set_window_prop','edit_window_prop'] }, // passive confirm whitelist (default off)
229
299
  checkpoint: true,
230
300
  contextPreset: 'auto', // auto/conservative/aggressive
231
- summaryLlm: { ... }, // 摘要专用 LLM(不配用主 llm
301
+ summaryLlm: { ... }, // summary-dedicated LLM (defaults to main llm)
232
302
  maxRetries: 2, maxParallelTools: 1,
233
303
  subagent: { allowedTools: [...] },
234
- middleware: [/* 自定义中间件 */],
304
+ middleware: [/* custom middleware */],
305
+ onEvent(e) { // SDK event callback: subscribe to common moments (window prop change / message update / tool call / error), replaces polling
306
+ if (e.type === 'window_prop_change') refreshUI()
307
+ },
235
308
  }).mount()
236
309
  ```
237
310
 
238
- ## 示例
311
+ ## Examples
239
312
 
240
- `npm run dev` 后访问对应页面:
313
+ After `npm run dev`, visit the corresponding page:
241
314
 
242
- | 示例 | 入口 | 演示 |
315
+ | Example | Entry | Demonstrates |
243
316
  |---|---|---|
244
- | page-demo | `/` | 自举 demo:左 JSON 响应式页面 + 右对话框 |
245
- | nested-demo | `/nested.html` | 嵌套区块树 + 人工确认 + checkpoint |
246
- | human-confirm-demo | `/human-confirm.html` | AI 主动征询(多方案点选)+ 写前确认 |
247
- | planner-demo | `/planner.html` | 规划-反思-执行(高温创意 planner + 低温 reflector |
248
- | subagent-demo | `/subagent.html` | agent 并行编排 |
249
- | mcp-demo | `/mcp.html` | MCP 远程工具(需 `npm run mcp:mock`) |
317
+ | page-demo | `/` | Self-bootstrapping demo: left JSON reactive page + right chat |
318
+ | nested-demo | `/nested.html` | Nested block tree + human confirm + checkpoint |
319
+ | human-confirm-demo | `/human-confirm.html` | AI proactive inquiry (multi-plan pick) + pre-write confirm |
320
+ | planner-demo | `/planner.html` | Plan-reflect-execute (high-temp creative planner + low-temp reflector) |
321
+ | subagent-demo | `/subagent.html` | Subagent parallel orchestration |
322
+ | mcp-demo | `/mcp.html` | MCP remote tools (needs `npm run mcp:mock`) |
250
323
 
251
- 框架无关集成:`demo/plain.html`(importmap + esm.sh)。
324
+ Framework-agnostic integration: `demo/plain.html` (importmap + esm.sh).
252
325
 
253
- ## 文档
326
+ ## Documentation
254
327
 
255
- | 文档 | 内容 |
328
+ | Doc | Contents |
256
329
  |---|---|
257
- | [文档索引](./doc/README.md) | 各文档导航 + 其他信息源(规范/变更/自测) |
258
- | [使用手册](./doc/usage-guide.md) | 安装 / 配置项 / 能力详解 / 自定义中间件 / FAQ |
259
- | [功能架构](./doc/architecture.md) | 分层 / 控制流 / window 操作安全流 |
260
- | [上下文与压缩](./doc/context-management.md) | 上下文组成 / 4 层压缩 / 流程图 |
261
- | [文件全览](./doc/architecture-files.md) | 逐文件职责 / 依赖 / 数据流 |
262
- | [CLAUDE.md](./CLAUDE.md) | **agent 必读** · 架构要点 / 约定坑 / 编码规范 |
330
+ | [Doc Index](./doc/README.en.md) | Navigation + other info sources (specs/changes/tests) |
331
+ | [Usage Guide](./doc/usage-guide.en.md) | Install / options / capability deep-dive / custom middleware / FAQ |
332
+ | [Architecture](./doc/architecture.md) *(Chinese)* | Layering / control flow / window-op safety flow |
333
+ | [Context & Compression](./doc/context-management.md) *(Chinese)* | Context composition / 4-layer compression / flow diagrams |
334
+ | [File Overview](./doc/architecture-files.md) *(Chinese)* | Per-file responsibilities / deps / data flow |
335
+ | [CLAUDE.md](./CLAUDE.md) | **agent must-read** · architecture / gotchas / coding conventions |
336
+
337
+ ## Self-tests
338
+
339
+ ```bash
340
+ npm test # 341 assertions, no LLM dependency
341
+ ```
342
+
343
+ ## Local npm package test
344
+
345
+ Verify the **published npm package** actually works (distinct from `src/` local code and `dist/*.iife.js` local build): set up a standalone vite app in an isolated directory, install `page-agent-sdk` from the npm registry, and run it.
346
+
347
+ **Scenario**: after publishing a new version, confirm the package from `npm install page-agent-sdk` imports + mounts + calls tools correctly; or reproduce an integrator's issue in a clean environment (ruling out local `node_modules` cache / stale `dist` artifacts).
263
348
 
264
- ## 自测
349
+ **Minimal steps**:
265
350
 
266
351
  ```bash
267
- npm test # 341 项断言,不依赖 LLM
352
+ mkdir npm-pkg-test && cd npm-pkg-test
353
+ npm init -y
354
+ npm install page-agent-sdk zod @langchain/openai @langchain/core
355
+ npm install -D vite typescript
356
+ ```
357
+
358
+ `index.html` (mount point) + `main.ts`:
359
+
360
+ ```ts
361
+ import { createChatSdk, z } from 'page-agent-sdk'
362
+ import 'page-agent-sdk/style.css'
363
+
364
+ window.app = { title: 'Demo', theme: 'light' }
365
+
366
+ createChatSdk({
367
+ container: '#root',
368
+ llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
369
+ systemPrompt: 'You are a page assistant; read/write window.app via tools.',
370
+ windowProps: [
371
+ { path: 'app.title', description: 'Title', schema: z.string() },
372
+ { path: 'app.theme', description: 'Theme', schema: z.enum(['light', 'dark']) },
373
+ ],
374
+ }).mount()
268
375
  ```
269
376
 
270
- ## 开发
377
+ `npx vite` → type "change app.theme to dark" in the dialog → AI calls `set_window_prop` → `window.app.theme` becomes `dark` → verified.
378
+
379
+ > Add this test dir to `.gitignore` (local only, not in repo) to avoid committing `.env` with real keys to remotes.
380
+
381
+ ## Development
271
382
 
272
383
  ```bash
273
384
  npm install
274
- npm run dev # 端口 3000(被占则 3001
385
+ npm run dev # port 3000 (3001 if occupied)
275
386
  npm run build # ESM + UMD + IIFE + CSS
276
387
  npm test
277
388
  ```
278
389
 
279
- ## Deep Agents 的关系
390
+ ## Relationship to Deep Agents
280
391
 
281
- 借鉴 [Deep Agents](https://github.com/langchain-ai/deepagents) 的 harness 思路(ReAct + 中间件 + planning + skills + memory + context 管理),但自研实现:不引 LangGraph/langchain 整包;面向浏览器端(持久化用 IndexedDB 而非服务端 DB);上下文用输入压缩 + 内存裁剪 + 大结果 offload,而非每步 checkpointer 存档。详见 [上下文与压缩 - Deep Agents 的差异](./doc/context-management.md#七与-deep-agents-的差异)
392
+ Borrows the harness idea from [Deep Agents](https://github.com/langchain-ai/deepagents) (ReAct + middleware + planning + skills + memory + context management), but implemented in-house: no LangGraph/langchain full bundle; browser-oriented (persistence via IndexedDB, not server-side DB); context via input compression + memory trim + large-result offload, rather than per-step checkpointer archival. See [Context & Compression - Differences from Deep Agents](./doc/context-management.md#七与-deep-agents-的差异).
282
393
 
283
394
  ## License
284
395