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 +258 -147
- package/README.zh-CN.md +341 -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 +1 -1
- 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".
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
|
36
|
+
| Scenario | User says | AI does |
|
|
22
37
|
|---|---|---|
|
|
23
|
-
| 🏗
|
|
24
|
-
| 📝
|
|
25
|
-
| 📰 **CMS
|
|
26
|
-
| 🖥
|
|
27
|
-
| 🤖 **AI
|
|
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
|
-
>
|
|
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: '
|
|
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)
|
|
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[
|
|
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[
|
|
196
|
-
AGENT --> TOOLS[
|
|
197
|
-
TOOLS
|
|
198
|
-
AGENT --> LLM[LLM<br/>OpenAI
|
|
199
|
-
SDK --> UI[ChatDialog UI<br/>Vue
|
|
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
|
-
-
|
|
203
|
-
- **
|
|
204
|
-
-
|
|
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
|
|
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', //
|
|
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, //
|
|
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: { ... }, //
|
|
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 | `/` |
|
|
245
|
-
| nested-demo | `/nested.html` |
|
|
246
|
-
| human-confirm-demo | `/human-confirm.html` | AI
|
|
247
|
-
| planner-demo | `/planner.html` |
|
|
248
|
-
| subagent-demo | `/subagent.html` |
|
|
249
|
-
| mcp-demo | `/mcp.html` | MCP
|
|
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
|
-
|
|
324
|
+
Framework-agnostic integration: `demo/plain.html` (importmap + esm.sh).
|
|
252
325
|
|
|
253
|
-
##
|
|
326
|
+
## Documentation
|
|
254
327
|
|
|
255
|
-
|
|
|
328
|
+
| Doc | Contents |
|
|
256
329
|
|---|---|
|
|
257
|
-
| [
|
|
258
|
-
| [
|
|
259
|
-
| [
|
|
260
|
-
| [
|
|
261
|
-
| [
|
|
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
|
|
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 #
|
|
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
|
-
##
|
|
390
|
+
## Relationship to Deep Agents
|
|
280
391
|
|
|
281
|
-
|
|
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
|
|