page-agent-sdk 3.47.0 → 4.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "page-agent-sdk",
3
- "version": "3.47.0",
3
+ "version": "4.0.0",
4
4
  "type": "module",
5
5
  "description": "AI agent SDK for web pages — embed a chat assistant that edits page data via schema-validated tools. A lighter, framework-agnostic alternative to CopilotKit/LangChain for in-page JSON-editing agents. Vue-bundled; works with DeepSeek, OpenAI, MCP.",
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 a structured ma
9
9
 
10
10
  ## Core concept
11
11
 
12
- The SDK is a **standardized JSON-operation agent**: the integrator declares ONE main data object (`data: { schema, bind, description? }`); the agent edits it via `read` / `write` (high-level entry; `write` merges set/edit/delete + auto optimistic lock + auto snapshot), validated by schema, scoped to schema-declared fields (ZodObject top-level keys auto-whitelist), with snapshot rollback. "Editing JSON" becomes structured + validatable + rollbackable, NOT free-form LLM text. `bind` is any reactive/plain object — tools read/write it directly, **no `window` dependency**. Advanced mode (`toolMode:'advanced'`) also exposes low-level `get_data`/`set_data`/`edit_data`/`delete_data` for precise control.
12
+ The SDK is a **standardized JSON-operation agent**: the integrator declares ONE main data object (`data: { schema, bind, description? }`); the agent edits it via `read` / `write` (high-level entry; `write` merges set/edit/delete + auto optimistic lock + auto snapshot), validated by schema, scoped to schema-declared fields (ZodObject top-level keys auto-whitelist), with snapshot rollback. "Editing JSON" becomes structured + validatable + rollbackable, NOT free-form LLM text. `bind` is any reactive/plain object — tools read/write it directly, **no `window` dependency**.
13
13
 
14
14
  ## Workflow
15
15
 
@@ -96,23 +96,19 @@ By default (`appendReliableWriteRules: true`), the SDK auto-appends `reliableWri
96
96
 
97
97
  ## Built-in data tools (auto-injected when `capabilities.dataOps`)
98
98
 
99
- Default `toolMode:'simple'` exposes high-level `read`/`write` + advanced query/snapshot tools (low-level `get`/`set`/`edit`/`delete`/`describe` are hidden, merged into `read`/`write`). `toolMode:'advanced'` exposes all; `toolMode:'minimal'` only `read`/`write`.
100
-
101
- | Tool | Purpose | Mode |
102
- |---|---|---|
103
- | **`read`** / **`write`** (2.2+, recommended) | High-level entry: `read({jsonPath?, fields?, depth?})` lists/reads (supports field projection + depth truncation); `write({value?, patch?, patches?, del?})` merges set/edit/delete + auto optimistic lock + auto snapshot | simple/minimal |
104
- | `describe_data` | Show main data description + schema field descriptions | advanced |
105
- | `get_data` | Read main data (supports `jsonPath` precise sub-path read) | advanced |
106
- | `set_data` | Write whole main data (schema-validated, scoped to declared fields) | advanced |
107
- | `edit_data` | Patch by `jsonPath` (set/remove/merge/append) avoids re-sending large JSON | advanced |
108
- | `delete_data` | Delete a sub-path (jsonPath) | advanced |
109
- | `snapshot_data` | Manual snapshot | simple/advanced |
110
- | `list_data_snapshots` | List snapshots | simple/advanced |
111
- | `restore_data` | Restore (no id = most recent) | simple/advanced |
112
- | `query_data` / `search_data` | JSONPath query / full-text search | simple/advanced |
113
- | `eval_script` | Sandboxed script on data (query/transform; transform supports `{patches:[...]}` incremental mode) | simple/advanced |
114
-
115
- **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).
99
+ High-level `read`/`write` are the main entry points; query/snapshot/eval tools are always available (no mode switch). Low-level CRUD `get_data`/`set_data`/`edit_data`/`delete_data` was **removed in 4.0** `read`/`write` cover everything (`get_data({p})`→`read({jsonPath:p})`, `set_data({value})`→`write({value})`, `edit_data({op,p,value})`→`write({patch:{op,jsonPath:p,value}})`, `delete_data({p})`→`write({patch:{jsonPath:p},del:true})`).
100
+
101
+ | Tool | Purpose |
102
+ |---|---|
103
+ | **`read`** / **`write`** (recommended) | High-level entry: `read({jsonPath?, jsonPaths?, fields?, depth?, offset?, limit?})` lists/reads (field projection + depth truncation + array paging); `write({value?, patch?, patches?, del?, dryRun?})` merges set/edit/delete + auto optimistic lock + auto snapshot |
104
+ | `describe_data` | Show main data description + format hints |
105
+ | `schema_data` / `diff_data` | Inspect schema constraints at a path / diff snapshots or JSON |
106
+ | `restore_data` / `history_data` | Restore snapshot (no id = most recent) / list & read snapshots |
107
+ | `query_data` / `search_data` | JSONPath query / full-text search |
108
+ | `eval_script` | Sandboxed script on data (query/transform; transform supports `{patches:[...]}` incremental mode) |
109
+ | `draft_write` / `draft_commit` | Opt-in (`capabilities.draftWrite`) chunked build for very large JSON + atomic commit |
110
+
111
+ **Key rule**: `write` (all four intents) only affects **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` writes in-place (preserves Vue reactive refs). `write` auto-tracks hash from `read` for optimistic lock (no manual `expectedHash` needed). Whole-set / `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).
116
112
 
117
113
  ### write / jsonPath edit operations
118
114
 
@@ -583,6 +583,8 @@ export type SkillToolFactory = () => any | any[] | Promise<any | any[]>;
583
583
  export interface VerifyCheckContext {
584
584
  messages: any[];
585
585
  state: any;
586
+ /** 结构化日志(debugLogs;render-check 类环境降级留痕用,可缺省) */
587
+ log?: (type: string, data: unknown) => void;
586
588
  }
587
589
  export interface VerifyCheckResult {
588
590
  ok: boolean;
@@ -1140,7 +1142,7 @@ export declare function defineTool(opts: {
1140
1142
  writeCapable?: boolean | ((args: Record<string, unknown>) => boolean);
1141
1143
  }): any;
1142
1144
  export declare function createDataOps(config: DataConfig, opts?: DataOpsOptions): any[];
1143
- /** 整体 set 写入纯函数:schema 校验 + 快照 + merge/替换 + audit。set_data / write(set) / draft_commit 共用。返回 {ok,hash,data} 或 {ok:false,error} */
1145
+ /** 整体 set 写入纯函数:schema 校验 + 快照 + merge/替换 + audit。write(set) / draft_commit 共用。返回 {ok,hash,data} 或 {ok:false,error} */
1144
1146
  export declare function commitSetToBind(args: { bindRef: unknown; value: unknown; schema: any; allowKeys: string[] | null; snapshots: any[]; maxSnapshots: number; audit: (e: any) => void; dryRun?: boolean; op?: 'set' | 'draft_commit'; snapshotLabel?: string }): { ok: true; hash: string; data: unknown; notices: string[] } | { ok: false; error: string };
1145
1147
  export interface LocalWriteBack {
1146
1148
  op: 'set' | 'remove' | 'move' | 'mergeKeys' | 'appendElems';
@@ -1455,7 +1457,7 @@ export interface JpNode {
1455
1457
  path: string;
1456
1458
  /** 匹配元素值 */
1457
1459
  value: unknown;
1458
- /** 父为数组时的索引(便于后续 edit_data_slot 的 jsonPath 定位) */
1460
+ /** 父为数组时的索引(便于后续 write patch 的 jsonPath 定位) */
1459
1461
  index?: number;
1460
1462
  }
1461
1463
  export interface SearchHit {
@@ -1640,6 +1642,76 @@ export interface HtmlFormatCheckOptions {
1640
1642
  }
1641
1643
  /** HTML 格式 verify check(beforeReturn 门禁):扫 state.files 代码文件,不通过回灌 feedback 自纠 */
1642
1644
  export declare function createHtmlFormatCheck(opts?: HtmlFormatCheckOptions): VerifyCheck;
1645
+ /** 沙箱采集到的原始渲染信号(console.error / js-error / unhandledrejection / 资源失败 / CSP 违规 / console.warn) */
1646
+ export interface RenderSignal {
1647
+ type: 'console-error' | 'console-warn' | 'js-error' | 'unhandledrejection' | 'resource-error' | 'csp-violation';
1648
+ message: string;
1649
+ source?: string;
1650
+ lineno?: number;
1651
+ }
1652
+ /** 渲染指标(收集窗结束时采集;白屏判定口径 = 内容级:body 子节点数 / scrollHeight / 图片数) */
1653
+ export interface RenderMetrics {
1654
+ bodyChildren: number;
1655
+ scrollHeight: number;
1656
+ imgCount: number;
1657
+ }
1658
+ /** 单组件沙箱渲染的原始结果(未归一;noDom = node/无 DOM 环境标记) */
1659
+ export interface RawRenderResult {
1660
+ handshake: boolean;
1661
+ signals: RenderSignal[];
1662
+ metrics?: RenderMetrics;
1663
+ timedOut?: boolean;
1664
+ noDom?: boolean;
1665
+ }
1666
+ /** 归一后的单组件判定:pass / fail(带 problems)/ unavailable(握手缺失或超时,不算通过防假绿) */
1667
+ export interface RenderVerdict {
1668
+ verdict: 'pass' | 'fail' | 'unavailable';
1669
+ problems: string[];
1670
+ warnings: string[];
1671
+ metrics?: RenderMetrics;
1672
+ reason?: 'handshake-missing' | 'timeout';
1673
+ }
1674
+ /** 渲染自检 VerifyCheck 工厂选项(runner 注入供测试桩用) */
1675
+ export interface HtmlRenderCheckOptions {
1676
+ vfsPrefix?: string;
1677
+ codeField?: string;
1678
+ writablePaths?: string[];
1679
+ runner?: (html: string) => Promise<RawRenderResult>;
1680
+ maxTargets?: number;
1681
+ }
1682
+ /** 渲染自检对象:check 组合进 createHtmlSubagent 的 formatCheck 链;两个注入槽由装配期回填 */
1683
+ export interface HtmlRenderCheck {
1684
+ check: VerifyCheck;
1685
+ setGetController: (g: () => {
1686
+ get?: () => { bind?: unknown } | null | undefined;
1687
+ } | null | undefined) => void;
1688
+ setWritablePaths: (paths: string[]) => void;
1689
+ }
1690
+ /** 沙箱运行参数(活动静默窗/硬上限/指标应答宽限;默认 900ms / 4000ms / 500ms) */
1691
+ export interface SandboxRunOptions {
1692
+ silenceMs?: number;
1693
+ hardCapMs?: number;
1694
+ metricsGraceMs?: number;
1695
+ }
1696
+ /**
1697
+ * 渲染级自检(render-check):本轮触达的 code 资产放沙箱 iframe(srcdoc + sandbox="allow-scripts")独立渲染,
1698
+ * 采集 console.error / window.onerror / unhandledrejection / 资源失败 / 白屏指标 → 归一回灌自纠。
1699
+ * 仅门禁形态(组合进 createHtmlSubagent 的 formatCheck 链);node/无 DOM 自动跳过渲染段保留结构段;
1700
+ * 握手缺失(宿主 CSP 拦沙箱内联脚本)/ 超时 → unavailable 不算通过(零信号 ≠ 通过)。
1701
+ */
1702
+ export declare function createHtmlRenderCheck(opts?: HtmlRenderCheckOptions): HtmlRenderCheck;
1703
+ /** 组合「结构 → 渲染」为单一 VerifyCheck(结构不过短路渲染;runBeforeReturn 不短路,两段必须单 check 内早返回) */
1704
+ export declare function composeStructureThenRender(structure: VerifyCheck, render: VerifyCheck): VerifyCheck;
1705
+ /** 信号归一纯函数:storage 类 SecurityError 降 warn(沙箱假阳性);无失败信号但 body 空 + scrollHeight<10 → 疑似白屏 fail */
1706
+ export declare function normalizeRenderResult(raw: RawRenderResult): RenderVerdict;
1707
+ /** 单组件沙箱渲染(离屏 iframe;用后销毁;node/无 DOM 返回 noDom) */
1708
+ export declare function renderInSandbox(html: string, opts?: SandboxRunOptions): Promise<RawRenderResult>;
1709
+ /** 沙箱 srcdoc 构造(collector 注入文档最前,不改组件原文) */
1710
+ export declare function buildSandboxSrcdoc(html: string, nonce: string): string;
1711
+ /** collector 采集脚本源码(nonce 握手 + 信号上报 + 活动信号 + 指标应答) */
1712
+ export declare function buildCollectorJs(nonce: string): string;
1713
+ /** 累计/销毁的沙箱 iframe 数(测试观察「用后销毁」契约) */
1714
+ export declare function getSandboxLifecycle(): { created: number; destroyed: number };
1643
1715
 
1644
1716
  // checkpoint / dataOps / permissions
1645
1717
  export interface CheckpointDeps { [k: string]: any }
package/types/index.d.ts CHANGED
@@ -950,6 +950,8 @@ export type SkillToolFactory = () => any | any[] | Promise<any | any[]>;
950
950
  export interface VerifyCheckContext {
951
951
  messages: any[];
952
952
  state: any;
953
+ /** 结构化日志(debugLogs;render-check 类环境降级留痕用,可缺省) */
954
+ log?: (type: string, data: unknown) => void;
953
955
  }
954
956
  export interface VerifyCheckResult {
955
957
  ok: boolean;
@@ -1569,7 +1571,7 @@ export declare function defineTool(opts: {
1569
1571
  writeCapable?: boolean | ((args: Record<string, unknown>) => boolean);
1570
1572
  }): any;
1571
1573
  export declare function createDataOps(config: DataConfig, opts?: DataOpsOptions): any[];
1572
- /** 整体 set 写入纯函数:schema 校验 + 快照 + merge/替换 + audit。set_data / write(set) / draft_commit 共用。返回 {ok,hash,data} 或 {ok:false,error} */
1574
+ /** 整体 set 写入纯函数:schema 校验 + 快照 + merge/替换 + audit。write(set) / draft_commit 共用。返回 {ok,hash,data} 或 {ok:false,error} */
1573
1575
  export declare function commitSetToBind(args: { bindRef: unknown; value: unknown; schema: any; allowKeys: string[] | null; snapshots: any[]; maxSnapshots: number; audit: (e: any) => void; dryRun?: boolean; op?: 'set' | 'draft_commit'; snapshotLabel?: string }): { ok: true; hash: string; data: unknown; notices: string[] } | { ok: false; error: string };
1574
1576
  /** path-scoped-validation:增量 patch 逐目标局部校验(全部 apply 后按最终态;兄弟脏数据不株连)。返回写回计划 */
1575
1577
  export interface LocalWriteBack {
@@ -1590,7 +1592,7 @@ export interface LocalValidationPlan {
1590
1592
  export declare function validateRootValueLocally(args: { schema: any; allowKeys: string[] | null; value: unknown; bindRef: unknown }): { ok: true; assembly: unknown; wholeParsed: Record<string, unknown> | null; notices: string[] } | { ok: false; error: string; notices: string[] };
1591
1593
  /** 增量 patch 逐目标局部校验纯函数(appendCaptures/moveCaptures 由 apply 循环捕获;valueAt 为位移兜底) */
1592
1594
  export declare function validateWriteLocally(args: { schema: any; bindRef: unknown; clone: unknown; patches: { op?: string; jsonPath?: string; value?: unknown }[]; schemaErrorMode?: 'zod' | 'schema_invalid'; appendCaptures: { jp: string; elems: unknown[] }[]; moveCaptures: { jp: string; toPath: string; elem: unknown }[]; valueAt?: (jp: string) => unknown }): LocalValidationPlan;
1593
- /** 增量 patch 写入纯函数(clone + 局部校验 + 快照 + 外科手术式写回);edit_data / write(edit) / eval 共用 */
1595
+ /** 增量 patch 写入纯函数(clone + 局部校验 + 快照 + 外科手术式写回);write(edit) / eval 共用 */
1594
1596
  export declare function applyPatchesToBind(args: { bindRef: unknown; patches: { op?: string; jsonPath?: string; value?: unknown }[]; schema: any; allowKeys: string[] | null; snapshots: any[]; maxSnapshots: number; markDataDirty?: () => void; schemaErrorMode?: 'zod' | 'schema_invalid'; snapshotLabel?: string; dryRun?: boolean; internalAfterWrite?: (bind: any, before: any) => void; protectedCtx?: unknown }): { ok: true; applied: { op: string; jp: string; value: unknown }[]; clone: unknown; notices: string[] } | { ok: false; error: string };
1595
1597
  /** 结构化追踪 span(revive-observability-tracing Phase 3) */
1596
1598
  export type SpanType = 'round' | 'model' | 'tool' | 'compression';
@@ -1934,7 +1936,7 @@ export interface JpNode {
1934
1936
  path: string;
1935
1937
  /** 匹配元素值 */
1936
1938
  value: unknown;
1937
- /** 父为数组时的索引(便于后续 edit_data_slot 的 jsonPath 定位) */
1939
+ /** 父为数组时的索引(便于后续 write patch 的 jsonPath 定位) */
1938
1940
  index?: number;
1939
1941
  }
1940
1942
  export interface SearchHit {
@@ -2126,6 +2128,76 @@ export interface HtmlFormatCheckOptions {
2126
2128
  }
2127
2129
  /** HTML 格式 verify check(beforeReturn 门禁):扫 state.files 代码文件,不通过回灌 feedback 自纠 */
2128
2130
  export declare function createHtmlFormatCheck(opts?: HtmlFormatCheckOptions): VerifyCheck;
2131
+ /** 沙箱采集到的原始渲染信号(console.error / js-error / unhandledrejection / 资源失败 / CSP 违规 / console.warn) */
2132
+ export interface RenderSignal {
2133
+ type: 'console-error' | 'console-warn' | 'js-error' | 'unhandledrejection' | 'resource-error' | 'csp-violation';
2134
+ message: string;
2135
+ source?: string;
2136
+ lineno?: number;
2137
+ }
2138
+ /** 渲染指标(收集窗结束时采集;白屏判定口径 = 内容级:body 子节点数 / scrollHeight / 图片数) */
2139
+ export interface RenderMetrics {
2140
+ bodyChildren: number;
2141
+ scrollHeight: number;
2142
+ imgCount: number;
2143
+ }
2144
+ /** 单组件沙箱渲染的原始结果(未归一;noDom = node/无 DOM 环境标记) */
2145
+ export interface RawRenderResult {
2146
+ handshake: boolean;
2147
+ signals: RenderSignal[];
2148
+ metrics?: RenderMetrics;
2149
+ timedOut?: boolean;
2150
+ noDom?: boolean;
2151
+ }
2152
+ /** 归一后的单组件判定:pass / fail(带 problems)/ unavailable(握手缺失或超时,不算通过防假绿) */
2153
+ export interface RenderVerdict {
2154
+ verdict: 'pass' | 'fail' | 'unavailable';
2155
+ problems: string[];
2156
+ warnings: string[];
2157
+ metrics?: RenderMetrics;
2158
+ reason?: 'handshake-missing' | 'timeout';
2159
+ }
2160
+ /** 渲染自检 VerifyCheck 工厂选项(runner 注入供测试桩用) */
2161
+ export interface HtmlRenderCheckOptions {
2162
+ vfsPrefix?: string;
2163
+ codeField?: string;
2164
+ writablePaths?: string[];
2165
+ runner?: (html: string) => Promise<RawRenderResult>;
2166
+ maxTargets?: number;
2167
+ }
2168
+ /** 渲染自检对象:check 组合进 createHtmlSubagent 的 formatCheck 链;两个注入槽由装配期回填 */
2169
+ export interface HtmlRenderCheck {
2170
+ check: VerifyCheck;
2171
+ setGetController: (g: () => {
2172
+ get?: () => { bind?: unknown } | null | undefined;
2173
+ } | null | undefined) => void;
2174
+ setWritablePaths: (paths: string[]) => void;
2175
+ }
2176
+ /** 沙箱运行参数(活动静默窗/硬上限/指标应答宽限;默认 900ms / 4000ms / 500ms) */
2177
+ export interface SandboxRunOptions {
2178
+ silenceMs?: number;
2179
+ hardCapMs?: number;
2180
+ metricsGraceMs?: number;
2181
+ }
2182
+ /**
2183
+ * 渲染级自检(render-check):本轮触达的 code 资产放沙箱 iframe(srcdoc + sandbox="allow-scripts")独立渲染,
2184
+ * 采集 console.error / window.onerror / unhandledrejection / 资源失败 / 白屏指标 → 归一回灌自纠。
2185
+ * 仅门禁形态(组合进 createHtmlSubagent 的 formatCheck 链);node/无 DOM 自动跳过渲染段保留结构段;
2186
+ * 握手缺失(宿主 CSP 拦沙箱内联脚本)/ 超时 → unavailable 不算通过(零信号 ≠ 通过)。
2187
+ */
2188
+ export declare function createHtmlRenderCheck(opts?: HtmlRenderCheckOptions): HtmlRenderCheck;
2189
+ /** 组合「结构 → 渲染」为单一 VerifyCheck(结构不过短路渲染;runBeforeReturn 不短路,两段必须单 check 内早返回) */
2190
+ export declare function composeStructureThenRender(structure: VerifyCheck, render: VerifyCheck): VerifyCheck;
2191
+ /** 信号归一纯函数:storage 类 SecurityError 降 warn(沙箱假阳性);无失败信号但 body 空 + scrollHeight<10 → 疑似白屏 fail */
2192
+ export declare function normalizeRenderResult(raw: RawRenderResult): RenderVerdict;
2193
+ /** 单组件沙箱渲染(离屏 iframe;用后销毁;node/无 DOM 返回 noDom) */
2194
+ export declare function renderInSandbox(html: string, opts?: SandboxRunOptions): Promise<RawRenderResult>;
2195
+ /** 沙箱 srcdoc 构造(collector 注入文档最前,不改组件原文) */
2196
+ export declare function buildSandboxSrcdoc(html: string, nonce: string): string;
2197
+ /** collector 采集脚本源码(nonce 握手 + 信号上报 + 活动信号 + 指标应答) */
2198
+ export declare function buildCollectorJs(nonce: string): string;
2199
+ /** 累计创建/销毁的沙箱 iframe 数(测试观察「用后销毁」契约) */
2200
+ export declare function getSandboxLifecycle(): { created: number; destroyed: number };
2129
2201
  /** 内置完整 HTML 生成规范 skill 构造器(示例路径按 root/codeField 参数化,集成方字段命名各异勿写死;默认快照 root='components'/codeField='code') */
2130
2202
  export declare function buildHtmlFragmentSkill(root?: string, codeField?: string): SkillSpec;
2131
2203
  /** 内置完整 HTML 生成规范 skill(createHtmlSubagent 默认装;传自定义 skills 覆盖默认时,显式并回此 skill 保住生成规范/安全底线;默认快照 root='components'/codeField='code') */