page-agent-sdk 2.8.0 → 2.9.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 +27 -3
- package/README.zh-CN.md +27 -3
- package/dist/page-agent-sdk.css +1 -1
- package/dist/page-agent-sdk.iife.js +112 -112
- package/dist/page-agent-sdk.js +1897 -1669
- package/dist/page-agent-sdk.umd.cjs +46 -46
- package/package.json +1 -1
- package/skills/page-agent-sdk-integrate/SKILL.md +1 -0
- package/skills/page-agent-sdk-integrate/references/api.md +1 -1
- package/skills/page-agent-sdk-integrate/references/integration-prompt.md +177 -0
- package/skills/page-agent-sdk-integrate/references/use-cases.md +31 -0
- package/types/index.d.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "page-agent-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "框架无关的页面内 Agent JS SDK —— 以对话框形态挂载到任意网页,通过自定义 tool 读写宿主预注册的数据槽(经 schema 校验 + jsonPath 增量 patch + 快照回退;GET 抓文档),具备 planning/skills/虚拟工作区/context 管理能力。Vue 打包进库,使用者无需安装 Vue。",
|
|
6
6
|
"main": "./dist/page-agent-sdk.umd.cjs",
|
|
@@ -113,6 +113,7 @@ Detailed docs live in this skill's `references/` folder — load the one matchin
|
|
|
113
113
|
- **[references/api.md](references/api.md)** — instance methods (`mount`/`send`/`stream`/`inspect`/`switchSession`/`hook`/`setData`/`getData`/checkpoints), `defineTool`/`defineSkill`/`presets`, built-in data tools, and the full `SdkEvent` type table. Read when the user asks about APIs, tools, or events.
|
|
114
114
|
- **[references/use-cases.md](references/use-cases.md)** — 10 end-to-end scenarios (low-code builder / form designer / CMS batch / ops console / AI-native / research / server-side / multi-agent / MCP / dynamic schema via setData). Read when the user wants a concrete pattern for their use case.
|
|
115
115
|
- **[references/advanced.md](references/advanced.md)** — detailed examples for the extensibility surfaces: **dynamic schema (`sdk.setData` to swap main data at runtime)**, custom `defineTool` (with error handling + coexisting with dataOps), `defineSkill` (inline content + remote doc), subagents (ad-hoc `spawn_agent`/`spawn_agents` + pre-declared `subagents` → `use_<id>`), MCP (http/sse/websocket + auth + dev gotcha). Read when the user asks "how to add custom tools / skills / subagents / MCP" or "swap data/schema at runtime".
|
|
116
|
+
- **[references/integration-prompt.md](references/integration-prompt.md)** — a generic integration prompt template to copy into the target project's AI (Cursor / Claude Code) when the skill is NOT installed there. Fill in `[...]` per scenario. Read when the user asks "give me a prompt to integrate the SDK in another project" or wants a copy-paste prompt for a teammate's AI tool.
|
|
116
117
|
|
|
117
118
|
Project-level docs (in the repo, not bundled in this skill):
|
|
118
119
|
- `doc/usage-guide.md` (zh) / `doc/usage-guide.en.md` — full options reference
|
|
@@ -99,7 +99,7 @@ Default `toolMode:'simple'` exposes high-level `read`/`write` + advanced query/s
|
|
|
99
99
|
| `query_data` / `search_data` | JSONPath query / full-text search | simple/advanced |
|
|
100
100
|
| `eval_script` | Sandboxed script on data (query/transform; transform supports `{patches:[...]}` incremental mode) | simple/advanced |
|
|
101
101
|
|
|
102
|
-
**Key rule**: `write`/`set`/`edit`/`delete` only affect **schema-declared**
|
|
102
|
+
**Key rule**: `write`/`set`/`edit`/`delete` only affect **schema-declared** fields (ZodObject auto-whitelist; undeclared fields hidden/denied). Sub-path reads are recursively projected by the sub-schema at that location (e.g. `read components.0` hides child undeclared fields). `jsonPath` is segment-by-segment validated against schema. Invalid schema → structured error, no write. `write`/`edit` writes in-place (preserves Vue reactive refs). `write` auto-tracks hash from `read` for optimistic lock (no manual `expectedHash` needed). Whole-set / `set_data` / `eval` transform become **merge** semantics in whitelist mode (only updates declared fields, undeclared fields preserved — prevents accidental deletion); `interceptors.write`-supplied invisible fields (not in schema) are written back to bind after schema+merge (not stripped).
|
|
103
103
|
|
|
104
104
|
### write / jsonPath edit operations
|
|
105
105
|
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Integration prompt template (generic)
|
|
2
|
+
|
|
3
|
+
Copy this prompt into the target project's Cursor / Claude Code so its AI integrates `page-agent-sdk` following the workflow. Fill in `[...]` per your scenario.
|
|
4
|
+
|
|
5
|
+
> Recommended: install the skill in the target project first (`cp -R node_modules/page-agent-sdk/skills/page-agent-sdk-integrate ~/.claude/skills/`) — the AI auto-integrates per workflow. Use this prompt only when the skill can't be installed.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Your task
|
|
10
|
+
|
|
11
|
+
Integrate `page-agent-sdk` (npm package) into the current project to enable "[business scenario: e.g. low-code page builder / form designer / ops config console / CMS batch ops / AI-native assistant...]". The integrator declares ONE main data object; an AI agent edits it via schema-validated tools `read`/`write` incrementally, with [UI form: built-in dialog / drawer mode / headless custom UI].
|
|
12
|
+
|
|
13
|
+
## Background
|
|
14
|
+
|
|
15
|
+
- `page-agent-sdk` is a **framework-agnostic JS SDK** (bundles Vue 3.5 internally, no conflict with host; works with Vue2/React/vanilla/Node)
|
|
16
|
+
- Core model: integrator declares **one main data object** `data: { schema, bind, description? }`; the agent reads/writes `bind` via tools (schema validation + whitelist + optimistic lock + snapshot)
|
|
17
|
+
- `bind` is any reactive/plain object; tools read/write it directly, **no `window` dependency**
|
|
18
|
+
- `schema` is a zod schema; field `.describe()` text is auto-injected into the systemPrompt so the LLM knows each field's purpose — no manual field descriptions needed
|
|
19
|
+
- Tools: `read` (read, supports jsonPath/fields/depth projection), `write` (write, merges set/edit/delete + auto optimistic lock + auto snapshot, supports patch jsonPath increments)
|
|
20
|
+
- Full docs: load the `page-agent-sdk-integrate` skill (if installed), or see `node_modules/page-agent-sdk/skills/page-agent-sdk-integrate/`
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
### 1. Install
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm i page-agent-sdk zod @langchain/openai @langchain/core
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Declare the main data object + schema (key step)
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// dataSchema.ts
|
|
34
|
+
import { z } from 'page-agent-sdk'
|
|
35
|
+
|
|
36
|
+
// [Define schema per business: field names/types/shapes; field .describe() auto-injects into systemPrompt]
|
|
37
|
+
export const mainSchema = z.object({
|
|
38
|
+
title: z.string().describe('Page title'),
|
|
39
|
+
items: z.array(z.object({
|
|
40
|
+
id: z.string().describe('Item id'),
|
|
41
|
+
name: z.string().describe('Name'),
|
|
42
|
+
// ... other fields
|
|
43
|
+
})).describe('List items array'),
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
export type MainData = z.infer<typeof mainSchema>
|
|
47
|
+
|
|
48
|
+
// [Optional] skill content: business field/component docs for Agent load_skill on demand (saves systemPrompt tokens)
|
|
49
|
+
export const builderSkillContent = `# [Business name] Skill
|
|
50
|
+
|
|
51
|
+
Main data = { title, items[] }.
|
|
52
|
+
|
|
53
|
+
## Fields
|
|
54
|
+
- title: page title
|
|
55
|
+
- items[]: list items, each = { id, name, ... }
|
|
56
|
+
|
|
57
|
+
## Edit rules
|
|
58
|
+
- Add/remove items: edit items array (append/splice)
|
|
59
|
+
- Prefer incremental patch for single-item edits (only changed fields), avoid re-sending the whole array
|
|
60
|
+
- Validation failures return structured errors; fix per hint and retry
|
|
61
|
+
- jsonPath locates relative to main data root (e.g. items.0.name)`
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Integrate the SDK
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { createChatSdk, defineSkill } from 'page-agent-sdk'
|
|
68
|
+
import 'page-agent-sdk/style.css'
|
|
69
|
+
import { mainSchema, builderSkillContent } from './dataSchema'
|
|
70
|
+
|
|
71
|
+
// [bind: use a reactive object (Vue3 reactive / Vue2 data() return / React useState or ref.current)]
|
|
72
|
+
const mainData = { title: 'Initial title', items: [] }
|
|
73
|
+
|
|
74
|
+
const sdk = createChatSdk({
|
|
75
|
+
container: '#agent-root',
|
|
76
|
+
id: '[stable id, e.g. page-builder]', // multi-agent isolation + persistence namespace
|
|
77
|
+
storage: 'memory',
|
|
78
|
+
llm: {
|
|
79
|
+
apiKey: import.meta.env.VITE_AI_API_KEY || 'YOUR_API_KEY',
|
|
80
|
+
baseUrl: 'https://api.deepseek.com/v1', // OpenAI-compatible protocol; DeepSeek by default
|
|
81
|
+
model: 'deepseek-chat',
|
|
82
|
+
temperature: 0.3, // low temp recommended for large JSON ops
|
|
83
|
+
},
|
|
84
|
+
// [UI form: built-in dialog (default) / drawer mode (drawer:true) / headless (ui:false)]
|
|
85
|
+
drawer: true, // drawer mode: right slide-in + mask; close defaults to hide() preserving history
|
|
86
|
+
// systemPrompt: describe business + data structure; reliableWriteRules auto-appended with '---' separator (default true)
|
|
87
|
+
systemPrompt: 'You are a [business] assistant. Main data = { title, items[] }. To edit, change title or items (add/remove/edit items, adjust fields); [page/UI] updates live. See load_skill("[skill-name]") for fields.',
|
|
88
|
+
appendReliableWriteRules: true, // default true, auto-appends reliable write rules (read-before-write, fields per describe, retry on validation error, prefer incremental patch)
|
|
89
|
+
// data single main object: schema + bind directly bound to object
|
|
90
|
+
data: { schema: mainSchema, bind: mainData, description: '[main data purpose]' },
|
|
91
|
+
// skill: business field docs, Agent load_skill on demand
|
|
92
|
+
skills: [
|
|
93
|
+
defineSkill({
|
|
94
|
+
name: '[skill-name]',
|
|
95
|
+
description: 'Edit [business] data. Use when user requests changes',
|
|
96
|
+
getContent: () => builderSkillContent,
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
debug: true,
|
|
100
|
+
title: '[Business] Agent',
|
|
101
|
+
placeholder: 'Try: [example operation]',
|
|
102
|
+
// onEvent: for non-reactive bind or new-property cases, use data_change to trigger re-render
|
|
103
|
+
onEvent(e) {
|
|
104
|
+
if (e.type === 'data_change') {
|
|
105
|
+
// [non-reactive bind: tick++ to force re-render; reactive bind: not needed or use for audit/联动]
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
}).mount()
|
|
109
|
+
|
|
110
|
+
// Drawer mode: call show() to open (hide() to close, preserves history & in-flight generation)
|
|
111
|
+
// sdk.show() / sdk.hide()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 4. [Optional] Page render + refresh
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// Reactive bind (Vue3 reactive / Vue2 data()): Agent write → auto-reactive, no manual refresh
|
|
118
|
+
// Non-reactive bind (plain object): onEvent('data_change') triggers tick, :key="tick" forces component rebuild to read latest bind
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Options cheat sheet
|
|
122
|
+
|
|
123
|
+
| Option | Value | Purpose |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `drawer` | `true` | Drawer mode: right slide-in + mask; close defaults to `hide()` |
|
|
126
|
+
| `ui` | `false` | headless: no dialog, use `sdk.messages` + `send`/`stream` to build your own UI |
|
|
127
|
+
| `data` | `{ schema, bind, description? }` | Main data declaration (key); `bind` directly bound |
|
|
128
|
+
| `systemPrompt` | string | Business description; `reliableWriteRules` auto-appended with `---` |
|
|
129
|
+
| `appendReliableWriteRules` | `true` (default) | Auto-append reliable write rules; set `false` to disable |
|
|
130
|
+
| `skills` | `defineSkill[]` | Business field docs, Agent `load_skill` on demand |
|
|
131
|
+
| `storage` | `'memory'`/`'local'`/... | Persistence (messages/vfs/todos/memory; **does NOT persist bind**) |
|
|
132
|
+
| `llm.temperature` | `0.3` | Low temp recommended for large JSON ops |
|
|
133
|
+
| `onEvent` | `(e) => {}` | Event callback; `data_change` triggers re-render |
|
|
134
|
+
| `checkpoint` | `true` | Session-level rollback (per-round snapshot; one-click restore if broken) |
|
|
135
|
+
| `approval` | `{ tools: ['write'] }` | Human-confirm before write ops (prevent AI mis-edits) |
|
|
136
|
+
| `capabilities` | `{ dataOps:false, fetch:false, ... }` | Turn off unused built-ins to save tokens/size |
|
|
137
|
+
|
|
138
|
+
## Common pitfalls
|
|
139
|
+
|
|
140
|
+
1. **bind not persisted**: `storage` persists messages/vfs/todos/memory but **NOT bind**; to restore across refresh, store it yourself + `sdk.setData({ bind: restoredBind })`
|
|
141
|
+
2. **DeepSeek 400 `missing field tool_call_id`**: handled internally; only relevant for custom tool plumbing (use snake_case)
|
|
142
|
+
3. **`.env` `VITE_AI_SYSTEM_PROMPT` must be single-line** (dotenv doesn't support multi-line)
|
|
143
|
+
4. **Large JSON incremental edit**: use `write({ value:180, patch:{ op:'set', jsonPath:'items.0.price' } })` to avoid re-sending the whole blob (truncated by max_tokens)
|
|
144
|
+
5. **Schema whitelist**: `z.object` auto-enables whitelist (only declared fields exposed); `discriminatedUnion`/`record`/`lazy` non-top-level don't enable (fully open)
|
|
145
|
+
6. **Vue2 new-property non-reactive**: `write` patch `set` on a new field — Vue2 `Object.defineProperty` won't react → `onEvent('data_change')` `tick++`, use `:key="tick"` to force rebuild
|
|
146
|
+
7. **MCP cold-start injects 0 tools**: `vite.config.ts` `optimizeDeps.include` pre-declares SDK sub-paths; keep those entries when forking config, else first MCP page load injects nothing (reload fixes)
|
|
147
|
+
|
|
148
|
+
## Verification checklist
|
|
149
|
+
|
|
150
|
+
- [ ] After `npm i`, `import { createChatSdk, z } from 'page-agent-sdk'` doesn't error
|
|
151
|
+
- [ ] `import 'page-agent-sdk/style.css'` styles load
|
|
152
|
+
- [ ] Agent `read` sees main data structure; `write` patch edits sub-path fields
|
|
153
|
+
- [ ] [Reactive bind] edits → UI reacts; [non-reactive] `data_change` → re-render
|
|
154
|
+
- [ ] [Drawer mode] close then open (`show()`) → history & in-flight generation preserved
|
|
155
|
+
- [ ] Schema validation failure → structured error, no write
|
|
156
|
+
|
|
157
|
+
## References
|
|
158
|
+
|
|
159
|
+
- `node_modules/page-agent-sdk/skills/page-agent-sdk-integrate/` (integration skill, full docs)
|
|
160
|
+
- `references/quickstart.md` (progressive setup), `references/options.md` (all options), `references/api.md` (API/tools/events)
|
|
161
|
+
- `references/use-cases.md` (10 end-to-end scenarios: low-code/form/CMS/ops/AI-native/research/server-side/multi-agent/MCP/dynamic schema)
|
|
162
|
+
- `references/advanced.md` (custom tools/skills/subagents/MCP/dynamic schema)
|
|
163
|
+
- `node_modules/page-agent-sdk/dist/` (build artifacts)
|
|
164
|
+
- Online: `https://esm.sh/page-agent-sdk@2.9.0` (CDN verify)
|
|
165
|
+
|
|
166
|
+
## Scenario customization
|
|
167
|
+
|
|
168
|
+
Per your business scenario, fill in `systemPrompt` / `skills` / `data.schema`:
|
|
169
|
+
|
|
170
|
+
- **Low-code page builder**: `data` = component tree; `write` patch jsonPath incremental; `onEvent('data_change')` refresh canvas; `checkpoint` + `approval`
|
|
171
|
+
- **Form designer**: `data` = field definitions (enum/required); schema validation prevents malformed forms
|
|
172
|
+
- **CMS batch ops**: `eval_script` loops; `search_data` filter; `write` patch targeted edits
|
|
173
|
+
- **Ops config console**: `approval:{tools:['write']}` human-confirm; `capabilities.verify:true` write-back read; `checkpoint`
|
|
174
|
+
- **AI-native assistant**: `capabilities:{dataOps:false,fetch:false}` + custom `tools` (your product API)
|
|
175
|
+
- **Multi-agent on one page**: same `id` + `shareContext:true` → multiple dialogs share one `AgentCore`; or independent `id`s + `drawer:true` + `hide`/`show` for exclusive switching
|
|
176
|
+
- **MCP integration**: `mcp:[{transport,url}]` remote tool servers; `@modelcontextprotocol/sdk` optional peerDep
|
|
177
|
+
- **Dynamic/lazy-loaded schema**: `sdk.setData({ schema, bind })` on component mount to swap main data; tools pick up immediately, no rebuild
|
|
@@ -265,3 +265,34 @@ sdk.inspect().skills // reflects runtime swap (reads controller.get())
|
|
|
265
265
|
|
|
266
266
|
**何时用**:多阶段业务流程(各阶段 skill 文档不同)、运行时按权限/角色加载不同 skill、skill 文档热更新(vfs doc 内容变化需主动失效缓存)。skills 关闭(`capabilities.skills:false`)时 `setSkills`/`invalidateSkillCache` 输出 warn 并 no-op,不抛错。
|
|
267
267
|
|
|
268
|
+
## 12. Multi-agent parallel + exclusive switch (drawer hide/show)
|
|
269
|
+
|
|
270
|
+
Multiple independent agents on one page (each `createChatSdk` + distinct `id`, each its own `data`/history/tools), running their own generation tasks in parallel; exclusive chatbox switching via `drawer` + `hide()`/`show()` — `hide` the old (keeps agent/history/in-flight generation), `show` the new (history resumes), no unmount, no lost conversation.
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
const boxA = document.createElement('div'); document.body.appendChild(boxA)
|
|
274
|
+
const boxB = document.createElement('div'); document.body.appendChild(boxB)
|
|
275
|
+
const boxC = document.createElement('div'); document.body.appendChild(boxC)
|
|
276
|
+
|
|
277
|
+
const agents = [
|
|
278
|
+
createChatSdk({ id: 'agent-page', container: boxA, drawer: true, storage: 'memory', llm: LLM, data: { schema: pageSchema, bind: pageObj }, systemPrompt: '页面构建助手…' }),
|
|
279
|
+
createChatSdk({ id: 'agent-copy', container: boxB, drawer: true, storage: 'memory', llm: LLM, data: { schema: copySchema, bind: copyObj }, systemPrompt: '文案优化助手…' }),
|
|
280
|
+
createChatSdk({ id: 'agent-stats', container: boxC, drawer: true, storage: 'memory', llm: LLM, data: { schema: statsSchema, bind: statsObj }, systemPrompt: '数据分析助手…' }),
|
|
281
|
+
]
|
|
282
|
+
await Promise.all(agents.map(a => a.mount())) // three independent agents ready in parallel
|
|
283
|
+
agents.slice(1).forEach(a => a.hide()) // show only the first initially
|
|
284
|
+
|
|
285
|
+
let active = 0
|
|
286
|
+
function switchTo(i: number) {
|
|
287
|
+
agents[active].hide(); active = i; agents[i].show() // exclusive switch, each history preserved
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**要点**:
|
|
292
|
+
- 不同 `id` 隔离:各自独立 agent 实例/历史/工具/storage,互不串扰
|
|
293
|
+
- 各管各 `data` 对象无冲突;多 agent 操作同一 `data` 需协调(乐观锁 `expectedHash` 或按 `jsonPath` 分区)
|
|
294
|
+
- `hide()` 不卸载 vueApp/不 release agent,保留聊天历史与正在进行的生成进程;`show()` 恢复可见
|
|
295
|
+
- 切换按钮若在抽屉遮罩下,需提高 `z-index`(高于遮罩 `9998` + ChatDialog `9999`)确保可点
|
|
296
|
+
|
|
297
|
+
完整示例:`examples/multi-agent-demo/`。
|
|
298
|
+
|
package/types/index.d.ts
CHANGED
|
@@ -432,6 +432,10 @@ export interface ChatSdkOptions {
|
|
|
432
432
|
streaming?: boolean;
|
|
433
433
|
title?: string;
|
|
434
434
|
placeholder?: string;
|
|
435
|
+
/** Drawer mode: ChatDialog slides in from the right + mask + close button (replaces the collapse arrow); clicking mask/close triggers unmount (with exit animation). Default false (inline, fills container). */
|
|
436
|
+
drawer?: boolean;
|
|
437
|
+
/** Drawer mode close callback: called when mask/close button clicked (default calls unmount with exit animation). Pass this to sync external mount state. */
|
|
438
|
+
onClose?: () => void;
|
|
435
439
|
}
|
|
436
440
|
|
|
437
441
|
export interface ChatSdk {
|
|
@@ -439,6 +443,10 @@ export interface ChatSdk {
|
|
|
439
443
|
/** 响应式消息数组(headless 模式自建 UI 读) */
|
|
440
444
|
messages: AgentMessage[];
|
|
441
445
|
unmount(): void;
|
|
446
|
+
/** 抽屉模式隐藏:加 cs-hidden class,不卸载 vueApp/不 release agent —— 保留聊天历史与正在进行的生成进程;再 mount() 直接 show 恢复 */
|
|
447
|
+
hide(): void;
|
|
448
|
+
/** 抽屉模式显示:移除 cs-hidden class 恢复可见(配合 hide 使用;首次挂载用 mount) */
|
|
449
|
+
show(): void;
|
|
442
450
|
send(message: string): Promise<string>;
|
|
443
451
|
switchSession(sessionId?: string): Promise<string>;
|
|
444
452
|
stream: (messages: AgentMessage[], onEvent: StreamHandler, signal?: AbortSignal) => Promise<string>;
|