page-agent-sdk 2.1.0 → 2.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "page-agent-sdk",
3
- "version": "2.1.0",
3
+ "version": "2.4.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",
@@ -9,7 +9,7 @@ Help the user embed `page-agent-sdk` so an AI agent safely edits their page's st
9
9
 
10
10
  ## Core concept
11
11
 
12
- The SDK is a **standardized JSON-operation agent**: the integrator declares writable `window` paths + zod schemas; the agent edits them via `set_data_slot` / `edit_data_slot` (jsonPath patches), validated by schema, scoped to the registry, with snapshot rollback. "Editing JSON" becomes structured + validatable + rollbackable, NOT free-form LLM text.
12
+ The SDK is a **standardized JSON-operation agent**: the integrator declares writable `window` paths + zod schemas; the agent edits them via `read` / `write` (high-level entry, 2.2+; `write` merges set/edit/delete + auto optimistic lock + auto snapshot), validated by schema, scoped to the registry, with snapshot rollback. "Editing JSON" becomes structured + validatable + rollbackable, NOT free-form LLM text. Advanced mode (`toolMode:'advanced'`) also exposes low-level `get_data_slot`/`set_data_slot`/`edit_data_slot`/`delete_data_slot` for precise control.
13
13
 
14
14
  ## Workflow
15
15
 
@@ -47,7 +47,7 @@ createChatSdk({
47
47
  }).mount()
48
48
  ```
49
49
 
50
- For large JSON, prefer `edit_data_slot` (jsonPath patch: set/remove/merge/append) over `set_data_slot` (whole value) — avoids re-sending the entire blob.
50
+ For large JSON, prefer `write` with `patch` (jsonPath patch: set/remove/merge/append) over `write` with whole `value` — avoids re-sending the entire blob.
51
51
 
52
52
  ### 3. Configure the LLM
53
53
 
@@ -83,10 +83,10 @@ Event types: `data_slot_change` / `message_update` / `tool_call` / `tool_result`
83
83
 
84
84
  | Scenario | Key setup |
85
85
  |---|---|
86
- | **Low-code page builder** | `dataSlots` = component tree; `edit_data_slot` jsonPath patches; `onEvent` → canvas refresh; `checkpoint` + `approval` |
86
+ | **Low-code page builder** | `dataSlots` = component tree; `write` patch jsonPath; `onEvent` → canvas refresh; `checkpoint` + `approval` |
87
87
  | **Form designer** | `dataSlots` = field definitions with enum/required schemas; schema validation prevents malformed forms |
88
- | **CMS batch ops** | `eval_script` for bulk loops; `search_data_slot` to filter; `edit_data_slot` for targeted edits |
89
- | **Ops config console** | `approval:{tools:[set,edit]}` human-confirm; `capabilities.verify:true` write-back read; `checkpoint` |
88
+ | **CMS batch ops** | `eval_script` for bulk loops; `search_data_slot` to filter; `write` patch for targeted edits |
89
+ | **Ops config console** | `approval:{tools:['write']}` human-confirm; `capabilities.verify:true` write-back read; `checkpoint` |
90
90
  | **AI-native assistant** | `capabilities:{dataSlotOps:false,fetch:false}` + custom `tools` (your product API) |
91
91
  | **Research agent** | `capabilities:{dataSlotOps:false}`; `subagent:{allowedTools:['fetch_document']}`; `contextPreset:'conservative'` |
92
92
  | **Headless / server-side** | `ui:false` + `storage:'memory'` + `capabilities:{dataSlotOps:false,fetch:false}`; drive via `sdk.send` |
@@ -19,7 +19,7 @@ const sdk = createChatSdk({
19
19
  // 组件懒加载时动态注册其 schema(结构各异)
20
20
  function onComponentMount(comp: { id: string; type: string; schema: z.ZodType }) {
21
21
  sdk.addDataSlot({ path: `app.components.${comp.id}`, description: `${comp.type} 组件`, schema: comp.schema })
22
- // 立即生效:AI 现在能 set/edit_data_slot 这个 path,按其 schema 校验
22
+ // 立即生效:AI 现在能 write 这个 path,按其 schema 校验
23
23
  }
24
24
 
25
25
  // 组件卸载时移除(快照栈一并清理)
@@ -177,7 +177,7 @@ createChatSdk({
177
177
  container: '#chat', llm: { ... },
178
178
  systemPrompt: '多源对比时用 spawn_agents 并行委派。',
179
179
  subagent: {
180
- allowedTools: ['fetch_document', 'get_data_slot'], // read-only subset (no spawn → no recursion)
180
+ allowedTools: ['fetch_document', 'read'], // read-only subset (no spawn → no recursion)
181
181
  maxDepth: 1, // physical recursion cut (default 1)
182
182
  maxParallel: 3, // max parallel subagents in spawn_agents
183
183
  temperature: 0.2, // subagent temperature (default inherits main)
@@ -199,13 +199,13 @@ createChatSdk({
199
199
  {
200
200
  id: 'researcher',
201
201
  description: '调研专家:搜集资料、对比方案(只读)',
202
- tools: ['fetch_document', 'get_data_slot'], // read-only
202
+ tools: ['fetch_document', 'read'], // read-only
203
203
  temperature: 0.2,
204
204
  },
205
205
  {
206
206
  id: 'reviewer',
207
207
  description: '审查专家:检查代码/配置的安全与性能问题',
208
- tools: ['get_data_slot', 'search_data_slot'],
208
+ tools: ['read', 'search_data_slot'],
209
209
  systemPrompt: '你是审查专家,只报告问题不改数据。',
210
210
  temperature: 0.1,
211
211
  },
@@ -276,7 +276,7 @@ createChatSdk({
276
276
  subagents: [{ id: 'researcher', description: '...', tools: ['fetch_document'] }], // pre-declared
277
277
  mcp: [{ transport: 'http', url: '...' }], // external tools
278
278
  capabilities: { verify: true }, // self-check
279
- approval: { tools: ['set_data_slot'] }, // human confirm writes
279
+ approval: { tools: ['write'] }, // human confirm writes
280
280
  checkpoint: true, // rollback
281
281
  }).mount()
282
282
  ```
@@ -73,36 +73,39 @@ createChatSdk({
73
73
  }).mount()
74
74
  ```
75
75
 
76
- `reliableWriteRules` — standardized "reliable write rules": read before write (`get_data_slot`), list in dynamic scenarios, fields per `describe_data_slot`, retry on schema-validation errors, prefer `edit_data_slot` incremental patches. Recommended for any scenario involving window writes.
76
+ `reliableWriteRules` — standardized "reliable write rules": read before write (`read`), list in dynamic scenarios (`read()` no path), fields per `read({path})` (returns format hint), retry on schema-validation errors, prefer `write` with `patch` incremental edits. Recommended for any scenario involving data-slot writes.
77
77
 
78
78
  ## Built-in data slot tools (auto-injected when `capabilities.dataSlotOps`)
79
79
 
80
- | Tool | Purpose |
81
- |---|---|
82
- | `list_data_slots` | List declared paths + descriptions |
83
- | `describe_data_slot` | Show a path's schema |
84
- | `get_data_slot` | Read a path (or ancestor/descendant sub-paths of registered props) |
85
- | `get_slot_paths` | Batch-read multiple paths |
86
- | `set_data_slot` | Write a whole path (schema-validated, scoped to registry) |
87
- | `edit_data_slot` | Patch by `jsonPath` (set/remove/merge/append) avoids re-sending large JSON |
88
- | `delete_data_slot` | Delete a path |
89
- | `snapshot_data_slot` | Manual snapshot |
90
- | `list_data_snapshots` | List snapshots |
91
- | `restore_data_snapshot` | Restore (no id = most recent) |
92
- | `query_data_slot` / `search_data_slot` | JSONPath query / full-text search |
93
- | `eval_script` | Sandboxed script on data (for batch ops) |
94
-
95
- **Key rule**: `set`/`edit`/`delete` only affect **declared** `dataSlots` paths. Invalid schema structured error, no write. `edit` writes in-place (preserves Vue reactive refs).
96
-
97
- ### jsonPath edit operations
98
-
99
- `edit_data_slot({ path, jsonPath, op, value })`:
100
- - `set` set a sub-path
80
+ Default `toolMode:'simple'` exposes high-level `read`/`write` + advanced query/snapshot tools (low-level `get`/`set`/`edit`/`delete`/`list`/`describe` are hidden, merged into `read`/`write`). `toolMode:'advanced'` exposes all; `toolMode:'minimal'` only `read`/`write`.
81
+
82
+ | Tool | Purpose | Mode |
83
+ |---|---|---|
84
+ | **`read`** / **`write`** (2.2+, recommended) | High-level entry: `read({path?})` lists/reads; `write({path, value?, patch?, del?})` merges set/edit/delete + auto optimistic lock + auto snapshot | simple/minimal |
85
+ | `list_data_slots` | List declared paths + descriptions | advanced |
86
+ | `describe_data_slot` | Show a path's schema | advanced |
87
+ | `get_data_slot` | Read a path (or ancestor/descendant sub-paths of registered props) | advanced |
88
+ | `get_slot_paths` | Batch-read multiple paths | simple/advanced |
89
+ | `set_data_slot` | Write a whole path (schema-validated, scoped to registry) | advanced |
90
+ | `edit_data_slot` | Patch by `jsonPath` (set/remove/merge/append) — avoids re-sending large JSON | advanced |
91
+ | `delete_data_slot` | Delete a path | advanced |
92
+ | `snapshot_data_slot` | Manual snapshot | simple/advanced |
93
+ | `list_data_snapshots` | List snapshots | simple/advanced |
94
+ | `restore_data_snapshot` | Restore (no id = most recent) | simple/advanced |
95
+ | `query_data_slot` / `search_data_slot` | JSONPath query / full-text search | simple/advanced |
96
+ | `eval_script` | Sandboxed script on data (for batch ops) | simple/advanced |
97
+
98
+ **Key rule**: `write`/`set`/`edit`/`delete` only affect **declared** `dataSlots` paths. 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).
99
+
100
+ ### write / jsonPath edit operations
101
+
102
+ `write({ path, value, patch: { op, jsonPath } })` (or `write({ path, del: true })` to delete):
103
+ - `set` — set a sub-path (or whole value when no `patch`)
101
104
  - `remove` — remove a sub-path / array element
102
105
  - `merge` — shallow-merge an object
103
106
  - `append` — append to an array
104
107
 
105
- Example: `edit_data_slot({ path: 'app.items', jsonPath: '0.price', op: 'set', value: 9.9 })` — precise local edit, no full re-send.
108
+ Example: `write({ path: 'app.items', value: 9.9, patch: { op: 'set', jsonPath: '0.price' } })` — precise local edit, no full re-send. `value` is a JSON object (recommended) or JSON string.
106
109
 
107
110
  ## Built-in fetch tools (`capabilities.fetch`)
108
111
 
@@ -119,12 +122,37 @@ Example: `edit_data_slot({ path: 'app.items', jsonPath: '0.price', op: 'set', va
119
122
  | `tool_result` | `name, result, status` | Tool returns (`status`: `done`/`error`) |
120
123
  | `subagent` | `taskId, label, kind, name, args?, result?, status?` | Subagent tool progress (forwarded to UI, NOT into main LLM context) |
121
124
  | `done` | `content` | Agent round completes |
122
- | `data_slot_change` | `path, operation, value?` | A data slot was written (`operation`: `set`/`edit`/`delete`/`restore`) |
125
+ | `data_slot_change` | `path, operation, value?` | A data slot was written via `write` (high-level, infers `set`/`edit`/`delete` from args) or low-level `set`/`edit`/`delete`/`restore_data_snapshot` |
123
126
  | `message_update` | `count` | The `messages` array changed |
124
127
  | `error` | `message` | An error occurred (abort excluded) |
125
128
 
126
129
  `approval_request` is **NOT** forwarded via `onEvent`/`hook` (UI handles it; headless integrators use a custom approval middleware listener).
127
130
 
131
+ ## `dataSlots` unified config (3.0+, declarative — schema + bind + auto field-hints)
132
+
133
+ `dataSlots` is the single entry for data-slot config — combining schema declaration + optional object direct-bind + auto field-hint injection:
134
+
135
+ ```ts
136
+ import { reactive } from 'vue' // or any reactivity impl
137
+ const PageSchema = z.object({ title: z.string().describe('页面标题'), count: z.number() })
138
+ const page = reactive({ title: '首页', count: 0 }) // reactive recommended for UI auto-refresh
139
+
140
+ createChatSdk({
141
+ dataSlots: [
142
+ {
143
+ path: 'page', // path on window (dot-nested supported)
144
+ schema: PageSchema, // write validation + field .describe() auto-injected into systemPrompt「可操作属性」section
145
+ bind: page, // optional: reactive/plain object auto-mounted to window[path] + registered as dataSlot
146
+ },
147
+ ],
148
+ })
149
+ // LLM write page → page reactively updates; integrator changes page → LLM read sees it
150
+ ```
151
+
152
+ - **`bind` is an optional `dataSlots` field** (any object): reactive → auto-refresh on write (recommended for UI); plain object → write works but no auto-refresh (suitable for headless / backend; integrator uses `onEvent`/`hook` `data_slot_change` to be notified). Omit `bind` when the integrator mounts `window[path]` themselves (object already exists / dynamic registration via `addDataSlot`/`removeDataSlot` / field-whitelist read).
153
+ - Tools `set`/`write` mutate in-place (`restoreInPlace`), compatible with reactive proxies; plain objects also write fine.
154
+ - **Notifying the outside world of changes**: subscribe `data_slot_change` via `onEvent` (constructor) or `sdk.hook` (runtime, multi-listener, cancellable) — fires after `write`/`set`/`edit`/`delete`/`restore`, with `path`/`operation`/`value`. For Vue + reactive bind, template/watch auto-react (no manual notify needed); `onEvent` can coexist for audit/analytics.
155
+
128
156
  ## Exported building blocks (for custom UIs)
129
157
 
130
158
  - `ChatDialog`, `MessageContent`, `CodePreview` — Vue components
@@ -28,7 +28,7 @@ Drop into any HTML page. The built-in dialog mounts itself. (`systemPrompt` is o
28
28
  </script>
29
29
  ```
30
30
 
31
- Talk to it: "change theme to dark" → AI calls `set_data_slot` → `window.app.theme === 'dark'`.
31
+ Talk to it: "change theme to dark" → AI calls `write({ path:'app.theme', value:'dark' })` → `window.app.theme === 'dark'`.
32
32
 
33
33
  ## Stage 2 — npm + module project
34
34
 
@@ -95,7 +95,7 @@ createChatSdk({
95
95
  // ...llm, dataSlots...
96
96
  capabilities: { verify: true }, // write-back self-check before agent returns
97
97
  verify: { maxAttempts: 2 }, // auto-correct on failure (default check = write-back read + schema)
98
- approval: { tools: ['set_data_slot', 'edit_data_slot'] }, // human-confirm before writes
98
+ approval: { tools: ['write'] }, // human-confirm before writes
99
99
  checkpoint: true, // session-level rollback on bad edits
100
100
  maxParallelTools: 1, // serial tool calls (safe for stateful middleware)
101
101
  contextPreset: 'conservative', // save cost on long sessions
@@ -17,7 +17,7 @@ window.page = {
17
17
  createChatSdk({
18
18
  container: '#chat',
19
19
  llm: { apiKey, baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat', temperature: 0.3 },
20
- systemPrompt: '你是页面搭建助手。用 edit_data_slot 按 jsonPath 增量改 components,不要重传整树。',
20
+ systemPrompt: '你是页面搭建助手。用 write 的 patch 按 jsonPath 增量改 components,不要重传整树。',
21
21
  dataSlots: [
22
22
  { path: 'page.components', description: '组件树',
23
23
  schema: z.array(z.object({
@@ -27,11 +27,11 @@ createChatSdk({
27
27
  ],
28
28
  onEvent(e) { if (e.type === 'data_slot_change') renderCanvas() }, // canvas reactive refresh
29
29
  checkpoint: true, // bad edit → one-click rollback
30
- approval: { tools: ['set_data_slot', 'edit_data_slot'] }, // confirm writes
30
+ approval: { tools: ['write'] }, // confirm writes
31
31
  }).mount()
32
32
  ```
33
33
 
34
- User: "顶部 Banner 改深色、主标题加粗、加一张新品卡" → AI calls `edit_data_slot` per component.
34
+ User: "顶部 Banner 改深色、主标题加粗、加一张新品卡" → AI calls `write` with `patch` per component.
35
35
 
36
36
  ## 2. Form designer
37
37
 
@@ -66,7 +66,7 @@ User: "手机号加格式校验、地址改三级联动" → AI patches `form.fi
66
66
 
67
67
  ## 3. CMS batch operation
68
68
 
69
- Bulk-edit a product list; use `eval_script` or `search_data_slot` + `edit_data_slot` for batch ops.
69
+ Bulk-edit a product list; use `eval_script` or `search_data_slot` + `write` with `patch` for batch ops.
70
70
 
71
71
  ```ts
72
72
  window.products = [
@@ -88,7 +88,7 @@ createChatSdk({
88
88
  }).mount()
89
89
  ```
90
90
 
91
- User: "标题加『限时』前缀、低于 100 元的标红" → AI uses `eval_script` for the prefix loop + `search_data_slot` to find `<100` then `edit_data_slot` to set `highlight`.
91
+ User: "标题加『限时』前缀、低于 100 元的标红" → AI uses `eval_script` for the prefix loop + `search_data_slot` to find `<100` then `write` with `patch` to set `highlight`.
92
92
 
93
93
  ## 4. Ops config console
94
94
 
@@ -109,7 +109,7 @@ createChatSdk({
109
109
  { path: 'config.featureB', description: 'B开关',
110
110
  schema: z.object({ enabled: z.boolean() }) },
111
111
  ],
112
- approval: { tools: ['set_data_slot', 'edit_data_slot'] }, // human-in-the-loop
112
+ approval: { tools: ['write'] }, // human-in-the-loop
113
113
  checkpoint: true,
114
114
  capabilities: { verify: true }, // write-back read + schema check
115
115
  }).mount()
@@ -208,7 +208,7 @@ const sdk = createChatSdk({
208
208
  container: '#chat', llm: { ... },
209
209
  // only the static container is pre-declared; per-component paths are dynamic
210
210
  dataSlots: [{ path: 'app.components', description: '动态组件容器', schema: z.record(z.any()) }],
211
- systemPrompt: '用 list_data_slots 查看当前可操作的组件 path,再按各自 schema 操作',
211
+ systemPrompt: '用 read() 查看当前可操作的组件 path,再按各自 schema 操作',
212
212
  }).mount()
213
213
 
214
214
  // 组件挂载(懒加载)→ 动态注册其 schema,立即对 AI 生效
package/types/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export type StreamHandler = (event: StreamEvent) => void;
45
45
  /**
46
46
  * SDK 事件(供 createChatSdk({ onEvent }) 订阅常用时机)。
47
47
  * 复用 StreamEvent(round_start/reasoning/text/tool_call/tool_result/subagent/done;approval_request 不外发)
48
- * + 额外时机:data_slot_change / message_update / error。
48
+ * + 额外时机:data_change / message_update / error。
49
49
  */
50
50
  export type SdkEvent =
51
51
  | { type: 'round_start'; round: number }
@@ -55,7 +55,7 @@ export type SdkEvent =
55
55
  | { type: 'tool_result'; name: string; result: string; status: 'done' | 'error' }
56
56
  | { type: 'subagent'; taskId: string; label: string; kind: 'tool_call' | 'tool_result'; name: string; args?: any; result?: string; status?: 'done' | 'error' }
57
57
  | { type: 'done'; content: string }
58
- | { type: 'data_slot_change'; path: string; operation: 'set' | 'edit' | 'delete' | 'restore'; value?: unknown }
58
+ | { type: 'data_change'; operation: 'set' | 'edit' | 'delete' | 'restore'; value?: unknown }
59
59
  | { type: 'message_update'; count: number }
60
60
  | { type: 'conflict'; conflict: PendingConflict }
61
61
  | { type: 'error'; message: string };
@@ -80,7 +80,7 @@ export interface ChatDialogProps {
80
80
 
81
81
  export interface ToolInfo { name: string; description: string; schema?: unknown; source?: string }
82
82
  export interface SkillInfo { name: string; description: string }
83
- export interface DataSlotInfo { path: string; description: string; schema?: unknown }
83
+ export interface DataInfo { description?: string; schema?: unknown }
84
84
  export interface SubagentInfo {
85
85
  enabled: boolean;
86
86
  maxDepth: number;
@@ -108,7 +108,7 @@ export interface AgentInfo {
108
108
  systemPrompt: string;
109
109
  tools: ToolInfo[];
110
110
  skills: SkillInfo[];
111
- dataSlots: DataSlotInfo[];
111
+ data?: DataInfo;
112
112
  memory: string;
113
113
  middleware: string[];
114
114
  todos: { content: string; status: string }[];
@@ -149,45 +149,49 @@ export type ChatModelLike = {
149
149
  bindTools: (tools: any[]) => any;
150
150
  };
151
151
 
152
- export interface DataSlotSpec {
153
- /** window 上的路径,支持点号嵌套 */
154
- path: string;
155
- description: string;
156
- /** 值的 zod schema(写入时校验) */
152
+ export interface DataConfig {
153
+ /** 值的 zod schema(写入时校验);字段的 .describe() 自动提取注入 systemPrompt「可操作数据」段 */
157
154
  schema: any;
158
- }
159
- /** createDataSlotOps 选项(审计回调 / 只读探测 / 快照上限 / 字段白名单读 / 乐观锁) */
160
- export interface DataSlotOpsOptions {
161
- onAudit?: (entry: { op: string; path: string; value?: any; detail?: string; timestamp: number }) => void;
162
- allowRawRead?: boolean;
155
+ /** 数据源:reactive/普通对象,工具直接读写 bind(reactive 写后响应式刷新;不挂 window) */
156
+ bind: any;
157
+ /** 数据说明,供 Agent 理解用途;不传则自动生成 */
158
+ description?: string;
159
+ }
160
+ /** createDataOps 选项(审计回调 / 快照上限 / 乐观锁) */
161
+ export interface DataOpsOptions {
162
+ onAudit?: (entry: { op: string; value?: any; detail?: string; timestamp: number }) => void;
163
163
  maxSnapshots?: number;
164
- /**
165
- * 字段白名单读模式(默认 true):仅允许读「注册 path 自身 / 其后代」,禁止读未注册的祖先,
166
- * 防止 LLM 经 get_data_slot('page') 把整个大 JSON 拉进上下文。
167
- * 集成方注册「可操作子路径」(如 page.theme.color / page.components)而非顶层时,默认即「LLM 只见声明字段」。
168
- * 设 false 回退原行为(允许读注册 path 的祖先,即整体读)。
169
- */
170
- whitelist?: boolean;
171
164
  /** 乐观锁冲突人工介入回调(详见 ConflictInfo/ConflictResolution);不传则冲突时返回 VERSION_CONFLICT 错误 */
172
165
  onConflict?: (conflict: ConflictInfo) => Promise<ConflictResolution>;
173
166
  /**
174
- * 自动乐观锁(默认 true):写入时若 LLM 未显式传 expectedHash,自动用「LLM 最后一次 get_data_slot 读到的 hash」作基准比对。
167
+ * 自动乐观锁(默认 true):写入时若 LLM 未显式传 expectedHash,自动用「LLM 最后一次 read/get 读到的 hash」作基准比对。
175
168
  * LLM 无需手动传 expectedHash 即可享受乐观锁保护;冲突走 onConflict(无 onConflict 则返回 VERSION_CONFLICT)。
176
169
  * LLM 未读过直接写(无基准记录)时跳过锁(等同不校验)。设 false 回退「不传 expectedHash = 不校验」的旧行为。
177
170
  */
178
171
  autoLock?: boolean;
172
+ /** 读写拦截器:read/write 透传给数据工具(脱敏/转换/审计/拒绝 LLM 读写) */
173
+ interceptors?: DataInterceptors;
179
174
  }
180
175
 
181
- /** 数据槽注册表控制器(运行时动态增删;createDataSlotOps 返回的工具数组上以不可枚举属性 `controller` 挂载) */
182
- export interface DataSlotOpsController {
183
- /** 新增/覆盖一个属性注册项(运行时懒加载组件场景);覆盖时旧快照栈保留 */
184
- add(spec: DataSlotSpec): void;
185
- /** 移除一个属性注册项;返回是否确实存在并移除。快照栈一并清理 */
186
- remove(path: string): boolean;
187
- /** 列出当前所有注册项(反映动态增删后的最新状态) */
188
- list(): DataSlotSpec[];
189
- /** 是否已注册某 path */
190
- has(path: string): boolean;
176
+ /** 数据读写拦截器(集成方可脱敏/转换/审计/拒绝 LLM 的读写) */
177
+ export interface DataInterceptors {
178
+ /** LLM 读时拦截:原始值 → 改写后返回给 LLM(如脱敏/派生);抛错则返回 READ_INTERCEPT 错误 */
179
+ read?: (value: any) => any;
180
+ /** LLM 写时拦截:欲写值 + 当前值 → 改写后的值,或 { error } 拒绝;抛错则拒绝 */
181
+ write?: (payload: any, current: any) => any | { error: string };
182
+ }
183
+
184
+ /** 工具呈现模式:simple=主推 read/write 但保留高级能力(默认)| advanced=全暴露| minimal=只 read/write */
185
+ export type ToolMode = 'simple' | 'advanced' | 'minimal';
186
+
187
+ /** 数据操作控制器(运行时替换配置;createDataOps 返回的工具数组上以不可枚举属性 `controller` 挂载) */
188
+ export interface DataOpsController {
189
+ /** 读取当前配置 */
190
+ get(): DataConfig;
191
+ /** 替换主数据配置(如页面切换、schema 变更);清空快照栈与乐观锁缓存 */
192
+ set(config: DataConfig): void;
193
+ /** 仅替换 bind 引用;清空快照栈与乐观锁缓存 */
194
+ update(bind: any): void;
191
195
  }
192
196
 
193
197
  export interface PermissionRule {
@@ -225,7 +229,7 @@ export interface VerifyMiddlewareOptions {
225
229
  }
226
230
  /** createWriteBackCheck 选项 */
227
231
  export interface WriteBackCheckOptions {
228
- /** path → zod schema(由 createChatSdk 从 dataSlots 构造注入);省略则只校验「读回非空」 */
232
+ /** name → zod schema(由 createChatSdk 从 data 构造注入,键 '' 代表主数据);省略则只校验「读回非空」 */
229
233
  schemas?: Record<string, any>;
230
234
  /** 读 window 的根对象(默认 globalThis.window) */
231
235
  window?: unknown;
@@ -333,15 +337,26 @@ export interface ChatSdkOptions {
333
337
  tools?: any[];
334
338
  skills?: SkillSpec[];
335
339
  memory?: string;
336
- dataSlots?: DataSlotSpec[];
340
+ data?: DataConfig;
337
341
  permissions?: PermissionRule[];
338
342
  /** 自定义中间件(注入到内置中间件之后;可拦截/观察模型调用、工具、prompt) */
339
343
  middleware?: any[];
340
344
  vfs?: { initialFiles?: Record<string, string>; maxBytes?: number };
341
- /** 每个 数据槽最多保留快照数(默认 20) */
345
+ /** 每个数据对象最多保留快照数(默认 20) */
342
346
  maxSnapshots?: number;
343
347
  /** 自动乐观锁(默认 true):写入时若 LLM 未传 expectedHash,自动用其最后 get 读到的 hash 比对;设 false 回退「不传 = 不校验」 */
344
348
  autoLock?: boolean;
349
+ /** 工具呈现模式:simple(默认,主推 read/write 但保留 query/search/eval/snapshot)| advanced(全暴露)| minimal(只 read/write) */
350
+ toolMode?: 'simple' | 'advanced' | 'minimal';
351
+ /** 读写拦截器:read/write 透传给数据工具(脱敏/转换/审计/拒绝 LLM 读写);input/output 在 agent IO 入口/出口预处理 */
352
+ interceptors?: {
353
+ read?: (value: any) => any;
354
+ write?: (payload: any, current: any) => any | { error: string };
355
+ /** agent 接收输入时拦截:send/stream 的 user message 预处理(可改写/审计) */
356
+ input?: (input: any) => any;
357
+ /** agent 产出输出时拦截:返回前 postprocess(可改写最终回复) */
358
+ output?: (json: any) => any;
359
+ };
345
360
  /** 内存中保留的对话轮数上限(默认 50);超限把最旧轮次压缩为摘要 system 消息(防 OOM);0 关闭 */
346
361
  maxMemoryRounds?: number;
347
362
  debug?: boolean;
@@ -355,7 +370,7 @@ export interface ChatSdkOptions {
355
370
  /** 模型最大输出(token);顶层声明对 llm 实例场景也生效,缺省按 model 名查表 */
356
371
  maxOutputTokens?: number;
357
372
  /** 子 agent 委派(默认开启;{ enabled: false } 关闭) */
358
- capabilities?: { dataSlotOps?: boolean; fetch?: boolean; planning?: boolean; skills?: boolean; vfs?: boolean; summarization?: boolean; memory?: boolean; subagent?: boolean; verify?: boolean };
373
+ capabilities?: { dataOps?: boolean; fetch?: boolean; planning?: boolean; skills?: boolean; vfs?: boolean; summarization?: boolean; memory?: boolean; subagent?: boolean; verify?: boolean };
359
374
  subagent?: { enabled?: boolean; allowedTools?: string[]; systemPrompt?: string; temperature?: number; maxTokens?: number; skills?: SkillSpec[]; llm?: LLMConfig | ChatModelLike; maxDepth?: number; maxParallel?: number };
360
375
  /** 预声明子 agent 列表:每个用同主配置方式声明,自动生成 use_<id> 委派工具(与 spawn_agent 共存) */
361
376
  subagents?: SubagentConfig[];
@@ -399,30 +414,27 @@ export interface ChatSdk {
399
414
  send(message: string): Promise<string>;
400
415
  switchSession(sessionId?: string): Promise<string>;
401
416
  stream: (messages: AgentMessage[], onEvent: StreamHandler, signal?: AbortSignal) => Promise<string>;
402
- /** 检视 agent 详细信息(tools/skills/dataSlots/middleware/todos) */
417
+ /** 检视 agent 详细信息(tools/skills/data/middleware/todos) */
403
418
  inspect(): AgentInfo;
404
- /** 回退到最近一次正常 checkpoint(整体还原对话历史 + 数据槽注册项 + vfs + todos);需开启 checkpoint,无可用返回 false */
419
+ /** 回退到最近一次正常 checkpoint(整体还原对话历史 + 主数据 + vfs + todos);需开启 checkpoint,无可用返回 false */
405
420
  restoreLastCheckpoint(): boolean;
406
421
  /** 列出可用 checkpoint(回退点);需开启 checkpoint,未开启返回空数组 */
407
422
  listCheckpoints(): CheckpointMeta[];
408
423
  /** 运行时订阅 SDK 事件(可多个监听器,返回取消函数);与构造时 onEvent 互补 */
409
424
  hook(handler: SdkEventHandler): () => void;
410
- /** 运行时动态新增/覆盖一个 数据槽注册项(懒加载组件:组件挂载时注册其 schema);立即对 数据槽工具生效,无需重建 agent。需开启 dataSlotOps */
411
- addDataSlot(spec: DataSlotSpec): void;
412
- /** 运行时移除一个 数据槽注册项(组件卸载);返回是否确实存在并移除。快照栈一并清理 */
413
- removeDataSlot(path: string): boolean;
414
- /** 列出当前所有已注册 数据槽(反映动态增删后的最新状态) */
415
- listDataSlots(): DataSlotSpec[];
425
+ /** 运行时替换主数据配置(如页面切换、schema 变更);立即对数据工具生效,无需重建 agent。需开启 dataOps */
426
+ setData(config: DataConfig): void;
427
+ /** 读取当前主数据配置;dataOps 关闭时返回 undefined */
428
+ getData(): DataConfig | undefined;
416
429
  /** 乐观锁冲突挂起状态(响应式 ref;无冲突为 null,有冲突时 UI 据此渲染冲突对话框)。headless 集成方可 watch 自建 UI */
417
430
  pendingConflict: Ref<PendingConflict | null>;
418
431
  /** 冲突解决:用户点「保留外部」(keep_external)/「强制覆盖」(overwrite)/「回退」(restore) → 收口挂起的 conflict,被挂起的工具调用继续 */
419
432
  resolveConflict(action: ConflictResolution['action']): void;
420
433
  }
421
434
 
422
- /** 乐观锁冲突挂起(dataSlotOps 写入时 expectedHash 不匹配,挂起等用户决定) */
435
+ /** 乐观锁冲突挂起(dataOps 写入时 expectedHash 不匹配,挂起等用户决定) */
423
436
  export interface PendingConflict {
424
437
  id: number;
425
- path: string;
426
438
  op: 'set' | 'edit' | 'delete';
427
439
  agentValue?: unknown;
428
440
  currentValue: unknown;
@@ -438,9 +450,8 @@ export type ConflictResolution =
438
450
  | { action: 'overwrite' }
439
451
  | { action: 'restore' };
440
452
 
441
- /** 乐观锁冲突信息(dataSlotOps onConflict 回调参数) */
453
+ /** 乐观锁冲突信息(dataOps onConflict 回调参数) */
442
454
  export interface ConflictInfo {
443
- path: string;
444
455
  op: 'set' | 'edit' | 'delete';
445
456
  agentValue?: unknown;
446
457
  currentValue: unknown;
@@ -456,12 +467,13 @@ export declare function defineTool(opts: {
456
467
  schema: any;
457
468
  handler: (args: any) => unknown | Promise<unknown>;
458
469
  }): any;
459
- export declare function createDataSlotOps(props: DataSlotSpec[], opts?: DataSlotOpsOptions): any[];
460
- export declare function selectBuiltinTools(caps: { dataSlotOps?: boolean; fetch?: boolean } | undefined, dataSlotOps: any[], fetchDocs: any[]): any[];
461
- export declare function createUsageHintsMiddleware(caps: { planning?: boolean; dataSlotOps?: boolean; subagent?: boolean } | undefined, hasDataSlotOps: boolean): any;
470
+ export declare function createDataOps(config: DataConfig, opts?: DataOpsOptions): any[];
471
+ export declare function filterByToolMode(tools: any[], mode?: 'simple' | 'advanced' | 'minimal'): any[];
472
+ export declare function selectBuiltinTools(caps: { dataOps?: boolean; fetch?: boolean } | undefined, dataOps: any[], fetchDocs: any[]): any[];
473
+ export declare function createUsageHintsMiddleware(caps: { planning?: boolean; dataOps?: boolean; subagent?: boolean } | undefined, hasDataOps: boolean, toolMode?: 'simple' | 'advanced' | 'minimal'): any;
462
474
  export declare const fetchDocTools: any[];
463
475
  export declare const fetchTools: any[];
464
- export declare function defineDataSlotToolset(props: DataSlotSpec[], opts?: DataSlotOpsOptions): any[];
476
+ export declare function defineDataToolset(config: DataConfig, opts?: DataOpsOptions): any[];
465
477
  export declare function defineSkill(spec: SkillSpec): SkillSpec;
466
478
  export declare function createAgent(options: any): any;
467
479
  /** 检测模型把工具调用写成文本(伪 XML/标签)而非标准 tool_calls 的异常格式;主循环据此回灌 feedback 自纠 */
@@ -475,6 +487,8 @@ export declare const systemPromptHelpers: {
475
487
  /** 可靠写入规则:改前先读、动态先 list、字段以 describe 为准、写错看校验错误重试、优先增量 patch */
476
488
  readonly reliableWriteRules: string;
477
489
  };
490
+ /** 从 zod schema 提取字段说明(io 契约注入 systemPrompt 用);非 object schema 用 description 兜底 */
491
+ export declare function extractSchemaHint(schema: any): string;
478
492
  export declare function createSessionStore(config?: StorageConfig): SessionStore;
479
493
  export declare function createMemoryBackend(): StorageBackend;
480
494
  export declare function createWebStorageBackend(storage: Storage): StorageBackend;
@@ -560,10 +574,10 @@ export declare function createSubagentsMiddleware(opts: any): any;
560
574
  export interface SubagentOptions { [k: string]: any }
561
575
  export interface SubagentLlmConfig { [k: string]: any }
562
576
 
563
- // checkpoint / dataSlotOps / permissions
577
+ // checkpoint / dataOps / permissions
564
578
  export interface CheckpointDeps { [k: string]: any }
565
- export interface DataSlotAuditEntry { [k: string]: any }
566
- export interface DataSlotSnapshotEntry { [k: string]: any }
579
+ export interface DataAuditEntry { [k: string]: any }
580
+ export interface DataSnapshotEntry { [k: string]: any }
567
581
  export type PermissionOp = string;
568
582
 
569
583
  // vfs