page-agent-sdk 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +281 -147
- package/README.zh-CN.md +364 -0
- package/dist/page-agent-sdk.iife.js +14 -14
- package/dist/page-agent-sdk.js +1498 -1441
- package/dist/page-agent-sdk.umd.cjs +12 -12
- package/package.json +3 -2
- package/skills/page-agent-sdk-integrate/SKILL.md +93 -0
- package/skills/page-agent-sdk-release/SKILL.md +44 -0
- package/types/index.d.ts +27 -0
package/README.md
CHANGED
|
@@ -1,34 +1,49 @@
|
|
|
1
1
|
# page-agent-sdk
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **[English](./README.md)** · **[中文](./README.zh-CN.md)**
|
|
4
4
|
|
|
5
|
-
> **AI
|
|
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
|
[](https://www.npmjs.com/package/page-agent-sdk)
|
|
8
10
|
[](./LICENSE)
|
|
9
|
-
[](
|
|
11
|
+
[](#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".
|
|
14
18
|
|
|
15
|
-
|
|
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.
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
### What it is: a standardized JSON-operation Agent
|
|
18
22
|
|
|
19
|
-
|
|
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:
|
|
20
24
|
|
|
21
|
-
|
|
|
25
|
+
| Constraint | Mechanism | Effect |
|
|
22
26
|
|---|---|---|
|
|
23
|
-
|
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
|
|
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".
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
## Use cases
|
|
35
|
+
|
|
36
|
+
| Scenario | User says | AI does |
|
|
37
|
+
|---|---|---|
|
|
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 |
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
> `examples/nested-demo` is a full low-code example: nested block tree + human confirm + one-click rollback.
|
|
45
|
+
|
|
46
|
+
## 30-second quickstart
|
|
32
47
|
|
|
33
48
|
```bash
|
|
34
49
|
npm install page-agent-sdk zod @langchain/openai @langchain/core
|
|
@@ -38,247 +53,366 @@ 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: '
|
|
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: '
|
|
61
|
+
systemPrompt: 'You are a page-builder assistant; read/write window.page via tools.',
|
|
47
62
|
windowProps: [
|
|
48
|
-
{ path: 'page.title', description: '
|
|
49
|
-
{ path: 'page.theme', description: '
|
|
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
|
-
|
|
71
|
+
User says "title → 'Summer New', theme → dark" → AI calls `edit_window_prop` (incremental) → schema validation → pre-write confirm → reactive refresh. Said wrong? Click "↩ Undo".
|
|
57
72
|
|
|
58
|
-
CDN
|
|
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
|
|
65
|
-
| 🧠 ReAct harness |
|
|
66
|
-
| 📋
|
|
67
|
-
| 🗄
|
|
68
|
-
| ↩️
|
|
69
|
-
| ✋
|
|
70
|
-
| ✅
|
|
71
|
-
| 🤖
|
|
72
|
-
| 🔌 MCP |
|
|
73
|
-
| 📦
|
|
74
|
-
| 💾
|
|
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
|
-
|
|
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
|
|
93
|
+
## Agent Integration Cheat Sheet (for AI agents)
|
|
79
94
|
|
|
80
|
-
>
|
|
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
|
-
###
|
|
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(
|
|
111
|
+
// UI (reuse when headless)
|
|
97
112
|
ChatDialog, MessageContent, CodePreview, useChat
|
|
98
|
-
//
|
|
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
|
-
|
|
|
106
|
-
| | `ui` | `boolean \| 'default'` ·
|
|
107
|
-
| | `llm` | `LLMConfig \| BaseChatModel` ·
|
|
108
|
-
| | `id` | `string` |
|
|
109
|
-
| | `systemPrompt` | `string` | Agent
|
|
110
|
-
|
|
|
111
|
-
| | `tools` / `skills` / `memory` | `Tool[]` / `SkillSpec[]` / `string` |
|
|
112
|
-
|
|
|
113
|
-
| | `permissions` | `PermissionRule[]` |
|
|
114
|
-
| | `humanConfirm` | `boolean` ·
|
|
115
|
-
| | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` ·
|
|
116
|
-
| | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` ·
|
|
117
|
-
| | `verify` | `{check?,maxAttempts?,adversarial?}` |
|
|
118
|
-
|
|
|
119
|
-
| | `subagents` | `SubagentConfig[]` |
|
|
120
|
-
|
|
|
121
|
-
| | `contextOptions` | `Partial<ContextManagerOptions> \| false` |
|
|
122
|
-
| | `summaryLlm` | `BaseChatModel \| LLMConfig` |
|
|
123
|
-
| | `maxMemoryRounds` | `number` ·
|
|
124
|
-
| | `vfs` | `{initialFiles?,maxBytes?}` ·
|
|
125
|
-
|
|
|
126
|
-
| | `session` | `{id?,autoResume?,title?}` |
|
|
127
|
-
| | `shareContext` | `boolean` ·
|
|
128
|
-
|
|
|
129
|
-
| | `mcp` | `McpServerConfig[]` |
|
|
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
|
-
// ②
|
|
141
|
-
const mySkill = defineSkill({ name: 'style_guide', description: '
|
|
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
|
-
// ③
|
|
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
|
-
// ④
|
|
163
|
+
// ④ Pre-declared subagents (planner-reflector-executor fixed roles)
|
|
149
164
|
createChatSdk({ subagents: [
|
|
150
|
-
{ id: 'planner', description: '
|
|
151
|
-
{ id: 'reflector', description: '
|
|
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
|
-
###
|
|
170
|
+
### Built-in tools (Agent-callable)
|
|
156
171
|
|
|
157
|
-
- **window
|
|
158
|
-
- **window
|
|
159
|
-
-
|
|
160
|
-
- **vfs
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
- **checkpoint
|
|
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 #
|
|
185
|
+
├── sdk/createChatSdk.ts # imperative entry (assembles harness + tools + middleware)
|
|
171
186
|
│ sdk/defineTool.ts presets.ts contextPreset.ts
|
|
172
|
-
├── 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(
|
|
178
|
-
├── backends/ # vfs(
|
|
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 #
|
|
200
|
+
CLAUDE.md # architecture + gotchas + coding conventions (agent must-read)
|
|
201
|
+
```
|
|
202
|
+
|
|
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
|
+
], /*...*/ })
|
|
186
223
|
```
|
|
187
224
|
|
|
188
|
-
|
|
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
|
+
## Skills for AI tools (for integrators)
|
|
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:
|
|
261
|
+
|
|
262
|
+
| Skill | When it triggers |
|
|
263
|
+
|---|---|
|
|
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
|
+
|
|
267
|
+
**Install** (pick one):
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# Option A — copy from the installed npm package
|
|
271
|
+
npm i page-agent-sdk
|
|
272
|
+
cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-* ~/.claude/skills/
|
|
273
|
+
|
|
274
|
+
# 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/
|
|
277
|
+
```
|
|
278
|
+
|
|
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".
|
|
280
|
+
|
|
281
|
+
## Architecture
|
|
189
282
|
|
|
190
283
|
```mermaid
|
|
191
284
|
flowchart TD
|
|
192
|
-
APP[
|
|
285
|
+
APP[Host page] -->|createChatSdk| SDK[createChatSdk<br/>assembles harness + tools + middleware]
|
|
193
286
|
SDK --> CORE[AgentCore<br/>messages / vfs / store / checkpoint]
|
|
194
|
-
CORE --> AGENT[createAgent<br/>ReAct
|
|
195
|
-
AGENT --> MW[
|
|
196
|
-
AGENT --> TOOLS[
|
|
197
|
-
TOOLS
|
|
198
|
-
AGENT --> LLM[LLM<br/>OpenAI
|
|
199
|
-
SDK --> UI[ChatDialog UI<br/>Vue
|
|
287
|
+
CORE --> AGENT[createAgent<br/>ReAct loop + middleware stack]
|
|
288
|
+
AGENT --> MW[Middleware stack<br/>usageHints→todos→skills→vfs→summarization<br/>→memory→permissions→checkpoint→approval<br/>→humanConfirm→verify→subagent→user]
|
|
289
|
+
AGENT --> TOOLS[Tools<br/>windowOps / fetchDoc / vfs / MCP / user]
|
|
290
|
+
TOOLS -->|zero-bridge| WIN[Host page window<br/>read/write registered props directly]
|
|
291
|
+
AGENT --> LLM[LLM<br/>OpenAI-compatible / any ChatModel]
|
|
292
|
+
SDK --> UI[ChatDialog UI<br/>Vue bundled in / or headless]
|
|
200
293
|
```
|
|
201
294
|
|
|
202
|
-
-
|
|
203
|
-
- **
|
|
204
|
-
-
|
|
295
|
+
- **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'`)
|
|
296
|
+
- **Provider-agnostic**: `llm` accepts any LangChain `BaseChatModel`, or `LLMConfig` (builds `ChatOpenAI` internally, OpenAI-compatible, default DeepSeek)
|
|
297
|
+
- **In-house harness**: no LangGraph/langchain full bundle; avoids browser bundling blockers
|
|
205
298
|
|
|
206
|
-
##
|
|
299
|
+
## Configuration
|
|
207
300
|
|
|
208
301
|
```bash
|
|
209
|
-
# .env
|
|
302
|
+
# .env (VITE_ prefix)
|
|
210
303
|
VITE_AI_API_KEY=sk-...
|
|
211
304
|
VITE_AI_BASE_URL=https://api.deepseek.com
|
|
212
305
|
VITE_AI_MODEL=deepseek-chat
|
|
213
|
-
VITE_AI_TEMPERATURE=0.3 #
|
|
214
|
-
# VITE_AI_MAX_TOKENS= #
|
|
306
|
+
VITE_AI_TEMPERATURE=0.3 # low temp recommended for structured ops
|
|
307
|
+
# VITE_AI_MAX_TOKENS= # omit → model default
|
|
215
308
|
```
|
|
216
309
|
|
|
217
310
|
```ts
|
|
218
311
|
createChatSdk({
|
|
219
312
|
container: '#root',
|
|
220
313
|
llm: { apiKey, baseUrl, model },
|
|
221
|
-
id: 'my-agent', //
|
|
314
|
+
id: 'my-agent', // stable id (multi-agent isolation + persistence resume)
|
|
222
315
|
systemPrompt: '...',
|
|
223
316
|
windowProps: [{ path, description, schema }],
|
|
224
|
-
storage: 'indexed', //
|
|
317
|
+
storage: 'indexed', // persistence (default off)
|
|
225
318
|
streaming: true, ui: 'default',
|
|
226
|
-
capabilities: { verify: true }, //
|
|
227
|
-
humanConfirm: true, //
|
|
228
|
-
approval: { tools: ['set_window_prop','edit_window_prop'] }, //
|
|
319
|
+
capabilities: { verify: true }, // capability toggles
|
|
320
|
+
humanConfirm: true, // proactive inquiry (default on)
|
|
321
|
+
approval: { tools: ['set_window_prop','edit_window_prop'] }, // passive confirm whitelist (default off)
|
|
229
322
|
checkpoint: true,
|
|
230
323
|
contextPreset: 'auto', // auto/conservative/aggressive
|
|
231
|
-
summaryLlm: { ... }, //
|
|
324
|
+
summaryLlm: { ... }, // summary-dedicated LLM (defaults to main llm)
|
|
232
325
|
maxRetries: 2, maxParallelTools: 1,
|
|
233
326
|
subagent: { allowedTools: [...] },
|
|
234
|
-
middleware: [/*
|
|
327
|
+
middleware: [/* custom middleware */],
|
|
328
|
+
onEvent(e) { // SDK event callback: subscribe to common moments (window prop change / message update / tool call / error), replaces polling
|
|
329
|
+
if (e.type === 'window_prop_change') refreshUI()
|
|
330
|
+
},
|
|
235
331
|
}).mount()
|
|
236
332
|
```
|
|
237
333
|
|
|
238
|
-
##
|
|
334
|
+
## Examples
|
|
239
335
|
|
|
240
|
-
`npm run dev
|
|
336
|
+
After `npm run dev`, visit the corresponding page:
|
|
241
337
|
|
|
242
|
-
|
|
|
338
|
+
| Example | Entry | Demonstrates |
|
|
243
339
|
|---|---|---|
|
|
244
|
-
| page-demo | `/` |
|
|
245
|
-
| nested-demo | `/nested
|
|
246
|
-
| human-confirm-demo | `/human-confirm
|
|
247
|
-
| planner-demo | `/planner
|
|
248
|
-
| subagent-demo | `/subagent
|
|
249
|
-
| mcp-demo | `/mcp
|
|
340
|
+
| page-demo | `/` | Self-bootstrapping demo: left JSON reactive page + right chat |
|
|
341
|
+
| nested-demo | `/examples/nested-demo/` | Nested block tree + human confirm + checkpoint |
|
|
342
|
+
| human-confirm-demo | `/examples/human-confirm-demo/` | AI proactive inquiry (multi-plan pick) + pre-write confirm |
|
|
343
|
+
| planner-demo | `/examples/planner-demo/` | Plan-reflect-execute (high-temp creative planner + low-temp reflector) |
|
|
344
|
+
| subagent-demo | `/examples/subagent-demo/` | Subagent parallel orchestration |
|
|
345
|
+
| mcp-demo | `/examples/mcp-demo/` | MCP remote tools (needs `npm run mcp:mock`) |
|
|
250
346
|
|
|
251
|
-
|
|
347
|
+
Framework-agnostic integration: `demo/plain.html` (importmap + esm.sh).
|
|
252
348
|
|
|
253
|
-
##
|
|
349
|
+
## Documentation
|
|
254
350
|
|
|
255
|
-
|
|
|
351
|
+
| Doc | Contents |
|
|
256
352
|
|---|---|
|
|
257
|
-
| [
|
|
258
|
-
| [
|
|
259
|
-
| [
|
|
260
|
-
| [
|
|
261
|
-
| [
|
|
262
|
-
| [CLAUDE.md](./CLAUDE.md) | **agent
|
|
353
|
+
| [Doc Index](./doc/README.en.md) | Navigation + other info sources (specs/changes/tests) |
|
|
354
|
+
| [Usage Guide](./doc/usage-guide.en.md) | Install / options / capability deep-dive / custom middleware / FAQ |
|
|
355
|
+
| [Architecture](./doc/architecture.md) *(Chinese)* | Layering / control flow / window-op safety flow |
|
|
356
|
+
| [Context & Compression](./doc/context-management.md) *(Chinese)* | Context composition / 4-layer compression / flow diagrams |
|
|
357
|
+
| [File Overview](./doc/architecture-files.md) *(Chinese)* | Per-file responsibilities / deps / data flow |
|
|
358
|
+
| [CLAUDE.md](./CLAUDE.md) | **agent must-read** · architecture / gotchas / coding conventions |
|
|
263
359
|
|
|
264
|
-
##
|
|
360
|
+
## Self-tests
|
|
265
361
|
|
|
266
362
|
```bash
|
|
267
|
-
npm test # 341
|
|
363
|
+
npm test # 341 assertions, no LLM dependency
|
|
268
364
|
```
|
|
269
365
|
|
|
270
|
-
##
|
|
366
|
+
## Local npm package test
|
|
367
|
+
|
|
368
|
+
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.
|
|
369
|
+
|
|
370
|
+
**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).
|
|
371
|
+
|
|
372
|
+
**Minimal steps**:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
mkdir npm-pkg-test && cd npm-pkg-test
|
|
376
|
+
npm init -y
|
|
377
|
+
npm install page-agent-sdk zod @langchain/openai @langchain/core
|
|
378
|
+
npm install -D vite typescript
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
`index.html` (mount point) + `main.ts`:
|
|
382
|
+
|
|
383
|
+
```ts
|
|
384
|
+
import { createChatSdk, z } from 'page-agent-sdk'
|
|
385
|
+
import 'page-agent-sdk/style.css'
|
|
386
|
+
|
|
387
|
+
window.app = { title: 'Demo', theme: 'light' }
|
|
388
|
+
|
|
389
|
+
createChatSdk({
|
|
390
|
+
container: '#root',
|
|
391
|
+
llm: { apiKey: 'sk-...', baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat' },
|
|
392
|
+
systemPrompt: 'You are a page assistant; read/write window.app via tools.',
|
|
393
|
+
windowProps: [
|
|
394
|
+
{ path: 'app.title', description: 'Title', schema: z.string() },
|
|
395
|
+
{ path: 'app.theme', description: 'Theme', schema: z.enum(['light', 'dark']) },
|
|
396
|
+
],
|
|
397
|
+
}).mount()
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
`npx vite` → type "change app.theme to dark" in the dialog → AI calls `set_window_prop` → `window.app.theme` becomes `dark` → verified.
|
|
401
|
+
|
|
402
|
+
> Add this test dir to `.gitignore` (local only, not in repo) to avoid committing `.env` with real keys to remotes.
|
|
403
|
+
|
|
404
|
+
## Development
|
|
271
405
|
|
|
272
406
|
```bash
|
|
273
407
|
npm install
|
|
274
|
-
npm run dev #
|
|
408
|
+
npm run dev # port 3000 (3001 if occupied)
|
|
275
409
|
npm run build # ESM + UMD + IIFE + CSS
|
|
276
410
|
npm test
|
|
277
411
|
```
|
|
278
412
|
|
|
279
|
-
##
|
|
413
|
+
## Relationship to Deep Agents
|
|
280
414
|
|
|
281
|
-
|
|
415
|
+
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
416
|
|
|
283
417
|
## License
|
|
284
418
|
|