page-agent-sdk 2.12.2 → 2.13.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.
@@ -14724,15 +14724,25 @@ function $g(e, n) {
14724
14724
  //#endregion
14725
14725
  //#region src/core/harness/memory.ts
14726
14726
  function e_(e = "") {
14727
- let t = e;
14727
+ let t = e, n = typeof e == "string" ? e : void 0;
14728
+ async function r() {
14729
+ if (typeof t == "string") return n = t, t;
14730
+ try {
14731
+ n = await t();
14732
+ } catch (e) {
14733
+ console.warn("[page-agent-sdk][memory] 异步求值失败,降级为空:", e), n = "";
14734
+ }
14735
+ return n;
14736
+ }
14728
14737
  return {
14729
14738
  name: "memory",
14730
- beforeAgent: () => ({ memory: t }),
14739
+ beforeAgent: async () => (n === void 0 && await r(), { memory: n ?? "" }),
14731
14740
  augmentPrompt: (e) => e.memory ? `## 持久指令(Memory)\n${e.memory}` : void 0,
14732
14741
  reset: (e) => {
14733
- t = e;
14742
+ t = e, n = typeof e == "string" ? e : void 0;
14734
14743
  },
14735
- get: () => t
14744
+ get: () => n ?? "",
14745
+ refresh: async () => typeof t == "function" ? r() : n ?? ""
14736
14746
  };
14737
14747
  }
14738
14748
  //#endregion
@@ -17726,7 +17736,9 @@ function ib(e, i) {
17726
17736
  z.sessionId && d && d.save(i, z.sessionId, { vfs: e });
17727
17737
  } } : void 0,
17728
17738
  maxBytes: e.vfs?.maxBytes
17729
- }), v = Kg(), y = e_(e.memory || ""), b = { current: null }, x = e.data ? {
17739
+ }), v = Kg(), y = e_(e.memory || "");
17740
+ typeof e.memory == "function" && y.refresh();
17741
+ let b = { current: null }, x = e.data ? {
17730
17742
  ...e.data,
17731
17743
  description: e.data.description ?? "主数据对象"
17732
17744
  } : void 0, S = e.checkpoint, C = S !== void 0 && S !== !1, w = C ? __({
@@ -17983,7 +17995,7 @@ function ib(e, i) {
17983
17995
  type: "session_restored",
17984
17996
  sessionId: n,
17985
17997
  rounds: r.messages?.length ?? 0
17986
- })), e.memory && d.save(i, z.sessionId, { memory: e.memory }), n;
17998
+ })), e.memory && d.save(i, z.sessionId, { memory: y.get() || (typeof e.memory == "string" ? e.memory : "") }), n;
17987
17999
  },
17988
18000
  stream: (e, t, n) => {
17989
18001
  if (!z.agent) throw Error("page-agent-sdk: agent 尚未初始化完成,请先 await mount()");
@@ -18031,7 +18043,10 @@ function ib(e, i) {
18031
18043
  typeof r.bindTools != "function" && e.debug && console.warn("[page-agent-sdk][setLlm] 新模型不支持 bindTools(tool calling 会失效)"), m = t, z.agent && z.agent.setLlm(r), z.infoTick.value++;
18032
18044
  },
18033
18045
  setMemory(e) {
18034
- y.reset(e), z.infoTick.value++;
18046
+ y.reset(e), typeof e == "function" && y.refresh(), z.infoTick.value++;
18047
+ },
18048
+ refreshMemory() {
18049
+ return y.refresh();
18035
18050
  },
18036
18051
  setSubagents(t) {
18037
18052
  if (!_e) {
@@ -18123,7 +18138,7 @@ function ib(e, i) {
18123
18138
  }), e.debug && console.log("[page-agent-sdk][restore] 恢复会话", z.sessionId, `${t.messages?.length ?? 0} msgs`)) : e.debug && console.log("[page-agent-sdk][restore] 会话 meta 存在但快照为空", z.sessionId);
18124
18139
  } else z.sessionId = await d.createSession(i, t.title), e.debug && console.log("[page-agent-sdk][restore] 新建会话(无历史)", z.sessionId);
18125
18140
  } else z.sessionId = await d.createSession(i, t.title);
18126
- e.memory && d.save(i, z.sessionId, { memory: e.memory });
18141
+ e.memory && d.save(i, z.sessionId, { memory: y.get() || (typeof e.memory == "string" ? e.memory : "") });
18127
18142
  }
18128
18143
  async function Ie() {
18129
18144
  await Me();
@@ -18360,6 +18375,7 @@ function ab(e) {
18360
18375
  removeTool: (e) => i.removeTool(e),
18361
18376
  setLlm: (e) => i.setLlm(e),
18362
18377
  setMemory: (e) => i.setMemory(e),
18378
+ refreshMemory: () => i.refreshMemory(),
18363
18379
  setSubagents: (e) => i.setSubagents(e),
18364
18380
  addSubagent: (e) => i.addSubagent(e),
18365
18381
  removeSubagent: (e) => i.removeSubagent(e)
@@ -18378,4 +18394,4 @@ function ob(e) {
18378
18394
  });
18379
18395
  }
18380
18396
  //#endregion
18381
- export { lv as CONTEXT_PRESETS, yg as ChatDialog, nf as CodePreview, s_ as HUMAN_CONFIRM_TOOL_NAME, af as MessageContent, sh as SkillPanel, K_ as connectMcp, wl as copyText, Wg as createAgent, o_ as createApprovalMiddleware, ab as createChatSdk, __ as createCheckpointManager, v_ as createCheckpointMiddleware, ly as createDataOps, u_ as createHumanConfirmMiddleware, l_ as createHumanConfirmTool, Ly as createMemoryBackend, v as createProxyLlm, Vy as createSessionStore, Ky as createSkillStore, E_ as createSubagentMiddleware, k_ as createSubagentsMiddleware, gy as createUsageHintsMiddleware, A_ as createVerifyMiddleware, hv as createVfs, zy as createWebStorageBackend, I_ as createWriteBackCheck, py as defineDataToolset, qg as defineSkill, ob as defineTool, zg as detectGarbledToolCall, Dg as estimateTokens, cv as extractSchemaHint, U_ as extractText, dy as fetchDocTools, fy as fetchTools, cy as filterByToolMode, dv as formatZodIssues, ky as isQuotaError, Mv as jpEval, pv as jsonParseError, kg as offloadPassThroughChars, Og as offloadThresholdChars, ov as presets, uv as resolveContextOptions, Eg as resolveModelCaps, Lv as runSandboxedScript, Pv as searchJson, my as selectBuiltinTools, sv as systemPromptHelpers, $ as toolError, Cl as useChat, e as z, fv as zodError };
18397
+ export { lv as CONTEXT_PRESETS, yg as ChatDialog, nf as CodePreview, s_ as HUMAN_CONFIRM_TOOL_NAME, af as MessageContent, sh as SkillPanel, K_ as connectMcp, wl as copyText, Wg as createAgent, o_ as createApprovalMiddleware, ab as createChatSdk, __ as createCheckpointManager, v_ as createCheckpointMiddleware, ly as createDataOps, u_ as createHumanConfirmMiddleware, l_ as createHumanConfirmTool, Ly as createMemoryBackend, e_ as createMemoryMiddleware, v as createProxyLlm, Vy as createSessionStore, Ky as createSkillStore, E_ as createSubagentMiddleware, k_ as createSubagentsMiddleware, gy as createUsageHintsMiddleware, A_ as createVerifyMiddleware, hv as createVfs, zy as createWebStorageBackend, I_ as createWriteBackCheck, py as defineDataToolset, qg as defineSkill, ob as defineTool, zg as detectGarbledToolCall, Dg as estimateTokens, cv as extractSchemaHint, U_ as extractText, dy as fetchDocTools, fy as fetchTools, cy as filterByToolMode, dv as formatZodIssues, ky as isQuotaError, Mv as jpEval, pv as jsonParseError, kg as offloadPassThroughChars, Og as offloadThresholdChars, ov as presets, uv as resolveContextOptions, Eg as resolveModelCaps, Lv as runSandboxedScript, Pv as searchJson, my as selectBuiltinTools, sv as systemPromptHelpers, $ as toolError, Cl as useChat, e as z, fv as zodError };
@@ -107,7 +107,7 @@ app.mount('#app');
107
107
  `)}function Ug(e=[]){let n=e.map(e=>({...e})),i=0;return{name:`todos`,tools:[(0,r.tool)(async({todos:e})=>(n=e,`已更新任务清单:${e.length} 项\n${e.map((e,t)=>`${t+1}. [${e.status}] ${e.content}`).join(`
108
108
  `)}`),{name:`write_todos`,description:`更新(整表替换)任务清单。用于多步任务的拆解与进度跟踪。每次传入完整的 todos 数组(状态 pending/in_progress/completed),不要增量 patch。`,schema:t.z.object({todos:t.z.array(t.z.object({content:t.z.string().describe(`任务描述`),status:t.z.enum([`pending`,`in_progress`,`completed`])})).describe(`完整的任务清单(整表替换)`)})})],beforeAgent:()=>({todos:n}),beforeModel:()=>(i=0,{todos:n}),augmentPrompt:()=>Hg(n),wrapToolCall:async(e,t)=>e.name===`write_todos`&&(i++,i>1)?{content:`错误:write_todos 不应在一轮中并行多次调用(整表替换语义)。请串行使用。`,status:`error`}:t(e),reset:e=>{n=e.map(e=>({...e}))}}}function Wg(e){return e}var Gg=/^https?:\/\//i;function Kg(e){return Gg.test(e)||e.startsWith(`//`)?`http`:`vfs`}function qg(e){return e.replace(/^vfs:\/\//,``).replace(/^\/+/,``).replace(/\/+/g,`/`)}async function Jg(e,t){if(Kg(e)===`http`)try{let t=await fetch(e);return t.ok?{ok:!0,content:await t.text()}:{ok:!1,error:`HTTP ${t.status} ${t.statusText}(${e})`}}catch(e){let t=e?.message||String(e);return/Failed to fetch|NetworkError|CORS|blocked/i.test(t)?{ok:!1,error:`CORS 跨域或网络错误(${t});浏览器仅能 GET 同源或已配 CORS 的资源`}:{ok:!1,error:t}}if(!t)return{ok:!1,error:`skill 文档 ${e} 是 vfs 路径,但 vfs 未启用`};let n=t(qg(e));return n==null?{ok:!1,error:`未找到 vfs 文档 ${e}(可用 vfs_ls 查看)`}:{ok:!0,content:n}}function Yg(e){if(e.length)return[`## 可用 Skills(渐进式披露)`,e.map(e=>`- ${e.name}: ${e.description}`).join(`
109
109
  `),`当某 skill 适用时,先调用 load_skill(name) 加载其完整指令,再按指令执行。不要凭记忆猜测 skill 内容。`].join(`
110
- `)}function Xg(e,n){let i=[...e],a=new Map(i.map(e=>[e.name,e])),o=new Set,s=new Map,c={set(e){i=[...e],a=new Map(i.map(e=>[e.name,e])),s.clear(),o.clear()},get(){return i},invalidateCache(e){e?s.delete(e):s.clear()},async getContent(e){let t=a.get(e);if(!t)return null;let r=s.get(e);if(r!=null)return r;if(t.doc){let e=await Jg(t.doc,n?.readVfs);if(!e.ok)return null;r=e.content}else if(t.getContent)r=await t.getContent();else return null;return s.set(e,r),r}},l={name:`skills`,tools:[(0,r.tool)(async({name:e})=>{let t=a.get(e);if(!t)return`未找到 skill "${e}"。`;if(o.has(e))return`skill "${e}" 已在本轮加载,无需重复。`;let r=s.get(e);if(r==null){if(t.doc){let i=await Jg(t.doc,n?.readVfs);if(!i.ok)return`加载 skill "${e}" 文档失败:${i.error}`;r=i.content}else if(t.getContent)r=await t.getContent();else return`skill "${e}" 未配置内容(doc 或 getContent 任选其一)。`;s.set(e,r)}return o.add(e),`skill "${e}" 完整指令:\n\n${r}`},{name:`load_skill`,description:`加载某个 skill 的完整指令到当前上下文。先从 system prompt 的 Skills 索引选合适的 skill,再调用此工具。`,schema:t.z.object({name:t.z.string().describe(`skill 名`)})})],beforeAgent:()=>(o.clear(),{skillsMetadata:i.map(e=>({name:e.name,description:e.description})),skillsLoaded:[]}),augmentPrompt:()=>Yg(i),afterModel:()=>({skillsLoaded:[...o]})};return Object.defineProperty(l,"controller",{value:c,enumerable:!1,configurable:!1,writable:!1}),l}function Zg(e=``){let t=e;return{name:`memory`,beforeAgent:()=>({memory:t}),augmentPrompt:e=>e.memory?`## 持久指令(Memory)\n${e.memory}`:void 0,reset:e=>{t=e},get:()=>t}}var Qg=new Set([`set_data`,`edit_data`,`delete_data`,`write`,`vfs_write`,`vfs_edit`]),$g=new Set([`get_data`,`describe_data`,`read`,`query_data`,`search_data`,`vfs_read`,`vfs_ls`,`vfs_glob`,`vfs_grep`]);function e_(e){let t=``;for(let n=0;n<e.length;n++){let r=e[n];r===`*`?e[n+1]===`*`?(t+=`.*`,n++):t+=`[^/]*`:".+?^${}()|[]\\".includes(r)?t+=`\\`+r:t+=r}return RegExp(`^`+t+`$`)}function t_(e,t,n){for(let r of e)if(r.operations.includes(t)&&r.scopes.some(e=>e_(e).test(n)))return r.mode;return`allow`}function n_(e){return{name:`permissions`,wrapToolCall:async(t,n)=>{let r=Qg.has(t.name)?`write`:$g.has(t.name)?`read`:null,i=t.args?.jsonPath||t.args?.path||``;return r&&i&&t_(e,r,i)===`deny`?{content:`权限拒绝:${r} 操作 "${i}" 被 permissions 规则禁止。`,status:`error`}:n(t)}}}function r_(e={}){let t=(t,n)=>e.confirm?!!e.confirm(t,n):e.tools===void 0||e.tools.includes(t);return{name:`approval`,wrapToolCall:async(n,r)=>t(n.name,n.args)?new Promise(t=>{let i=!1,a=[],o=e=>{i||(i=!0,a.forEach(e=>e()),e===!1?t({content:`用户拒绝了 ${n.name} 调用${n.args?.path?`(path=${n.args.path})`:``}。请改用只读工具、调整路径或换方案后再试。`,status:`error`}):r(n).then(t,e=>t({content:`工具执行失败:${e?.message??e}`,status:`error`})))};if(n.signal){if(n.signal.aborted)return o(!1);let e=()=>o(!1);n.signal.addEventListener(`abort`,e,{once:!0}),a.push(()=>n.signal?.removeEventListener(`abort`,e))}if(e.timeoutMs&&e.timeoutMs>0){let t=setTimeout(()=>o(!1),e.timeoutMs);a.push(()=>clearTimeout(t))}n.emit?.({type:`approval_request`,toolName:n.name,args:n.args,resolve:o})}):r(n)}}var i_=`request_human_confirmation`,a_=t.z.object({question:t.z.string().describe(`要征询用户的问题/方案描述。清晰具体:说明当前情况、为什么需要确认、确认什么。`),options:t.z.array(t.z.string()).optional().describe(`可选方案列表(2-4 个)。用户从中选一个。不传则用户只回答允许/拒绝。`),recommendation:t.z.string().optional().describe(`你推荐的方案(优先在 options 中选一个)及推荐理由,帮用户快速决策。`),context:t.z.string().optional().describe(`补充上下文:已做了什么、约束、影响范围等,帮用户判断。`)});function o_(){return(0,r.tool)(async()=>`人工确认中间件未装载,无法征询用户。请直接向用户说明情况并等待回复。`,{name:i_,description:[`当遇到以下情况时,主动调用本工具征询用户确认后再继续(不要默默猜测后直接执行高风险动作):`,`1) 不确定用户意图、需求有歧义;`,`2) 存在多种可行方案且取舍影响较大;`,`3) 即将执行高风险或不可逆操作(删除、覆盖、批量改动、对外发布等);`,`4) 操作超出原始指令范围。`,`入参:question=问题/方案描述;options=可选方案列表(多方案时给);recommendation=你推荐的方案及理由。`,`用户选择后,据其回答继续;若用户拒绝,停止当前操作并询问如何调整。`].join(``),schema:a_})}function s_(){return{name:`humanConfirm`,wrapToolCall:async(e,t)=>e.name===`request_human_confirmation`?new Promise(t=>{let n=!1,r=[],i=i=>{n||(n=!0,r.forEach(e=>e()),t(i===!1?{content:`用户拒绝了该方案。请停止当前操作,询问用户希望如何调整,不要擅自执行。`,status:`done`}:i===!0?{content:`用户同意了方案${e.args?.recommendation?`(${e.args.recommendation})`:``}。请继续执行。`,status:`done`}:{content:`用户选择了:${i}。请据此方案继续。`,status:`done`}))};if(e.signal){if(e.signal.aborted)return i(!1);let t=()=>i(!1);e.signal.addEventListener(`abort`,t,{once:!0}),r.push(()=>e.signal?.removeEventListener(`abort`,t))}e.emit?.({type:`approval_request`,toolName:e.name,args:e.args,resolve:i})}):t(e)}}function c_(e){if(typeof e!=`object`||!e)return e;if(typeof structuredClone==`function`)try{return structuredClone(e)}catch{}return JSON.parse(JSON.stringify(e))}function l_(e,t){let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r}function u_(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++)i[r[e]]??(i[r[e]]={}),i=i[r[e]];i[r[r.length-1]]=n}function d_(e,t){if(Array.isArray(e)){e.length=0,Array.isArray(t)&&e.push(...t);return}let n=t&&typeof t==`object`&&!Array.isArray(t)?t:{};for(let t of Object.keys(e))t in n||delete e[t];for(let t of Object.keys(n))e[t]=n[t]}function f_(e,t){let n=l_(window,e);typeof n==`object`&&n?d_(n,t):u_(window,e,t)}function p_(e){let t=e.slice();for(;t.length;){let e=t[t.length-1];if(e.role===`assistant`&&!e.content&&!e.steps?.length&&!e.reasoning)t.pop();else break}return t}function m_(e){let t=[],n=e.maxCheckpoints??5,r=1;return{save(i){let a=p_(e.messages),o={};if(e.getData)o[``]=c_(e.getData());else for(let t of e.slotPaths??[])o[t]=c_(l_(window,t));let s={id:r++,label:i,timestamp:Date.now(),messages:c_(a),windowVals:o,vfs:c_(e.vfsStore.files),todos:c_(e.getTodos()),messageCount:a.length};for(t.push(s);t.length>n;)t.shift();return s.id},list(){return t.map(e=>({id:e.id,label:e.label,timestamp:e.timestamp,messageCount:e.messageCount}))},canRestore(){return t.length>0},restore(n){let r=n==null?t[t.length-1]:t.find(e=>e.id===n);if(!r)return!1;if(e.messages.splice(0,e.messages.length,...c_(r.messages)),e.getData){let t=r.windowVals[``];if(t!==void 0){let n=e.getData();typeof n==`object`&&n&&d_(n,c_(t))}}else for(let[e,t]of Object.entries(r.windowVals))f_(e,c_(t));let i=e.vfsStore.files;for(let e of Object.keys(i))delete i[e];return Object.assign(i,c_(r.vfs)),e.todosMw.reset(c_(r.todos)),!0}}}function h_(e){let t=!1;return{name:`checkpoint`,beforeAgent:()=>{t=!1},beforeModel:()=>{t||(t=!0,e.save(`auto`))}}}function g_(e){return!!e&&typeof e==`object`&&typeof e.invoke==`function`&&typeof e.stream==`function`}var __=[`describe_data`,`get_data`,`read`,`query_data`,`search_data`,`fetch_document`],v_=1,y_=4,b_=6,x_=[`spawn_agent`,`spawn_agents`];async function S_(e,t,n,r,i){let a=t.depth??0,o=t.maxDepth??v_,s=new Set([...__,...t.allowedTools??[]]),c=[...t.allTools.filter(e=>s.has(e.name)&&!x_.includes(e.name)),...t.extraTools??[]],l=a+1<o?[C_({...t,depth:a+1})]:[],u=Vg({...g_(t.llm)?{llm:t.llm}:{apiKey:t.llm.apiKey,baseUrl:t.llm.baseUrl,model:e.model??t.llm.model,temperature:t.temperature??t.llm.temperature,maxTokens:t.maxTokens??t.llm.maxTokens},systemPrompt:e.role?.trim()||t.systemPrompt||`你是一个专注的子任务执行者。你只有只读工具(读主数据 / 抓文档),用它们完成给定任务,给出简洁结论,不要展开多余解释。`,tools:c,middleware:[...t.skills?.length?[Xg(t.skills)]:[],...l],maxToolRounds:t.maxToolRounds??b_,onLog:i,debug:t.debug});return t.debug&&console.log(`[subagent] 启动子 agent(depth=${a},工具 ${c.length} 个)`),u.stream([{role:`user`,content:e.prompt,timestamp:Date.now()}],e=>{r&&(e.type===`tool_call`||e.type===`tool_result`)&&r(e)},n)}function C_(e){let n=e.maxParallel??y_,i,a,o,s=(e,t)=>n=>{a&&a({type:`subagent`,taskId:e,label:t,kind:n.type,name:n.name,args:n.type===`tool_call`?n.args:void 0,result:n.type===`tool_result`?n.result:void 0,status:n.type===`tool_result`?n.status:void 0})};return{name:`subagent`,tools:[(0,r.tool)(async({prompt:t,role:n,tools:r,model:a})=>{let c=r?.length?{...e,allowedTools:r}:e,l=`sub-${Math.random().toString(36).slice(2,8)}`,u=n?.trim()||`子任务`;return await S_({prompt:t,role:n,model:a},c,i,s(l,u),e=>o?.({...e,source:`子:${u}`}))},{name:`spawn_agent`,description:`委派一个独立子 agent 执行子任务,返回其最终结论(过程隔离,不占主上下文)。用于:分治大任务、专项调研、独立验证。子 agent 默认只读(不改页面)。`,schema:t.z.object({prompt:t.z.string().describe(`子任务描述(子 agent 的唯一输入)`),role:t.z.string().optional().describe(`子 agent 身份(如"你是代码审查专家")`),tools:t.z.array(t.z.string()).optional().describe(`子 agent 可用工具名白名单(默认只读主数据 + fetch)`),model:t.z.string().optional().describe(`覆盖模型(默认同主)`)})}),(0,r.tool)(async({tasks:t})=>(await bg(t,n,async(t,n)=>{let r=`sub-${n}-${Math.random().toString(36).slice(2,6)}`,a=t.role?.trim()||`子任务${n+1}`;return S_(t,e,i,s(r,a),e=>o?.({...e,source:`子:${a}`}))},i)).map((e,t)=>`【子任务 ${t+1}】\n${e??`(未完成)`}`).join(`
110
+ `)}function Xg(e,n){let i=[...e],a=new Map(i.map(e=>[e.name,e])),o=new Set,s=new Map,c={set(e){i=[...e],a=new Map(i.map(e=>[e.name,e])),s.clear(),o.clear()},get(){return i},invalidateCache(e){e?s.delete(e):s.clear()},async getContent(e){let t=a.get(e);if(!t)return null;let r=s.get(e);if(r!=null)return r;if(t.doc){let e=await Jg(t.doc,n?.readVfs);if(!e.ok)return null;r=e.content}else if(t.getContent)r=await t.getContent();else return null;return s.set(e,r),r}},l={name:`skills`,tools:[(0,r.tool)(async({name:e})=>{let t=a.get(e);if(!t)return`未找到 skill "${e}"。`;if(o.has(e))return`skill "${e}" 已在本轮加载,无需重复。`;let r=s.get(e);if(r==null){if(t.doc){let i=await Jg(t.doc,n?.readVfs);if(!i.ok)return`加载 skill "${e}" 文档失败:${i.error}`;r=i.content}else if(t.getContent)r=await t.getContent();else return`skill "${e}" 未配置内容(doc 或 getContent 任选其一)。`;s.set(e,r)}return o.add(e),`skill "${e}" 完整指令:\n\n${r}`},{name:`load_skill`,description:`加载某个 skill 的完整指令到当前上下文。先从 system prompt 的 Skills 索引选合适的 skill,再调用此工具。`,schema:t.z.object({name:t.z.string().describe(`skill 名`)})})],beforeAgent:()=>(o.clear(),{skillsMetadata:i.map(e=>({name:e.name,description:e.description})),skillsLoaded:[]}),augmentPrompt:()=>Yg(i),afterModel:()=>({skillsLoaded:[...o]})};return Object.defineProperty(l,"controller",{value:c,enumerable:!1,configurable:!1,writable:!1}),l}function Zg(e=``){let t=e,n=typeof e==`string`?e:void 0;async function r(){if(typeof t==`string`)return n=t,t;try{n=await t()}catch(e){console.warn(`[page-agent-sdk][memory] 异步求值失败,降级为空:`,e),n=``}return n}return{name:`memory`,beforeAgent:async()=>(n===void 0&&await r(),{memory:n??``}),augmentPrompt:e=>e.memory?`## 持久指令(Memory)\n${e.memory}`:void 0,reset:e=>{t=e,n=typeof e==`string`?e:void 0},get:()=>n??``,refresh:async()=>typeof t==`function`?r():n??``}}var Qg=new Set([`set_data`,`edit_data`,`delete_data`,`write`,`vfs_write`,`vfs_edit`]),$g=new Set([`get_data`,`describe_data`,`read`,`query_data`,`search_data`,`vfs_read`,`vfs_ls`,`vfs_glob`,`vfs_grep`]);function e_(e){let t=``;for(let n=0;n<e.length;n++){let r=e[n];r===`*`?e[n+1]===`*`?(t+=`.*`,n++):t+=`[^/]*`:".+?^${}()|[]\\".includes(r)?t+=`\\`+r:t+=r}return RegExp(`^`+t+`$`)}function t_(e,t,n){for(let r of e)if(r.operations.includes(t)&&r.scopes.some(e=>e_(e).test(n)))return r.mode;return`allow`}function n_(e){return{name:`permissions`,wrapToolCall:async(t,n)=>{let r=Qg.has(t.name)?`write`:$g.has(t.name)?`read`:null,i=t.args?.jsonPath||t.args?.path||``;return r&&i&&t_(e,r,i)===`deny`?{content:`权限拒绝:${r} 操作 "${i}" 被 permissions 规则禁止。`,status:`error`}:n(t)}}}function r_(e={}){let t=(t,n)=>e.confirm?!!e.confirm(t,n):e.tools===void 0||e.tools.includes(t);return{name:`approval`,wrapToolCall:async(n,r)=>t(n.name,n.args)?new Promise(t=>{let i=!1,a=[],o=e=>{i||(i=!0,a.forEach(e=>e()),e===!1?t({content:`用户拒绝了 ${n.name} 调用${n.args?.path?`(path=${n.args.path})`:``}。请改用只读工具、调整路径或换方案后再试。`,status:`error`}):r(n).then(t,e=>t({content:`工具执行失败:${e?.message??e}`,status:`error`})))};if(n.signal){if(n.signal.aborted)return o(!1);let e=()=>o(!1);n.signal.addEventListener(`abort`,e,{once:!0}),a.push(()=>n.signal?.removeEventListener(`abort`,e))}if(e.timeoutMs&&e.timeoutMs>0){let t=setTimeout(()=>o(!1),e.timeoutMs);a.push(()=>clearTimeout(t))}n.emit?.({type:`approval_request`,toolName:n.name,args:n.args,resolve:o})}):r(n)}}var i_=`request_human_confirmation`,a_=t.z.object({question:t.z.string().describe(`要征询用户的问题/方案描述。清晰具体:说明当前情况、为什么需要确认、确认什么。`),options:t.z.array(t.z.string()).optional().describe(`可选方案列表(2-4 个)。用户从中选一个。不传则用户只回答允许/拒绝。`),recommendation:t.z.string().optional().describe(`你推荐的方案(优先在 options 中选一个)及推荐理由,帮用户快速决策。`),context:t.z.string().optional().describe(`补充上下文:已做了什么、约束、影响范围等,帮用户判断。`)});function o_(){return(0,r.tool)(async()=>`人工确认中间件未装载,无法征询用户。请直接向用户说明情况并等待回复。`,{name:i_,description:[`当遇到以下情况时,主动调用本工具征询用户确认后再继续(不要默默猜测后直接执行高风险动作):`,`1) 不确定用户意图、需求有歧义;`,`2) 存在多种可行方案且取舍影响较大;`,`3) 即将执行高风险或不可逆操作(删除、覆盖、批量改动、对外发布等);`,`4) 操作超出原始指令范围。`,`入参:question=问题/方案描述;options=可选方案列表(多方案时给);recommendation=你推荐的方案及理由。`,`用户选择后,据其回答继续;若用户拒绝,停止当前操作并询问如何调整。`].join(``),schema:a_})}function s_(){return{name:`humanConfirm`,wrapToolCall:async(e,t)=>e.name===`request_human_confirmation`?new Promise(t=>{let n=!1,r=[],i=i=>{n||(n=!0,r.forEach(e=>e()),t(i===!1?{content:`用户拒绝了该方案。请停止当前操作,询问用户希望如何调整,不要擅自执行。`,status:`done`}:i===!0?{content:`用户同意了方案${e.args?.recommendation?`(${e.args.recommendation})`:``}。请继续执行。`,status:`done`}:{content:`用户选择了:${i}。请据此方案继续。`,status:`done`}))};if(e.signal){if(e.signal.aborted)return i(!1);let t=()=>i(!1);e.signal.addEventListener(`abort`,t,{once:!0}),r.push(()=>e.signal?.removeEventListener(`abort`,t))}e.emit?.({type:`approval_request`,toolName:e.name,args:e.args,resolve:i})}):t(e)}}function c_(e){if(typeof e!=`object`||!e)return e;if(typeof structuredClone==`function`)try{return structuredClone(e)}catch{}return JSON.parse(JSON.stringify(e))}function l_(e,t){let n=t.split(`.`),r=e;for(let e of n){if(r==null)return;r=r[e]}return r}function u_(e,t,n){let r=t.split(`.`),i=e;for(let e=0;e<r.length-1;e++)i[r[e]]??(i[r[e]]={}),i=i[r[e]];i[r[r.length-1]]=n}function d_(e,t){if(Array.isArray(e)){e.length=0,Array.isArray(t)&&e.push(...t);return}let n=t&&typeof t==`object`&&!Array.isArray(t)?t:{};for(let t of Object.keys(e))t in n||delete e[t];for(let t of Object.keys(n))e[t]=n[t]}function f_(e,t){let n=l_(window,e);typeof n==`object`&&n?d_(n,t):u_(window,e,t)}function p_(e){let t=e.slice();for(;t.length;){let e=t[t.length-1];if(e.role===`assistant`&&!e.content&&!e.steps?.length&&!e.reasoning)t.pop();else break}return t}function m_(e){let t=[],n=e.maxCheckpoints??5,r=1;return{save(i){let a=p_(e.messages),o={};if(e.getData)o[``]=c_(e.getData());else for(let t of e.slotPaths??[])o[t]=c_(l_(window,t));let s={id:r++,label:i,timestamp:Date.now(),messages:c_(a),windowVals:o,vfs:c_(e.vfsStore.files),todos:c_(e.getTodos()),messageCount:a.length};for(t.push(s);t.length>n;)t.shift();return s.id},list(){return t.map(e=>({id:e.id,label:e.label,timestamp:e.timestamp,messageCount:e.messageCount}))},canRestore(){return t.length>0},restore(n){let r=n==null?t[t.length-1]:t.find(e=>e.id===n);if(!r)return!1;if(e.messages.splice(0,e.messages.length,...c_(r.messages)),e.getData){let t=r.windowVals[``];if(t!==void 0){let n=e.getData();typeof n==`object`&&n&&d_(n,c_(t))}}else for(let[e,t]of Object.entries(r.windowVals))f_(e,c_(t));let i=e.vfsStore.files;for(let e of Object.keys(i))delete i[e];return Object.assign(i,c_(r.vfs)),e.todosMw.reset(c_(r.todos)),!0}}}function h_(e){let t=!1;return{name:`checkpoint`,beforeAgent:()=>{t=!1},beforeModel:()=>{t||(t=!0,e.save(`auto`))}}}function g_(e){return!!e&&typeof e==`object`&&typeof e.invoke==`function`&&typeof e.stream==`function`}var __=[`describe_data`,`get_data`,`read`,`query_data`,`search_data`,`fetch_document`],v_=1,y_=4,b_=6,x_=[`spawn_agent`,`spawn_agents`];async function S_(e,t,n,r,i){let a=t.depth??0,o=t.maxDepth??v_,s=new Set([...__,...t.allowedTools??[]]),c=[...t.allTools.filter(e=>s.has(e.name)&&!x_.includes(e.name)),...t.extraTools??[]],l=a+1<o?[C_({...t,depth:a+1})]:[],u=Vg({...g_(t.llm)?{llm:t.llm}:{apiKey:t.llm.apiKey,baseUrl:t.llm.baseUrl,model:e.model??t.llm.model,temperature:t.temperature??t.llm.temperature,maxTokens:t.maxTokens??t.llm.maxTokens},systemPrompt:e.role?.trim()||t.systemPrompt||`你是一个专注的子任务执行者。你只有只读工具(读主数据 / 抓文档),用它们完成给定任务,给出简洁结论,不要展开多余解释。`,tools:c,middleware:[...t.skills?.length?[Xg(t.skills)]:[],...l],maxToolRounds:t.maxToolRounds??b_,onLog:i,debug:t.debug});return t.debug&&console.log(`[subagent] 启动子 agent(depth=${a},工具 ${c.length} 个)`),u.stream([{role:`user`,content:e.prompt,timestamp:Date.now()}],e=>{r&&(e.type===`tool_call`||e.type===`tool_result`)&&r(e)},n)}function C_(e){let n=e.maxParallel??y_,i,a,o,s=(e,t)=>n=>{a&&a({type:`subagent`,taskId:e,label:t,kind:n.type,name:n.name,args:n.type===`tool_call`?n.args:void 0,result:n.type===`tool_result`?n.result:void 0,status:n.type===`tool_result`?n.status:void 0})};return{name:`subagent`,tools:[(0,r.tool)(async({prompt:t,role:n,tools:r,model:a})=>{let c=r?.length?{...e,allowedTools:r}:e,l=`sub-${Math.random().toString(36).slice(2,8)}`,u=n?.trim()||`子任务`;return await S_({prompt:t,role:n,model:a},c,i,s(l,u),e=>o?.({...e,source:`子:${u}`}))},{name:`spawn_agent`,description:`委派一个独立子 agent 执行子任务,返回其最终结论(过程隔离,不占主上下文)。用于:分治大任务、专项调研、独立验证。子 agent 默认只读(不改页面)。`,schema:t.z.object({prompt:t.z.string().describe(`子任务描述(子 agent 的唯一输入)`),role:t.z.string().optional().describe(`子 agent 身份(如"你是代码审查专家")`),tools:t.z.array(t.z.string()).optional().describe(`子 agent 可用工具名白名单(默认只读主数据 + fetch)`),model:t.z.string().optional().describe(`覆盖模型(默认同主)`)})}),(0,r.tool)(async({tasks:t})=>(await bg(t,n,async(t,n)=>{let r=`sub-${n}-${Math.random().toString(36).slice(2,6)}`,a=t.role?.trim()||`子任务${n+1}`;return S_(t,e,i,s(r,a),e=>o?.({...e,source:`子:${a}`}))},i)).map((e,t)=>`【子任务 ${t+1}】\n${e??`(未完成)`}`).join(`
111
111
 
112
112
  `),{name:`spawn_agents`,description:`并行委派多个独立子 agent,聚合各自结论(子 agent 间互不通信,由你汇总)。适合:多路调研、多视角审查、批量处理。`,schema:t.z.object({tasks:t.z.array(t.z.object({prompt:t.z.string().describe(`子任务描述`),role:t.z.string().optional()})).min(1).max(8).describe(`子任务列表(最多 8 个)`)})})],wrapToolCall:async(e,t)=>(e.signal&&(i=e.signal),e.emit&&(a=e.emit),e.logSink&&(o=e.logSink),t(e))}}var w_=/^[a-zA-Z_][a-zA-Z0-9_]*$/;function T_(e,t){let n=e.tools??[];return{llm:e.llm??t.llm,allTools:t.allTools,systemPrompt:e.systemPrompt,temperature:e.temperature,maxTokens:e.maxTokens,skills:e.skills,extraTools:n.length?n:void 0,maxToolRounds:e.maxToolRounds,debug:t.debug}}function E_(e,n){let i,a,o,s=(e,t)=>n=>{a&&a({type:`subagent`,taskId:e,label:t,kind:n.type,name:n.name,args:n.type===`tool_call`?n.args:void 0,result:n.type===`tool_result`?n.result:void 0,status:n.type===`tool_result`?n.status:void 0})},c=[],l=[],u;function d(e){let a=new Set,c=[],l=[];for(let u of e){if(!w_.test(u.id)){console.warn(`[subagents] id "${u.id}" 非合法工具名(须 [a-zA-Z_][a-zA-Z0-9_]*),已跳过`);continue}let e=`use_${u.id}`;if(a.has(e)){console.warn(`[subagents] id "${u.id}" 重复,已跳过`);continue}a.add(e),c.push(u),l.push((0,r.tool)(async({task:e})=>{let t=T_(u,n);return S_({prompt:e},t,i,s(`use_${u.id}`,u.id),e=>o?.({...e,source:`子:${u.id}`}))},{name:`use_${u.id}`,description:`委派给「${u.description}」子 agent 执行任务,返回其结论(过程隔离,不占主上下文)。`,schema:t.z.object({task:t.z.string().describe(`委派给该子 agent 的任务描述`)})}))}return{valid:c,tools:l}}let f=d(e);c=f.valid,l=f.tools;let p={set(e){let t=d(e);c=t.valid,l=t.tools,u?.()},add(e){if(c.some(t=>t.id===e.id)){console.warn(`[subagents] add: id "${e.id}" 已存在,已跳过`);return}let t=d([...c,e]);c=t.valid,l=t.tools,u?.()},remove(e){if(c.findIndex(t=>t.id===e)<0)return!1;let t=d(c.filter(t=>t.id!==e));return c=t.valid,l=t.tools,u?.(),!0},get:()=>[...c]},m={name:`subagents`,get tools(){return l},augmentPrompt:()=>c.length?[`## 可用子 agent(预声明,经专属工具委派)`,...c.map(e=>`- use_${e.id}: ${e.description}`),`需要某子 agent 时,直接调用对应的 use_<id>({ task }) 委派,任务描述要清晰。`].join(`
113
113
  `):void 0,wrapToolCall:async(e,t)=>(e.signal&&(i=e.signal),e.emit&&(a=e.emit),e.logSink&&(o=e.logSink),t(e))};return Object.defineProperty(m,"controller",{value:p,enumerable:!1}),Object.defineProperty(m,"setReconfigureHook",{value:e=>{u=e},enumerable:!1}),m}function D_(e){return{name:`verify`,async beforeReturn({messages:t,state:n,log:r}){let i=await e.check({messages:t,state:n});if(!i.ok)return i.feedback??`结果未通过验证,请复查。`;if(e.adversarial){r?.(`middleware`,{stage:`adversarial_start`,model:F_(e.adversarial.llm),tools:(e.adversarial.tools??[]).length});let n=await z_(t,e.adversarial.llm,r,e.adversarial.tools);if(r?.(`middleware`,{stage:`adversarial_done`,clean:n===null,feedback:n}),n)return n}return null}}}var O_=new Set([`set_data`,`edit_data`,`delete_data`,`write`]),k_=/校验失败|SCHEMA_INVALID|未注册|不存在|仅支持|必须是|NOT_OBJECT|PATH_UNSAFE|VERSION_CONFLICT|WRITE_INTERCEPT/;function A_(e){let t=new Map;for(let n of e){let e=n?.tool_calls;if(Array.isArray(e)){for(let n of e)if(O_.has(n.name)){let e=typeof n?.args?.jsonPath==`string`?n.args.jsonPath:``;t.set(e,{path:e,op:n.name,callId:n.id})}}}return[...t.values()]}function j_(e){let t=new Map;for(let n of e){let e=n?.tool_call_id,r=n?.content;typeof e==`string`&&typeof r==`string`&&t.set(e,r)}return t}function M_(e,t){if(t===``)return e;if(e==null)return;let n=e;for(let e of t.split(`.`)){if(n==null)return;n=n[e]}return n}function N_(e={}){let t=typeof e.root==`function`?e.root:e.root===void 0?()=>e.window??globalThis.window:()=>e.root,n=typeof e.schemas==`function`?e.schemas:()=>e.schemas??{};return async({messages:e})=>{let r=A_(e);if(!r.length)return{ok:!0};let i=j_(e),a=n()[``],o=t(),s=[];for(let{path:e,op:t,callId:n}of r){let r=n?i.get(n):void 0;if(r&&k_.test(r))continue;let c=M_(o,e);if(t===`delete_data`)c!==void 0&&s.push(`${e} 删除后读回仍有值,疑似未生效`);else if(c==null)s.push(`写入 ${e} 后读回为空,疑似未生效`);else if(a){let t=a.safeParse(o);t.success||s.push(`${e} 读回值不符合 schema:${t.error.issues?.[0]?.message??`校验失败`}`)}}return s.length?{ok:!1,feedback:s.join(`;
@@ -149,10 +149,10 @@ self.onmessage = async (e) => {
149
149
  `):void 0}}}function my(){try{if(typeof crypto<`u`&&typeof crypto.randomUUID==`function`)return crypto.randomUUID()}catch{}return Date.now().toString(36)+Math.random().toString(36).slice(2,10)}var hy=`chat-sdk`,gy=50*1024*1024,_y=4*1024*1024,vy=10*1024*1024,yy=.9,by=500,xy=300,Sy=`__meta__`,Cy=`v:1`,wy=[`messages`,`vfs`,`todos`,`memory`];function Ty(e){return e===`local`||e===`session`?_y:gy}function Ey(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.name===`QuotaExceededError`||t.name===`NS_ERROR_DOM_QUOTA_REACHED`||t.code===22||t.code===1014}function Dy(e,t,n,r){return[Cy,e,t,n,r].join(`::`)}function Oy(e,t,n){return[Cy,e,t,n].join(`::`)+`::`}function ky(e,t){return[Cy,e,t].join(`::`)+`::`}function Ay(e){return[Cy,e].join(`::`)+`::`}var jy=null;function My(e){jy||=new TextEncoder;try{return jy.encode(JSON.stringify(e)).length}catch{return 0}}function Ny(e,t,n){let r=e.reduce((e,t)=>e+t.bytes,0);if(r<=t)return[];let i=t*n,a=[...e].sort((e,t)=>e.lastAccessed-t.lastAccessed),o=[];for(let e of a){if(r<=i)break;o.push(e),r-=e.bytes}return o}function Py(){let e=new Map;return{async get(t){return e.has(t)?e.get(t):void 0},async set(t,n){e.set(t,n)},async del(t){e.delete(t)},async scan(t,n){for(let r of Array.from(e.keys()).sort())if(r.startsWith(t)&&n(r,e.get(r))===!1)return},async clearPrefix(t){for(let n of Array.from(e.keys()))n.startsWith(t)&&e.delete(n)}}}function Fy(e){return new Promise((t,n)=>{if(typeof indexedDB>`u`){n(Error(`indexedDB 不可用`));return}let r=indexedDB.open(e,1);r.onupgradeneeded=()=>{let e=r.result;e.objectStoreNames.contains(`kv`)||e.createObjectStore(`kv`)},r.onblocked=()=>n(Error(`indexedDB 升级被阻塞,请关闭其他标签页后重试`)),r.onsuccess=()=>{let e=r.result;e.onversionchange=()=>{e.close()},t({get(t){return new Promise((n,r)=>{let i=e.transaction(`kv`,`readonly`).objectStore(`kv`).get(t);i.onsuccess=()=>n(i.result),i.onerror=()=>r(i.error)})},set(t,n){return new Promise((r,i)=>{let a=e.transaction(`kv`,`readwrite`);a.objectStore(`kv`).put(n,t),a.oncomplete=()=>r(),a.onerror=()=>i(a.error),a.onabort=()=>i(a.error)})},del(t){return new Promise((n,r)=>{let i=e.transaction(`kv`,`readwrite`);i.objectStore(`kv`).delete(t),i.oncomplete=()=>n(),i.onerror=()=>r(i.error),i.onabort=()=>r(i.error)})},scan(t,n){return new Promise((r,i)=>{let a=!1,o=e.transaction(`kv`,`readonly`),s=IDBKeyRange.bound(t,t+`￿`),c=o.objectStore(`kv`).openCursor(s);c.onsuccess=()=>{let e=c.result;if(!e||a)return;let r=e.key;if(r.startsWith(t)&&n(r,e.value)===!1){a=!0;return}e.continue()},c.onerror=()=>i(c.error),o.oncomplete=()=>r(),o.onerror=()=>i(o.error),o.onabort=()=>i(o.error)})},clearPrefix(t){return new Promise((n,r)=>{let i=e.transaction(`kv`,`readwrite`),a=IDBKeyRange.bound(t,t+`￿`),o=i.objectStore(`kv`).openCursor(a);o.onsuccess=()=>{let e=o.result;e&&(e.key.startsWith(t)&&e.delete(),e.continue())},o.onerror=()=>r(o.error),i.oncomplete=()=>n(),i.onerror=()=>r(i.error),i.onabort=()=>r(i.error)})}})},r.onerror=()=>n(r.error)})}function Iy(e){return{async get(t){let n=e.getItem(t);return n==null?void 0:JSON.parse(n)},async set(t,n){e.setItem(t,JSON.stringify(n))},async del(t){e.removeItem(t)},async scan(t,n){let r=[];for(let n=0;n<e.length;n++){let i=e.key(n);i&&i.startsWith(t)&&r.push(i)}r.sort();for(let t of r){let r=e.getItem(t);if(r!=null&&n(t,JSON.parse(r))===!1)return}},async clearPrefix(t){let n=[];for(let r=0;r<e.length;r++){let i=e.key(r);i&&i.startsWith(t)&&n.push(i)}for(let t of n)e.removeItem(t)}}}function Ly(e,t,n){let r=(e.get(t)??Promise.resolve()).then(n,n);return e.set(t,r.then(()=>void 0,()=>void 0)),r}function Ry(e={}){let t=e.dbName??hy,n=e.backend??`indexed`,r=e.maxBytes??Ty(n),i=e.maxBytesPerSession??vy,a=e.evictionWatermark??yy,o=e.debounceMs??by,s=new Set;function c(e){for(let t of s)try{t(e)}catch{}}let l,u=!1,d,f=new Promise(e=>{d=e});(async()=>{try{if(n===`indexed`){if(typeof indexedDB>`u`)throw Error(`indexedDB 不可用`);l=await Fy(t),d(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);l=Iy(sessionStorage),d(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);l=Iy(localStorage),d(!0)}else l=Py(),d(!1)}catch(e){l=Py();let t=e instanceof Error?e.message:String(e);d(!1),Promise.resolve().then(()=>c({type:`degraded`,reason:t}))}})();let p=new Map,m=new Map,h=new Map;function g(e,n,r,a){let o=Dy(t,r,a,Sy);return Ly(h,o,async()=>{let t=async()=>{let t=await l.get(o),s=await l.get(e),u=s==null?0:My(s),d=My(n),f=(t?.bytes??0)+(d-u);if(f>i){c({type:`quota`,sessionBytes:f,limit:i});return}await l.set(e,n);let p=Date.now(),m=t??{agentId:r,sessionId:a,createdAt:p,lastAccessed:p,bytes:0};m.bytes+=d-u,m.lastAccessed=p,await l.set(o,m),y()};try{await t()}catch(e){if(Ey(e)&&!u){u=!0;try{await b()}catch{}l=Py(),Promise.resolve().then(()=>c({type:`degraded`,reason:`存储配额超限(QuotaExceededError),已淘汰最旧会话并降级内存`}));try{await t()}catch{}}}})}function _(e,n,r,i){let a=Dy(t,e,n,r),s=p.get(a);s&&s.resolve();let c=m.get(a);return c&&clearTimeout(c),new Promise(t=>{p.set(a,{value:i,agentId:e,sessionId:n,kind:r,resolve:t});let s=setTimeout(()=>{m.delete(a);let e=p.get(a);if(p.delete(a),!e){t();return}g(a,e.value,e.agentId,e.sessionId).then(t,t)},o);m.set(a,s)})}let v=null;function y(){v||=setTimeout(()=>{v=null,b()},xy)}async function b(){let e=[];await l.scan(Ay(t),(t,n)=>{t.endsWith(`::__meta__`)&&e.push(n)});let n=Ny(e,r,a);for(let e of n)await l.clearPrefix(Oy(t,e.agentId,e.sessionId)),c({type:`evicted`,agentId:e.agentId,sessionId:e.sessionId,bytes:e.bytes})}return{ready:f,async listSessions(e){let n=[];return await l.scan(ky(t,e),(e,t)=>{e.endsWith(`::__meta__`)&&n.push(t)}),n.sort((e,t)=>t.lastAccessed-e.lastAccessed)},async load(e,n){let r=Dy(t,e,n,Sy);return await Ly(h,r,async()=>{let i=await l.get(r);if(!i)return;let a={messages:[],vfs:{},todos:[],memory:``};for(let r of wy){let i=await l.get(Dy(t,e,n,r));i!=null&&(a[r]=i)}return i.lastAccessed=Date.now(),await l.set(r,i),a})},async save(e,t,n){let r=[];for(let i of wy)n[i]!==void 0&&r.push(_(e,t,i,n[i]));await Promise.all(r)},async flush(){for(let e of Array.from(m.keys())){let t=m.get(e);t&&(clearTimeout(t),m.delete(e))}let e=Array.from(p.entries());p.clear(),await Promise.all(e.map(async([e,t])=>{await g(e,t.value,t.agentId,t.sessionId),t.resolve()})),c({type:`flush`}),await b()},async deleteSession(e,n){await l.clearPrefix(Oy(t,e,n))},async createSession(e,n,r){let i=r??my(),a=Date.now(),o={agentId:e,sessionId:i,createdAt:a,lastAccessed:a,bytes:0,title:n};return await l.set(Dy(t,e,i,Sy),o),i},onEvent(e){s.add(e)},dispose(){for(let e of m.values())clearTimeout(e);m.clear();for(let e of p.values())e.resolve();p.clear(),v&&=(clearTimeout(v),null),h.clear(),s.clear()}}}var zy=`v:1::skill-store`,By=`chat-sdk`;function Vy(e,t,n){return`${zy}::${e}::${t}::${n}`}function Hy(e,t){return`${zy}::${e}::${t}::`}function Uy(e={}){let t=e.dbName??By,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 Fy(t),a(!0)}else if(n===`session`){if(typeof sessionStorage>`u`)throw Error(`sessionStorage 不可用`);i=Iy(sessionStorage),a(!0)}else if(n===`local`){if(typeof localStorage>`u`)throw Error(`localStorage 不可用`);i=Iy(localStorage),a(!0)}else i=Py(),a(!1)}catch{i=Py(),a(!1)}})(),{ready:o,async list(){let e=[];return await i.scan(Hy(t,r),(t,n)=>{e.push(n)}),e},async get(e){return await i.get(Vy(t,r,e))},async put(e){try{await i.set(Vy(t,r,e.name),e)}catch(e){Ey(e)&&(i=Py())}},async remove(e){let n=Vy(t,r,e);return await i.get(n)==null?!1:(await i.del(n),!0)},async clear(){await i.clearPrefix(Hy(t,r))},dispose(){}}}var Wy=[`你是一个 JSON 操作助手。集成方声明了一个主数据对象(含 zod schema 校验),你通过专用工具安全地读写它来完成任务。`,`所有写操作都经范围控制(仅 schema 声明字段内)与 schema 校验(不合法会返回结构化错误而非写入),并自动留快照可回退。`,`大对象/数组优先用增量 patch(只发改动)而非整体重传,避免输出被截断。`,`---`,iv.reliableWriteRules].join(`
150
150
 
151
151
  `);function Gy(e){if(!e)return``;let t=av(e.schema);return`\n\n## 可操作数据(字段以 read 工具返回的实际值为准)\n${e.description?e.description+`
152
- `:``}${t}`}var Ky=50;function qy(e){return e===void 0||e===!1?null:typeof e==`string`?Ry({backend:e}):e.enabled===!1?null:Ry(e)}function Jy(e){return e.dialog??{}}function Yy(e){return!!e&&typeof e==`object`&&typeof e.invoke==`function`&&typeof e.stream==`function`}var Xy=new Map;function Zy(e){let t=e.content;return typeof t==`string`?t:Array.isArray(t)?t.map(e=>typeof e==`string`?e:e?.text??``).join(``):String(t??``)}function Qy(e){let t=e.summaryLlm??e.llm;if(!t)return;let r=e.summaryTemperature??.3,a=e.summaryMaxTokens??1024,o=e.summaryTimeoutMs??15e3,s;if(Yy(t))s=t;else{let i=t;if(!i.apiKey){e.summaryLlm&&console.warn(`[page-agent-sdk][summarization] summaryLlm 已配置但缺 apiKey,摘要回退主 agent 模型或零成本索引摘要`);return}s=new n.ChatOpenAI({apiKey:i.apiKey,model:i.model,temperature:r,maxTokens:a,configuration:{...i.baseUrl?{baseURL:i.baseUrl}:{},...i.extraConfig},...i.extraBody?{modelKwargs:i.extraBody}:{}})}return async e=>{let t=new AbortController,n=setTimeout(()=>t.abort(),o);try{return Zy(await s.invoke([new i.SystemMessage(`你是对话历史压缩助手。把下面按轮次索引的对话要点,改写成一段连贯、紧凑的中文摘要,保留关键事实、用户意图与已用工具,不要编造。直接输出摘要正文。`),new i.HumanMessage(e)],{signal:t.signal})).trim()}finally{clearTimeout(n)}}}function $y(e,t){return e===`set_data`?`set`:e===`edit_data`?`edit`:e===`delete_data`?`delete`:e===`restore_data`?`restore`:e===`write`?t?.del?`delete`:t?.patch?`edit`:`set`:null}function eb(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=$y(t.name,t.args);return a&&e({type:`data_change`,operation:a,value:n()?.bind}),i},afterModel:t=>{let n=t.message.additional_kwargs||{},a=t.message.response_metadata||{},o=n.usage||a.usage||a.token_usage||a.tokenUsage;if(o&&typeof o==`object`){let t=Number(o.prompt_tokens??o.promptTokens??0)||0,n=Number(o.completion_tokens??o.completionTokens??0)||0,a=Number(o.total_tokens??o.totalTokens??t+n)||0,s={prompt_tokens:t,completion_tokens:n,total_tokens:a};r.prompt_tokens=(r.prompt_tokens??0)+t,r.completion_tokens=(r.completion_tokens??0)+n,r.total_tokens=(r.total_tokens??0)+a,i++,e({type:`usage`,round:i,usage:s,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens}})}},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function tb(e,i){let a={prompt_tokens:0,completion_tokens:0,total_tokens:0},o=U(null),s=U(0),c=0;function l(e){return new Promise(t=>{let n=o.value;n&&n.resolve({action:`keep_external`});let r={...e,id:++c,resolve:t};o.value=r,Te({type:`conflict`,conflict:r})})}function u(e){let t=o.value;t&&(o.value=null,t.resolve({action:e}))}let d=qy(e.storage);e.debug&&d&&d.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let f=Yy(e.llm)?void 0:e.llm,p=Cg({model:f?.model,contextWindow:e.contextWindow??f?.contextWindow,maxOutputTokens:e.maxOutputTokens??f?.maxOutputTokens});e.debug&&console.log(`[page-agent-sdk][modelCaps]`,p);let m=e.llm,h=Qy(e);e.debug&&!h&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let g=Qt([]),_=fv(e.vfs?.initialFiles,{persist:d?{save:e=>{z.sessionId&&d&&d.save(i,z.sessionId,{vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes}),v=Ug(),y=Zg(e.memory||``),b={current:null},x=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,S=e.checkpoint,C=S!==void 0&&S!==!1,w=C?m_({getData:()=>N()?.bind,slotPaths:x?[``]:[],vfsStore:_,todosMw:v,getTodos:()=>b.current?.getState?.()?.todos??[],messages:g,maxCheckpoints:S&&typeof S==`object`?S.maxCheckpoints:void 0}):null,T=!S||typeof S!=`object`||S.auto!==!1,E=e.capabilities,D=E?.dataOps!==!1,O=e.appendReliableWriteRules!==!1,k=e.systemPrompt?O?e.systemPrompt+`
152
+ `:``}${t}`}var Ky=50;function qy(e){return e===void 0||e===!1?null:typeof e==`string`?Ry({backend:e}):e.enabled===!1?null:Ry(e)}function Jy(e){return e.dialog??{}}function Yy(e){return!!e&&typeof e==`object`&&typeof e.invoke==`function`&&typeof e.stream==`function`}var Xy=new Map;function Zy(e){let t=e.content;return typeof t==`string`?t:Array.isArray(t)?t.map(e=>typeof e==`string`?e:e?.text??``).join(``):String(t??``)}function Qy(e){let t=e.summaryLlm??e.llm;if(!t)return;let r=e.summaryTemperature??.3,a=e.summaryMaxTokens??1024,o=e.summaryTimeoutMs??15e3,s;if(Yy(t))s=t;else{let i=t;if(!i.apiKey){e.summaryLlm&&console.warn(`[page-agent-sdk][summarization] summaryLlm 已配置但缺 apiKey,摘要回退主 agent 模型或零成本索引摘要`);return}s=new n.ChatOpenAI({apiKey:i.apiKey,model:i.model,temperature:r,maxTokens:a,configuration:{...i.baseUrl?{baseURL:i.baseUrl}:{},...i.extraConfig},...i.extraBody?{modelKwargs:i.extraBody}:{}})}return async e=>{let t=new AbortController,n=setTimeout(()=>t.abort(),o);try{return Zy(await s.invoke([new i.SystemMessage(`你是对话历史压缩助手。把下面按轮次索引的对话要点,改写成一段连贯、紧凑的中文摘要,保留关键事实、用户意图与已用工具,不要编造。直接输出摘要正文。`),new i.HumanMessage(e)],{signal:t.signal})).trim()}finally{clearTimeout(n)}}}function $y(e,t){return e===`set_data`?`set`:e===`edit_data`?`edit`:e===`delete_data`?`delete`:e===`restore_data`?`restore`:e===`write`?t?.del?`delete`:t?.patch?`edit`:`set`:null}function eb(e,t,n,r){let i=0;return{name:`sdk-events`,wrapToolCall:async(t,r)=>{let i=await r(t),a=$y(t.name,t.args);return a&&e({type:`data_change`,operation:a,value:n()?.bind}),i},afterModel:t=>{let n=t.message.additional_kwargs||{},a=t.message.response_metadata||{},o=n.usage||a.usage||a.token_usage||a.tokenUsage;if(o&&typeof o==`object`){let t=Number(o.prompt_tokens??o.promptTokens??0)||0,n=Number(o.completion_tokens??o.completionTokens??0)||0,a=Number(o.total_tokens??o.totalTokens??t+n)||0,s={prompt_tokens:t,completion_tokens:n,total_tokens:a};r.prompt_tokens=(r.prompt_tokens??0)+t,r.completion_tokens=(r.completion_tokens??0)+n,r.total_tokens=(r.total_tokens??0)+a,i++,e({type:`usage`,round:i,usage:s,cumulative:{prompt_tokens:r.prompt_tokens,completion_tokens:r.completion_tokens,total_tokens:r.total_tokens}})}},afterAgent:async()=>{e({type:`message_update`,count:t.length})}}}function tb(e,i){let a={prompt_tokens:0,completion_tokens:0,total_tokens:0},o=U(null),s=U(0),c=0;function l(e){return new Promise(t=>{let n=o.value;n&&n.resolve({action:`keep_external`});let r={...e,id:++c,resolve:t};o.value=r,Te({type:`conflict`,conflict:r})})}function u(e){let t=o.value;t&&(o.value=null,t.resolve({action:e}))}let d=qy(e.storage);e.debug&&d&&d.onEvent(e=>console.log(`[page-agent-sdk][storage]`,e));let f=Yy(e.llm)?void 0:e.llm,p=Cg({model:f?.model,contextWindow:e.contextWindow??f?.contextWindow,maxOutputTokens:e.maxOutputTokens??f?.maxOutputTokens});e.debug&&console.log(`[page-agent-sdk][modelCaps]`,p);let m=e.llm,h=Qy(e);e.debug&&!h&&console.warn(`[page-agent-sdk][summarization] 未构造 llmInvoke(apiKey 缺失?),摘要回退零成本索引摘要`);let g=Qt([]),_=fv(e.vfs?.initialFiles,{persist:d?{save:e=>{z.sessionId&&d&&d.save(i,z.sessionId,{vfs:e})}}:void 0,maxBytes:e.vfs?.maxBytes}),v=Ug(),y=Zg(e.memory||``);typeof e.memory==`function`&&y.refresh();let b={current:null},x=e.data?{...e.data,description:e.data.description??`主数据对象`}:void 0,S=e.checkpoint,C=S!==void 0&&S!==!1,w=C?m_({getData:()=>N()?.bind,slotPaths:x?[``]:[],vfsStore:_,todosMw:v,getTodos:()=>b.current?.getState?.()?.todos??[],messages:g,maxCheckpoints:S&&typeof S==`object`?S.maxCheckpoints:void 0}):null,T=!S||typeof S!=`object`||S.auto!==!1,E=e.capabilities,D=E?.dataOps!==!1,O=e.appendReliableWriteRules!==!1,k=e.systemPrompt?O?e.systemPrompt+`
153
153
 
154
154
  ---
155
155
 
156
156
  `+iv.reliableWriteRules:e.systemPrompt:Wy,A=D&&x?oy(x,{onAudit:e.onAudit??(e.debug?e=>console.log(`[page-agent-sdk][data audit]`,e):void 0),maxSnapshots:e.maxSnapshots,onConflict:l,autoLock:e.autoLock,interceptors:e.interceptors}):[],j=D?ay(A,e.toolMode):[],M=D&&x?A.controller??null:null,N=()=>M?.get()??x,P=new Map,ee=dy(E,j,cy);ee.forEach(e=>P.set(e.name,`builtin`));let F=[...e.tools||[]];F.forEach(e=>P.set(e.name,`user`));let I=[],L=e.humanConfirm!==!1&&(!e.approval||e.approval.humanConfirmTool!==!1),te=L?o_():null;te&&P.set(i_,`builtin`);let ne=C&&w?[(0,r.tool)(async()=>{let e=w.list();return e.length?w.restore()?`已回退到最近一次正常状态(checkpoint #${e[e.length-1].id})。对话历史、主数据、vfs、todos 已整体还原。请基于回退后的状态重新判断并继续。`:`回退失败:无可用 checkpoint。`:`无可用 checkpoint,无法回退。`},{name:`restore_last_checkpoint`,description:`回退到最近一次正常状态(整体还原对话历史 + 主数据 + vfs + todos)。当本轮操作出错、页面被改坏、或走偏时调用,回到本轮起点重新来过。不传参数即回退最近一次。`,schema:t.z.object({}).optional()}),(0,r.tool)(async()=>{let e=w.list();return e.length?`可用 checkpoint:
157
157
  `+e.map(e=>`#${e.id} [${e.label??`auto`}] 消息数=${e.messageCount} 时间=${new Date(e.timestamp).toLocaleTimeString()}`).join(`
158
- `):`无可用 checkpoint。`},{name:`list_checkpoints`,description:`列出可用会话 checkpoint(回退点)。`,schema:t.z.object({}).optional()})]:[];ne.forEach(e=>P.set(e.name,`builtin`));let re=[...ee,...F,...te?[te]:[],...ne];function ie(){return[...ee,...F,...te?[te]:[],...ne,...I]}let ae=E?.planning!==!1,oe=E?.skills!==!1,se=E?.vfs!==!1,ce=E?.summarization!==!1,le=E?.memory!==!1,ue=E?.subagent!==!1,de=e.verify?.maxAttempts??2,fe=E?.verify===!0&&e.verify?.enabled!==!1&&de>0;e.verify?.check&&E?.verify!==!0&&console.warn(`[page-agent-sdk][verify] 检测到 verify.check 但 capabilities.verify 未开启,verify 未装载`);let pe=e.subagent,me=pe?.allowedTools??[],he=!ue||pe?.enabled===!1?void 0:C_({llm:pe?.llm??e.llm,allTools:re,allowedTools:me.length?me:void 0,systemPrompt:pe?.systemPrompt,temperature:pe?.temperature,maxTokens:pe?.maxTokens,skills:pe?.skills,maxDepth:pe?.maxDepth,maxParallel:pe?.maxParallel,debug:e.debug}),ge=ue&&e.subagents!==void 0?E_(e.subagents,{llm:e.llm,allTools:re,debug:e.debug}):void 0,_e=ge?ge.controller:null,ve=[`get_data`,`describe_data`,`read`,`fetch_document`],ye=re.filter(e=>ve.includes(e.name)),be=fe?D_({check:e.verify.check??N_({schemas:()=>N()?{"":N().schema}:{},root:()=>N()?.bind}),adversarial:e.verify?.adversarial?{llm:e.llm,tools:ye}:void 0}):void 0,xe=py({...E,humanConfirm:L,subagents:e.subagents?.map(e=>({id:e.id,description:e.description,temperature:e.temperature}))},D&&!!x,e.toolMode),Se=x?{name:`dataHint`,augmentPrompt:()=>Gy(N())||void 0}:null,Ce=e.augmentSystem?{name:`augmentSystem`,augmentPrompt:t=>{try{return e.augmentSystem({state:t,data:N()})}catch(t){e.debug&&console.log(`[page-agent-sdk][augmentSystem] 回调抛错,降级跳过:`,t.message);return}}}:null,R=e.onEvent,we=new Set,Te=e=>{if(e.type!==`approval_request`){if(R)try{R(e)}catch{}for(let t of we)try{t(e)}catch{}}},Ee,De=[],Oe=e=>({name:e.name,description:e.description,content:typeof e.getContent==`function`?e.getContent():``}),ke=e=>({name:e.name,description:e.description,getContent:()=>e.content}),Ae=e.skillStorage===!1?null:Uy({...typeof e.skillStorage==`object`?e.skillStorage:{},id:e.skillStorage&&typeof e.skillStorage==`object`&&e.skillStorage.id?e.skillStorage.id:`agent::${i}`}),je=()=>{let t=Ee?Ee.controller:null;if(t){let n=(e.skills||[]).filter(e=>!De.some(t=>t.name===e.name));t.set([...n,...De])}z.infoTick.value++},Me=async()=>{if(Ae)try{let t=await Ae.list();if(t.length){De=t.map(ke);let n=Ee?Ee.controller:null;if(n){let t=(e.skills||[]).filter(e=>!De.some(t=>t.name===e.name));n.set([...t,...De])}z.infoTick.value++}}catch{}},Ne=[...Se?[Se]:[],xe,...ae?[v]:[],...oe?[Ee=Xg(e.skills||[],{readVfs:se?e=>_.files[e]?.content:void 0})]:[],...se?[yv(_)]:[],...ce?[nv({...sv(e,p.contextWindow),llmInvoke:h,getRegisteredData:()=>N()?[{description:N().description??`主数据对象`}]:[],preserveLastToolResults:(e.contextOptions&&e.contextOptions.preserveLastToolResults)??[`describe_data`,`read`]})]:[],...le?[y]:[],...e.permissions?.length?[n_(e.permissions)]:[],...C&&T&&w?[h_(w)]:[],...L?[s_()]:[],...e.approval&&(e.approval.tools!==void 0||e.approval.confirm)?[r_(e.approval)]:[],...be?[be]:[],...he?[he]:[],...ge?[ge]:[],...Ce?[Ce]:[],...e.middleware||[],eb(Te,g,N,a)],Pe=e.maxMemoryRounds??Ky,z={agentId:i,store:d,messages:g,vfsStore:_,listeners:we,todosMw:v,memoryMw:y,agent:null,initDone:Promise.resolve(),sessionId:``,refCount:0,mcpClosers:[],mcpServers:[],checkpoint:w,dataOpsController:M,skillsController:Ee?Ee.controller:null,infoTick:s,pendingConflict:o,liveData:N,usage:a,emit:Te,applySnapshot(t){t.messages?.length&&g.push(...t.messages),t.vfs&&_.hydrate&&_.hydrate(t.vfs),t.todos?.length&&v.reset(t.todos),t.memory&&!e.memory&&y.reset(t.memory)},addSkill(e){let t=De.findIndex(t=>t.name===e.name);t>=0?De[t]=e:De.push(e),je(),Ae&&Ae.put(Oe(e))},removeSkill(e){let t=De.findIndex(t=>t.name===e);return t<0?!1:(De.splice(t,1),je(),Ae&&Ae.remove(e),!0)},listUserSkills(){return De.map(e=>e.name)},getUserSkill(e){let t=De.find(t=>t.name===e);if(t)return{name:t.name,description:t.description,content:typeof t.getContent==`function`?t.getContent():``}},afterRound(){Ie(),Le()},async send(t){await z.initDone;let n=t;if(e.interceptors?.input)try{let r=e.interceptors.input(t);typeof r==`string`&&(n=r)}catch{}g.push({role:`user`,content:n,timestamp:Date.now()});try{let t=await z.agent.invoke(g);if(e.interceptors?.output)try{let n=e.interceptors.output(t);typeof n==`string`&&(t=n)}catch{}return g.push({role:`assistant`,content:t,timestamp:Date.now()}),z.afterRound(),d&&await d.flush(),t}catch(e){throw Te({type:`error`,message:e?.message||String(e)}),e}},async switchSession(t){if(await z.initDone,!d)throw Error(`page-agent-sdk: storage 未开启,无法切换会话(请传 storage 选项)`);u(`keep_external`),_.flush?.(),await d.flush();let n=t??``,r;return n?(r=await d.load(i,n),r||await d.createSession(i,e.session?.title,n)):n=await d.createSession(i,e.session?.title),z.sessionId=n,g.splice(0,g.length),_.clear?.(),v.reset([]),e.memory||y.reset(``),z.agent.debugLogs.value=[],r||=await d.load(i,n),r&&(z.applySnapshot(r),Te({type:`session_restored`,sessionId:n,rounds:r.messages?.length??0})),e.memory&&d.save(i,z.sessionId,{memory:e.memory}),n},stream:(e,t,n)=>{if(!z.agent)throw Error(`page-agent-sdk: agent 尚未初始化完成,请先 await mount()`);let r=R?e=>{t?.(e),Te(e)}:t;if(n){let e=()=>u(`keep_external`);n.aborted?e():n.addEventListener(`abort`,e,{once:!0})}return z.agent.stream(e,r,n)},release(){if(z.refCount--,z.refCount<=0){d&&(_.flush?.(),d.flush(),d.dispose()),Ae&&Ae.dispose();let e=z.mcpClosers.splice(0);e.length&&Promise.allSettled(e.map(e=>e())),Xy.delete(i)}},resolveConflict:u,setTools(e){F.length=0,e.forEach(e=>{F.push(e),P.set(e.name,`user`)}),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++},addTool(e){F.some(t=>t.name===e.name)||(F.push(e),P.set(e.name,`user`),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++)},removeTool(e){let t=F.findIndex(t=>t.name===e);return t<0?!1:(F.splice(t,1),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++,!0)},setLlm(t){let r=Yy(t)?t:new n.ChatOpenAI({apiKey:t.apiKey,model:t.model,temperature:t.temperature,maxTokens:t.maxTokens,configuration:{...t.baseUrl?{baseURL:t.baseUrl}:{},...t.extraConfig},...t.extraBody?{modelKwargs:t.extraBody}:{}});typeof r.bindTools!=`function`&&e.debug&&console.warn(`[page-agent-sdk][setLlm] 新模型不支持 bindTools(tool calling 会失效)`),m=t,z.agent&&z.agent.setLlm(r),z.infoTick.value++},setMemory(e){y.reset(e),z.infoTick.value++},setSubagents(t){if(!_e){e.debug&&console.warn(`[page-agent-sdk][setSubagents] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`);return}_e.set(t),z.infoTick.value++},addSubagent(t){if(!_e){e.debug&&console.warn(`[page-agent-sdk][addSubagent] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`);return}_e.add(t),z.infoTick.value++},removeSubagent(t){if(!_e)return e.debug&&console.warn(`[page-agent-sdk][removeSubagent] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`),!1;let n=_e.remove(t);return n&&z.infoTick.value++,n},getInfo(){return{id:i,model:Yy(m)?m.model??m.modelName:m.model,systemPrompt:k+Gy(N())+(Ce&&Ce.augmentPrompt(z.agent?.getState?.()??Dg())||``),tools:(z.agent?.allTools??re).map(e=>({name:e.name,description:e.description,schema:e.schema,source:P.get(e.name)||`user`})),skills:(Ee?Ee.controller.get():e.skills??[]).map(e=>({name:e.name,description:e.description})),data:N()?{description:N().description,schema:N().schema}:void 0,memory:y.get(),middleware:Ne.map(e=>e.name),todos:(z.agent?.getState?.()?.todos??[]).map(e=>({content:e.content,status:e.status})),subagent:{enabled:!!he,maxDepth:e.subagent?.maxDepth??1,maxParallel:e.subagent?.maxParallel??4,allowedTools:e.subagent?.allowedTools??[],subagents:_e?.get()??[]},verify:{enabled:!!be,maxAttempts:fe?de:0,adversarial:fe&&!!e.verify?.adversarial},mcp:{servers:z.mcpServers},lastCompression:z.agent?.getState?.()?.lastCompression,checkpoints:w?{enabled:!0,auto:T,list:w.list()}:void 0}}};async function B(){if(!d)return;await d.ready;let t=e.session||{};if(t.id){z.sessionId=t.id;let e=await d.load(i,z.sessionId);e?(z.applySnapshot(e),Te({type:`session_restored`,sessionId:z.sessionId,rounds:e.messages?.length??0})):await d.createSession(i,t.title,z.sessionId)}else if(t.autoResume!==!1){let n=await d.listSessions(i);if(e.debug&&console.log(`[page-agent-sdk][restore] listSessions`,i,n.length,n.map(e=>e.sessionId)),n.length){z.sessionId=n[0].sessionId;let t=await d.load(i,z.sessionId);t?(z.applySnapshot(t),Te({type:`session_restored`,sessionId:z.sessionId,rounds:t.messages?.length??0}),e.debug&&console.log(`[page-agent-sdk][restore] 恢复会话`,z.sessionId,`${t.messages?.length??0} msgs`)):e.debug&&console.log(`[page-agent-sdk][restore] 会话 meta 存在但快照为空`,z.sessionId)}else z.sessionId=await d.createSession(i,t.title),e.debug&&console.log(`[page-agent-sdk][restore] 新建会话(无历史)`,z.sessionId)}else z.sessionId=await d.createSession(i,t.title);e.memory&&d.save(i,z.sessionId,{memory:e.memory})}async function Fe(){await Me()}function Ie(){let e=q_(g,Pe);e.trimmed&&g.splice(e.deleteFrom,e.deleteCount,e.summary)}function Le(){if(!z.sessionId||!d)return;let t=JSON.parse(JSON.stringify(g));d.save(i,z.sessionId,{messages:t});let n=z.agent?.getState?.()?.todos??[];d.save(i,z.sessionId,{todos:n}),e.debug&&console.log(`[page-agent-sdk][persist] save`,z.sessionId,`${g.length} msgs`)}return z.initDone=(async()=>{if(await B(),await Fe(),e.mcp?.length){let t=await Promise.allSettled(e.mcp.map(e=>U_(e)));z.mcpClosers=t.flatMap(e=>e.status===`fulfilled`?[e.value.close]:[]),z.mcpServers=[];let n=[];t.forEach((t,r)=>{let i=e.mcp[r],a=i.name??i.url;t.status===`fulfilled`?(z.mcpServers.push({name:a,url:i.url,toolCount:t.value.tools.length}),t.value.tools.forEach(e=>P.set(e.name,`mcp:${a}`)),n.push(...t.value.tools)):console.warn(`[page-agent-sdk][mcp] server ${a} 连接失败:`,t.reason)}),re=ie(),e.debug&&console.log(`[page-agent-sdk][mcp] 注入 ${n.length} 个工具,${z.mcpServers.length} 个 server`)}z.agent=Vg({...Yy(e.llm)?{llm:e.llm}:{apiKey:e.llm.apiKey,baseUrl:e.llm.baseUrl,model:e.llm.model,temperature:e.llm.temperature,maxTokens:e.llm.maxTokens,extraBody:e.llm.extraBody,extraConfig:e.llm.extraConfig},systemPrompt:k,tools:re,middleware:Ne,maxToolRounds:e.maxToolRounds,maxRetries:e.maxRetries,maxParallelTools:e.maxParallelTools,contextWindow:p.contextWindow,maxOutputTokens:p.maxOutputTokens,maxVerifyAttempts:fe?de:0,onLlmChange:t=>{let n=Yy(t)?void 0:t;p=Cg({model:n?.model??t.model??t.modelName,contextWindow:e.contextWindow??n?.contextWindow,maxOutputTokens:e.maxOutputTokens??n?.maxOutputTokens}),m=t,e.debug&&console.log(`[page-agent-sdk][setLlm] 重解析 modelCaps:`,p)},debug:e.debug}),b.current=z.agent,ge&&ge.setReconfigureHook&&ge.setReconfigureHook(()=>{z.agent&&z.agent.setTools(ie())})})(),z}function nb(e){let t=e.id??my();e.id||console.warn(`[page-agent-sdk] 未传 options.id,已生成随机 id "${t}"。刷新后持久化数据无法恢复,请传稳定 id。`);let n=e.streaming??!0,r=e.ui??`default`,i,a=e.shareContext?Xy.get(t):void 0;a?i=a:(i=tb(e,t),e.shareContext&&Xy.set(t,i)),i.refCount++;let o=null,s=null,c=Jy(e),l=null,u=null;async function d(t){if(await i.initDone,o){m();return}if(t!==void 0&&(e.container=t),r===!1){i.store&&(l=()=>{i.vfsStore.flush?.(),i.store.flush()},u=()=>{document.visibilityState===`hidden`&&i.store.flush()},typeof window<`u`&&window.addEventListener(`pagehide`,l),typeof document<`u`&&document.addEventListener(`visibilitychange`,u));return}let a=typeof e.container==`string`?document.querySelector(e.container):e.container;if(!a)throw Error(`createChatSdk: 挂载点未找到(${e.container})`);s=a;let d=i.agent.debugLogs;o=ll(Ci({setup(){return()=>zs(gg,{fetchStream:n?i.agent.stream:void 0,fetchResponse:n?void 0:(e,t)=>{if(t){let e=()=>i.resolveConflict(`keep_external`);t.aborted?e():t.addEventListener(`abort`,e,{once:!0})}return i.agent.invoke(e,t)},title:c.title,placeholder:c.placeholder,debugLogs:d.value,initialMessages:i.messages,getInfo:()=>i.getInfo(),onUndo:i.checkpoint?()=>i.checkpoint.restore():void 0,canUndo:i.checkpoint?()=>i.checkpoint.canRestore():void 0,onPersist:async()=>{i.afterRound(),i.store&&await i.store.flush()},onClear:()=>{i.store&&(i.sessionId=my(),i.vfsStore.clear?.(),i.todosMw.reset([]),e.memory||i.memoryMw.reset(``),i.agent.debugLogs.value=[],i.store.createSession(i.agentId,e.session?.title,i.sessionId))},pendingConflict:i.pendingConflict.value,onResolveConflict:e=>i.resolveConflict(e),infoTick:i.infoTick,getSkillContent:i.skillsController?e=>i.skillsController.getContent(e):void 0,onAddSkill:i.skillsController?e=>i.addSkill(e):void 0,onRemoveSkill:i.skillsController?e=>i.removeSkill(e):void 0,getUserSkillNames:i.skillsController?()=>i.listUserSkills():void 0,onGetSkill:i.skillsController?e=>i.getUserSkill(e):void 0,drawer:c.drawer===!0,drawerWidth:c.drawerWidth,drawerHidden:c.drawerHidden===!0,inputRows:c.inputRows,onClose:c.onClose??(c.drawer===!0?()=>p():()=>f())})}})),o.mount(a),c.drawer===!0&&c.drawerHidden===!0&&p(),i.store&&(l=()=>{i.vfsStore.flush?.(),i.store.flush()},u=()=>{document.visibilityState===`hidden`&&i.store.flush()},typeof window<`u`&&window.addEventListener(`pagehide`,l),typeof document<`u`&&document.addEventListener(`visibilitychange`,u))}function f(){i.resolveConflict(`keep_external`),l&&typeof window<`u`&&window.removeEventListener(`pagehide`,l),u&&typeof document<`u`&&document.removeEventListener(`visibilitychange`,u),l=null,u=null;let e=s?.querySelector?.(`.chat-dialog`);if(o&&e){e.classList.add(`cs-leaving`);let t=s?.querySelector?.(`.chat-mask`);t&&t.classList.add(`cs-leaving`);let n=!1,r=()=>{n||(n=!0,o?.unmount(),o=null,s=null,i.release())};e.addEventListener(`transitionend`,r,{once:!0}),setTimeout(r,320);return}o?.unmount(),o=null,s=null,i.release()}function p(){if(!o)return;let e=s?.querySelector?.(`.chat-dialog`),t=s?.querySelector?.(`.chat-mask`);e&&e.classList.add(`cs-hidden`),t&&t.classList.add(`cs-hidden`)}function m(){if(!o)return;let e=s?.querySelector?.(`.chat-dialog`),t=s?.querySelector?.(`.chat-mask`);e&&e.classList.remove(`cs-hidden`),t&&t.classList.remove(`cs-hidden`)}return{mount:d,unmount:f,hide:p,show:m,send:i.send,switchSession:i.switchSession,stream:i.stream,inspect:i.getInfo,messages:i.messages,restoreLastCheckpoint:()=>i.checkpoint?.restore()??!1,listCheckpoints:()=>i.checkpoint?.list()??[],hook:e=>(i.listeners.add(e),()=>i.listeners.delete(e)),setData:e=>{if(!i.dataOpsController){console.warn(`[page-agent-sdk] setData 忽略:dataOps 已关闭(capabilities.dataOps:false)`);return}i.dataOpsController.set(e),i.infoTick.value++},getData:()=>i.liveData(),setSkills:e=>{let t=i.skillsController;if(!t){console.warn(`[page-agent-sdk] setSkills 忽略:skills 已关闭(capabilities.skills:false)`);return}t.set(e),i.infoTick.value++},addSkill:e=>{if(!i.skillsController){console.warn(`[page-agent-sdk] addSkill 忽略:skills 已关闭(capabilities.skills:false)`);return}i.addSkill(e)},removeSkill:e=>i.skillsController?i.removeSkill(e):(console.warn(`[page-agent-sdk] removeSkill 忽略:skills 已关闭(capabilities.skills:false)`),!1),listUserSkills:()=>i.listUserSkills(),getUserSkill:e=>i.getUserSkill(e),invalidateSkillCache:e=>{let t=i.skillsController;if(!t){console.warn(`[page-agent-sdk] invalidateSkillCache 忽略:skills 已关闭(capabilities.skills:false)`);return}t.invalidateCache(e)},exportData:()=>{let e=i.liveData()?.bind;return e==null?null:JSON.parse(JSON.stringify(e))},importData:(e,t)=>{let n=i.liveData();if(!n||!i.dataOpsController)return{ok:!1,error:`dataOps 未开启或无主数据`};let r=n.bind;if(typeof r!=`object`||!r)return{ok:!1,error:`主数据 bind 非对象,无法就地还原(集成方应用对象包裹)`};if(t?.validate!==!1){let t=n.schema.safeParse(e);if(!t.success)return{ok:!1,error:`schema 校验失败:`+(t.error?.message??`未知错误`)}}return d_(r,e),t?.emit!==!1&&i.emit({type:`data_change`,operation:`set`,value:r}),{ok:!0}},usage:i.usage,pendingConflict:i.pendingConflict,resolveConflict:e=>i.resolveConflict(e),setTools:e=>i.setTools(e),addTool:e=>i.addTool(e),removeTool:e=>i.removeTool(e),setLlm:e=>i.setLlm(e),setMemory:e=>i.setMemory(e),setSubagents:e=>i.setSubagents(e),addSubagent:e=>i.addSubagent(e),removeSubagent:e=>i.removeSubagent(e)}}function rb(e){return(0,r.tool)(async t=>{let n=await e.handler(t);return typeof n==`string`?n:JSON.stringify(n)},{name:e.name,description:e.description,schema:e.schema})}e.CONTEXT_PRESETS=ov,e.ChatDialog=gg,e.CodePreview=$d,e.HUMAN_CONFIRM_TOOL_NAME=i_,e.MessageContent=tf,e.SkillPanel=ih,e.connectMcp=U_,e.copyText=xl,e.createAgent=Vg,e.createApprovalMiddleware=r_,e.createChatSdk=nb,e.createCheckpointManager=m_,e.createCheckpointMiddleware=h_,e.createDataOps=oy,e.createHumanConfirmMiddleware=s_,e.createHumanConfirmTool=o_,e.createMemoryBackend=Py,e.createProxyLlm=h,e.createSessionStore=Ry,e.createSkillStore=Uy,e.createSubagentMiddleware=C_,e.createSubagentsMiddleware=E_,e.createUsageHintsMiddleware=py,e.createVerifyMiddleware=D_,e.createVfs=fv,e.createWebStorageBackend=Iy,e.createWriteBackCheck=N_,e.defineDataToolset=uy,e.defineSkill=Wg,e.defineTool=rb,e.detectGarbledToolCall=Ig,e.estimateTokens=wg,e.extractSchemaHint=av,e.extractText=B_,e.fetchDocTools=cy,e.fetchTools=ly,e.filterByToolMode=ay,e.formatZodIssues=cv,e.isQuotaError=Ey,e.jpEval=kv,e.jsonParseError=uv,e.offloadPassThroughChars=Eg,e.offloadThresholdChars=Tg,e.presets=rv,e.resolveContextOptions=sv,e.resolveModelCaps=Cg,e.runSandboxedScript=Pv,e.searchJson=jv,e.selectBuiltinTools=dy,e.systemPromptHelpers=iv,e.toolError=$,e.useChat=bl,Object.defineProperty(e,"z",{enumerable:!0,get:function(){return t.z}}),e.zodError=lv});
158
+ `):`无可用 checkpoint。`},{name:`list_checkpoints`,description:`列出可用会话 checkpoint(回退点)。`,schema:t.z.object({}).optional()})]:[];ne.forEach(e=>P.set(e.name,`builtin`));let re=[...ee,...F,...te?[te]:[],...ne];function ie(){return[...ee,...F,...te?[te]:[],...ne,...I]}let ae=E?.planning!==!1,oe=E?.skills!==!1,se=E?.vfs!==!1,ce=E?.summarization!==!1,le=E?.memory!==!1,ue=E?.subagent!==!1,de=e.verify?.maxAttempts??2,fe=E?.verify===!0&&e.verify?.enabled!==!1&&de>0;e.verify?.check&&E?.verify!==!0&&console.warn(`[page-agent-sdk][verify] 检测到 verify.check 但 capabilities.verify 未开启,verify 未装载`);let pe=e.subagent,me=pe?.allowedTools??[],he=!ue||pe?.enabled===!1?void 0:C_({llm:pe?.llm??e.llm,allTools:re,allowedTools:me.length?me:void 0,systemPrompt:pe?.systemPrompt,temperature:pe?.temperature,maxTokens:pe?.maxTokens,skills:pe?.skills,maxDepth:pe?.maxDepth,maxParallel:pe?.maxParallel,debug:e.debug}),ge=ue&&e.subagents!==void 0?E_(e.subagents,{llm:e.llm,allTools:re,debug:e.debug}):void 0,_e=ge?ge.controller:null,ve=[`get_data`,`describe_data`,`read`,`fetch_document`],ye=re.filter(e=>ve.includes(e.name)),be=fe?D_({check:e.verify.check??N_({schemas:()=>N()?{"":N().schema}:{},root:()=>N()?.bind}),adversarial:e.verify?.adversarial?{llm:e.llm,tools:ye}:void 0}):void 0,xe=py({...E,humanConfirm:L,subagents:e.subagents?.map(e=>({id:e.id,description:e.description,temperature:e.temperature}))},D&&!!x,e.toolMode),Se=x?{name:`dataHint`,augmentPrompt:()=>Gy(N())||void 0}:null,Ce=e.augmentSystem?{name:`augmentSystem`,augmentPrompt:t=>{try{return e.augmentSystem({state:t,data:N()})}catch(t){e.debug&&console.log(`[page-agent-sdk][augmentSystem] 回调抛错,降级跳过:`,t.message);return}}}:null,R=e.onEvent,we=new Set,Te=e=>{if(e.type!==`approval_request`){if(R)try{R(e)}catch{}for(let t of we)try{t(e)}catch{}}},Ee,De=[],Oe=e=>({name:e.name,description:e.description,content:typeof e.getContent==`function`?e.getContent():``}),ke=e=>({name:e.name,description:e.description,getContent:()=>e.content}),Ae=e.skillStorage===!1?null:Uy({...typeof e.skillStorage==`object`?e.skillStorage:{},id:e.skillStorage&&typeof e.skillStorage==`object`&&e.skillStorage.id?e.skillStorage.id:`agent::${i}`}),je=()=>{let t=Ee?Ee.controller:null;if(t){let n=(e.skills||[]).filter(e=>!De.some(t=>t.name===e.name));t.set([...n,...De])}z.infoTick.value++},Me=async()=>{if(Ae)try{let t=await Ae.list();if(t.length){De=t.map(ke);let n=Ee?Ee.controller:null;if(n){let t=(e.skills||[]).filter(e=>!De.some(t=>t.name===e.name));n.set([...t,...De])}z.infoTick.value++}}catch{}},Ne=[...Se?[Se]:[],xe,...ae?[v]:[],...oe?[Ee=Xg(e.skills||[],{readVfs:se?e=>_.files[e]?.content:void 0})]:[],...se?[yv(_)]:[],...ce?[nv({...sv(e,p.contextWindow),llmInvoke:h,getRegisteredData:()=>N()?[{description:N().description??`主数据对象`}]:[],preserveLastToolResults:(e.contextOptions&&e.contextOptions.preserveLastToolResults)??[`describe_data`,`read`]})]:[],...le?[y]:[],...e.permissions?.length?[n_(e.permissions)]:[],...C&&T&&w?[h_(w)]:[],...L?[s_()]:[],...e.approval&&(e.approval.tools!==void 0||e.approval.confirm)?[r_(e.approval)]:[],...be?[be]:[],...he?[he]:[],...ge?[ge]:[],...Ce?[Ce]:[],...e.middleware||[],eb(Te,g,N,a)],Pe=e.maxMemoryRounds??Ky,z={agentId:i,store:d,messages:g,vfsStore:_,listeners:we,todosMw:v,memoryMw:y,agent:null,initDone:Promise.resolve(),sessionId:``,refCount:0,mcpClosers:[],mcpServers:[],checkpoint:w,dataOpsController:M,skillsController:Ee?Ee.controller:null,infoTick:s,pendingConflict:o,liveData:N,usage:a,emit:Te,applySnapshot(t){t.messages?.length&&g.push(...t.messages),t.vfs&&_.hydrate&&_.hydrate(t.vfs),t.todos?.length&&v.reset(t.todos),t.memory&&!e.memory&&y.reset(t.memory)},addSkill(e){let t=De.findIndex(t=>t.name===e.name);t>=0?De[t]=e:De.push(e),je(),Ae&&Ae.put(Oe(e))},removeSkill(e){let t=De.findIndex(t=>t.name===e);return t<0?!1:(De.splice(t,1),je(),Ae&&Ae.remove(e),!0)},listUserSkills(){return De.map(e=>e.name)},getUserSkill(e){let t=De.find(t=>t.name===e);if(t)return{name:t.name,description:t.description,content:typeof t.getContent==`function`?t.getContent():``}},afterRound(){Ie(),Le()},async send(t){await z.initDone;let n=t;if(e.interceptors?.input)try{let r=e.interceptors.input(t);typeof r==`string`&&(n=r)}catch{}g.push({role:`user`,content:n,timestamp:Date.now()});try{let t=await z.agent.invoke(g);if(e.interceptors?.output)try{let n=e.interceptors.output(t);typeof n==`string`&&(t=n)}catch{}return g.push({role:`assistant`,content:t,timestamp:Date.now()}),z.afterRound(),d&&await d.flush(),t}catch(e){throw Te({type:`error`,message:e?.message||String(e)}),e}},async switchSession(t){if(await z.initDone,!d)throw Error(`page-agent-sdk: storage 未开启,无法切换会话(请传 storage 选项)`);u(`keep_external`),_.flush?.(),await d.flush();let n=t??``,r;return n?(r=await d.load(i,n),r||await d.createSession(i,e.session?.title,n)):n=await d.createSession(i,e.session?.title),z.sessionId=n,g.splice(0,g.length),_.clear?.(),v.reset([]),e.memory||y.reset(``),z.agent.debugLogs.value=[],r||=await d.load(i,n),r&&(z.applySnapshot(r),Te({type:`session_restored`,sessionId:n,rounds:r.messages?.length??0})),e.memory&&d.save(i,z.sessionId,{memory:y.get()||(typeof e.memory==`string`?e.memory:``)}),n},stream:(e,t,n)=>{if(!z.agent)throw Error(`page-agent-sdk: agent 尚未初始化完成,请先 await mount()`);let r=R?e=>{t?.(e),Te(e)}:t;if(n){let e=()=>u(`keep_external`);n.aborted?e():n.addEventListener(`abort`,e,{once:!0})}return z.agent.stream(e,r,n)},release(){if(z.refCount--,z.refCount<=0){d&&(_.flush?.(),d.flush(),d.dispose()),Ae&&Ae.dispose();let e=z.mcpClosers.splice(0);e.length&&Promise.allSettled(e.map(e=>e())),Xy.delete(i)}},resolveConflict:u,setTools(e){F.length=0,e.forEach(e=>{F.push(e),P.set(e.name,`user`)}),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++},addTool(e){F.some(t=>t.name===e.name)||(F.push(e),P.set(e.name,`user`),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++)},removeTool(e){let t=F.findIndex(t=>t.name===e);return t<0?!1:(F.splice(t,1),re=ie(),z.agent&&z.agent.setTools(re),z.infoTick.value++,!0)},setLlm(t){let r=Yy(t)?t:new n.ChatOpenAI({apiKey:t.apiKey,model:t.model,temperature:t.temperature,maxTokens:t.maxTokens,configuration:{...t.baseUrl?{baseURL:t.baseUrl}:{},...t.extraConfig},...t.extraBody?{modelKwargs:t.extraBody}:{}});typeof r.bindTools!=`function`&&e.debug&&console.warn(`[page-agent-sdk][setLlm] 新模型不支持 bindTools(tool calling 会失效)`),m=t,z.agent&&z.agent.setLlm(r),z.infoTick.value++},setMemory(e){y.reset(e),typeof e==`function`&&y.refresh(),z.infoTick.value++},refreshMemory(){return y.refresh()},setSubagents(t){if(!_e){e.debug&&console.warn(`[page-agent-sdk][setSubagents] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`);return}_e.set(t),z.infoTick.value++},addSubagent(t){if(!_e){e.debug&&console.warn(`[page-agent-sdk][addSubagent] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`);return}_e.add(t),z.infoTick.value++},removeSubagent(t){if(!_e)return e.debug&&console.warn(`[page-agent-sdk][removeSubagent] 未配 subagents:[] 或 capabilities.subagent 关闭,忽略`),!1;let n=_e.remove(t);return n&&z.infoTick.value++,n},getInfo(){return{id:i,model:Yy(m)?m.model??m.modelName:m.model,systemPrompt:k+Gy(N())+(Ce&&Ce.augmentPrompt(z.agent?.getState?.()??Dg())||``),tools:(z.agent?.allTools??re).map(e=>({name:e.name,description:e.description,schema:e.schema,source:P.get(e.name)||`user`})),skills:(Ee?Ee.controller.get():e.skills??[]).map(e=>({name:e.name,description:e.description})),data:N()?{description:N().description,schema:N().schema}:void 0,memory:y.get(),middleware:Ne.map(e=>e.name),todos:(z.agent?.getState?.()?.todos??[]).map(e=>({content:e.content,status:e.status})),subagent:{enabled:!!he,maxDepth:e.subagent?.maxDepth??1,maxParallel:e.subagent?.maxParallel??4,allowedTools:e.subagent?.allowedTools??[],subagents:_e?.get()??[]},verify:{enabled:!!be,maxAttempts:fe?de:0,adversarial:fe&&!!e.verify?.adversarial},mcp:{servers:z.mcpServers},lastCompression:z.agent?.getState?.()?.lastCompression,checkpoints:w?{enabled:!0,auto:T,list:w.list()}:void 0}}};async function B(){if(!d)return;await d.ready;let t=e.session||{};if(t.id){z.sessionId=t.id;let e=await d.load(i,z.sessionId);e?(z.applySnapshot(e),Te({type:`session_restored`,sessionId:z.sessionId,rounds:e.messages?.length??0})):await d.createSession(i,t.title,z.sessionId)}else if(t.autoResume!==!1){let n=await d.listSessions(i);if(e.debug&&console.log(`[page-agent-sdk][restore] listSessions`,i,n.length,n.map(e=>e.sessionId)),n.length){z.sessionId=n[0].sessionId;let t=await d.load(i,z.sessionId);t?(z.applySnapshot(t),Te({type:`session_restored`,sessionId:z.sessionId,rounds:t.messages?.length??0}),e.debug&&console.log(`[page-agent-sdk][restore] 恢复会话`,z.sessionId,`${t.messages?.length??0} msgs`)):e.debug&&console.log(`[page-agent-sdk][restore] 会话 meta 存在但快照为空`,z.sessionId)}else z.sessionId=await d.createSession(i,t.title),e.debug&&console.log(`[page-agent-sdk][restore] 新建会话(无历史)`,z.sessionId)}else z.sessionId=await d.createSession(i,t.title);e.memory&&d.save(i,z.sessionId,{memory:y.get()||(typeof e.memory==`string`?e.memory:``)})}async function Fe(){await Me()}function Ie(){let e=q_(g,Pe);e.trimmed&&g.splice(e.deleteFrom,e.deleteCount,e.summary)}function Le(){if(!z.sessionId||!d)return;let t=JSON.parse(JSON.stringify(g));d.save(i,z.sessionId,{messages:t});let n=z.agent?.getState?.()?.todos??[];d.save(i,z.sessionId,{todos:n}),e.debug&&console.log(`[page-agent-sdk][persist] save`,z.sessionId,`${g.length} msgs`)}return z.initDone=(async()=>{if(await B(),await Fe(),e.mcp?.length){let t=await Promise.allSettled(e.mcp.map(e=>U_(e)));z.mcpClosers=t.flatMap(e=>e.status===`fulfilled`?[e.value.close]:[]),z.mcpServers=[];let n=[];t.forEach((t,r)=>{let i=e.mcp[r],a=i.name??i.url;t.status===`fulfilled`?(z.mcpServers.push({name:a,url:i.url,toolCount:t.value.tools.length}),t.value.tools.forEach(e=>P.set(e.name,`mcp:${a}`)),n.push(...t.value.tools)):console.warn(`[page-agent-sdk][mcp] server ${a} 连接失败:`,t.reason)}),re=ie(),e.debug&&console.log(`[page-agent-sdk][mcp] 注入 ${n.length} 个工具,${z.mcpServers.length} 个 server`)}z.agent=Vg({...Yy(e.llm)?{llm:e.llm}:{apiKey:e.llm.apiKey,baseUrl:e.llm.baseUrl,model:e.llm.model,temperature:e.llm.temperature,maxTokens:e.llm.maxTokens,extraBody:e.llm.extraBody,extraConfig:e.llm.extraConfig},systemPrompt:k,tools:re,middleware:Ne,maxToolRounds:e.maxToolRounds,maxRetries:e.maxRetries,maxParallelTools:e.maxParallelTools,contextWindow:p.contextWindow,maxOutputTokens:p.maxOutputTokens,maxVerifyAttempts:fe?de:0,onLlmChange:t=>{let n=Yy(t)?void 0:t;p=Cg({model:n?.model??t.model??t.modelName,contextWindow:e.contextWindow??n?.contextWindow,maxOutputTokens:e.maxOutputTokens??n?.maxOutputTokens}),m=t,e.debug&&console.log(`[page-agent-sdk][setLlm] 重解析 modelCaps:`,p)},debug:e.debug}),b.current=z.agent,ge&&ge.setReconfigureHook&&ge.setReconfigureHook(()=>{z.agent&&z.agent.setTools(ie())})})(),z}function nb(e){let t=e.id??my();e.id||console.warn(`[page-agent-sdk] 未传 options.id,已生成随机 id "${t}"。刷新后持久化数据无法恢复,请传稳定 id。`);let n=e.streaming??!0,r=e.ui??`default`,i,a=e.shareContext?Xy.get(t):void 0;a?i=a:(i=tb(e,t),e.shareContext&&Xy.set(t,i)),i.refCount++;let o=null,s=null,c=Jy(e),l=null,u=null;async function d(t){if(await i.initDone,o){m();return}if(t!==void 0&&(e.container=t),r===!1){i.store&&(l=()=>{i.vfsStore.flush?.(),i.store.flush()},u=()=>{document.visibilityState===`hidden`&&i.store.flush()},typeof window<`u`&&window.addEventListener(`pagehide`,l),typeof document<`u`&&document.addEventListener(`visibilitychange`,u));return}let a=typeof e.container==`string`?document.querySelector(e.container):e.container;if(!a)throw Error(`createChatSdk: 挂载点未找到(${e.container})`);s=a;let d=i.agent.debugLogs;o=ll(Ci({setup(){return()=>zs(gg,{fetchStream:n?i.agent.stream:void 0,fetchResponse:n?void 0:(e,t)=>{if(t){let e=()=>i.resolveConflict(`keep_external`);t.aborted?e():t.addEventListener(`abort`,e,{once:!0})}return i.agent.invoke(e,t)},title:c.title,placeholder:c.placeholder,debugLogs:d.value,initialMessages:i.messages,getInfo:()=>i.getInfo(),onUndo:i.checkpoint?()=>i.checkpoint.restore():void 0,canUndo:i.checkpoint?()=>i.checkpoint.canRestore():void 0,onPersist:async()=>{i.afterRound(),i.store&&await i.store.flush()},onClear:()=>{i.store&&(i.sessionId=my(),i.vfsStore.clear?.(),i.todosMw.reset([]),e.memory||i.memoryMw.reset(``),i.agent.debugLogs.value=[],i.store.createSession(i.agentId,e.session?.title,i.sessionId))},pendingConflict:i.pendingConflict.value,onResolveConflict:e=>i.resolveConflict(e),infoTick:i.infoTick,getSkillContent:i.skillsController?e=>i.skillsController.getContent(e):void 0,onAddSkill:i.skillsController?e=>i.addSkill(e):void 0,onRemoveSkill:i.skillsController?e=>i.removeSkill(e):void 0,getUserSkillNames:i.skillsController?()=>i.listUserSkills():void 0,onGetSkill:i.skillsController?e=>i.getUserSkill(e):void 0,drawer:c.drawer===!0,drawerWidth:c.drawerWidth,drawerHidden:c.drawerHidden===!0,inputRows:c.inputRows,onClose:c.onClose??(c.drawer===!0?()=>p():()=>f())})}})),o.mount(a),c.drawer===!0&&c.drawerHidden===!0&&p(),i.store&&(l=()=>{i.vfsStore.flush?.(),i.store.flush()},u=()=>{document.visibilityState===`hidden`&&i.store.flush()},typeof window<`u`&&window.addEventListener(`pagehide`,l),typeof document<`u`&&document.addEventListener(`visibilitychange`,u))}function f(){i.resolveConflict(`keep_external`),l&&typeof window<`u`&&window.removeEventListener(`pagehide`,l),u&&typeof document<`u`&&document.removeEventListener(`visibilitychange`,u),l=null,u=null;let e=s?.querySelector?.(`.chat-dialog`);if(o&&e){e.classList.add(`cs-leaving`);let t=s?.querySelector?.(`.chat-mask`);t&&t.classList.add(`cs-leaving`);let n=!1,r=()=>{n||(n=!0,o?.unmount(),o=null,s=null,i.release())};e.addEventListener(`transitionend`,r,{once:!0}),setTimeout(r,320);return}o?.unmount(),o=null,s=null,i.release()}function p(){if(!o)return;let e=s?.querySelector?.(`.chat-dialog`),t=s?.querySelector?.(`.chat-mask`);e&&e.classList.add(`cs-hidden`),t&&t.classList.add(`cs-hidden`)}function m(){if(!o)return;let e=s?.querySelector?.(`.chat-dialog`),t=s?.querySelector?.(`.chat-mask`);e&&e.classList.remove(`cs-hidden`),t&&t.classList.remove(`cs-hidden`)}return{mount:d,unmount:f,hide:p,show:m,send:i.send,switchSession:i.switchSession,stream:i.stream,inspect:i.getInfo,messages:i.messages,restoreLastCheckpoint:()=>i.checkpoint?.restore()??!1,listCheckpoints:()=>i.checkpoint?.list()??[],hook:e=>(i.listeners.add(e),()=>i.listeners.delete(e)),setData:e=>{if(!i.dataOpsController){console.warn(`[page-agent-sdk] setData 忽略:dataOps 已关闭(capabilities.dataOps:false)`);return}i.dataOpsController.set(e),i.infoTick.value++},getData:()=>i.liveData(),setSkills:e=>{let t=i.skillsController;if(!t){console.warn(`[page-agent-sdk] setSkills 忽略:skills 已关闭(capabilities.skills:false)`);return}t.set(e),i.infoTick.value++},addSkill:e=>{if(!i.skillsController){console.warn(`[page-agent-sdk] addSkill 忽略:skills 已关闭(capabilities.skills:false)`);return}i.addSkill(e)},removeSkill:e=>i.skillsController?i.removeSkill(e):(console.warn(`[page-agent-sdk] removeSkill 忽略:skills 已关闭(capabilities.skills:false)`),!1),listUserSkills:()=>i.listUserSkills(),getUserSkill:e=>i.getUserSkill(e),invalidateSkillCache:e=>{let t=i.skillsController;if(!t){console.warn(`[page-agent-sdk] invalidateSkillCache 忽略:skills 已关闭(capabilities.skills:false)`);return}t.invalidateCache(e)},exportData:()=>{let e=i.liveData()?.bind;return e==null?null:JSON.parse(JSON.stringify(e))},importData:(e,t)=>{let n=i.liveData();if(!n||!i.dataOpsController)return{ok:!1,error:`dataOps 未开启或无主数据`};let r=n.bind;if(typeof r!=`object`||!r)return{ok:!1,error:`主数据 bind 非对象,无法就地还原(集成方应用对象包裹)`};if(t?.validate!==!1){let t=n.schema.safeParse(e);if(!t.success)return{ok:!1,error:`schema 校验失败:`+(t.error?.message??`未知错误`)}}return d_(r,e),t?.emit!==!1&&i.emit({type:`data_change`,operation:`set`,value:r}),{ok:!0}},usage:i.usage,pendingConflict:i.pendingConflict,resolveConflict:e=>i.resolveConflict(e),setTools:e=>i.setTools(e),addTool:e=>i.addTool(e),removeTool:e=>i.removeTool(e),setLlm:e=>i.setLlm(e),setMemory:e=>i.setMemory(e),refreshMemory:()=>i.refreshMemory(),setSubagents:e=>i.setSubagents(e),addSubagent:e=>i.addSubagent(e),removeSubagent:e=>i.removeSubagent(e)}}function rb(e){return(0,r.tool)(async t=>{let n=await e.handler(t);return typeof n==`string`?n:JSON.stringify(n)},{name:e.name,description:e.description,schema:e.schema})}e.CONTEXT_PRESETS=ov,e.ChatDialog=gg,e.CodePreview=$d,e.HUMAN_CONFIRM_TOOL_NAME=i_,e.MessageContent=tf,e.SkillPanel=ih,e.connectMcp=U_,e.copyText=xl,e.createAgent=Vg,e.createApprovalMiddleware=r_,e.createChatSdk=nb,e.createCheckpointManager=m_,e.createCheckpointMiddleware=h_,e.createDataOps=oy,e.createHumanConfirmMiddleware=s_,e.createHumanConfirmTool=o_,e.createMemoryBackend=Py,e.createMemoryMiddleware=Zg,e.createProxyLlm=h,e.createSessionStore=Ry,e.createSkillStore=Uy,e.createSubagentMiddleware=C_,e.createSubagentsMiddleware=E_,e.createUsageHintsMiddleware=py,e.createVerifyMiddleware=D_,e.createVfs=fv,e.createWebStorageBackend=Iy,e.createWriteBackCheck=N_,e.defineDataToolset=uy,e.defineSkill=Wg,e.defineTool=rb,e.detectGarbledToolCall=Ig,e.estimateTokens=wg,e.extractSchemaHint=av,e.extractText=B_,e.fetchDocTools=cy,e.fetchTools=ly,e.filterByToolMode=ay,e.formatZodIssues=cv,e.isQuotaError=Ey,e.jpEval=kv,e.jsonParseError=uv,e.offloadPassThroughChars=Eg,e.offloadThresholdChars=Tg,e.presets=rv,e.resolveContextOptions=sv,e.resolveModelCaps=Cg,e.runSandboxedScript=Pv,e.searchJson=jv,e.selectBuiltinTools=dy,e.systemPromptHelpers=iv,e.toolError=$,e.useChat=bl,Object.defineProperty(e,"z",{enumerable:!0,get:function(){return t.z}}),e.zodError=lv});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "page-agent-sdk",
3
- "version": "2.12.2",
3
+ "version": "2.13.0",
4
4
  "type": "module",
5
5
  "description": "Browser-native AI agent SDK: chat dialog + ReAct tool-calling + schema-validated JSON ops. Vue bundled, framework-agnostic. Works with DeepSeek/OpenAI/MCP.",
6
6
  "main": "./dist/page-agent-sdk.umd.cjs",
@@ -296,6 +296,20 @@ sdk.setLlm(otherChatModel) // or pass a BaseChatModel i
296
296
  sdk.setMemory('User is VIP; prefer concise answers; use incremental patch when editing.')
297
297
  sdk.setMemory('') // clear (empty string skips injection)
298
298
 
299
+ // 3.5 Memory async function source (RAG): load knowledge base doc asynchronously
300
+ // - Async fn evaluated in background on first beforeAgent, cached afterwards
301
+ // - refreshMemory() forces re-evaluation (e.g. after KB doc updated)
302
+ createChatSdk({
303
+ memory: async () => await fetch('/kb/faq.md').then((r) => r.text()),
304
+ /* ... */
305
+ })
306
+ sdk.setMemory(async () => await fetch('/kb/faq-v2.md').then((r) => r.text())) // switch KB
307
+ await sdk.refreshMemory() // force re-fetch after KB doc updated
308
+ // Sync fn reads runtime variable (cached on first eval; refresh to re-evaluate)
309
+ let lang = 'zh'
310
+ sdk.setMemory(() => `请用${lang}回答。`)
311
+ lang = 'en'; await sdk.refreshMemory() // re-evaluate with new lang
312
+
299
313
  // 4. Subagents: runtime add/remove pre-declared subagents (requires subagents:[] at creation)
300
314
  // Pass subagents: [] (empty array) at creation to enable the controller for dynamic add later.
301
315
  sdk.addSubagent({ id: 'translator', description: '中英互译子 agent', systemPrompt: '你是翻译助手。' })
@@ -23,7 +23,8 @@
23
23
  | `addTool(tool)` | `(tool: StructuredToolInterface) => void` | Append user tool at runtime (dedup by name; built-ins untouched). |
24
24
  | `removeTool(name)` | `(name: string) => boolean` | Remove user tool at runtime (built-ins untouched). Returns whether removed. |
25
25
  | `setLlm(llm)` | `(llm: BaseChatModel \| LLMConfig) => void` | Switch LLM at runtime (quota-exhausted→cheaper model / complex task→stronger model / switch provider). Param `BaseChatModel` or `LLMConfig` (constructs `ChatOpenAI` internally). Rebinds tools + re-resolves model caps (`contextWindow`/`maxOutputTokens`). `summaryLlm` unaffected. If new model lacks `bindTools`, tool-calling degrades (agent stays up). |
26
- | `setMemory(text)` | `(text: string) => void` | Update persistent memory directive at runtime (next `augmentPrompt` injects latest; `setMemory('')` clears). |
26
+ | `setMemory(source)` | `(source: string \| (() => string \| Promise<string>)) => void` | Update memory at runtime. Supports `string` and sync/async function (async fn evaluated in background, fits RAG doc loading). `setMemory('')` clears. |
27
+ | `refreshMemory()` | `() => Promise<string>` | Re-evaluate current memory function source (force refresh after RAG doc update). String source returns current value. |
27
28
  | `setSubagents(configs)` | `(configs: SubagentConfig[]) => void` | Runtime swap pre-declared subagents (regenerates `use_<id>` delegation tools + triggers rebind). Requires `subagents:[]` at creation (else controller is null, setter warns, no throw). |
28
29
  | `addSubagent(config)` | `(config: SubagentConfig) => void` | Append pre-declared subagent at runtime (duplicate id warns & skips). Requires `subagents:[]` at creation. |
29
30
  | `removeSubagent(id)` | `(id: string) => boolean` | Remove pre-declared subagent at runtime (by id). Returns whether removed. Requires `subagents:[]` at creation. |
@@ -175,7 +176,7 @@ createChatSdk({
175
176
  - **Runtime dynamic reconfiguration (zero-breakage; not calling = current behavior)**: beyond data/skills, you can also dynamically reconfigure tools / LLM / memory / subagents at runtime without rebuilding the agent:
176
177
  - `sdk.setTools(tools)` / `addTool(tool)` / `removeTool(name)` — swap/append/remove user tools (built-ins untouched; internal `rebindTools` re-binds to LLM; next round uses new set). Use cases: per-permission tool groups, business-stage gating, A/B experiments.
177
178
  - `sdk.setLlm(llm)` — switch LLM at runtime (quota-exhausted→cheaper model / complex task→stronger model / switch provider). Param `BaseChatModel` or `LLMConfig`. Rebinds tools + re-resolves model caps. `summaryLlm` unaffected.
178
- - `sdk.setMemory(text)` — update the persistent memory directive at runtime (next `augmentPrompt` injects latest).
179
+ - `sdk.setMemory(source)` — update memory at runtime; supports `string` and sync/async function (async fn evaluated in background, fits RAG doc loading). `sdk.refreshMemory()` re-evaluates the current function source (force refresh after RAG doc update).
179
180
  - `sdk.setSubagents(configs)` / `addSubagent(config)` / `removeSubagent(id)` — swap/append/remove pre-declared subagents (regenerates `use_<id>` delegation tools + triggers rebind). Requires `subagents:[]` at creation.
180
181
  - All setters trigger `infoTick++` → DebugDrawer refreshes; `inspect()` reflects the latest tools/model/memory/subagent.subagents.
181
182
 
package/types/index.d.ts CHANGED
@@ -413,7 +413,8 @@ export interface ChatSdkOptions {
413
413
  skills?: SkillSpec[];
414
414
  /** 用户创建 skill 的独立持久化存储(与 storage 选项分离)。默认 `{ backend: 'indexed' }`(即使 storage:false 也持久化);`false` 关闭;`id` 手动指定同一 id 可跨页面/跨 agent 复用 */
415
415
  skillStorage?: SkillStoreConfig | false;
416
- memory?: string;
416
+ /** AGENTS.md 风格持久指令。支持 string 与同步/异步函数(异步函数适合加载 RAG 文档) */
417
+ memory?: string | (() => string | Promise<string>);
417
418
  data?: DataConfig;
418
419
  permissions?: PermissionRule[];
419
420
  /** 自定义中间件(注入到内置中间件之后;可拦截/观察模型调用、工具、prompt) */
@@ -559,8 +560,10 @@ export interface ChatSdk {
559
560
  removeTool(name: string): boolean;
560
561
  /** 运行时切换 LLM(BaseChatModel 或 LLMConfig);rebind + 重解析能力 + infoTick */
561
562
  setLlm(llm: ChatModelLike | LLMConfig): void;
562
- /** 运行时更新 memory 文本;立即生效 + infoTick */
563
- setMemory(text: string): void;
563
+ /** 运行时更新 memory;支持 string 与同步/异步函数(异步函数后台求值,下一轮 beforeAgent 前就绪) */
564
+ setMemory(source: string | (() => string | Promise<string>)): void;
565
+ /** 重新求值当前 memory 函数 source(RAG 文档更新后强制刷新);返回最新文本 */
566
+ refreshMemory(): Promise<string>;
564
567
  /** 运行时替换预声明子 agent 列表(重新生成委派工具 + rebind);需创建时配 subagents:[] */
565
568
  setSubagents(configs: SubagentConfig[]): void;
566
569
  /** 运行时追加预声明子 agent(id 重复 warn 跳过);需创建时配 subagents:[] */
@@ -618,6 +621,8 @@ export declare function detectGarbledToolCall(content: string): boolean;
618
621
  export declare function createSubagentMiddleware(opts: any): any;
619
622
  export declare function createVerifyMiddleware(opts: VerifyMiddlewareOptions): any;
620
623
  export declare function createWriteBackCheck(opts?: WriteBackCheckOptions): VerifyCheck;
624
+ export declare function createMemoryMiddleware(memory?: string | (() => string | Promise<string>)): any;
625
+ export type MemorySource = string | (() => string | Promise<string>);
621
626
  export declare const presets: Record<string, any>;
622
627
  /** systemPrompt 辅助片段(标准化最佳实践,拼进 systemPrompt 降低写错门槛) */
623
628
  export declare const systemPromptHelpers: {