page-agent-sdk 4.4.0 → 4.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/README.md
CHANGED
|
@@ -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 # 987 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
|
@@ -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 # 987 项集成断言(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 包测试
|
|
@@ -12156,7 +12156,7 @@ function $p() {
|
|
|
12156
12156
|
//#region src/core/sdk/createChatSdk.ts
|
|
12157
12157
|
var em = 30, tm = /* @__PURE__ */ new Map();
|
|
12158
12158
|
function nm(e, t) {
|
|
12159
|
-
return e === "restore_data" ? "restore" : e === "write" ? t?.del ? "delete" : t?.patch ? "edit" : "set" : null;
|
|
12159
|
+
return e === "restore_data" ? "restore" : e === "write" ? t?.dryRun ? null : t?.del ? "delete" : t?.patch || t?.patches ? "edit" : "set" : e === "eval_script" ? t?.mode === "transform" ? "edit" : null : e === "draft_commit" || e === "resource_update" ? "edit" : null;
|
|
12160
12160
|
}
|
|
12161
12161
|
function rm(e) {
|
|
12162
12162
|
return e === "spawn_agent" || e === "spawn_agents" || e.startsWith("use_");
|
|
@@ -354,7 +354,7 @@ ${`- 输出形态:完整、自包含的 HTML 页面(.${r},可独立成页)`}
|
|
|
354
354
|
`),tools:[()=>[a3,o3]]};Jp();function Efe(e){let t=e;return typeof t.tagName==`string`||typeof t.nodeType==`number`&&typeof t.nodeName==`string`}function c3(e,t=3,n=2e3,r,i){if(e==null)return e;if(typeof e==`string`)return e.length>n?e.slice(0,n)+`…(已截断)`:e;if(typeof e==`number`||typeof e==`boolean`)return e;if(typeof e==`function`)return`[Function: ${e.name||`anonymous`}]`;if(typeof e==`symbol`)return e.toString();if(typeof e==`bigint`)return`${e.toString()}n`;if(typeof e!=`object`)return String(e);let a=e;if(Efe(a)){let e=a;return e.tagName?`[Element: <${e.tagName.toLowerCase()}>]`:`[Node: ${e.nodeName}]`}if(r?.has(a))return`[Circular]`;let o=r??new WeakSet;if(o.add(a),Array.isArray(e)){let r=e.slice(0,100).map(e=>c3(e,t-1,n,o,i));return e.length>100&&r.push(`…(共 ${e.length} 项,已截断)`),r}if(t<0)return`(对象,已截断)`;let s={},c=Object.keys(a);for(let e=0;e<c.length;e++){let r=c[e];if(e>=50){s[`…`]=`(共 ${c.length} 键,已截断)`;break}try{let e=a[r];i?.test(r)?s[r]=`[REDACTED]`:s[r]=c3(e,t-1,n,o,i)}catch{s[r]=`(getter 抛错)`}}return s}function l3(e){let t=e??(typeof window<`u`?window:{}),n=t.navigator,r=t.location,i=t.document;return{location:{href:r?.href,origin:r?.origin,protocol:r?.protocol,host:r?.host,hostname:r?.hostname,pathname:r?.pathname,search:r?.search},navigator:{userAgent:n?.userAgent,language:n?.language,languages:n?.languages,platform:n?.platform,onLine:n?.onLine},viewport:{innerWidth:t.innerWidth,innerHeight:t.innerHeight,devicePixelRatio:t.devicePixelRatio,scrollX:t.scrollX,scrollY:t.scrollY},document:i?{title:i.title,readyState:i.readyState,characterSet:i.characterSet}:`(无 document)`}}var Dfe=/^(localStorage|sessionStorage|cookie|document|frames|frameElement|opener|parent|top|self|window|globalThis|closed|history|navigation|trustedTypes|origin|crossOriginIsolated)$/,u3=/token|secret|password|passwd|api[-_]?key|auth|cred|csrf|session|ticket/i,d3=VI(({key:e})=>{if(e){if(Dfe.test(e)||u3.test(e))return JSON.stringify({key:e,denied:!0,reason:`安全:该 key 在 denylist(localStorage/sessionStorage/cookie/document 或敏感命名 token/secret/key/auth),不读取防泄漏`},null,2);let t=(typeof window<`u`?window:{})[e];return JSON.stringify({key:e,exists:t!==void 0,type:typeof t,value:c3(t,3,2e3,void 0,u3)},null,2)}return JSON.stringify(l3(),null,2)},{name:`inspect_env`,description:`读宿主页面环境信息(排查调试)。不传参返回摘要(URL/origin、浏览器/语言、viewport、title/readyState);传 key 读指定 window 属性值(如 key:"appConfig")。只读,大结果自动外存 vfs。`,schema:B({key:R().optional().describe(`要读取的 window 属性名(如 "appConfig"/"__DEBUG__");不传 = 返回环境摘要`)})}),f3=[d3];function Ofe(e,t,n){let r=0;return{name:`budget`,beforeAgent:()=>{r=Date.now()},wrapModelCall:async(i,a)=>{let{tokenBudget:o,timeBudgetMs:s}=t,c=o!=null&&(e.total_tokens??0)>o,l=s!=null&&Date.now()-r>s;return c||l?(n({type:`error`,severity:`observable`,code:`BUDGET_EXCEEDED`,message:`资源预算超限:${c?`token 超限(累计 ${e.total_tokens??0} > 上限 ${o})`:`时间超限(${Date.now()-r}ms > 上限 ${s}ms)`},agent 已停止(未完成部分可用 restoreLastCheckpoint 回退)。`}),{message:new hS({content:``}),content:``,toolCalls:[],aborted:!0}):a(i)}}}Jp();var p3=/^[a-zA-Z][a-zA-Z0-9_]*$/;function m3(e){let t=[];for(let[n,r]of Object.entries(e)){if(!p3.test(n)){console.warn(`[page-agent-sdk][actions] 动作名 "${n}" 非法(须匹配 ${p3}),已跳过`);continue}let e=r.description||`宿主动作 ${n}`;t.push(VI(async e=>{try{let t=await r.run(e||{});return t===void 0?`动作 ${n} 执行完成。`:typeof t==`string`?t:JSON.stringify(t)}catch(e){let t=e?.message||String(e);return`动作 ${n} 执行失败:${t}`}},{name:n,description:e,schema:r.params??B({})}))}return t}function h3(e){let t={};for(let[n,r]of Object.entries(e))p3.test(n)&&(t[n]={description:r.description,hasParams:!!r.params});return t}var kfe=W4,Afe=X4;function jfe(e,t){return j2(e,t)}function g3(e,t,n,r,i){let a=z4(e);return[...a.dataOps?t:[],...a.fetch?n:[],...a.domInspect&&r?r:[],...a.inspectEnv&&i?i:[]]}function Mfe(e){let t=new Map,n=[];for(let r of e)for(let e of r.tools){let i=t.get(e.name);i&&n.push({name:e.name,winner:r.label,loser:i.label}),t.set(e.name,{tool:e,label:r.label})}return{tools:[...t.values()].map(e=>e.tool),collisions:n}}var _3=.7;function v3(e,t,n){let r=z4(e);return{name:`usageHints`,augmentPrompt:i=>{let a=[];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(`不确定主数据字段结构时用 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);改多处用 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){let t=e.subagents.filter(e=>(e.temperature??0)>=_3||/规划|创意|设计|方案|brainstorm|plan/i.test(e.description)),n=e.subagents.filter(e=>(e.temperature??0)<_3&&/反思|审查|挑刺|校验|review|critique|reflect/i.test(e.description));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(` · 简单/明确任务(如"标题改红色")直接执行,不必走规划-反思。`)}e?.humanConfirm&&(a.push(`【人工确认·必读】以下情形必须先调 request_human_confirmation 征询用户、拿到答复后再继续,不要自行拍板:`),a.push(` 1) 用户让你「给方案/列选项/我来选/挑一个」时:把每个方案作为一个 option,调 request_human_confirmation(question=简述, options=[方案A,方案B,...], recommendation=你推荐的)。不要只回文字罗列方案让用户自己回复——要用工具把选项做成可点选按钮。`),a.push(` 2) 需求有歧义/不确定时:调工具问清楚(options 不传则用户答同意或拒绝)。`),a.push(` 3) 即将执行高风险不可逆操作(删除/覆盖/批量改动)前:调工具确认。`),a.push(` 4) 规划出多步方案需用户确认时:把整个方案(或关键分步)作为 option 调 request_human_confirmation,确认后再执行。`),a.push(`用户在选项里选了哪个,就按那个方案继续;选「拒绝」则停止并询问如何调整。`));let o=i?.loopProgress;if(o){let e=o.invokeUsage.prompt_tokens||o.invokeUsage.total_tokens,t=n?.promptSoftCap??1/0,r=t!==1/0&&e>=t*.5;!o.budgetHinted&&r&&e>0&&(o.budgetHinted=!0,a.push(`⏳ 预算提示:本任务累计约 ${Math.max(1,Math.round(e/1e3))}K prompt tokens(已过 softCap 半程)。若已接近目标请收敛并给出总结;尚未接近请向用户汇报进度与剩余计划,勿默默继续。轮次预算吃紧时系统会另行注入轮次提示段。`));let i=Object.entries(o.writeFailures).filter(([,e])=>e>=2);if(i.length){let e=i.map(([e,t])=>`${e||`(整体)`}×${t}`).join(`、`);a.push(`⚠️ 以下路径已连续写失败:${e}。连续失败常意味着方向错了——先 read 重新核对实际值/类型,或 restore_data 回退后再改;若确需继续,换思路而非原样重试。`)}}return a.length&&a.unshift(`调用工具务必用标准 function calling(工具调用)格式发起,不要在回复正文里输出伪 XML/标签(如 deepseek 的 tool_calls 标签、invoke、function_call、tool_call 等)或 JSON 文本——那不会被识别为工具调用,会被当普通文字,工具不执行。`),a.length?`## 能力使用提示
|
|
355
355
|
`+a.join(`
|
|
356
356
|
`):void 0}}}function Nfe(e){return{name:`resourcesPin`,augmentPrompt:()=>{let t=e.getResourcesSnapshot();if(!t.length)return;let n=[`## 受保护资源(跨压缩保留 · 精确值保护)`];for(let e of t)e.mode===`freeze`?n.push(`- ${e.path} (freeze 已冻结,不可改)`):n.push(`- ${e.path} (verbatim 原样保留)${e.handle?` ⟦res:${e.handle}⟧`:``}`);return n.push(`读到 ⟦frozen:path⟧/⟦res:handle⟧ 占位符 = 精确值在冻结区/资源池(不入消息流);需真值用 resource_get({path});freeze 字段不可写(撞 FROZEN_FIELD 即放弃);verbatim 直接写新值会 VERBATIM_MISMATCH,先 resource_update 再写回句柄;撞 RESOURCE_EVICTED/RESOURCE_NOT_FOUND 重新 read 懒注册。`),n.join(`
|
|
357
|
-
`)}}}var y3=`v:1::skill-store`,Pfe=`chat-sdk`;function b3(e,t,n){return`${y3}::${e}::${t}::${n}`}function x3(e,t){return`${y3}::${e}::${t}::`}function S3(e={}){let t=e.dbName??Pfe,n=e.backend??`indexed`,r=e.id??``,i,a,o=new Promise(e=>{a=e});return(async()=>{try{if(n===`indexed`){if(typeof indexedDB>`u`)throw Error(`indexedDB 不可用`);i=await j4(t),a(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);i=M4(sessionStorage),a(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);i=M4(localStorage),a(!0)}else i=A4(),a(!1)}catch{i=A4(),a(!1)}})(),{ready:o,async list(){let e=[];return await i.scan(x3(t,r),(t,n)=>{e.push(n)}),e},async get(e){return await i.get(b3(t,r,e))},async put(e){try{await i.set(b3(t,r,e.name),e)}catch(e){T4(e)&&(i=A4())}},async remove(e){let n=b3(t,r,e);return await i.get(n)==null?!1:(await i.del(n),!0)},async clear(){await i.clearPrefix(x3(t,r))},dispose(){}}}var C3=/large_results\/[^\s"'`),]+\.txt/g;function w3(e){let t=new Set,n=e=>{if(typeof e!=`string`||!e)return;let n;for(C3.lastIndex=0;(n=C3.exec(e))!==null;)t.add(n[0])};for(let r of e){if(n(r.content),r.steps)for(let e of r.steps)n(e.result);if(r.images)for(let e of r.images)e.vfsRef&&t.add(e.vfsRef)}return t}function Ffe(e,t){let n=[];for(let r of Object.keys(e))r.startsWith(`large_results/`)&&!t.has(r)&&n.push(r);return n}function T3(){let e=Promise.resolve();return function(t){let n=e.then(t,t);return e=n.then(()=>void 0,()=>void 0),n}}Jp();var Ife=30,E3=new Map;function Lfe(e,t){return e===`restore_data`?`restore`:e===`write`?t?.del?`delete`:t?.patch?`edit`:`set`:null}function Rfe(e){return e===`spawn_agent`||e===`spawn_agents`||e.startsWith(`use_`)}function zfe(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=Lfe(t.name,t.args);return a?e({type:`data_change`,operation:a,value:n()?.bind}):i.status===`done`&&Rfe(t.name)&&e({type:`data_change`,operation:`edit`,value:n()?.bind}),i},afterModel:t=>{let n=uL(t.message);n&&(r.prompt_tokens=(r.prompt_tokens??0)+(n.prompt_tokens??0),r.completion_tokens=(r.completion_tokens??0)+(n.completion_tokens??0),r.total_tokens=(r.total_tokens??0)+(n.total_tokens??0),n.reasoning_tokens&&(r.reasoning_tokens=(r.reasoning_tokens??0)+n.reasoning_tokens),i++,e({type:`usage`,round:i,usage:n,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens,...r.reasoning_tokens?{reasoning_tokens:r.reasoning_tokens}:{}}}))},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function D3(e,t,n,r,i){if(!n)return i&&console.warn(`[page-agent-sdk][focus] capabilities.focus 关闭,${t} 忽略`),{ok:!1,error:`capabilities.focus 关闭`};if(!e||!e.path)return i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path 必填且非空`),{ok:!1,error:`path 必填且非空`};let a=r();return a?oK(a,e.path)?{ok:!0}:(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path "${e.path}" 不在 schema 内(getSchemaAtPath 返 null;数组组件须 z.array(...) 包裹,裸 discriminatedUnion/Union 会降级)`),{ok:!1,error:`path "${e.path}" 不在 schema 内`}):(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:当前无主数据 schema`),{ok:!1,error:`当前无主数据 schema,无法聚焦`})}function Bfe(e,t){let n={prompt_tokens:0,completion_tokens:0,total_tokens:0},r=b4(()=>Ct,()=>e.conflictPolicy??`ask`),i=hz(0),a=I4(e.storage);e.debug&&a&&a.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let{modelCaps:o,summaryLlmInvoke:s,titleLlmInvoke:c,compressDecisionInvoke:l}=y4(e),u=o;if(e.debug&&console.log(`[page-agent-sdk][modelCaps]`,u),u.contextWindow<2e5)throw Error(`[page-agent-sdk] 模型上下文窗口 ${u.contextWindow} 小于最小支持 ${YI}(需 ≥200K 窗口模型,如 GLM-5.2/Claude/Kimi/Qwen-1M/DeepSeek-v4)`);let d=H4(e,u.contextWindow),f=d.enableLLMSummary!==!1,p=(e.contextOptions&&e.contextOptions.preserveLastToolResults)??Sfe[e.contextPreset??`auto`],m=new Set(p),h=e.llm;e.debug&&!s&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let g=iz([]),_=Q0(e.vfs?.initialFiles,{persist:a?{save:e=>{Yt({vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes,poolBytes:e.vfs?.poolBytes}),v=TG([],{maxPlanRevisions:e.maxPlanRevisions}),y=WK(),b=XK(e=>{L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`intent_guard`,preview:e}})}),x=QK(()=>{L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`resume_notice`}})}),S,C=e.approval?.timeoutMs,w=C!==void 0&&Number.isFinite(C)&&C>0?C:C!==void 0&&(!Number.isFinite(C)||C<0)?0:3e4,T=e=>{Ct({type:`error`,message:`确认请求(${e.toolName})${Math.round(e.waitedMs/1e3)}s 无响应已自动拒绝 —— 当前路径无 UI 响应方;可传 approval.timeoutMs 调整(Infinity = 无限等)`,severity:`observable`,code:`APPROVAL_AUTO_REJECTED`,context:e})},E=JJ(e=>{S=e,Yt({planConfirmation:e}),L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`plan_confirmation`,summary:e.summary,choice:e.choice}})},{timeoutMs:w,onAutoReject:T}),D=Eq({getSchema:()=>F()?.schema,getBind:()=>F()?.bind,onChange:e=>Ct({type:`focus_change`,focuses:e})}),ee=IJ(),O=LJ(e.memory||``);typeof e.memory==`function`&&O.refresh();let k={current:null},te=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,A=!(e.subagents??[]).some(e=>e._codeAsset)&&z4(e.capabilities).subagent,ne=e.subagents;A&&te?.schema&&vK(te.schema).length&&(ne=[...e.subagents??[],d4()],console.info(`[page-agent-sdk] 检测到 schema 含代码组件数组(如 components[].code),已自动装配 HTML 代码子 agent(委派编排 + vfs 工作副本 + 格式校验 + 增量 commit)。需定制(codeField/formatCheck/craftNotes 等)请显式传 createHtmlSubagent(...)`));let j=(ne??[]).filter(e=>!!e._codeAsset),re=new Set;for(let e of j){if(e._codeAsset.writablePaths.length)continue;let t=vK(te?.schema,e._codeAsset.codeField);t.length?(e._codeAsset.writablePaths=t,Array.isArray(e.writablePaths)&&(e.writablePaths=t),e._rebuildCodeAssetPaths?.(t[0]),console.info(`[page-agent-sdk][createHtmlSubagent] 未传 writablePaths,已从 schema 推断: [${t.map(e=>`'${e}'`).join(`, `)}]`)):(console.warn(`[page-agent-sdk][createHtmlSubagent] 未能从 schema 推断 writablePaths(开放 schema(z.any()/z.record())/嵌套容器(如 sections[].children[])/点路径 codeField(如 props.html_code)不支持自动推断),已跳过该 html 子 agent(整体不受影响);如确需代码资产机制(vfs + 格式校验 + 增量 commit),请显式传 writablePaths(代码组件 data 区,如 ['components'])`),re.add(e))}let M=re.size?j.filter(e=>!re.has(e)):j,ie=re.size?(ne??[]).filter(e=>!re.has(e)):ne,ae=M.length>0,oe=M.flatMap(e=>e._codeAsset.writablePaths),se=M.flatMap(e=>e._codeAsset.writablePaths.map(t=>`${t}.${e._codeAsset.codeField}`)),ce=e.checkpoint,le=ce!==void 0&&ce!==!1,ue=le?tY({getData:()=>F()?.bind,consumeDataDirty:()=>P?.consumeDataDirty?.()??!0,slotPaths:te?[``]:[],vfsStore:_,todosMw:v,getTodos:()=>k.current?.getState?.()?.todos??[],messages:g,maxCheckpoints:ce&&typeof ce==`object`?ce.maxCheckpoints:void 0}):null,de=!ce||typeof ce!=`object`||ce.auto!==!1,fe=z4(e.capabilities),N=fe.dataOps,pe=fe.draftWrite,me=fe.automation,he=Y0({...e,locale:e.i18n?.locale});if(ae){let e=M.map(e=>e._codeAsset.orchestratorPrompt).filter(Boolean).join(`
|
|
357
|
+
`)}}}var y3=`v:1::skill-store`,Pfe=`chat-sdk`;function b3(e,t,n){return`${y3}::${e}::${t}::${n}`}function x3(e,t){return`${y3}::${e}::${t}::`}function S3(e={}){let t=e.dbName??Pfe,n=e.backend??`indexed`,r=e.id??``,i,a,o=new Promise(e=>{a=e});return(async()=>{try{if(n===`indexed`){if(typeof indexedDB>`u`)throw Error(`indexedDB 不可用`);i=await j4(t),a(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);i=M4(sessionStorage),a(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);i=M4(localStorage),a(!0)}else i=A4(),a(!1)}catch{i=A4(),a(!1)}})(),{ready:o,async list(){let e=[];return await i.scan(x3(t,r),(t,n)=>{e.push(n)}),e},async get(e){return await i.get(b3(t,r,e))},async put(e){try{await i.set(b3(t,r,e.name),e)}catch(e){T4(e)&&(i=A4())}},async remove(e){let n=b3(t,r,e);return await i.get(n)==null?!1:(await i.del(n),!0)},async clear(){await i.clearPrefix(x3(t,r))},dispose(){}}}var C3=/large_results\/[^\s"'`),]+\.txt/g;function w3(e){let t=new Set,n=e=>{if(typeof e!=`string`||!e)return;let n;for(C3.lastIndex=0;(n=C3.exec(e))!==null;)t.add(n[0])};for(let r of e){if(n(r.content),r.steps)for(let e of r.steps)n(e.result);if(r.images)for(let e of r.images)e.vfsRef&&t.add(e.vfsRef)}return t}function Ffe(e,t){let n=[];for(let r of Object.keys(e))r.startsWith(`large_results/`)&&!t.has(r)&&n.push(r);return n}function T3(){let e=Promise.resolve();return function(t){let n=e.then(t,t);return e=n.then(()=>void 0,()=>void 0),n}}Jp();var Ife=30,E3=new Map;function Lfe(e,t){return e===`restore_data`?`restore`:e===`write`?t?.dryRun?null:t?.del?`delete`:t?.patch||t?.patches?`edit`:`set`:e===`eval_script`?t?.mode===`transform`?`edit`:null:e===`draft_commit`||e===`resource_update`?`edit`:null}function Rfe(e){return e===`spawn_agent`||e===`spawn_agents`||e.startsWith(`use_`)}function zfe(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=Lfe(t.name,t.args);return a?e({type:`data_change`,operation:a,value:n()?.bind}):i.status===`done`&&Rfe(t.name)&&e({type:`data_change`,operation:`edit`,value:n()?.bind}),i},afterModel:t=>{let n=uL(t.message);n&&(r.prompt_tokens=(r.prompt_tokens??0)+(n.prompt_tokens??0),r.completion_tokens=(r.completion_tokens??0)+(n.completion_tokens??0),r.total_tokens=(r.total_tokens??0)+(n.total_tokens??0),n.reasoning_tokens&&(r.reasoning_tokens=(r.reasoning_tokens??0)+n.reasoning_tokens),i++,e({type:`usage`,round:i,usage:n,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens,...r.reasoning_tokens?{reasoning_tokens:r.reasoning_tokens}:{}}}))},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function D3(e,t,n,r,i){if(!n)return i&&console.warn(`[page-agent-sdk][focus] capabilities.focus 关闭,${t} 忽略`),{ok:!1,error:`capabilities.focus 关闭`};if(!e||!e.path)return i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path 必填且非空`),{ok:!1,error:`path 必填且非空`};let a=r();return a?oK(a,e.path)?{ok:!0}:(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path "${e.path}" 不在 schema 内(getSchemaAtPath 返 null;数组组件须 z.array(...) 包裹,裸 discriminatedUnion/Union 会降级)`),{ok:!1,error:`path "${e.path}" 不在 schema 内`}):(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:当前无主数据 schema`),{ok:!1,error:`当前无主数据 schema,无法聚焦`})}function Bfe(e,t){let n={prompt_tokens:0,completion_tokens:0,total_tokens:0},r=b4(()=>Ct,()=>e.conflictPolicy??`ask`),i=hz(0),a=I4(e.storage);e.debug&&a&&a.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let{modelCaps:o,summaryLlmInvoke:s,titleLlmInvoke:c,compressDecisionInvoke:l}=y4(e),u=o;if(e.debug&&console.log(`[page-agent-sdk][modelCaps]`,u),u.contextWindow<2e5)throw Error(`[page-agent-sdk] 模型上下文窗口 ${u.contextWindow} 小于最小支持 ${YI}(需 ≥200K 窗口模型,如 GLM-5.2/Claude/Kimi/Qwen-1M/DeepSeek-v4)`);let d=H4(e,u.contextWindow),f=d.enableLLMSummary!==!1,p=(e.contextOptions&&e.contextOptions.preserveLastToolResults)??Sfe[e.contextPreset??`auto`],m=new Set(p),h=e.llm;e.debug&&!s&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let g=iz([]),_=Q0(e.vfs?.initialFiles,{persist:a?{save:e=>{Yt({vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes,poolBytes:e.vfs?.poolBytes}),v=TG([],{maxPlanRevisions:e.maxPlanRevisions}),y=WK(),b=XK(e=>{L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`intent_guard`,preview:e}})}),x=QK(()=>{L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`resume_notice`}})}),S,C=e.approval?.timeoutMs,w=C!==void 0&&Number.isFinite(C)&&C>0?C:C!==void 0&&(!Number.isFinite(C)||C<0)?0:3e4,T=e=>{Ct({type:`error`,message:`确认请求(${e.toolName})${Math.round(e.waitedMs/1e3)}s 无响应已自动拒绝 —— 当前路径无 UI 响应方;可传 approval.timeoutMs 调整(Infinity = 无限等)`,severity:`observable`,code:`APPROVAL_AUTO_REJECTED`,context:e})},E=JJ(e=>{S=e,Yt({planConfirmation:e}),L.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`plan_confirmation`,summary:e.summary,choice:e.choice}})},{timeoutMs:w,onAutoReject:T}),D=Eq({getSchema:()=>F()?.schema,getBind:()=>F()?.bind,onChange:e=>Ct({type:`focus_change`,focuses:e})}),ee=IJ(),O=LJ(e.memory||``);typeof e.memory==`function`&&O.refresh();let k={current:null},te=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,A=!(e.subagents??[]).some(e=>e._codeAsset)&&z4(e.capabilities).subagent,ne=e.subagents;A&&te?.schema&&vK(te.schema).length&&(ne=[...e.subagents??[],d4()],console.info(`[page-agent-sdk] 检测到 schema 含代码组件数组(如 components[].code),已自动装配 HTML 代码子 agent(委派编排 + vfs 工作副本 + 格式校验 + 增量 commit)。需定制(codeField/formatCheck/craftNotes 等)请显式传 createHtmlSubagent(...)`));let j=(ne??[]).filter(e=>!!e._codeAsset),re=new Set;for(let e of j){if(e._codeAsset.writablePaths.length)continue;let t=vK(te?.schema,e._codeAsset.codeField);t.length?(e._codeAsset.writablePaths=t,Array.isArray(e.writablePaths)&&(e.writablePaths=t),e._rebuildCodeAssetPaths?.(t[0]),console.info(`[page-agent-sdk][createHtmlSubagent] 未传 writablePaths,已从 schema 推断: [${t.map(e=>`'${e}'`).join(`, `)}]`)):(console.warn(`[page-agent-sdk][createHtmlSubagent] 未能从 schema 推断 writablePaths(开放 schema(z.any()/z.record())/嵌套容器(如 sections[].children[])/点路径 codeField(如 props.html_code)不支持自动推断),已跳过该 html 子 agent(整体不受影响);如确需代码资产机制(vfs + 格式校验 + 增量 commit),请显式传 writablePaths(代码组件 data 区,如 ['components'])`),re.add(e))}let M=re.size?j.filter(e=>!re.has(e)):j,ie=re.size?(ne??[]).filter(e=>!re.has(e)):ne,ae=M.length>0,oe=M.flatMap(e=>e._codeAsset.writablePaths),se=M.flatMap(e=>e._codeAsset.writablePaths.map(t=>`${t}.${e._codeAsset.codeField}`)),ce=e.checkpoint,le=ce!==void 0&&ce!==!1,ue=le?tY({getData:()=>F()?.bind,consumeDataDirty:()=>P?.consumeDataDirty?.()??!0,slotPaths:te?[``]:[],vfsStore:_,todosMw:v,getTodos:()=>k.current?.getState?.()?.todos??[],messages:g,maxCheckpoints:ce&&typeof ce==`object`?ce.maxCheckpoints:void 0}):null,de=!ce||typeof ce!=`object`||ce.auto!==!1,fe=z4(e.capabilities),N=fe.dataOps,pe=fe.draftWrite,me=fe.automation,he=Y0({...e,locale:e.i18n?.locale});if(ae){let e=M.map(e=>e._codeAsset.orchestratorPrompt).filter(Boolean).join(`
|
|
358
358
|
|
|
359
359
|
`);e&&(he+=`
|
|
360
360
|
|
package/dist/page-agent-sdk.js
CHANGED
|
@@ -14578,7 +14578,7 @@ function Vy() {
|
|
|
14578
14578
|
//#region src/core/sdk/createChatSdk.ts
|
|
14579
14579
|
var Hy = 30, Uy = /* @__PURE__ */ new Map();
|
|
14580
14580
|
function Wy(e, t) {
|
|
14581
|
-
return e === "restore_data" ? "restore" : e === "write" ? t?.del ? "delete" : t?.patch ? "edit" : "set" : null;
|
|
14581
|
+
return e === "restore_data" ? "restore" : e === "write" ? t?.dryRun ? null : t?.del ? "delete" : t?.patch || t?.patches ? "edit" : "set" : e === "eval_script" ? t?.mode === "transform" ? "edit" : null : e === "draft_commit" || e === "resource_update" ? "edit" : null;
|
|
14582
14582
|
}
|
|
14583
14583
|
function Gy(e) {
|
|
14584
14584
|
return e === "spawn_agent" || e === "spawn_agents" || e.startsWith("use_");
|
|
@@ -72305,7 +72305,7 @@ function eMe() {
|
|
|
72305
72305
|
QP(), Of(), M(), P();
|
|
72306
72306
|
var tMe = ["schema"], nMe = 30, H8 = /* @__PURE__ */ new Map();
|
|
72307
72307
|
function rMe(e, t) {
|
|
72308
|
-
return e === "restore_data" ? "restore" : e === "write" ? t != null && t.del ? "delete" : t != null && t.patch ? "edit" : "set" : null;
|
|
72308
|
+
return e === "restore_data" ? "restore" : e === "write" ? t != null && t.dryRun ? null : t != null && t.del ? "delete" : t != null && t.patch || t != null && t.patches ? "edit" : "set" : e === "eval_script" ? (t == null ? void 0 : t.mode) === "transform" ? "edit" : null : e === "draft_commit" || e === "resource_update" ? "edit" : null;
|
|
72309
72309
|
}
|
|
72310
72310
|
function iMe(e) {
|
|
72311
72311
|
return e === "spawn_agent" || e === "spawn_agents" || e.startsWith("use_");
|
|
@@ -198,7 +198,7 @@ ${`- 输出形态:完整、自包含的 HTML 页面(.${r},可独立成页)`}
|
|
|
198
198
|
`),tools:[()=>[cy,ly]]};function dy(e){let t=e;return typeof t.tagName==`string`||typeof t.nodeType==`number`&&typeof t.nodeName==`string`}function fy(e,t=3,n=2e3,r,i){if(e==null)return e;if(typeof e==`string`)return e.length>n?e.slice(0,n)+`…(已截断)`:e;if(typeof e==`number`||typeof e==`boolean`)return e;if(typeof e==`function`)return`[Function: ${e.name||`anonymous`}]`;if(typeof e==`symbol`)return e.toString();if(typeof e==`bigint`)return`${e.toString()}n`;if(typeof e!=`object`)return String(e);let a=e;if(dy(a)){let e=a;return e.tagName?`[Element: <${e.tagName.toLowerCase()}>]`:`[Node: ${e.nodeName}]`}if(r?.has(a))return`[Circular]`;let o=r??new WeakSet;if(o.add(a),Array.isArray(e)){let r=e.slice(0,100).map(e=>fy(e,t-1,n,o,i));return e.length>100&&r.push(`…(共 ${e.length} 项,已截断)`),r}if(t<0)return`(对象,已截断)`;let s={},c=Object.keys(a);for(let e=0;e<c.length;e++){let r=c[e];if(e>=50){s[`…`]=`(共 ${c.length} 键,已截断)`;break}try{let e=a[r];i?.test(r)?s[r]=`[REDACTED]`:s[r]=fy(e,t-1,n,o,i)}catch{s[r]=`(getter 抛错)`}}return s}function py(e){let t=e??(typeof window<`u`?window:{}),n=t.navigator,r=t.location,i=t.document;return{location:{href:r?.href,origin:r?.origin,protocol:r?.protocol,host:r?.host,hostname:r?.hostname,pathname:r?.pathname,search:r?.search},navigator:{userAgent:n?.userAgent,language:n?.language,languages:n?.languages,platform:n?.platform,onLine:n?.onLine},viewport:{innerWidth:t.innerWidth,innerHeight:t.innerHeight,devicePixelRatio:t.devicePixelRatio,scrollX:t.scrollX,scrollY:t.scrollY},document:i?{title:i.title,readyState:i.readyState,characterSet:i.characterSet}:`(无 document)`}}var my=/^(localStorage|sessionStorage|cookie|document|frames|frameElement|opener|parent|top|self|window|globalThis|closed|history|navigation|trustedTypes|origin|crossOriginIsolated)$/,hy=/token|secret|password|passwd|api[-_]?key|auth|cred|csrf|session|ticket/i,gy=(0,r.tool)(({key:e})=>{if(e){if(my.test(e)||hy.test(e))return JSON.stringify({key:e,denied:!0,reason:`安全:该 key 在 denylist(localStorage/sessionStorage/cookie/document 或敏感命名 token/secret/key/auth),不读取防泄漏`},null,2);let t=(typeof window<`u`?window:{})[e];return JSON.stringify({key:e,exists:t!==void 0,type:typeof t,value:fy(t,3,2e3,void 0,hy)},null,2)}return JSON.stringify(py(),null,2)},{name:`inspect_env`,description:`读宿主页面环境信息(排查调试)。不传参返回摘要(URL/origin、浏览器/语言、viewport、title/readyState);传 key 读指定 window 属性值(如 key:"appConfig")。只读,大结果自动外存 vfs。`,schema:t.z.object({key:t.z.string().optional().describe(`要读取的 window 属性名(如 "appConfig"/"__DEBUG__");不传 = 返回环境摘要`)})}),_y=[gy];function vy(e,t,n){let r=0;return{name:`budget`,beforeAgent:()=>{r=Date.now()},wrapModelCall:async(a,o)=>{let{tokenBudget:s,timeBudgetMs:c}=t,l=s!=null&&(e.total_tokens??0)>s,u=c!=null&&Date.now()-r>c;return l||u?(n({type:`error`,severity:`observable`,code:`BUDGET_EXCEEDED`,message:`资源预算超限:${l?`token 超限(累计 ${e.total_tokens??0} > 上限 ${s})`:`时间超限(${Date.now()-r}ms > 上限 ${c}ms)`},agent 已停止(未完成部分可用 restoreLastCheckpoint 回退)。`}),{message:new i.AIMessage({content:``}),content:``,toolCalls:[],aborted:!0}):o(a)}}}var yy=/^[a-zA-Z][a-zA-Z0-9_]*$/;function by(e){let n=[];for(let[i,a]of Object.entries(e)){if(!yy.test(i)){console.warn(`[page-agent-sdk][actions] 动作名 "${i}" 非法(须匹配 ${yy}),已跳过`);continue}let e=a.description||`宿主动作 ${i}`;n.push((0,r.tool)(async e=>{try{let t=await a.run(e||{});return t===void 0?`动作 ${i} 执行完成。`:typeof t==`string`?t:JSON.stringify(t)}catch(e){let t=e?.message||String(e);return`动作 ${i} 执行失败:${t}`}},{name:i,description:e,schema:a.params??t.z.object({})}))}return n}function xy(e){let t={};for(let[n,r]of Object.entries(e))yy.test(n)&&(t[n]={description:r.description,hasParams:!!r.params});return t}var Sy=Kv,Cy=Qv;function wy(e,t){return Hg(e,t)}function Ty(e,t,n,r,i){let a=Rv(e);return[...a.dataOps?t:[],...a.fetch?n:[],...a.domInspect&&r?r:[],...a.inspectEnv&&i?i:[]]}function Ey(e){let t=new Map,n=[];for(let r of e)for(let e of r.tools){let i=t.get(e.name);i&&n.push({name:e.name,winner:r.label,loser:i.label}),t.set(e.name,{tool:e,label:r.label})}return{tools:[...t.values()].map(e=>e.tool),collisions:n}}var Dy=.7;function Oy(e,t,n){let r=Rv(e);return{name:`usageHints`,augmentPrompt:i=>{let a=[];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(`不确定主数据字段结构时用 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);改多处用 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){let t=e.subagents.filter(e=>(e.temperature??0)>=Dy||/规划|创意|设计|方案|brainstorm|plan/i.test(e.description)),n=e.subagents.filter(e=>(e.temperature??0)<Dy&&/反思|审查|挑刺|校验|review|critique|reflect/i.test(e.description));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(` · 简单/明确任务(如"标题改红色")直接执行,不必走规划-反思。`)}e?.humanConfirm&&(a.push(`【人工确认·必读】以下情形必须先调 request_human_confirmation 征询用户、拿到答复后再继续,不要自行拍板:`),a.push(` 1) 用户让你「给方案/列选项/我来选/挑一个」时:把每个方案作为一个 option,调 request_human_confirmation(question=简述, options=[方案A,方案B,...], recommendation=你推荐的)。不要只回文字罗列方案让用户自己回复——要用工具把选项做成可点选按钮。`),a.push(` 2) 需求有歧义/不确定时:调工具问清楚(options 不传则用户答同意或拒绝)。`),a.push(` 3) 即将执行高风险不可逆操作(删除/覆盖/批量改动)前:调工具确认。`),a.push(` 4) 规划出多步方案需用户确认时:把整个方案(或关键分步)作为 option 调 request_human_confirmation,确认后再执行。`),a.push(`用户在选项里选了哪个,就按那个方案继续;选「拒绝」则停止并询问如何调整。`));let o=i?.loopProgress;if(o){let e=o.invokeUsage.prompt_tokens||o.invokeUsage.total_tokens,t=n?.promptSoftCap??1/0,r=t!==1/0&&e>=t*.5;!o.budgetHinted&&r&&e>0&&(o.budgetHinted=!0,a.push(`⏳ 预算提示:本任务累计约 ${Math.max(1,Math.round(e/1e3))}K prompt tokens(已过 softCap 半程)。若已接近目标请收敛并给出总结;尚未接近请向用户汇报进度与剩余计划,勿默默继续。轮次预算吃紧时系统会另行注入轮次提示段。`));let i=Object.entries(o.writeFailures).filter(([,e])=>e>=2);if(i.length){let e=i.map(([e,t])=>`${e||`(整体)`}×${t}`).join(`、`);a.push(`⚠️ 以下路径已连续写失败:${e}。连续失败常意味着方向错了——先 read 重新核对实际值/类型,或 restore_data 回退后再改;若确需继续,换思路而非原样重试。`)}}return a.length&&a.unshift(`调用工具务必用标准 function calling(工具调用)格式发起,不要在回复正文里输出伪 XML/标签(如 deepseek 的 tool_calls 标签、invoke、function_call、tool_call 等)或 JSON 文本——那不会被识别为工具调用,会被当普通文字,工具不执行。`),a.length?`## 能力使用提示
|
|
199
199
|
`+a.join(`
|
|
200
200
|
`):void 0}}}function ky(e){return{name:`resourcesPin`,augmentPrompt:()=>{let t=e.getResourcesSnapshot();if(!t.length)return;let n=[`## 受保护资源(跨压缩保留 · 精确值保护)`];for(let e of t)e.mode===`freeze`?n.push(`- ${e.path} (freeze 已冻结,不可改)`):n.push(`- ${e.path} (verbatim 原样保留)${e.handle?` ⟦res:${e.handle}⟧`:``}`);return n.push(`读到 ⟦frozen:path⟧/⟦res:handle⟧ 占位符 = 精确值在冻结区/资源池(不入消息流);需真值用 resource_get({path});freeze 字段不可写(撞 FROZEN_FIELD 即放弃);verbatim 直接写新值会 VERBATIM_MISMATCH,先 resource_update 再写回句柄;撞 RESOURCE_EVICTED/RESOURCE_NOT_FOUND 重新 read 懒注册。`),n.join(`
|
|
201
|
-
`)}}}var Ay=`v:1::skill-store`,jy=`chat-sdk`;function My(e,t,n){return`${Ay}::${e}::${t}::${n}`}function Ny(e,t){return`${Ay}::${e}::${t}::`}function Py(e={}){let t=e.dbName??jy,n=e.backend??`indexed`,r=e.id??``,i,a,o=new Promise(e=>{a=e});return(async()=>{try{if(n===`indexed`){if(typeof indexedDB>`u`)throw Error(`indexedDB 不可用`);i=await kv(t),a(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);i=Av(sessionStorage),a(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);i=Av(localStorage),a(!0)}else i=Ov(),a(!1)}catch{i=Ov(),a(!1)}})(),{ready:o,async list(){let e=[];return await i.scan(Ny(t,r),(t,n)=>{e.push(n)}),e},async get(e){return await i.get(My(t,r,e))},async put(e){try{await i.set(My(t,r,e.name),e)}catch(e){bv(e)&&(i=Ov())}},async remove(e){let n=My(t,r,e);return await i.get(n)==null?!1:(await i.del(n),!0)},async clear(){await i.clearPrefix(Ny(t,r))},dispose(){}}}var Fy=/large_results\/[^\s"'`),]+\.txt/g;function Iy(e){let t=new Set,n=e=>{if(typeof e!=`string`||!e)return;let n;for(Fy.lastIndex=0;(n=Fy.exec(e))!==null;)t.add(n[0])};for(let r of e){if(n(r.content),r.steps)for(let e of r.steps)n(e.result);if(r.images)for(let e of r.images)e.vfsRef&&t.add(e.vfsRef)}return t}function Ly(e,t){let n=[];for(let r of Object.keys(e))r.startsWith(`large_results/`)&&!t.has(r)&&n.push(r);return n}function Ry(){let e=Promise.resolve();return function(t){let n=e.then(t,t);return e=n.then(()=>void 0,()=>void 0),n}}var zy=30,By=new Map;function Vy(e,t){return e===`restore_data`?`restore`:e===`write`?t?.del?`delete`:t?.patch?`edit`:`set`:null}function Hy(e){return e===`spawn_agent`||e===`spawn_agents`||e.startsWith(`use_`)}function Uy(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=Vy(t.name,t.args);return a?e({type:`data_change`,operation:a,value:n()?.bind}):i.status===`done`&&Hy(t.name)&&e({type:`data_change`,operation:`edit`,value:n()?.bind}),i},afterModel:t=>{let n=M(t.message);n&&(r.prompt_tokens=(r.prompt_tokens??0)+(n.prompt_tokens??0),r.completion_tokens=(r.completion_tokens??0)+(n.completion_tokens??0),r.total_tokens=(r.total_tokens??0)+(n.total_tokens??0),n.reasoning_tokens&&(r.reasoning_tokens=(r.reasoning_tokens??0)+n.reasoning_tokens),i++,e({type:`usage`,round:i,usage:n,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens,...r.reasoning_tokens?{reasoning_tokens:r.reasoning_tokens}:{}}}))},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function Wy(e,t,n,r,i){if(!n)return i&&console.warn(`[page-agent-sdk][focus] capabilities.focus 关闭,${t} 忽略`),{ok:!1,error:`capabilities.focus 关闭`};if(!e||!e.path)return i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path 必填且非空`),{ok:!1,error:`path 必填且非空`};let a=r();return a?xf(a,e.path)?{ok:!0}:(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path "${e.path}" 不在 schema 内(getSchemaAtPath 返 null;数组组件须 z.array(...) 包裹,裸 discriminatedUnion/Union 会降级)`),{ok:!1,error:`path "${e.path}" 不在 schema 内`}):(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:当前无主数据 schema`),{ok:!1,error:`当前无主数据 schema,无法聚焦`})}function Gy(e,n){let i={prompt_tokens:0,completion_tokens:0,total_tokens:0},a=ov(()=>xt,()=>e.conflictPolicy??`ask`),o=kn(0),s=Fv(e.storage);e.debug&&s&&s.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let{modelCaps:c,summaryLlmInvoke:l,titleLlmInvoke:u,compressDecisionInvoke:d}=av(e),f=c;if(e.debug&&console.log(`[page-agent-sdk][modelCaps]`,f),f.contextWindow<2e5)throw Error(`[page-agent-sdk] 模型上下文窗口 ${f.contextWindow} 小于最小支持 ${y}(需 ≥200K 窗口模型,如 GLM-5.2/Claude/Kimi/Qwen-1M/DeepSeek-v4)`);let p=Hv(e,f.contextWindow),m=p.enableLLMSummary!==!1,h=(e.contextOptions&&e.contextOptions.preserveLastToolResults)??Vv[e.contextPreset??`auto`],g=new Set(h),_=e.llm;e.debug&&!l&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let v=hn([]),x=Zh(e.vfs?.initialFiles,{persist:s?{save:e=>{qt({vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes,poolBytes:e.vfs?.poolBytes}),S=zd([],{maxPlanRevisions:e.maxPlanRevisions}),C=ap(),w=dp(e=>{G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`intent_guard`,preview:e}})}),T=pp(()=>{G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`resume_notice`}})}),E,D=e.approval?.timeoutMs,k=D!==void 0&&Number.isFinite(D)&&D>0?D:D!==void 0&&(!Number.isFinite(D)||D<0)?0:3e4,te=e=>{xt({type:`error`,message:`确认请求(${e.toolName})${Math.round(e.waitedMs/1e3)}s 无响应已自动拒绝 —— 当前路径无 UI 响应方;可传 approval.timeoutMs 调整(Infinity = 无限等)`,severity:`observable`,code:`APPROVAL_AUTO_REJECTED`,context:e})},A=lh(e=>{E=e,qt({planConfirmation:e}),G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`plan_confirmation`,summary:e.summary,choice:e.choice}})},{timeoutMs:k,onAutoReject:te}),j=Vp({getSchema:()=>ge()?.schema,getBind:()=>ge()?.bind,onChange:e=>xt({type:`focus_change`,focuses:e})}),M=Zm(),ne=Qm(e.memory||``);typeof e.memory==`function`&&ne.refresh();let N={current:null},P=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,F=!(e.subagents??[]).some(e=>e._codeAsset)&&Rv(e.capabilities).subagent,re=e.subagents;F&&P?.schema&&Nf(P.schema).length&&(re=[...e.subagents??[],W_()],console.info(`[page-agent-sdk] 检测到 schema 含代码组件数组(如 components[].code),已自动装配 HTML 代码子 agent(委派编排 + vfs 工作副本 + 格式校验 + 增量 commit)。需定制(codeField/formatCheck/craftNotes 等)请显式传 createHtmlSubagent(...)`));let ie=(re??[]).filter(e=>!!e._codeAsset),ae=new Set;for(let e of ie){if(e._codeAsset.writablePaths.length)continue;let t=Nf(P?.schema,e._codeAsset.codeField);t.length?(e._codeAsset.writablePaths=t,Array.isArray(e.writablePaths)&&(e.writablePaths=t),e._rebuildCodeAssetPaths?.(t[0]),console.info(`[page-agent-sdk][createHtmlSubagent] 未传 writablePaths,已从 schema 推断: [${t.map(e=>`'${e}'`).join(`, `)}]`)):(console.warn(`[page-agent-sdk][createHtmlSubagent] 未能从 schema 推断 writablePaths(开放 schema(z.any()/z.record())/嵌套容器(如 sections[].children[])/点路径 codeField(如 props.html_code)不支持自动推断),已跳过该 html 子 agent(整体不受影响);如确需代码资产机制(vfs + 格式校验 + 增量 commit),请显式传 writablePaths(代码组件 data 区,如 ['components'])`),ae.add(e))}let I=ae.size?ie.filter(e=>!ae.has(e)):ie,oe=ae.size?(re??[]).filter(e=>!ae.has(e)):re,se=I.length>0,L=I.flatMap(e=>e._codeAsset.writablePaths),R=I.flatMap(e=>e._codeAsset.writablePaths.map(t=>`${t}.${e._codeAsset.codeField}`)),z=e.checkpoint,ce=z!==void 0&&z!==!1,B=ce?gh({getData:()=>ge()?.bind,consumeDataDirty:()=>me?.consumeDataDirty?.()??!0,slotPaths:P?[``]:[],vfsStore:x,todosMw:S,getTodos:()=>N.current?.getState?.()?.todos??[],messages:v,maxCheckpoints:z&&typeof z==`object`?z.maxCheckpoints:void 0}):null,V=!z||typeof z!=`object`||z.auto!==!1,H=Rv(e.capabilities),le=H.dataOps,U=H.draftWrite,ue=H.automation,de=qh({...e,locale:e.i18n?.locale});if(se){let e=I.map(e=>e._codeAsset.orchestratorPrompt).filter(Boolean).join(`
|
|
201
|
+
`)}}}var Ay=`v:1::skill-store`,jy=`chat-sdk`;function My(e,t,n){return`${Ay}::${e}::${t}::${n}`}function Ny(e,t){return`${Ay}::${e}::${t}::`}function Py(e={}){let t=e.dbName??jy,n=e.backend??`indexed`,r=e.id??``,i,a,o=new Promise(e=>{a=e});return(async()=>{try{if(n===`indexed`){if(typeof indexedDB>`u`)throw Error(`indexedDB 不可用`);i=await kv(t),a(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);i=Av(sessionStorage),a(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);i=Av(localStorage),a(!0)}else i=Ov(),a(!1)}catch{i=Ov(),a(!1)}})(),{ready:o,async list(){let e=[];return await i.scan(Ny(t,r),(t,n)=>{e.push(n)}),e},async get(e){return await i.get(My(t,r,e))},async put(e){try{await i.set(My(t,r,e.name),e)}catch(e){bv(e)&&(i=Ov())}},async remove(e){let n=My(t,r,e);return await i.get(n)==null?!1:(await i.del(n),!0)},async clear(){await i.clearPrefix(Ny(t,r))},dispose(){}}}var Fy=/large_results\/[^\s"'`),]+\.txt/g;function Iy(e){let t=new Set,n=e=>{if(typeof e!=`string`||!e)return;let n;for(Fy.lastIndex=0;(n=Fy.exec(e))!==null;)t.add(n[0])};for(let r of e){if(n(r.content),r.steps)for(let e of r.steps)n(e.result);if(r.images)for(let e of r.images)e.vfsRef&&t.add(e.vfsRef)}return t}function Ly(e,t){let n=[];for(let r of Object.keys(e))r.startsWith(`large_results/`)&&!t.has(r)&&n.push(r);return n}function Ry(){let e=Promise.resolve();return function(t){let n=e.then(t,t);return e=n.then(()=>void 0,()=>void 0),n}}var zy=30,By=new Map;function Vy(e,t){return e===`restore_data`?`restore`:e===`write`?t?.dryRun?null:t?.del?`delete`:t?.patch||t?.patches?`edit`:`set`:e===`eval_script`?t?.mode===`transform`?`edit`:null:e===`draft_commit`||e===`resource_update`?`edit`:null}function Hy(e){return e===`spawn_agent`||e===`spawn_agents`||e.startsWith(`use_`)}function Uy(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=Vy(t.name,t.args);return a?e({type:`data_change`,operation:a,value:n()?.bind}):i.status===`done`&&Hy(t.name)&&e({type:`data_change`,operation:`edit`,value:n()?.bind}),i},afterModel:t=>{let n=M(t.message);n&&(r.prompt_tokens=(r.prompt_tokens??0)+(n.prompt_tokens??0),r.completion_tokens=(r.completion_tokens??0)+(n.completion_tokens??0),r.total_tokens=(r.total_tokens??0)+(n.total_tokens??0),n.reasoning_tokens&&(r.reasoning_tokens=(r.reasoning_tokens??0)+n.reasoning_tokens),i++,e({type:`usage`,round:i,usage:n,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens,...r.reasoning_tokens?{reasoning_tokens:r.reasoning_tokens}:{}}}))},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function Wy(e,t,n,r,i){if(!n)return i&&console.warn(`[page-agent-sdk][focus] capabilities.focus 关闭,${t} 忽略`),{ok:!1,error:`capabilities.focus 关闭`};if(!e||!e.path)return i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path 必填且非空`),{ok:!1,error:`path 必填且非空`};let a=r();return a?xf(a,e.path)?{ok:!0}:(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:path "${e.path}" 不在 schema 内(getSchemaAtPath 返 null;数组组件须 z.array(...) 包裹,裸 discriminatedUnion/Union 会降级)`),{ok:!1,error:`path "${e.path}" 不在 schema 内`}):(i&&console.warn(`[page-agent-sdk][focus] ${t} 拒绝:当前无主数据 schema`),{ok:!1,error:`当前无主数据 schema,无法聚焦`})}function Gy(e,n){let i={prompt_tokens:0,completion_tokens:0,total_tokens:0},a=ov(()=>xt,()=>e.conflictPolicy??`ask`),o=kn(0),s=Fv(e.storage);e.debug&&s&&s.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let{modelCaps:c,summaryLlmInvoke:l,titleLlmInvoke:u,compressDecisionInvoke:d}=av(e),f=c;if(e.debug&&console.log(`[page-agent-sdk][modelCaps]`,f),f.contextWindow<2e5)throw Error(`[page-agent-sdk] 模型上下文窗口 ${f.contextWindow} 小于最小支持 ${y}(需 ≥200K 窗口模型,如 GLM-5.2/Claude/Kimi/Qwen-1M/DeepSeek-v4)`);let p=Hv(e,f.contextWindow),m=p.enableLLMSummary!==!1,h=(e.contextOptions&&e.contextOptions.preserveLastToolResults)??Vv[e.contextPreset??`auto`],g=new Set(h),_=e.llm;e.debug&&!l&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let v=hn([]),x=Zh(e.vfs?.initialFiles,{persist:s?{save:e=>{qt({vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes,poolBytes:e.vfs?.poolBytes}),S=zd([],{maxPlanRevisions:e.maxPlanRevisions}),C=ap(),w=dp(e=>{G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`intent_guard`,preview:e}})}),T=pp(()=>{G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`resume_notice`}})}),E,D=e.approval?.timeoutMs,k=D!==void 0&&Number.isFinite(D)&&D>0?D:D!==void 0&&(!Number.isFinite(D)||D<0)?0:3e4,te=e=>{xt({type:`error`,message:`确认请求(${e.toolName})${Math.round(e.waitedMs/1e3)}s 无响应已自动拒绝 —— 当前路径无 UI 响应方;可传 approval.timeoutMs 调整(Infinity = 无限等)`,severity:`observable`,code:`APPROVAL_AUTO_REJECTED`,context:e})},A=lh(e=>{E=e,qt({planConfirmation:e}),G.agent?.debugLogs?.value?.push({timestamp:Date.now(),type:`middleware`,data:{stage:`plan_confirmation`,summary:e.summary,choice:e.choice}})},{timeoutMs:k,onAutoReject:te}),j=Vp({getSchema:()=>ge()?.schema,getBind:()=>ge()?.bind,onChange:e=>xt({type:`focus_change`,focuses:e})}),M=Zm(),ne=Qm(e.memory||``);typeof e.memory==`function`&&ne.refresh();let N={current:null},P=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,F=!(e.subagents??[]).some(e=>e._codeAsset)&&Rv(e.capabilities).subagent,re=e.subagents;F&&P?.schema&&Nf(P.schema).length&&(re=[...e.subagents??[],W_()],console.info(`[page-agent-sdk] 检测到 schema 含代码组件数组(如 components[].code),已自动装配 HTML 代码子 agent(委派编排 + vfs 工作副本 + 格式校验 + 增量 commit)。需定制(codeField/formatCheck/craftNotes 等)请显式传 createHtmlSubagent(...)`));let ie=(re??[]).filter(e=>!!e._codeAsset),ae=new Set;for(let e of ie){if(e._codeAsset.writablePaths.length)continue;let t=Nf(P?.schema,e._codeAsset.codeField);t.length?(e._codeAsset.writablePaths=t,Array.isArray(e.writablePaths)&&(e.writablePaths=t),e._rebuildCodeAssetPaths?.(t[0]),console.info(`[page-agent-sdk][createHtmlSubagent] 未传 writablePaths,已从 schema 推断: [${t.map(e=>`'${e}'`).join(`, `)}]`)):(console.warn(`[page-agent-sdk][createHtmlSubagent] 未能从 schema 推断 writablePaths(开放 schema(z.any()/z.record())/嵌套容器(如 sections[].children[])/点路径 codeField(如 props.html_code)不支持自动推断),已跳过该 html 子 agent(整体不受影响);如确需代码资产机制(vfs + 格式校验 + 增量 commit),请显式传 writablePaths(代码组件 data 区,如 ['components'])`),ae.add(e))}let I=ae.size?ie.filter(e=>!ae.has(e)):ie,oe=ae.size?(re??[]).filter(e=>!ae.has(e)):re,se=I.length>0,L=I.flatMap(e=>e._codeAsset.writablePaths),R=I.flatMap(e=>e._codeAsset.writablePaths.map(t=>`${t}.${e._codeAsset.codeField}`)),z=e.checkpoint,ce=z!==void 0&&z!==!1,B=ce?gh({getData:()=>ge()?.bind,consumeDataDirty:()=>me?.consumeDataDirty?.()??!0,slotPaths:P?[``]:[],vfsStore:x,todosMw:S,getTodos:()=>N.current?.getState?.()?.todos??[],messages:v,maxCheckpoints:z&&typeof z==`object`?z.maxCheckpoints:void 0}):null,V=!z||typeof z!=`object`||z.auto!==!1,H=Rv(e.capabilities),le=H.dataOps,U=H.draftWrite,ue=H.automation,de=qh({...e,locale:e.i18n?.locale});if(se){let e=I.map(e=>e._codeAsset.orchestratorPrompt).filter(Boolean).join(`
|
|
202
202
|
|
|
203
203
|
`);e&&(de+=`
|
|
204
204
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "page-agent-sdk",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.1",
|
|
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",
|