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.
- package/README.md +9 -3
- package/README.zh-CN.md +9 -3
- package/dist/page-agent-sdk.iife.js +69 -69
- package/dist/page-agent-sdk.js +25 -9
- package/dist/page-agent-sdk.umd.cjs +3 -3
- package/package.json +1 -1
- package/skills/page-agent-sdk-integrate/references/advanced.md +14 -0
- package/skills/page-agent-sdk-integrate/references/api.md +3 -2
- package/types/index.d.ts +8 -3
package/dist/page-agent-sdk.js
CHANGED
|
@@ -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:
|
|
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: () =>
|
|
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 || "")
|
|
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:
|
|
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||``)
|
|
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.
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
563
|
-
setMemory(
|
|
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: {
|