page-agent-sdk 2.9.1 → 2.10.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 +21 -6
- package/README.zh-CN.md +21 -6
- package/dist/page-agent-sdk.css +1 -1
- package/dist/page-agent-sdk.iife.js +112 -112
- package/dist/page-agent-sdk.js +1016 -721
- package/dist/page-agent-sdk.umd.cjs +45 -45
- package/package.json +1 -1
- package/skills/page-agent-sdk-integrate/references/api.md +4 -0
- package/skills/page-agent-sdk-integrate/references/integration-prompt.md +7 -5
- package/skills/page-agent-sdk-integrate/references/options.md +30 -2
- package/skills/page-agent-sdk-integrate/references/use-cases.md +3 -3
- package/types/index.d.ts +47 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "page-agent-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.10.0",
|
|
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",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
| `usage` | `TokenUsage` | Cumulative token usage `{prompt_tokens, completion_tokens, total_tokens}` (accumulated per LLM call). |
|
|
22
22
|
| `restoreLastCheckpoint()` | `() => boolean` | Restore last good checkpoint (needs `checkpoint` enabled). |
|
|
23
23
|
| `listCheckpoints()` | `() => CheckpointMeta[]` | List available checkpoints. |
|
|
24
|
+
| `addSkill(skill)` | `(skill: { name, description, prompt \| getContent \| doc }) => void` | Add a user-created skill at runtime. Auto-merges into the skill list, persists via **independent SkillStore** (default indexedDB, separate from `storage` option), takes effect next round. Same-name overwrites. Requires `capabilities.skills` (default on) + `skillStorage` not `false` for persistence. |
|
|
25
|
+
| `removeSkill(name)` | `(name: string) => void` | Remove a user-created skill by name (only user-created, not init-time skills). Removes from SkillStore. No-op if not found. |
|
|
26
|
+
| `listUserSkills()` | `() => string[]` | List names of user-created skills (not init-time skills). Useful for UI panels. |
|
|
27
|
+
| `getUserSkill(name)` | `(name: string) => { name, description, content } \| undefined` | Read a user-created skill's detail (for SkillPanel edit). Returns `undefined` if not found. |
|
|
24
28
|
|
|
25
29
|
## defineTool (custom tools)
|
|
26
30
|
|
|
@@ -81,8 +81,12 @@ const sdk = createChatSdk({
|
|
|
81
81
|
model: 'deepseek-chat',
|
|
82
82
|
temperature: 0.3, // low temp recommended for large JSON ops
|
|
83
83
|
},
|
|
84
|
-
// [UI form: built-in dialog (default) / drawer mode (drawer:true) / headless (ui:false)]
|
|
85
|
-
|
|
84
|
+
// [UI form: built-in dialog (default) / drawer mode (dialog.drawer:true) / headless (ui:false)]
|
|
85
|
+
dialog: {
|
|
86
|
+
drawer: true, // drawer mode: right slide-in + mask; close defaults to hide() preserving history
|
|
87
|
+
title: '[Business] Agent',
|
|
88
|
+
placeholder: 'Try: [example operation]',
|
|
89
|
+
},
|
|
86
90
|
// systemPrompt: describe business + data structure; reliableWriteRules auto-appended with '---' separator (default true)
|
|
87
91
|
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
92
|
appendReliableWriteRules: true, // default true, auto-appends reliable write rules (read-before-write, fields per describe, retry on validation error, prefer incremental patch)
|
|
@@ -97,8 +101,6 @@ const sdk = createChatSdk({
|
|
|
97
101
|
}),
|
|
98
102
|
],
|
|
99
103
|
debug: true,
|
|
100
|
-
title: '[Business] Agent',
|
|
101
|
-
placeholder: 'Try: [example operation]',
|
|
102
104
|
// onEvent: for non-reactive bind or new-property cases, use data_change to trigger re-render
|
|
103
105
|
onEvent(e) {
|
|
104
106
|
if (e.type === 'data_change') {
|
|
@@ -172,6 +174,6 @@ Per your business scenario, fill in `systemPrompt` / `skills` / `data.schema`:
|
|
|
172
174
|
- **CMS batch ops**: `eval_script` loops; `search_data` filter; `write` patch targeted edits
|
|
173
175
|
- **Ops config console**: `approval:{tools:['write']}` human-confirm; `capabilities.verify:true` write-back read; `checkpoint`
|
|
174
176
|
- **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
|
|
177
|
+
- **Multi-agent on one page**: same `id` + `shareContext:true` → multiple dialogs share one `AgentCore`; or independent `id`s + `dialog.drawer:true` + `hide`/`show` for exclusive switching
|
|
176
178
|
- **MCP integration**: `mcp:[{transport,url}]` remote tool servers; `@modelcontextprotocol/sdk` optional peerDep
|
|
177
179
|
- **Dynamic/lazy-loaded schema**: `sdk.setData({ schema, bind })` on component mount to swap main data; tools pick up immediately, no rebuild
|
|
@@ -10,7 +10,6 @@ Full reference for `createChatSdk(options)`. Grouped by purpose. Required: `llm`
|
|
|
10
10
|
| `systemPrompt` | `string` | built-in default (JSON-operation assistant + reliable write rules) | Agent identity/instructions. Inject here, not hardcoded. Keep single-line in `.env` (`VITE_AI_SYSTEM_PROMPT`). If omitted, a built-in default is used (JSON-operation assistant + `systemPromptHelpers.reliableWriteRules`); passing your own fully overrides it. |
|
|
11
11
|
| `appendReliableWriteRules` | `boolean` | `true` | When `true` (default) and a custom `systemPrompt` is set, auto-append `systemPromptHelpers.reliableWriteRules` to it with a `---` separator (clearly distinguishes user content from SDK-appended write rules; avoids forgetting the write rules). Set `false` to disable. No effect when `systemPrompt` is omitted (default prompt already includes them). |
|
|
12
12
|
| `id` | `string` | random + warn | Stable agent id for multi-agent isolation & persistence. **Must pass a stable value** if you use `storage` or run multiple agents on one page. |
|
|
13
|
-
| `title` / `placeholder` | `string` | — | Dialog title / input placeholder (cosmetic). |
|
|
14
13
|
|
|
15
14
|
## UI & mounting
|
|
16
15
|
|
|
@@ -19,6 +18,19 @@ Full reference for `createChatSdk(options)`. Grouped by purpose. Required: `llm`
|
|
|
19
18
|
| `container` | `string \| HTMLElement` | — | Where the built-in dialog mounts. Required when `ui !== false`. |
|
|
20
19
|
| `ui` | `boolean \| 'default'` | `true` | `false` = headless (no built-in dialog; you build UI from `sdk.messages` + `sdk.send`). `'default'` = built-in `ChatDialog`. |
|
|
21
20
|
| `streaming` | `boolean` | `true` | Stream tokens live. `false` = wait for full reply. Headless `sdk.send` always uses invoke (no stream events, but data/message/error still fire). |
|
|
21
|
+
| `dialog` | `DialogConfig` | — | Grouped dialog UI config (recommended form). See `DialogConfig` fields below. |
|
|
22
|
+
|
|
23
|
+
### `DialogConfig` fields
|
|
24
|
+
|
|
25
|
+
| Field | Type | Default | Purpose / when |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| `title` | `string` | — | Dialog title (cosmetic). |
|
|
28
|
+
| `placeholder` | `string` | — | Input placeholder (cosmetic). |
|
|
29
|
+
| `drawer` | `boolean` | `false` | Drawer mode: ChatDialog slides in from the right + mask + close button (replaces the collapse arrow). Default `false` (inline, fills container). |
|
|
30
|
+
| `drawerWidth` | `number \| string` | `420` | Drawer mode width (pixels or CSS string, e.g. `500` / `'500px'` / `'40vw'`). Only effective when `drawer: true`. Inline mode width is determined by `container`. |
|
|
31
|
+
| `drawerHidden` | `boolean` | `false` | Drawer mode hidden by default (not shown after `mount`; requires `sdk.show()` to display): for "click button to show chatbox" scenarios. Only effective when `drawer: true`. |
|
|
32
|
+
| `inputRows` | `number` | `2` | Input box rows (visible height). `1` = single row; `2` = 2-row initial height, auto-expands up to max-height:100px; `>2` = taller initial height. |
|
|
33
|
+
| `onClose` | `() => void` | — | Drawer mode close callback (called when mask/close button clicked). Default: `hide()` in drawer mode (keeps agent/history/in-flight generation), `unmount()` otherwise. Pass this to sync external mount state. |
|
|
22
34
|
|
|
23
35
|
## Data operation (the core)
|
|
24
36
|
|
|
@@ -39,6 +51,7 @@ Full reference for `createChatSdk(options)`. Grouped by purpose. Required: `llm`
|
|
|
39
51
|
|---|---|---|---|
|
|
40
52
|
| `tools` | `Tool[]` | `[]` | Custom tools beyond built-ins. Use `defineTool({ name, description, schema, handler })`. |
|
|
41
53
|
| `skills` | `SkillSpec[]` | `[]` | Progressive-disclosure skills (`defineSkill({ name, description, prompt }`) loaded on demand by the agent. |
|
|
54
|
+
| `skillStorage` | `SkillStoreConfig \| false` | `{ backend: 'indexed' }` | **User-created skill independent persistence** (separate from `storage`). Default indexedDB (persists even when `storage: false`); `false` disables persistence (current session only). `id` manually specifies the same id to share skills across pages/agents; omit for per-agent isolation. |
|
|
42
55
|
| `memory` | `string` | — | AGENTS.md-style persistent instructions injected into every prompt (project conventions, hard rules). |
|
|
43
56
|
| `middleware` | `Middleware[]` | `[]` | Custom middleware appended after built-ins. 8 hooks: `beforeAgent`/`wrapModelCall`/`beforeModel`/`afterModel`/`wrapToolCall`/`afterAgent`/`beforeReturn` + `augmentPrompt`/`compressInput`/`tools`. For interception, instrumentation, prompt enhancement. |
|
|
44
57
|
|
|
@@ -124,13 +137,28 @@ Full reference for `createChatSdk(options)`. Grouped by purpose. Required: `llm`
|
|
|
124
137
|
|
|
125
138
|
Runtime subscription via `sdk.hook(handler) => () => void` (multi-listener, cancellable) — see [api.md](api.md).
|
|
126
139
|
|
|
127
|
-
## Convenience APIs (export / import / usage)
|
|
140
|
+
## Convenience APIs (export / import / usage / user skills)
|
|
128
141
|
|
|
129
142
|
| API | Purpose | Notes |
|
|
130
143
|
|---|---|---|
|
|
131
144
|
| `sdk.exportData()` | Deep copy of main data `bind` (backup/migration) | Returns `null` if dataOps off / no data; mutating return does not affect original bind |
|
|
132
145
|
| `sdk.importData(json, opts?)` | Replace `bind` entirely (in-place, preserves reactive ref) | Schema-validated by default → `{ok:false,error}` if invalid; `opts.validate:false` skips; `opts.emit:false` suppresses `data_change` |
|
|
133
146
|
| `sdk.usage` | Cumulative token usage `{prompt_tokens, completion_tokens, total_tokens}` | Accumulated per LLM call; per-round detail via `onEvent('usage')` |
|
|
147
|
+
| `sdk.addSkill(skill)` | Add a user-created skill at runtime | `skill: { name, description, prompt \| getContent \| doc }`. Auto-merges into the skill list, **persists via independent SkillStore** (default indexedDB, separate from `storage` option — even `storage:false` persists skills), and takes effect next round. Same-name overwrites. Requires `capabilities.skills` (default on) + `skillStorage` not `false` for persistence. |
|
|
148
|
+
| `sdk.removeSkill(name)` | Remove a user-created skill by name | Only removes user-created skills (not the ones passed via `skills` option at init). Removes from SkillStore. No-op if not found. |
|
|
149
|
+
| `sdk.listUserSkills()` | List names of user-created skills | Returns `string[]` (only user-created, not init-time skills). Useful for UI panels. |
|
|
150
|
+
| `sdk.getUserSkill(name)` | Read a user-created skill's detail | Returns `{ name, description, content }` or `undefined` if not found. Used by SkillPanel for editing. |
|
|
151
|
+
|
|
152
|
+
**User-created skills** are skills added at runtime via `sdk.addSkill` (or via the built-in `SkillPanel` UI component). They are persisted via an **independent SkillStore** (default indexedDB), **separate from the `storage` option** — even when `storage: false` (session persistence off), user skills still persist across refreshes. To **share the same set of user skills across pages/agents**, manually specify the same `skillStorage.id`:
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
// Page A
|
|
156
|
+
createChatSdk({ id: 'agent-a', skillStorage: { id: 'shared-skills' }, ... })
|
|
157
|
+
// Page B (different agent, same skill set)
|
|
158
|
+
createChatSdk({ id: 'agent-b', skillStorage: { id: 'shared-skills' }, ... })
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Without `skillStorage.id`, skills default to per-agent isolation (`agent::{agentId}`). The built-in `ChatDialog` exposes a "Skill Management" button (header) that opens `SkillPanel` — supports create, **edit** (click a skill to load into the form), and delete. Integrators can also `import { SkillPanel }` directly for custom UIs.
|
|
134
162
|
|
|
135
163
|
## vfs (in-memory workspace)
|
|
136
164
|
|
|
@@ -275,9 +275,9 @@ const boxB = document.createElement('div'); document.body.appendChild(boxB)
|
|
|
275
275
|
const boxC = document.createElement('div'); document.body.appendChild(boxC)
|
|
276
276
|
|
|
277
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: '数据分析助手…' }),
|
|
278
|
+
createChatSdk({ id: 'agent-page', container: boxA, dialog: { drawer: true }, storage: 'memory', llm: LLM, data: { schema: pageSchema, bind: pageObj }, systemPrompt: '页面构建助手…' }),
|
|
279
|
+
createChatSdk({ id: 'agent-copy', container: boxB, dialog: { drawer: true }, storage: 'memory', llm: LLM, data: { schema: copySchema, bind: copyObj }, systemPrompt: '文案优化助手…' }),
|
|
280
|
+
createChatSdk({ id: 'agent-stats', container: boxC, dialog: { drawer: true }, storage: 'memory', llm: LLM, data: { schema: statsSchema, bind: statsObj }, systemPrompt: '数据分析助手…' }),
|
|
281
281
|
]
|
|
282
282
|
await Promise.all(agents.map(a => a.mount())) // three independent agents ready in parallel
|
|
283
283
|
agents.slice(1).forEach(a => a.hide()) // show only the first initially
|
package/types/index.d.ts
CHANGED
|
@@ -137,6 +137,7 @@ export interface McpServerConfig { transport: 'http' | 'sse' | 'websocket'; url:
|
|
|
137
137
|
export declare const ChatDialog: DefineComponent<ChatDialogProps>;
|
|
138
138
|
export declare const MessageContent: DefineComponent<any>;
|
|
139
139
|
export declare const CodePreview: DefineComponent<any>;
|
|
140
|
+
export declare const SkillPanel: DefineComponent<any>;
|
|
140
141
|
export declare function useChat(opts?: any): any;
|
|
141
142
|
|
|
142
143
|
// ===== 框架无关 SDK(页面内 Agent)=====
|
|
@@ -301,6 +302,15 @@ export interface StorageConfig {
|
|
|
301
302
|
evictionWatermark?: number;
|
|
302
303
|
debounceMs?: number;
|
|
303
304
|
}
|
|
305
|
+
/** Skill 独立持久化存储配置(与 storage 选项分离) */
|
|
306
|
+
export interface SkillStoreConfig {
|
|
307
|
+
/** 存储 id(命名空间)。手动指定同一 id 即可跨页面/跨 agent 复用同一套用户 skill;不传默认按 agentId 隔离 */
|
|
308
|
+
id?: string;
|
|
309
|
+
/** 后端类型,默认 'indexed'(大容量、跨刷新);'local' 跨页持久;'session' 刷新保留关页清;'memory' 纯内存降级 */
|
|
310
|
+
backend?: StorageBackendType;
|
|
311
|
+
/** DB 命名空间,默认 'chat-sdk'(与 SessionStore 同库,不同 key 前缀) */
|
|
312
|
+
dbName?: string;
|
|
313
|
+
}
|
|
304
314
|
export interface SessionMeta {
|
|
305
315
|
agentId: string;
|
|
306
316
|
sessionId: string;
|
|
@@ -362,6 +372,8 @@ export interface ChatSdkOptions {
|
|
|
362
372
|
appendReliableWriteRules?: boolean;
|
|
363
373
|
tools?: any[];
|
|
364
374
|
skills?: SkillSpec[];
|
|
375
|
+
/** 用户创建 skill 的独立持久化存储(与 storage 选项分离)。默认 `{ backend: 'indexed' }`(即使 storage:false 也持久化);`false` 关闭;`id` 手动指定同一 id 可跨页面/跨 agent 复用 */
|
|
376
|
+
skillStorage?: SkillStoreConfig | false;
|
|
365
377
|
memory?: string;
|
|
366
378
|
data?: DataConfig;
|
|
367
379
|
permissions?: PermissionRule[];
|
|
@@ -430,11 +442,19 @@ export interface ChatSdkOptions {
|
|
|
430
442
|
onEvent?: SdkEventHandler;
|
|
431
443
|
/** 流式输出(默认 true);false 时等整段回复再显示 */
|
|
432
444
|
streaming?: boolean;
|
|
445
|
+
/** Dialog UI config (title/placeholder/drawer/drawerWidth/drawerHidden/inputRows/onClose grouped) */
|
|
446
|
+
dialog?: DialogConfig;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** Dialog UI config (grouped form, recommended) */
|
|
450
|
+
export interface DialogConfig {
|
|
433
451
|
title?: string;
|
|
434
452
|
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
453
|
drawer?: boolean;
|
|
437
|
-
|
|
454
|
+
drawerWidth?: number | string;
|
|
455
|
+
drawerHidden?: boolean;
|
|
456
|
+
/** Input box rows (visible height); default 2 (2-row initial height, auto-expands up to max-height:100px). 1 = single row; >2 = taller. */
|
|
457
|
+
inputRows?: number;
|
|
438
458
|
onClose?: () => void;
|
|
439
459
|
}
|
|
440
460
|
|
|
@@ -467,6 +487,14 @@ export interface ChatSdk {
|
|
|
467
487
|
* 清空 skill 全文缓存与本轮已加载记录,下次 load_skill 重新取最新全文(含 vfs doc)。需开启 skills(默认开)
|
|
468
488
|
*/
|
|
469
489
|
setSkills(skills: SkillSpec[]): void;
|
|
490
|
+
/** 添加用户创建的 skill(持久化,跨刷新恢复;同名覆盖)。需开启 skills(默认开) */
|
|
491
|
+
addSkill(skill: SkillSpec): void;
|
|
492
|
+
/** 删除用户创建的 skill(仅删用户创建的,不删集成方 initialSkills)。返回是否删除成功 */
|
|
493
|
+
removeSkill(name: string): boolean;
|
|
494
|
+
/** 列出用户创建的 skill 名(仅用户创建的,不含集成方 initialSkills) */
|
|
495
|
+
listUserSkills(): string[];
|
|
496
|
+
/** 读取用户创建的 skill 详情(返回 {name, description, content};不存在返回 undefined) */
|
|
497
|
+
getUserSkill(name: string): { name: string; description: string; content: string } | undefined;
|
|
470
498
|
/**
|
|
471
499
|
* 清 skill 全文缓存(动态 skill 内容变化时主动失效)。不传 name 清全部;传 name 清指定。
|
|
472
500
|
* 下次 load_skill 重新 getContent/readSkillDoc 取最新。需开启 skills(默认开)
|
|
@@ -545,6 +573,23 @@ export declare function createSessionStore(config?: StorageConfig): SessionStore
|
|
|
545
573
|
export declare function createMemoryBackend(): StorageBackend;
|
|
546
574
|
export declare function createWebStorageBackend(storage: Storage): StorageBackend;
|
|
547
575
|
export declare function isQuotaError(err: unknown): boolean;
|
|
576
|
+
/** 创建 Skill 独立持久化存储(与 storage 选项分离;默认 indexedDB,可手动指定 id 跨页复用) */
|
|
577
|
+
export declare function createSkillStore(config?: SkillStoreConfig): SkillStore;
|
|
578
|
+
export interface SkillStore {
|
|
579
|
+
ready: Promise<boolean>;
|
|
580
|
+
list(): Promise<PersistedSkill[]>;
|
|
581
|
+
get(name: string): Promise<PersistedSkill | undefined>;
|
|
582
|
+
put(skill: PersistedSkill): Promise<void>;
|
|
583
|
+
remove(name: string): Promise<boolean>;
|
|
584
|
+
clear(): Promise<void>;
|
|
585
|
+
dispose(): void;
|
|
586
|
+
}
|
|
587
|
+
/** 持久化的用户创建 skill(getContent 函数不可序列化,故 content 直接存字符串) */
|
|
588
|
+
export interface PersistedSkill {
|
|
589
|
+
name: string;
|
|
590
|
+
description: string;
|
|
591
|
+
content: string;
|
|
592
|
+
}
|
|
548
593
|
|
|
549
594
|
// ============ 大 JSON 查询/搜索/沙箱脚本(dataSlotQuery)============
|
|
550
595
|
export interface JpNode {
|