page-agent-sdk 4.25.4 → 4.26.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 CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/page-agent-sdk.svg)](https://www.npmjs.com/package/page-agent-sdk)
10
10
  [![license](https://img.shields.io/badge/license-ISC-blue.svg)](https://github.com/whyymj/page-agent-sdk/blob/master/LICENSE)
11
- [![tests](https://img.shields.io/badge/self%20tests-3825%20asserts-brightgreen.svg)](#self-tests)
11
+ [![tests](https://img.shields.io/badge/self%20tests-3856%20asserts-brightgreen.svg)](#self-tests)
12
12
 
13
13
  ---
14
14
 
@@ -32,7 +32,7 @@ Starting point for both humans and AI agents (Claude Code / Cursor): find the fe
32
32
  | Docs-site QA (quote a selection + read the current page) | [options cheat sheet](#createchatsdk-options-cheat-sheet) (`dialog.autoQuote` / `capabilities.domInspect` + `pageContext`) · [usage-guide §6.20](https://github.com/whyymj/page-agent-sdk/blob/master/doc/usage-guide.en.md#620-text-selection-quoting--page-qa-page-quote--read_page--pagecontext) · `examples/docs-demo` |
33
33
  | Host-page QA reliability (SPA doc-switch invalidation / no-guessing gate / quote DOM anchor) | `sdk.notifyHostChange({reason})` on route change · page-assertion gate auto-mounted with `domInspect` · quote anchor captured with selections (`setQuote` 3rd arg) · [usage-guide §6.20](https://github.com/whyymj/page-agent-sdk/blob/master/doc/usage-guide.en.md#620-text-selection-quoting--page-qa-page-quote--read_page--pagecontext) |
34
34
  | 📡 Auto host-change reporting (4.21+) | `hostWatch: true` — URL change (hashchange/popstate) auto-fires the full notifyHostChange chain, turning "the defense relies on the host remembering to call" into "the defense is automatic"; pushState patch / title watching are opt-in; debounce merging + `ignore` hook; server/headless degrades to a silent no-op (`inspect().hostWatch` reflection). Also: dom_edit/dom_restore landing auto-invalidates prior page reads (default-on) | `hostWatch` |
35
- | 📝 Content proposals — review & apply (4.22+) | `proposals: { read, onProposal }`: controlled editing for content outside the data slot — `read_content` (base + hash) → `propose_content` (**incremental ops**: literal unique anchors, atomic; tokens scale with the change; base-hash drift rejected) → host diff panel → write-back only on explicit user apply; `sdk.resolveProposal` closes the loop (events + next-turn outcome notice); model has zero write permission, unconfigured = zero registration; `lineDiff/applyProposalOps/hashContent` exported | `proposals` + `sdk.resolveProposal` |
35
+ | 📝 Content proposals — review & apply (4.22+) | `proposals: { read, onProposal }`: controlled editing for content outside the data slot — `read_content` (base + hash) → `propose_content` (**incremental ops**: literal unique anchors, atomic; tokens scale with the change; base-hash drift rejected) → host diff panel → write-back only on explicit user apply; `sdk.resolveProposal` closes the loop (events + next-turn outcome notice); model has zero write permission, unconfigured = zero registration; `lineDiff/applyProposalOps/hashContent` exported; **(4.26.1+) read-channel failures come back as structured `ERROR: {code:'CONTENT_READ_FAILED'}` with a don't-retry hint + a `read_failed` debugLogs entry** (`read` returning `null` stays a normal empty state) | `proposals` + `sdk.resolveProposal` |
36
36
  | ✏️ Edit sent message & rerun (4.25+) | hover any sent user message → "Edit" → edit in-bubble (Enter save / Esc cancel / IME-safe) → history after it is truncated and rerun from that point; focus/image/quote attachments preserved; clicking edit mid-generation auto-stops first; `roundSeq` generation-guard makes the stale round's async teardown a no-op; `useChat.editAndResend(index, newContent)` for programmatic use in custom UI | built-in UI automatic; custom UI via `useChat` |
37
37
  | Customize UI (theme / icons / i18n / button labels) | [`DialogConfig` fields](#dialogconfig-fields) · [usage-guide §6.15](https://github.com/whyymj/page-agent-sdk/blob/master/doc/usage-guide.en.md#615-ui-customization--i18n-icons--theme--language--message-overrides-317321) · `examples/i18n-demo` |
38
38
  | Sessions / persistence (IndexedDB) | [options cheat sheet](#createchatsdk-options-cheat-sheet) (`storage`/`session`) · `examples/page-demo` (`storage:'indexed'` + built-in history dropdown) |
@@ -260,7 +260,7 @@ ChatDialog, MessageContent, CodePreview, SkillPanel, DebugDrawer, useChat
260
260
  | **Capability toggles** | `capabilities` | `{planning?,dataOps?,fetch?,skills?,vfs?,summarization?,memory?,subagent?,verify?,focus?}` | Default all on (`verify` default off, opt-in; `focus` = context focus for refining one component, default on); `false` to turn off |
261
261
  | | `permissions` | `PermissionRule[]` | Scope whitelist (first-match-wins, default off) |
262
262
  | | `humanConfirm` | `boolean` · default `true` | Proactive inquiry (AI asks when uncertain/multi-plan) |
263
- | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · default off | Passive confirm whitelist (pre-write allow/deny) |
263
+ | | `approval` | `{tools?,confirm?,remember?,timeoutMs?,humanConfirmTool?}` · default off | Passive confirm whitelist (pre-write allow/deny); `remember:true` adds "Allow & don't ask again (this session)" to the bar — session-scoped one-time grants, revoked via `sdk.revokeApprovalGrants()`, cleared on session switch/reset |
264
264
  | | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` · default off | Session-level rollback (`auto` default `true`) |
265
265
  | | `verify` | `{check?,maxAttempts?,adversarial?}` | Needs `capabilities.verify:true`; `check` omitted → `createWriteBackCheck` (read-back root auto-bound to `data.bind`, adapts to `sdk.setData` runtime swap) |
266
266
  | **Subagents** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | Runtime ad-hoc delegation (`spawn_agent`/`spawn_agents`) |
package/README.zh-CN.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/page-agent-sdk.svg)](https://www.npmjs.com/package/page-agent-sdk)
10
10
  [![license](https://img.shields.io/badge/license-ISC-blue.svg)](https://github.com/whyymj/page-agent-sdk/blob/master/LICENSE)
11
- [![tests](https://img.shields.io/badge/self%20tests-3825%20asserts-brightgreen.svg)](#自测)
11
+ [![tests](https://img.shields.io/badge/self%20tests-3856%20asserts-brightgreen.svg)](#自测)
12
12
 
13
13
  ---
14
14
 
@@ -179,7 +179,7 @@ CDN 零配置:`<script src="https://unpkg.com/page-agent-sdk"></script>` → `
179
179
  | 🖍 DOM 编辑 | `dom_edit` 批量原子操作(set_text/set_html/set_attr/add_class/set_style/insert/remove/move/highlight)+ `dom_restore` 快照回滚(栈 20 批);唯一 selector 纪律(多匹配拒)/危险闸(script·on*·javascript: 拒)/SDK 自身 DOM 保护/单根快照 256KB 上限;改动为会话临时态,数据驱动页面仍走 write | `capabilities: { domInspect: true, domEdit: true }` |
180
180
  | 🔁 宿主变更通知(4.18) | `sdk.notifyHostChange({reason?})`:SPA 换文/路由切换后调 —— 流内页面读结果(read_page/dom_search/dom_info/get_dom/take_screenshot)置过期占位(通知后新读不受影响)+ 一次性「须重读当前页面」提示段;数据槽读不受影响;`inspect().hostReadsInvalidated` 累计 | 路由切换 handler 调一次 |
181
181
  | 📡 宿主导航自动报案(4.21) | `hostWatch: true`:URL 一变(hashchange/popstate)自动触发 notifyHostChange 全链路 —— 把「防线靠宿主记得调」变「防线自动」;pushState patch/title 观察 opt-in;去抖合并 + `ignore` 钩子;服务端/headless 特性探测静默 no-op(`inspect().hostWatch` 反射)。另:dom_edit/dom_restore 落地后旧页面读自动失效(默认开) | `hostWatch` |
182
- | 📝 内容提案-评审-应用(4.22) | `proposals: { read, onProposal }`:数据槽外内容的受控修改 —— `read_content`(基底+hash)→ `propose_content`(**增量 ops**:字面锚唯一命中/原子,token 只花在改动上;baseHash 漂移显式拒)→ 宿主 diff 面板 → 用户点应用才写回;`sdk.resolveProposal` 裁决闭环(事件 + 下轮结局告知);模型零写权限、未配置零注册;`lineDiff/applyProposalOps/hashContent` 纯函数导出 | `proposals` + `sdk.resolveProposal` |
182
+ | 📝 内容提案-评审-应用(4.22) | `proposals: { read, onProposal }`:数据槽外内容的受控修改 —— `read_content`(基底+hash)→ `propose_content`(**增量 ops**:字面锚唯一命中/原子,token 只花在改动上;baseHash 漂移显式拒)→ 宿主 diff 面板 → 用户点应用才写回;`sdk.resolveProposal` 裁决闭环(事件 + 下轮结局告知);模型零写权限、未配置零注册;`lineDiff/applyProposalOps/hashContent` 纯函数导出;**(4.26.1+)读通道故障回结构化 `ERROR: {code:'CONTENT_READ_FAILED'}` + 勿重试提示 + `read_failed` 留痕**(`read` 返回 `null` 仍是正常空态,不算故障) | `proposals` + `sdk.resolveProposal` |
183
183
  | ✏️ 编辑消息重跑(4.25) | hover 任意已发送 user 消息点「编辑」→ 气泡内改文(Enter 保存/Esc 取消,IME 合成期不误发)→ 截断其后历史从该点重跑;焦点/图片/引用附带字段保留;生成中点编辑先自动停止;`roundSeq` 代次守卫使旧轮异步收口失效(不拆新轮状态);自建 UI 可编程式用 `useChat.editAndResend(index, newContent)` | 内置 UI 自动;自建 UI 走 `useChat` |
184
184
  | 🛡 页面断言门禁(4.18) | 「本页写了/原文提到…」× 本轮零页面依据(含截图)× 非诚实不存在声明 → 回灌「先读页面再断言 + 事实清单」(独立预算 ≤2,超限 EXHAUSTED observable);仅 domInspect 开启装配(数据槽误伤路径结构切断) | 随 `domInspect` 自动 |
185
185
  | 📍 引用 DOM 锚点(4.18) | 划词捕获一并记录选区位置(块级 selector/块内偏移/出现序号/最近标题/捕获时 URL),引用块附 `[位置: …]` 元信息行 → `read_page({selector})` 直达;捕获与发送 URL 不一致自动标「锚点属于另一文档」;锚点是提示不是保证(失效回退 dom_search) | 随划词捕获自动;`setQuote` 第三参可自定义 |
@@ -262,7 +262,7 @@ ChatDialog, MessageContent, CodePreview, SkillPanel, DebugDrawer, useChat
262
262
  | | `capabilities.domEdit` | `boolean` | **DOM 编辑(默认 false;需 domInspect)**:装配 `dom_edit`(宿主页面批量原子操作:set_text/set_html/set_attr/add_class/set_style/insert/remove/move/highlight)+ `dom_restore`(快照回滚,栈 20 批)。唯一 selector 纪律/危险闸(script·on\*·javascript:)//SDK 自身 DOM 保护;改动为会话临时态 —— 数据驱动页面应改数据(`write`)。见 [usage-guide §6.22](doc/usage-guide.md#622-dom-编辑dom_edit--dom_restore) |
263
263
  | | `permissions` | `PermissionRule[]` | scope 白名单(first-match-wins,默认不启用) |
264
264
  | | `humanConfirm` | `boolean` · 默认 `true` | 主动征询(AI 不确定/多方案主动问你,不猜测) |
265
- | | `approval` | `{tools?,confirm?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝) |
265
+ | | `approval` | `{tools?,confirm?,remember?,timeoutMs?,humanConfirmTool?}` · 默认关 | 被动确认白名单(写操作前弹允许/拒绝);`remember:true` 确认条多一枚「允许并不再询问(本会话)」—— 会话级一次性授权,`sdk.revokeApprovalGrants()` 可撤销,切会话/重置自动失效 |
266
266
  | | `checkpoint` | `boolean \| {maxCheckpoints?,auto?}` · 默认关 | 会话级回滚(`auto` 默认 `true` 每轮存档) |
267
267
  | | `verify` | `{check?,maxAttempts?,adversarial?}` | 需 `capabilities.verify:true`;`check` 省略用 `createWriteBackCheck`(读回根对象自动取 `data.bind`,适配 `sdk.setData` 运行时替换) |
268
268
  | **子 agent** | `subagent` | `{allowedTools?,systemPrompt?,temperature?,llm?,maxDepth?·1,maxParallel?·4}` | 运行时自由委派(`spawn_agent`/`spawn_agents`) |