page-agent-sdk 4.5.0 → 4.6.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 +3 -3
- package/README.zh-CN.md +3 -3
- package/dist/page-agent-sdk.headless.js +65 -54
- package/dist/page-agent-sdk.iife.js +5 -5
- package/dist/page-agent-sdk.js +65 -54
- package/dist/page-agent-sdk.legacy.js +67 -56
- package/dist/page-agent-sdk.umd.cjs +5 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/page-agent-sdk)
|
|
10
10
|
[](https://github.com/whyymj/page-agent-sdk/blob/master/LICENSE)
|
|
11
|
-
[](#self-tests)
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -52,7 +52,7 @@ At its core, it gives the AI a **standardized, safe JSON-operation channel**. AI
|
|
|
52
52
|
| **Scope control** | Declared schema fields (`data`) — only declared keys are writable; schema shape auto-whitelist (top-level + sub-path recursively projected by sub-schema; undeclared fields hidden/denied; whole-set becomes merge to prevent accidental deletion) | AI touching undeclared fields → `PATH_DENIED` |
|
|
53
53
|
| **Validity check** | zod schema — `write`/`set`/`edit` validated against schema | Invalid type/enum/structure → structured error, no write |
|
|
54
54
|
| **Incremental op** | `write` with `patch` (set/remove/merge/append/move) or `patches` (batch, atomic rollback) by `jsonPath` | Avoid re-sending the whole large JSON; precise local edits; use `patches` to edit many at once |
|
|
55
|
-
| **Large-object retrieval** | `read` supports `fields` (projection) + `depth` (truncation) to shrink payload; `query_data` (JSONPath)/`search_data` (text)/`eval_script` (sandboxed JS) | Efficient retrieval + pinpoint location in large JSON |
|
|
55
|
+
| **Large-object retrieval** | `read` supports `fields` (projection) + `depth` (truncation) to shrink payload; `query_data` (JSONPath, 4.6+ batch `queries` 2-10 in one call)/`search_data` (text)/`eval_script` (sandboxed JS) | Efficient retrieval + pinpoint location in large JSON |
|
|
56
56
|
| **Rollbackable** | per-path snapshots (auto-stacked) + session checkpoint | Bad edit → one-click restore to the last good state |
|
|
57
57
|
| **Optimistic lock** | `conflictWatchFields` opt-in optimistic lock + conflict human-in-the-loop (3.29+ `conflictPolicy` declares auto-adjudication: overwrite / keep_external) | Concurrent external edits detected → suspend, user picks keep/overwrite/restore |
|
|
58
58
|
|
|
@@ -500,7 +500,7 @@ function switchTo(i: number) {
|
|
|
500
500
|
|
|
501
501
|
```bash
|
|
502
502
|
npm test # 2894 assertions (tsx, source-level; no LLM dependency)
|
|
503
|
-
npm run test:e2e #
|
|
503
|
+
npm run test:e2e # 1020 integration assertions (node, built dist; covers APIs/options/modules/simple&complex scenes: default systemPrompt(capability overview) / dynamic register + inspect sync / inspect(tools/middleware/subagent/verify/mcp/todos/lastCompression/checkpoints reflect config) / custom tools/middleware/skills/memory injection / runtime dynamic reconfiguration(setTools/addTool/removeTool/setLlm/setMemory/setSubagents reflect) / switchSession(on/off) / shareContext on/off sharing/independent / storage backends + object config / presets(3) / checkpoint / exports complete(39+ fns/components) / util fns usable(isQuotaError/estimateTokens/jpEval/searchJson) / source=builtin / mount boundary / hook multi-listener / llm config / hide/show / error scenes)
|
|
504
504
|
```
|
|
505
505
|
|
|
506
506
|
## Local npm package test
|
package/README.zh-CN.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/page-agent-sdk)
|
|
10
10
|
[](https://github.com/whyymj/page-agent-sdk/blob/master/LICENSE)
|
|
11
|
-
[](#自测)
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
| **范围控制** | schema 校验(`data`)—— 只能改 schema 允许的值;schema 形状自动白名单(顶层 + 子路径按子 schema 递归投影,未声明字段隐藏/拒改/整体 set 转 merge 防误删) | AI 传非法值 → 拒绝;非声明字段 → `PATH_DENIED` |
|
|
53
53
|
| **合法性校验** | zod schema —— `write`/`set`/`edit` 按 schema 校验 | 类型/枚举/结构不合法 → 结构化错误,不写入 |
|
|
54
54
|
| **增量操作** | `write` 的 `patch`(set/remove/merge/append/move)或 `patches`(批量,原子回滚)按 `jsonPath` 发 patch | 避免重传整个大 JSON,精确改局部;一次改多处用 `patches` |
|
|
55
|
-
| **大对象检索** | `read` 支持 `fields`(字段裁剪)+ `depth`(深度截断)减体积;`query_data`(JSONPath)/`search_data`(文本)/`eval_script`(沙箱 JS) | 大 JSON 高效检索 + 局部定位 |
|
|
55
|
+
| **大对象检索** | `read` 支持 `fields`(字段裁剪)+ `depth`(深度截断)减体积;`query_data`(JSONPath,4.6+ 批量 `queries` 2-10 条一次取回)/`search_data`(文本)/`eval_script`(沙箱 JS) | 大 JSON 高效检索 + 局部定位 |
|
|
56
56
|
| **可回滚** | per-path 快照(自动入栈)+ 会话 checkpoint | 改坏了一键回退到上次正常态 |
|
|
57
57
|
| **乐观锁** | `conflictWatchFields` 声明式乐观锁 + 冲突人工介入(3.29+ `conflictPolicy` 可声明自动裁决:overwrite / keep_external) | 检测并发外部修改 → 挂起,用户选保留/覆盖/回退 |
|
|
58
58
|
|
|
@@ -503,7 +503,7 @@ function switchTo(i: number) {
|
|
|
503
503
|
|
|
504
504
|
```bash
|
|
505
505
|
npm test # 2894 项断言(tsx 源码级,不依赖 LLM)
|
|
506
|
-
npm run test:e2e #
|
|
506
|
+
npm run test:e2e # 1020 项集成断言(node 跑构建产物 dist;覆盖各 API/配置项/功能模块/简单与复杂场景:默认 systemPrompt(含能力概述) / 动态注册与 inspect 同步 / inspect(tools/middleware/subagent/verify/mcp/todos/lastCompression/checkpoints 反映配置) / 自定义 tools/middleware/skills/memory 注入 / 运行时动态重配置(setTools/addTool/removeTool/setLlm/setMemory/setSubagents 反映) / switchSession(开/未开) / shareContext 开/关共享独立 / storage 后端+对象配置 / presets 三预设 / checkpoint / 导出项完整(39+ 函数/组件) / 工具函数可用(isQuotaError/estimateTokens/jpEval/searchJson) / source=builtin / mount 边界 / hook 多监听器 / llm 配置 / 错误场景)
|
|
507
507
|
```
|
|
508
508
|
|
|
509
509
|
## 本地 npm 包测试
|
|
@@ -3024,7 +3024,7 @@ function Sa(e) {
|
|
|
3024
3024
|
}
|
|
3025
3025
|
function Ca(e, t) {
|
|
3026
3026
|
let n = t || {};
|
|
3027
|
-
if (e === "query_data") return
|
|
3027
|
+
if (e === "query_data") return (Array.isArray(n.queries) && n.queries.length ? n.queries.map(String) : [String(n.expr || "")]).map((e) => Sa(e));
|
|
3028
3028
|
if (e === "search_data") return [pa];
|
|
3029
3029
|
let r = [];
|
|
3030
3030
|
if (typeof n.jsonPath == "string" && n.jsonPath && r.push(n.jsonPath), Array.isArray(n.jsonPaths)) for (let e of n.jsonPaths) typeof e == "string" && e && r.push(e);
|
|
@@ -3072,7 +3072,7 @@ function wa(e) {
|
|
|
3072
3072
|
}
|
|
3073
3073
|
function Ta(e, t, n, r) {
|
|
3074
3074
|
let i = e.map(ya).join("、"), a = [...new Set(n.flatMap((e) => e.paths))].map(ya).join("、"), o = [`⏱[过期快照] 此前读取 ${i} 的结果已失效(${r === void 0 ? `已写入 ${a}` : `第 ${r} 轮写入了 ${a}`})。`];
|
|
3075
|
-
return n.some((e) => e.hasPostValue) ? o.push(`该轮写入结果已含 ${a} 最新值与新 hash
|
|
3075
|
+
return n.some((e) => e.hasPostValue) ? o.push(`该轮写入结果已含 ${a} 最新值与新 hash,直接引用即可;原读取结果整体已过期,未提及路径需引用时按下方指引重读/重跑。`) : o.push("原读取结果整体已过期(含未触及的兄弟路径),需引用时按下方指引重读/重跑。"), t === "query_data" || t === "search_data" ? o.push(`需当前结果时重跑 ${t}(表达式/条件不变即可)。`) : o.push(`需当前精确值时再 read(建议窄读:${i})。`), o.join("\n");
|
|
3076
3076
|
}
|
|
3077
3077
|
function Ea(e, t, n = {}) {
|
|
3078
3078
|
let r = n.maxParallelTools ?? 1, i = t.map((e) => wa(e)).filter((e) => e !== null);
|
|
@@ -8731,7 +8731,7 @@ function ad(e, n = {}) {
|
|
|
8731
8731
|
e.writeCapable = t;
|
|
8732
8732
|
}, oe = r(async () => [`说明: ${l}`, "格式: 写入值需为 JSON,且通过声明的 schema 校验(校验失败时 write 会返回结构化错误,含具体字段与期望类型)。"].join("\n"), {
|
|
8733
8733
|
name: "describe_data",
|
|
8734
|
-
description: "
|
|
8734
|
+
description: "获取主数据的说明与格式要求(等价于 read 不传 jsonPath;优先用 read 单一入口)。",
|
|
8735
8735
|
schema: t.object({})
|
|
8736
8736
|
}), L = r(async ({ id: e }, t) => {
|
|
8737
8737
|
let n = y(t);
|
|
@@ -8759,8 +8759,8 @@ function ad(e, n = {}) {
|
|
|
8759
8759
|
});
|
|
8760
8760
|
}, {
|
|
8761
8761
|
name: "restore_data",
|
|
8762
|
-
description: "把主数据回退到某个快照(
|
|
8763
|
-
schema: t.object({ id: t.number().int().optional().describe("
|
|
8762
|
+
description: "把主数据回退到某个快照(不传 id 回退最近一次)。快照列表用 history_data({list:true})。",
|
|
8763
|
+
schema: t.object({ id: t.number().int().optional().describe("快照序号;不传回退最近一次") })
|
|
8764
8764
|
});
|
|
8765
8765
|
I(L);
|
|
8766
8766
|
let se = r(async ({ id: e, jsonPath: t, list: n }) => {
|
|
@@ -8802,43 +8802,54 @@ function ad(e, n = {}) {
|
|
|
8802
8802
|
return `快照 #${r.id}[${r.op}]${r.label ? `(${r.label})` : ""}${a ? ` @ ${a}` : ""} = ${$(i)}`;
|
|
8803
8803
|
}, {
|
|
8804
8804
|
name: "history_data",
|
|
8805
|
-
description: "查看主数据快照(
|
|
8805
|
+
description: "查看主数据快照(只读不回退):list:true 列时间线;传 id 看某次内容(默认最近),jsonPath 可只看子路径。对比差异用 diff_data;回退用 restore_data。",
|
|
8806
8806
|
schema: t.object({
|
|
8807
|
-
id: t.number().int().optional().describe("
|
|
8808
|
-
jsonPath: t.string().optional().describe("只看快照的某子路径
|
|
8809
|
-
list: t.boolean().optional().describe("true
|
|
8807
|
+
id: t.number().int().optional().describe("快照序号;不传看最近一次(list:true 时忽略)"),
|
|
8808
|
+
jsonPath: t.string().optional().describe("只看快照的某子路径"),
|
|
8809
|
+
list: t.boolean().optional().describe("true 列出快照时间线(序号/操作/标签/时间/大小)")
|
|
8810
8810
|
})
|
|
8811
|
-
}), ce = r(async ({ expr: e,
|
|
8812
|
-
let
|
|
8811
|
+
}), ce = r(async ({ expr: e, queries: t, limit: n }, r) => {
|
|
8812
|
+
let i = y(r);
|
|
8813
8813
|
if (typeof c != "object" || !c) return Z({
|
|
8814
8814
|
code: "NOT_OBJECT",
|
|
8815
8815
|
message: `主数据不是对象/数组,无法查询(当前为 ${c === void 0 ? "undefined" : typeof c})`,
|
|
8816
8816
|
hint: "query 仅适用于对象/数组;叶子用 read 读"
|
|
8817
8817
|
});
|
|
8818
|
-
let
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8818
|
+
let a = u ? Zo(c, s) : c, o = b(r), l = (e) => {
|
|
8819
|
+
let t;
|
|
8820
|
+
try {
|
|
8821
|
+
t = ca(a, e);
|
|
8822
|
+
} catch (t) {
|
|
8823
|
+
return Z({
|
|
8824
|
+
code: "JSONPATH_SYNTAX",
|
|
8825
|
+
message: `JSONPath 解析错误: ${t.message}`,
|
|
8826
|
+
hint: "语法子集:$ .key [n] [\"key\"] [*] [?(filter)] ..key ..*;filter:@.field op literal,&&/||/();对象根需先点出数组字段再过滤,如 $.components[?(@.x>1)]",
|
|
8827
|
+
details: { expr: e }
|
|
8828
|
+
});
|
|
8829
|
+
}
|
|
8830
|
+
let r = n ?? 50, s = t.slice(0, r), c = s.map((e) => `{"path":${JSON.stringify(e.path)},"index":${e.index === void 0 ? "null" : e.index},"value":${$(ed(e.value, i === "", re, j, {
|
|
8831
|
+
rootExempt: !1,
|
|
8832
|
+
rootPath: String(e.path ?? ""),
|
|
8833
|
+
fullTextPrefixes: o,
|
|
8834
|
+
onSummarized: ee
|
|
8835
|
+
}))}}`);
|
|
8836
|
+
return `{"matched":${t.length},"returned":${s.length},"truncated":${t.length > r},"results":[${c.join(",")}]}`;
|
|
8837
|
+
};
|
|
8838
|
+
return t && t.length ? `{"batch":true,"results":[${t.map((e) => {
|
|
8839
|
+
let t = l(e);
|
|
8840
|
+
return t.startsWith("ERROR:") ? `{"expr":${JSON.stringify(e)},"ok":false,"error":${JSON.stringify(t)}}` : `{"expr":${JSON.stringify(e)},"ok":true,${t.slice(1)}`;
|
|
8841
|
+
}).join(",")}]}` : e === void 0 ? Z({
|
|
8842
|
+
code: "SCHEMA_INVALID",
|
|
8843
|
+
message: "query_data 需传 expr(单条 JSONPath)或 queries(2-10 条批量),两者都没传",
|
|
8844
|
+
hint: "单表达式用 expr;多条件筛选一次取回用 queries"
|
|
8845
|
+
}) : l(e);
|
|
8836
8846
|
}, {
|
|
8837
8847
|
name: "query_data",
|
|
8838
|
-
description: "用 JSONPath 查询主数据(只读):$ 根/.key/[n]/[*]/[?(==/!=/</<=/>/>=,&&/||)]/..key 递归。返回匹配元素 path/index/value(path 可作 write patch 的 jsonPath)
|
|
8848
|
+
description: "用 JSONPath 查询主数据(只读):$ 根/.key/[n]/[*]/[?(==/!=/</<=/>/>=,&&/||)]/..key 递归。返回匹配元素 path/index/value(path 可作 write patch 的 jsonPath);大数组筛选定位用它;多条件筛选传 queries 数组一次取回。",
|
|
8839
8849
|
schema: t.object({
|
|
8840
|
-
expr: t.string().describe("JSONPath 表达式,如 $.components[?(@.type==\"card\" && @.price<100)] 或 $..title(递归找所有 title)"),
|
|
8841
|
-
|
|
8850
|
+
expr: t.string().optional().describe("单条 JSONPath 表达式,如 $.components[?(@.type==\"card\" && @.price<100)] 或 $..title(递归找所有 title)"),
|
|
8851
|
+
queries: t.array(t.string()).min(2).max(10).optional().describe("批量模式:2-10 条 JSONPath 一次取回(与 expr 同传按 queries);逐条独立返回,单条失败该项标 error 不整批"),
|
|
8852
|
+
limit: t.number().int().min(1).max(200).optional().describe("返回结果上限(批量时逐条适用),默认 50")
|
|
8842
8853
|
})
|
|
8843
8854
|
}), le = r(async ({ query: e, mode: t, fuzzyThreshold: n, matchKey: r, limit: i }) => {
|
|
8844
8855
|
if (c == null) return Z({
|
|
@@ -9015,11 +9026,11 @@ function ad(e, n = {}) {
|
|
|
9015
9026
|
});
|
|
9016
9027
|
}, {
|
|
9017
9028
|
name: "eval_script",
|
|
9018
|
-
description: "在 Worker 沙箱对主数据跑自定义 JS(
|
|
9029
|
+
description: "在 Worker 沙箱对主数据跑自定义 JS(无网络,超时 3s)。入参 data(深拷贝);mode:query 只读回给 LLM/transform 校验后落地(完整新值或 {patches:[…]} 增量);jsonPath 可限定子树。",
|
|
9019
9030
|
schema: t.object({
|
|
9020
|
-
script: t.string().describe("JS
|
|
9021
|
-
mode: t.enum(["query", "transform"]).optional().describe("query=只读返回结果(默认)
|
|
9022
|
-
jsonPath: t.string().optional().describe("
|
|
9031
|
+
script: t.string().describe("JS 脚本(入参 data;末尾表达式或 return 即返回值),如 data.filter(c=>c.stock>0)"),
|
|
9032
|
+
mode: t.enum(["query", "transform"]).optional().describe("query=只读返回结果(默认)/transform=校验后落地为新值"),
|
|
9033
|
+
jsonPath: t.string().optional().describe("子树模式:仅对该子树执行;transform 返回值作为子树新值")
|
|
9023
9034
|
})
|
|
9024
9035
|
});
|
|
9025
9036
|
I(ue, (e) => e?.mode === "transform");
|
|
@@ -9104,14 +9115,14 @@ function ad(e, n = {}) {
|
|
|
9104
9115
|
return v === void 0 ? `${x}主数据${h ? ` @ ${h}` : ""}${T} = (undefined) (hash=${p})` : `${x}主数据${h ? ` @ ${h}` : ""}${T} = ${$(v)} (hash=${p})`;
|
|
9105
9116
|
}, {
|
|
9106
9117
|
name: "read",
|
|
9107
|
-
description: "
|
|
9118
|
+
description: "读主数据(只读):不传 jsonPath 返回整体说明+格式;传 jsonPath 返回该路径当前值+hash;传 jsonPaths 一次读多个不相关路径。fields/depth 裁剪、offset/limit 数组分页减体积;详细规则见系统提示。",
|
|
9108
9119
|
schema: t.object({
|
|
9109
|
-
jsonPath: t.string().optional().describe("要读的子路径(
|
|
9110
|
-
jsonPaths: t.array(t.string()).optional().describe("
|
|
9111
|
-
fields: t.array(t.string()).optional().describe("
|
|
9112
|
-
depth: t.number().int().min(0).optional().describe("
|
|
9113
|
-
offset: t.number().int().min(0).optional().describe("数组分页起始偏移(
|
|
9114
|
-
limit: t.number().int().min(1).max(200).optional().describe("数组分页每页条数(默认 50,上限 200
|
|
9120
|
+
jsonPath: t.string().optional().describe("要读的子路径(如 components.0.text);不传读整体+说明"),
|
|
9121
|
+
jsonPaths: t.array(t.string()).optional().describe("多路径一次读(与 jsonPath 互斥,优先);非法路径单项标错不整批"),
|
|
9122
|
+
fields: t.array(t.string()).optional().describe("只返回指定字段(投影减体积),如 [\"id\",\"title\"]"),
|
|
9123
|
+
depth: t.number().int().min(0).optional().describe("嵌套深度限制(0=只根占位,逐层截断减体积)"),
|
|
9124
|
+
offset: t.number().int().min(0).optional().describe("数组分页起始偏移(仅数组目标,默认 0)"),
|
|
9125
|
+
limit: t.number().int().min(1).max(200).optional().describe("数组分页每页条数(默认 50,上限 200),返回切片+total/hasMore")
|
|
9115
9126
|
})
|
|
9116
9127
|
}), de = r(async ({ value: e, patch: t, patches: n, del: r, dryRun: a }, l) => {
|
|
9117
9128
|
let d = y(l), f = "set";
|
|
@@ -9230,9 +9241,9 @@ function ad(e, n = {}) {
|
|
|
9230
9241
|
}
|
|
9231
9242
|
}, {
|
|
9232
9243
|
name: "write",
|
|
9233
|
-
description: "
|
|
9244
|
+
description: "写主数据(唯一写入口;自动 schema 校验+乐观锁+快照)。四意图:整体替换 {value}/增量 {patch:{op,jsonPath,value}}(op set/remove/merge/append/move)/原子批 {patches:[…]}(任一失败回滚)/删子路径 {patch:{jsonPath},del:true};dryRun 预检;详细规则见系统提示。",
|
|
9234
9245
|
schema: t.object({
|
|
9235
|
-
value: t.unknown().optional().describe("JSON 对象(
|
|
9246
|
+
value: t.unknown().optional().describe("JSON 对象(推荐)或 JSON 字符串;set 整体或 patch 的 set/merge/append 必填"),
|
|
9236
9247
|
patch: t.object({
|
|
9237
9248
|
op: t.enum([
|
|
9238
9249
|
"set",
|
|
@@ -9240,10 +9251,10 @@ function ad(e, n = {}) {
|
|
|
9240
9251
|
"merge",
|
|
9241
9252
|
"append",
|
|
9242
9253
|
"move"
|
|
9243
|
-
]).optional().describe("
|
|
9244
|
-
jsonPath: t.string().optional().describe("相对主数据根的点号路径(如 components.0.text);set/remove 必填,merge/append
|
|
9245
|
-
value: t.unknown().optional().describe("该 patch 的值(JSON
|
|
9246
|
-
}).optional().describe("单个增量编辑(自带 value
|
|
9254
|
+
]).optional().describe("set 设值/remove 删/merge 合并对象/append 追加数组/move 移动元素(value=目标路径字符串);缺省 set"),
|
|
9255
|
+
jsonPath: t.string().optional().describe("相对主数据根的点号路径(如 components.0.text);set/remove 必填,merge/append 不填作用于根"),
|
|
9256
|
+
value: t.unknown().optional().describe("该 patch 的值(JSON 或 JSON 字符串);与顶层 value 二选一,优先 patch.value")
|
|
9257
|
+
}).optional().describe("单个增量编辑(自带 value)"),
|
|
9247
9258
|
patches: t.array(t.object({
|
|
9248
9259
|
op: t.enum([
|
|
9249
9260
|
"set",
|
|
@@ -9252,11 +9263,11 @@ function ad(e, n = {}) {
|
|
|
9252
9263
|
"append",
|
|
9253
9264
|
"move"
|
|
9254
9265
|
]),
|
|
9255
|
-
jsonPath: t.string().optional().describe("相对主数据根的点号路径;set/remove 必填,merge/append
|
|
9256
|
-
value: t.unknown().optional().describe("JSON 值(推荐直传)或 JSON 字符串;set/merge/append
|
|
9257
|
-
})).optional().describe("
|
|
9266
|
+
jsonPath: t.string().optional().describe("相对主数据根的点号路径;set/remove 必填,merge/append 不填作用于根"),
|
|
9267
|
+
value: t.unknown().optional().describe("JSON 值(推荐直传)或 JSON 字符串;set/merge/append 必填")
|
|
9268
|
+
})).optional().describe("批量原子编辑:一次提交多个 patch,任一失败整体不写入;适合一次改多处"),
|
|
9258
9269
|
del: t.boolean().optional().describe("true 则删除 patch.jsonPath 指定的子路径"),
|
|
9259
|
-
dryRun: t.boolean().optional().describe("
|
|
9270
|
+
dryRun: t.boolean().optional().describe("预检:走完整校验链但不落盘不入快照;冲突返回 VERSION_CONFLICT 不挂起")
|
|
9260
9271
|
})
|
|
9261
9272
|
});
|
|
9262
9273
|
I(de);
|
|
@@ -12087,7 +12098,7 @@ function Kp(e, t, n) {
|
|
|
12087
12098
|
name: "usageHints",
|
|
12088
12099
|
augmentPrompt: (i) => {
|
|
12089
12100
|
let a = [];
|
|
12090
|
-
if (r.planning && (a.push("【自适应规划】按任务复杂度决定是否先规划,不要对简单任务过度编排:"), a.push(" · 简单/明确任务(改单字段、调样式、查值)→ 直接 read/write 执行,不必 write_todos。"), a.push(" · 复杂任务(多步、大改、有歧义、不可逆)→ 先 write_todos 拆解,首个任务标 in_progress,逐项推进。"), a.push(" · 执行中发现步骤要改/补/细分 → 用 update_todo({id, content?, status?}) 按 id 增量改单项,不必重传整个清单。"), a.push(" · update_todo 标 completed 时附 evidence: 本次实际写入的 jsonPath(如 \"components.2\"),供收口对账;工作经委派子 agent 完成等无主写路径时,如实写明完成方式(勿编造路径)。"), e?.humanConfirm ? a.push(" · 规划出多步方案若需用户拍板 → 先 request_human_confirmation 给方案选项,确认后再执行。") : a.push(" · 规划出多步方案若需用户拍板 → 以文字列出方案选项等用户回复,勿自行拍板。"), a.push(" · 计划修订有次数上限(maxPlanRevisions,默认 5,只计 write_todos 调用、调研轮不计):勿反复改计划而不执行,规划充分后即开始 write 落地。")), t && (a.push("改主数据前先 read({jsonPath}) 读其当前真实值(返回末尾 hash=xxx 为乐观锁标识),基于真实值改,不要凭记忆。写入是否被自动校验由集成方 conflictWatchFields 声明决定:若已声明且主数据在你 read 之后被外部改过,会触发冲突——集成方若开启人工介入,工具会挂起等用户决定(保留外部/强制覆盖/回退),你应等待工具返回后按结果继续(保留外部→重新 read 再改;强制覆盖→已写入,继续;回退→已回退到历史快照,基于回退值重写);未开启人工介入时返回 VERSION_CONFLICT 不写入,重新 read 拿最新值再改。"), a.push("
|
|
12101
|
+
if (r.planning && (a.push("【自适应规划】按任务复杂度决定是否先规划,不要对简单任务过度编排:"), a.push(" · 简单/明确任务(改单字段、调样式、查值)→ 直接 read/write 执行,不必 write_todos。"), a.push(" · 复杂任务(多步、大改、有歧义、不可逆)→ 先 write_todos 拆解,首个任务标 in_progress,逐项推进。"), a.push(" · 执行中发现步骤要改/补/细分 → 用 update_todo({id, content?, status?}) 按 id 增量改单项,不必重传整个清单。"), a.push(" · update_todo 标 completed 时附 evidence: 本次实际写入的 jsonPath(如 \"components.2\"),供收口对账;工作经委派子 agent 完成等无主写路径时,如实写明完成方式(勿编造路径)。"), e?.humanConfirm ? a.push(" · 规划出多步方案若需用户拍板 → 先 request_human_confirmation 给方案选项,确认后再执行。") : a.push(" · 规划出多步方案若需用户拍板 → 以文字列出方案选项等用户回复,勿自行拍板。"), a.push(" · 计划修订有次数上限(maxPlanRevisions,默认 5,只计 write_todos 调用、调研轮不计):勿反复改计划而不执行,规划充分后即开始 write 落地。")), t && (a.push("改主数据前先 read({jsonPath}) 读其当前真实值(返回末尾 hash=xxx 为乐观锁标识),基于真实值改,不要凭记忆。写入是否被自动校验由集成方 conflictWatchFields 声明决定:若已声明且主数据在你 read 之后被外部改过,会触发冲突——集成方若开启人工介入,工具会挂起等用户决定(保留外部/强制覆盖/回退),你应等待工具返回后按结果继续(保留外部→重新 read 再改;强制覆盖→已写入,继续;回退→已回退到历史快照,基于回退值重写);未开启人工介入时返回 VERSION_CONFLICT 不写入,重新 read 拿最新值再改。"), a.push("读类分流:取值/结构 → read(多路径用 jsonPaths);字段约束 → schema_data;条件筛选定位 → query_data(多条一次用 queries);名字模糊找 → search_data;整体说明 → read 不传路径(= describe_data)。"), a.push("修改大对象/数组优先用 write 增量改({patch:{op,jsonPath,value}} 只发改动部分),避免 write({value}) 整体重传被 max_tokens 截断导致 JSON 不完整、校验失败。"), a.push("修改主数据出错时可用 restore_data 回退最近一次。"), a.push("在大数组里按条件筛选元素用 query_data(JSONPath,如 $.components[?(@.type==\"card\" && @.price<100)]),返回匹配元素的 path/index;定位后再 write({patch}) 改。"), a.push("找名字记不清的元素用 search_data(支持 substring/regex/fuzzy 模糊搜索)。"), a.push("需要过滤/映射/聚合/批量重写大数组时用 eval_script(沙箱脚本,入参 data);只读探查用 mode=query,批量重写用 mode=transform(返回值经校验后落地)。"), a.push("读大数组用 read({jsonPath,offset,limit}) 分页(返回 hasMore=true 时 offset+=limit 续读);一次读多个不相关子路径用 read({jsonPaths});复杂改动先 write({...,dryRun:true}) 预检不落盘。"), a.push("【省轮次·批量】≥2 个路径一律 read({jsonPaths:[...]}) 一次取回(路径互不相关也合批,禁止连续单路径 read);多条件筛选用 query_data({queries:[expr1,expr2,…]}) 一次取回(2-10 条);改多处用 write({patches:[{op:\"set\",jsonPath,value},...]}) 一次提交多改动(原子任一失败回滚),勿逐个 write 烧轮次预算。"), a.push("读到 <subtree Nkb keys:[…] #指纹> 或 <code Nkb> 占位 = 该子树键名/体积可见但内容未见:写入前先窄读全文(read({jsonPath:\"该子树路径\"}),结果根豁免返全文)或 set_focus 聚焦该区域;勿凭键名印象猜路径/猜值直写(直接写占位子树会被拦下要求先窄读)。"), a.push("对比当前与历史快照(或一段 JSON against)的差异用 diff_data({snapshotId?,against?})(返回结构化 path→from/to,verify 自纠/操作审计/\"刚才改了啥\");只读查历史快照值用 history_data({id?,jsonPath?})。")), r.subagent && a.push("独立子任务可 spawn_agent 委派(过程隔离,不占主上下文):默认只读,需要子 agent 写数据时传 writablePaths(路径前缀白名单,越界 PATH_OUT_OF_SCOPE)。多个独立子任务可 spawn_agents 并行委派(各子互不通信,结论由你汇总;并行委派不可授写权限,写操作由你收尾执行)。"), r.inspectEnv && a.push("排查页面环境(当前 URL/浏览器/视口/集成方调试变量)用 inspect_env——不传参返回环境摘要(location/navigator/viewport/document),传 key 读特定 window 属性(如 inspect_env({key:\"appConfig\"}) 读 window.appConfig)。改完数据看渲染、定位\"为何没生效\"时用它(只读,不改数据)。"), r.domInspect && a.push("改完数据想确认渲染是否生效(或定位元素/辅助 UI 设计问答)用 get_dom({selector?,depth?}) 读渲染后 DOM(结构化返回 tag/attrs/text/children,depth 控制深度防爆炸,只读)。配合宿主 actions(save_draft/publish 等)形成\"改数据→get_dom 看渲染→触发动作\"闭环。"), r.draftWrite && (a.push("生成超大 JSON(如 50+ 组件页面,单次 write 受 max_tokens 限制装不下)用 draft_write 分块构建 → draft_commit 原子提交:draft_write({draftId, chunk, mode}) mode:\"start\" 新建/\"append\" 追加(拼 JSON 片段到 drafts 池);累积完 draft_commit({draftId}) 合并 + schema 校验 + 写主数据(失败草稿保留可修后重试,成功自动清草稿)。小改仍用 write patch,只在大 JSON 从零生成时用 draft。"), a.push("⚠️ 大 JSON 分块构建是典型多轮工具调用(draft_write×N + draft_commit + read 确认 + 调研 read/query),默认 maxToolRounds=30(3.43 起;轮次预算吃紧时 system 会注入预算提示段,按提示优先收口);目标组件数很大时集成方仍可在 createChatSdk 显式上调 maxToolRounds(按 N+10 估算)。draft_commit 提交同样走乐观锁(改前 read 拿 hash,bind 被改过会触发冲突介入,不静默覆盖)。")), r.focus && (a.push("【上下文聚焦】判断任务范围,用 set_focus/add_focus/remove_focus/clear_focus 自动收敛工作范围:"), a.push(" · 局部任务(只改某一组件/区域,如「调导航栏」「改 components.3 样式」)→ 先 read 定位 jsonPath,再 set_focus({path:\"该子树路径\"}) 聚焦;聚焦后每轮只看该子树结构,写其他位置会被 PATH_DENIED 拒绝。"), a.push(" · 多个相关组件(如「同时改导航栏和页脚」)→ set_focus 聚焦首个后用 add_focus({path}) 追加其余;聚焦后可写任一焦点子树,越界仍被拒;移除单个用 remove_focus({path})。"), a.push(" · 全局任务(多处/整体结构,如「重排所有组件」「换主题」)→ 不要聚焦,保持全量视野直接写。"), a.push(" · 完成局部精修、要转向其他区域或做整体改动 → 调 clear_focus 退出聚焦(清空全部焦点),恢复全部读写权限。"), a.push(" · set_focus/add_focus 的 path 必须在 schema 内(类型校验);不确定路径先 read/describe_data 查。")), e?.subagents?.length) {
|
|
12091
12102
|
let t = e.subagents.filter((e) => (e.temperature ?? 0) >= Gp || /规划|创意|设计|方案|brainstorm|plan/i.test(e.description)), n = e.subagents.filter((e) => (e.temperature ?? 0) < Gp && /反思|审查|挑刺|校验|review|critique|reflect/i.test(e.description));
|
|
12092
12103
|
a.push("【规划-反思-执行·路由】按任务性质选模式,不要对简单任务过度编排:"), t.length && (a.push(` · 创作/设计/开放性需求(如"设计主题风格""换个感觉")→ 先调 ${t.map((e) => "use_" + e.id).join("/")} 出 2-3 套方案(高温创意),`), a.push(e?.humanConfirm ? " 不要自己拍板;拿到方案后,若需用户拍板用 request_human_confirmation 弹选项。" : " 不要自己拍板;拿到方案后以文字列出选项等用户回复(humanConfirm 未开,勿调不存在工具)。")), n.length && a.push(` · 严谨/易错/校验类 → 可先调 ${n.map((e) => "use_" + e.id).join("/")} 反思挑刺(低温审查),据反馈修订。`), a.push(" · 方案定稿后,由你(主 agent)用 write 落地成 JSON(低温度执行 + schema 校验 + 写前确认)。"), a.push(" · 简单/明确任务(如\"标题改红色\")直接执行,不必走规划-反思。");
|
|
12093
12104
|
}
|