page-agent-sdk 2.12.1 → 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 +83 -83
- package/dist/page-agent-sdk.js +640 -610
- package/dist/page-agent-sdk.umd.cjs +6 -6
- 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 +15 -4
|
@@ -98,16 +98,16 @@ app.mount('#app');
|
|
|
98
98
|
…(已截断)`:t}catch{return String(e)}}),v=U(!1);Wr(()=>n.pendingConflict,()=>{v.value=!1});let y=Rs(()=>o.value?.toolName===`request_human_confirmation`),b=Rs(()=>{let e=o.value?.args?.options;return Array.isArray(e)?e.map(String):[]}),x=U(!1);Wr(o,()=>{x.value=!1});let S=Rs(()=>typeof n.canUndo==`function`&&!!n.canUndo());function C(){n.onUndo?.()&&(i.error=null)}let w=U(``),T=U(!0),E=U(!1),D=U(!1),O=U({}),k=Rs(()=>i.messages.length>0),A=Rs(()=>i.messages.some(e=>e.role===`user`)),j=Rs(()=>(n.debugLogs?.length??0)>0);function M(e){return O.value[e]!==!1}function N(e){O.value[e]=!M(e)}function P(e){return e.status===`running`?`⏳`:e.status===`error`?`❌`:`✅`}function ee(e){let t=[];for(let n of e){let e=t.length?t[t.length-1]:null;e&&e.name===n.name?(e.count++,n.status===`running`&&(e.hasRunning=!0),n.status===`error`&&(e.hasError=!0),n.children?.length&&e.children.push(...n.children)):t.push({name:n.name,count:1,hasRunning:n.status===`running`,hasError:n.status===`error`,children:n.children?.length?[...n.children]:[]})}return t.map(e=>({name:e.name,count:e.count,status:e.hasError?`error`:e.hasRunning?`running`:`done`,children:e.children}))}function F(e){return e===`running`?`⏳`:e===`error`?`❌`:`✅`}function I(e){let t=i.messages[e];return!!t&&t.role===`assistant`&&i.loading&&e===i.messages.length-1&&!t.content&&!t.reasoning}function L(){w.value.trim()&&(s(w.value),w.value=``)}function te(e){e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),L())}function ne(e){return new Date(e).toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`})}let re=Rs(()=>{let e=n.getInfo?.();return{mcp:e?.mcp?.servers?.length??0,tools:e?.tools?.length??0}});function ie(e){xl(e).then(e=>{e&&(ae.value=!0,setTimeout(()=>ae.value=!1,1500))})}let ae=U(!1),oe=Rs(()=>{if(!n.drawer||n.drawerWidth==null)return null;let e=n.drawerWidth;return typeof e==`number`?`${e}px`:e});return(t,s)=>(q(),J(K,null,[e.drawer?(q(),J(`div`,{key:0,class:`chat-mask`,onClick:s[0]||=e=>r(`close`)})):X(``,!0),Y(`div`,{class:R([`chat-dialog`,{collapsed:!T.value&&!e.drawer,drawer:e.drawer}]),style:ye(oe.value?{width:oe.value,maxWidth:oe.value}:null)},[Y(`div`,ah,[Y(`div`,oh,[s[23]||=Y(`span`,{class:`header-icon`},`🤖`,-1),Y(`span`,sh,B(e.title),1),W(i).loading?(q(),J(`span`,ch)):X(``,!0)]),Y(`div`,lh,[Y(`button`,{class:R([`action-btn debug-btn`,{active:E.value}]),title:`日志 / 执行流程 / Agent 信息`,onClick:s[1]||=e=>E.value=!0},[s[24]||=Y(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[Y(`path`,{d:`M9 2v8l-3 3v2h12v-2l-3-3V2`}),Y(`path`,{d:`M9 2h6`}),Y(`path`,{d:`M9 18h6`})],-1),j.value?(q(),J(`span`,uh,B(e.debugLogs?.length),1)):X(``,!0)],2),n.onAddSkill?(q(),J(`button`,{key:0,class:R([`action-btn`,{active:D.value}]),title:`创建 / 管理自定义 Skill`,onClick:s[2]||=e=>D.value=!0},[...s[25]||=[Y(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[Y(`path`,{d:`M12 2l2.4 7.4H22l-6 4.4 2.3 7.2L12 16.8 5.7 21l2.3-7.2-6-4.4h7.6z`})],-1)]],2)):X(``,!0),Y(`button`,{class:`action-btn`,title:`清空对话`,onClick:s[3]||=(...e)=>W(c)&&W(c)(...e),disabled:!k.value},[...s[26]||=[Y(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[Y(`polyline`,{points:`3 6 5 6 21 6`}),Y(`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`})],-1)]],8,dh),e.drawer?(q(),J(`button`,{key:1,class:`action-btn`,title:`关闭`,onClick:s[4]||=e=>r(`close`)},[...s[27]||=[Y(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`},[Y(`path`,{d:`M18 6L6 18M6 6l12 12`})],-1)]])):(q(),J(`button`,{key:2,class:`action-btn`,onClick:s[5]||=e=>T.value=!T.value},[(q(),J(`svg`,fh,[T.value?(q(),J(`path`,ph)):(q(),J(`path`,mh))]))]))])]),Qo(nc,{name:`cs-slide`},{default:Ir(()=>[Rr(Y(`div`,{class:`chat-body`,ref_key:`scrollContainer`,ref:a,onScroll:s[8]||=(...e)=>W(p)&&W(p)(...e),onWheel:s[9]||=(...e)=>W(m)&&W(m)(...e)},[k.value?X(``,!0):(q(),J(`div`,hh,[...s[28]||=[Y(`div`,{class:`empty-icon`},`💬`,-1),Y(`p`,null,`有什么可以帮你的?`,-1)]])),(q(!0),J(K,null,Yi(W(i).messages,(t,n)=>(q(),J(`div`,{key:n,class:R([`message-row`,t.role]),"data-msg-idx":n},[e.showAvatar?(q(),J(`div`,_h,B(t.role===`user`?`👤`:`🤖`),1)):X(``,!0),Y(`div`,vh,[t.role===`assistant`&&t.reasoning?(q(),J(`div`,{key:0,class:R([`reasoning-block`,{expanded:M(n)}])},[Y(`div`,{class:`reasoning-header`,onClick:e=>N(n)},[s[29]||=Y(`span`,{class:`reasoning-icon`},`🧠`,-1),s[30]||=Y(`span`,{class:`reasoning-title`},`思考过程`,-1),Y(`span`,bh,B(M(n)?`▾`:`▸`),1)],8,yh),M(n)?(q(),J(`div`,xh,B(t.reasoning),1)):X(``,!0)],2)):X(``,!0),t.role===`assistant`&&t.steps&&t.steps.length?(q(),J(`div`,Sh,[(q(!0),J(K,null,Yi(ee(t.steps),(e,t)=>(q(),J(`div`,{key:t,class:`step-item`},[Y(`div`,Ch,[Y(`span`,wh,B(F(e.status)),1),Y(`span`,Th,B(e.name),1),e.count>1?(q(),J(`span`,Eh,`×`+B(e.count),1)):X(``,!0),e.status===`running`?(q(),J(`span`,Dh,`执行中…`)):X(``,!0)]),e.children&&e.children.length?(q(),J(`div`,Oh,[s[31]||=Y(`div`,{class:`step-children-label`},`🧬 子 agent 进度`,-1),(q(!0),J(K,null,Yi(e.children,(e,t)=>(q(),J(`div`,{key:t,class:`step-child`},[Y(`span`,kh,B(P(e)),1),Y(`span`,Ah,B(e.name),1),e.status===`running`?(q(),J(`span`,jh,`…`)):X(``,!0)]))),128))])):X(``,!0)]))),128))])):X(``,!0),Y(`div`,{class:R([`message-bubble`,{typing:I(n)}])},[I(n)?(q(),J(K,{key:0},[e.showTyping?(q(),J(K,{key:0},[s[32]||=Y(`span`,{class:`dot`},null,-1),s[33]||=Y(`span`,{class:`dot`},null,-1),s[34]||=Y(`span`,{class:`dot`},null,-1)],64)):(q(),J(`span`,Mh,`思考中…`))],64)):(q(),J(K,{key:1},[t.role===`assistant`?(q(),Go(tf,{key:0,content:t.content},null,8,[`content`])):(q(),J(K,{key:1},[rs(B(t.content),1)],64))],64))],2),t.role===`assistant`&&W(i).loading&&n===W(i).messages.length-1&&t.content?(q(),J(`span`,Nh)):X(``,!0),Y(`div`,Ph,B(ne(t.timestamp)),1),t.role===`assistant`&&t.content&&!W(i).loading&&n===W(i).messages.length-1?(q(),J(`div`,Fh,[Y(`button`,{class:`msg-action-btn`,title:ae.value?`已复制`:`复制`,onClick:e=>ie(t.content)},B(ae.value?`✓ 已复制`:`📋 复制`),9,Ih),Y(`button`,{class:`msg-action-btn`,title:`重新生成`,onClick:s[6]||=(...e)=>W(d)&&W(d)(...e)},`🔄 重新生成`)])):X(``,!0)])],10,gh))),128)),W(i).loading&&W(i).messages[W(i).messages.length-1]?.role!==`assistant`?(q(),J(`div`,Lh,[e.showAvatar?(q(),J(`div`,Rh,`🤖`)):X(``,!0),Y(`div`,zh,[Y(`div`,Bh,[e.showTyping?(q(),J(K,{key:0},[s[35]||=Y(`span`,{class:`dot`},null,-1),s[36]||=Y(`span`,{class:`dot`},null,-1),s[37]||=Y(`span`,{class:`dot`},null,-1)],64)):(q(),J(`span`,Vh,`思考中…`))])])])):X(``,!0),W(i).error?(q(),J(`div`,Hh,[Y(`span`,Uh,B(W(i).error),1),A.value?(q(),J(`button`,{key:0,class:`retry-btn`,onClick:s[7]||=(...e)=>W(u)&&W(u)(...e)},`重试`)):X(``,!0),S.value?(q(),J(`button`,{key:1,class:`undo-btn`,title:`回退到上次正常状态(还原对话历史 + 页面属性 + 工作区)`,onClick:C},`↩ 回退`)):X(``,!0)])):X(``,!0)],544),[[bc,T.value]])]),_:1}),W(o)?(q(),J(`div`,Wh,[y.value?(q(),J(K,{key:0},[s[38]||=Y(`div`,{class:`approval-head`},[Y(`span`,{class:`approval-icon`},`❓`),Y(`span`,{class:`approval-title`},`AI 需要你确认`)],-1),W(o).args?.question?(q(),J(`div`,Gh,B(W(o).args.question),1)):X(``,!0),W(o).args?.context?(q(),J(`div`,Kh,B(W(o).args.context),1)):X(``,!0),W(o).args?.recommendation?(q(),J(`div`,qh,`💡 推荐:`+B(W(o).args.recommendation),1)):X(``,!0),Y(`div`,Jh,[Y(`button`,{class:`approval-deny`,onClick:s[10]||=e=>W(f)(!1)},`拒绝`),b.value.length?(q(!0),J(K,{key:0},Yi(b.value,e=>(q(),J(`button`,{key:e,class:`approval-opt`,onClick:t=>W(f)(e)},B(e),9,Yh))),128)):(q(),J(`button`,{key:1,class:`approval-allow`,onClick:s[11]||=e=>W(f)(!0)},`允许`))])],64)):(q(),J(K,{key:1},[Y(`div`,Xh,[s[40]||=Y(`span`,{class:`approval-icon`},`✋`,-1),Y(`span`,Zh,[s[39]||=rs(`需确认工具调用:`,-1),Y(`code`,null,B(W(o).toolName),1)]),h.value?(q(),J(`button`,{key:0,class:`approval-toggle`,onClick:s[12]||=e=>x.value=!x.value},B(x.value?`收起参数`:`查看参数`)+B(x.value?` ▴`:` ▾`),1)):X(``,!0)]),h.value&&x.value?(q(),J(`pre`,Qh,B(h.value),1)):X(``,!0),Y(`div`,$h,[Y(`button`,{class:`approval-deny`,onClick:s[13]||=e=>W(f)(!1)},`拒绝`),Y(`button`,{class:`approval-allow`,onClick:s[14]||=e=>W(f)(!0)},`允许`)])],64))])):X(``,!0),n.pendingConflict?(q(),J(`div`,eg,[Y(`div`,tg,[s[43]||=Y(`span`,{class:`conflict-icon`},`⚠️`,-1),Y(`span`,ng,[s[41]||=rs(`写入冲突:`,-1),Y(`code`,null,B(n.pendingConflict.path),1),s[42]||=rs(` 已被外部修改`,-1)])]),Y(`div`,rg,` AI 基于「读取时的旧值」准备`+B(n.pendingConflict.op===`delete`?`删除`:`写入`)+`,但该属性在你读取之后被外部代码/其他 agent/手动改过。 `,1),Y(`button`,{class:`conflict-toggle`,onClick:s[15]||=e=>v.value=!v.value},B(v.value?`收起对比`:`查看值对比`)+B(v.value?` ▴`:` ▾`),1),v.value?(q(),J(`div`,ig,[Y(`div`,ag,[s[44]||=Y(`div`,{class:`conflict-diff-label`},`AI 想写的值`,-1),Y(`pre`,og,B(g.value||`(delete 操作无值)`),1)]),Y(`div`,sg,[s[45]||=Y(`div`,{class:`conflict-diff-label`},`外部改后的当前值`,-1),Y(`pre`,cg,B(_.value),1)])])):X(``,!0),Y(`div`,lg,[Y(`button`,{class:`conflict-keep`,onClick:s[16]||=e=>n.onResolveConflict?.(`keep_external`),title:`不写入,保留外部修改后的值,AI 重新读取再改`},`保留外部`),Y(`button`,{class:`conflict-overwrite`,onClick:s[17]||=e=>n.onResolveConflict?.(`overwrite`),title:`用 AI 的值覆盖外部修改`},`强制覆盖`),Y(`button`,{class:`conflict-restore`,onClick:s[18]||=e=>n.onResolveConflict?.(`restore`),title:`回退到最近一次历史快照(agent 之前操作的检查点),撤销外部修改 + AI 不写入`},`回退`)])])):X(``,!0),Qo(nc,{name:`cs-slide`},{default:Ir(()=>[Rr(Y(`div`,ug,[n.getInfo?(q(),J(`span`,dg,` 🔌`+B(re.value.mcp)+` · 🔧`+B(re.value.tools),1)):X(``,!0),S.value?(q(),J(`button`,{key:1,class:`undo-foot-btn`,title:`回退到上次正常状态(还原对话历史 + 页面属性 + 工作区)`,onClick:C},`↩ 回退`)):X(``,!0),Rr(Y(`textarea`,{"onUpdate:modelValue":s[19]||=e=>w.value=e,class:`chat-input`,placeholder:e.placeholder,rows:n.inputRows,onKeydown:te},null,40,fg),[[nl,w.value]]),Y(`button`,{class:R([`send-btn`,{"stop-btn":W(i).loading}]),disabled:!W(i).loading&&!w.value.trim(),title:W(i).loading?`停止生成`:`发送`,onClick:s[20]||=e=>W(i).loading?W(l)():L()},[W(i).loading?(q(),J(`svg`,mg,[...s[46]||=[Y(`rect`,{x:`6`,y:`6`,width:`12`,height:`12`,rx:`2`},null,-1)]])):(q(),J(`svg`,hg,[...s[47]||=[Y(`line`,{x1:`22`,y1:`2`,x2:`11`,y2:`13`},null,-1),Y(`polygon`,{points:`22 2 15 22 11 13 2 9 22 2`},null,-1)]]))],10,pg)],512),[[bc,T.value]])]),_:1}),Qo(Vm,{visible:E.value,"onUpdate:visible":s[21]||=e=>E.value=e,logs:e.debugLogs,"get-info":n.getInfo,"info-tick":n.infoTick,"get-skill-content":n.getSkillContent},null,8,[`visible`,`logs`,`get-info`,`info-tick`,`get-skill-content`]),Qo(ih,{visible:D.value,"on-add-skill":n.onAddSkill,"on-remove-skill":n.onRemoveSkill,"get-user-skill-names":n.getUserSkillNames,"on-get-skill":n.onGetSkill,onClose:s[22]||=e=>D.value=!1},null,8,[`visible`,`on-add-skill`,`on-remove-skill`,`get-user-skill-names`,`on-get-skill`])],6)],64))}}),[[`__scopeId`,`data-v-58dec249`]]);function _g(e){return e.replace(/^\/+/,``).replace(/\/+/g,`/`)}function vg(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n)|0;return(t>>>0).toString(36)}function yg(e,t){let n=t.threshold??6e3;if(e.length<=n)return e;if(t.vfsAvailable&&t.files){let n=`large_results/${t.toolName}-${vg(e)}.txt`,r=_g(n);return t.files[r]={content:e,updatedAt:Date.now()},[e.slice(0,1e3),`…[结果过大(共 ${e.length} 字符),已转存到虚拟工作区:${n}]`,`需要完整或局部数据时:用 vfs_read({ path: "${n}", offset, limit }) 分页回读,或 vfs_grep({ pattern, path: "${n}" }) 局部检索。`].join(`
|
|
99
99
|
`)}let r=t.passThroughChars??n;return e.length<=r?e:e.slice(0,r)+`\n…[结果过大(共 ${e.length} 字符),vfs 未启用无法外存,已截断,仅显示前 ${r} 字符。建议开启 vfs(capabilities.vfs 默认开启)以完整外存可回读]`}async function bg(e,t,n,r){let i=Array(e.length),a=Math.max(1,t);if(a===1){for(let t=0;t<e.length&&!r?.aborted;t++)i[t]=await n(e[t],t);return i}let o=0,s=Array.from({length:Math.min(a,e.length)},async()=>{for(;o<e.length;){if(r?.aborted)return;let t=o++;i[t]=await n(e[t],t)}});return await Promise.all(s),i}var xg=[{pattern:/deepseek-v4/i,caps:{contextWindow:1048576,maxOutputTokens:393216}},{pattern:/deepseek-reasoner|deepseek-r1/i,caps:{contextWindow:65536,maxOutputTokens:8192}},{pattern:/deepseek/i,caps:{contextWindow:131072,maxOutputTokens:8192}},{pattern:/gpt-4\.1/i,caps:{contextWindow:1047576,maxOutputTokens:32768}},{pattern:/gpt-4o-mini/i,caps:{contextWindow:131072,maxOutputTokens:16384}},{pattern:/gpt-4o/i,caps:{contextWindow:131072,maxOutputTokens:16384}},{pattern:/gpt-4-turbo|gpt-4-1106|gpt-4-0125/i,caps:{contextWindow:131072,maxOutputTokens:4096}},{pattern:/gpt-3\.5/i,caps:{contextWindow:16385,maxOutputTokens:4096}},{pattern:/claude-3-7-sonnet/i,caps:{contextWindow:2e5,maxOutputTokens:8192}},{pattern:/claude-3-5-sonnet/i,caps:{contextWindow:2e5,maxOutputTokens:8192}},{pattern:/claude-3-opus/i,caps:{contextWindow:2e5,maxOutputTokens:4096}},{pattern:/claude-3-haiku/i,caps:{contextWindow:2e5,maxOutputTokens:4096}},{pattern:/qwen-max|qwen-plus/i,caps:{contextWindow:32768,maxOutputTokens:8192}},{pattern:/qwen2\.5-1m|qwen-1m/i,caps:{contextWindow:1048576,maxOutputTokens:8192}},{pattern:/qwen2\.5/i,caps:{contextWindow:32768,maxOutputTokens:8192}},{pattern:/glm-5\.2/i,caps:{contextWindow:1048576,maxOutputTokens:65536}},{pattern:/glm-5/i,caps:{contextWindow:2e5,maxOutputTokens:65536}},{pattern:/glm-4\.[6-9]/i,caps:{contextWindow:131072,maxOutputTokens:131072}},{pattern:/glm-4\.5/i,caps:{contextWindow:131072,maxOutputTokens:98304}},{pattern:/glm-4|glm4/i,caps:{contextWindow:131072,maxOutputTokens:4096}},{pattern:/kimi-k3/i,caps:{contextWindow:1048576,maxOutputTokens:65536}},{pattern:/kimi-k2|kimi|moonshot/i,caps:{contextWindow:262144,maxOutputTokens:32768}},{pattern:/yi-34b|yi-large/i,caps:{contextWindow:32768,maxOutputTokens:4096}}],Sg={contextWindow:32768,maxOutputTokens:4096};function Cg(e={}){let t=(()=>{if(e.model)return xg.find(t=>t.pattern.test(e.model))?.caps})();return{contextWindow:e.contextWindow??t?.contextWindow??Sg.contextWindow,maxOutputTokens:e.maxOutputTokens??t?.maxOutputTokens??Sg.maxOutputTokens}}function wg(e){if(!e)return 0;let t=(e.match(/[\u4e00-\u9fff]/g)||[]).length,n=e.length-t;return Math.ceil(t*1.5+n*.25)}function Tg(e){return Math.max(2e3,Math.min(2e4,Math.round(e*.035)))}function Eg(e){let t=Tg(e);return Math.min(2e5,Math.max(t,Math.round(e*.7)))}function Dg(){return{messages:[],todos:[],files:{},skillsMetadata:[],skillsLoaded:[],memory:``,verifyAttempts:0}}function Og(e,t){return t?{...e,...t}:e}async function kg(e,t){let n=t;for(let t of e)t.beforeAgent&&(n=Og(n,await t.beforeAgent(n)));return n}function Ag(e,t){let n=t.state;for(let r of e)r.beforeModel&&(n=Og(n,r.beforeModel({messages:t.messages,state:n})));return n}function jg(e,t,n){let r=n;for(let n=e.length-1;n>=0;n--){let i=e[n];i.afterModel&&(r=Og(r,i.afterModel(t,r)))}return r}async function Mg(e,t){let n=t;for(let t=e.length-1;t>=0;t--){let r=e[t];r.afterAgent&&(n=Og(n,await r.afterAgent(n)))}return n}async function Ng(e,t){let n=[];for(let r of e){if(!r.beforeReturn)continue;let e=await r.beforeReturn(t);e&&n.push(e)}return n.length?n.join(`
|
|
100
100
|
|
|
101
|
-
`):null}function Pg(e,t){return e.reduceRight((e,t)=>n=>t.wrapModelCall?t.wrapModelCall(n,e):e(n),t)}function Fg(e,t){return e.reduceRight((e,t)=>n=>t.wrapToolCall?t.wrapToolCall(n,e):e(n),t)}function Ig(e){return e?/<|tool_calls|>|<||[^>]*tool_call|<invoke\s+name=|<\/?tool_call>|<function_call>/i.test(e):!1}var Lg=10,Rg=300,zg=6e3;function Bg(e,t){let n=e.reduce((e,t)=>e+(typeof t.content==`string`?t.content.length:JSON.stringify(t.content).length),0);if(n<=t)return e;let r=0,a=n-t,o=Math.max(100,Math.min(400,Math.round(t/500)));return e.map(e=>{if(r>=a||!(e instanceof i.ToolMessage))return e;let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);if(t.length<=400)return e;let n=`…[已自动压缩 ${t.length} 字符,保留首 ${o}]\n`+t.slice(0,o);return r+=t.length-n.length,new i.ToolMessage({tool_call_id:e.tool_call_id,content:n})})}function Vg(e){let{apiKey:t,baseUrl:r,model:a=`gpt-3.5-turbo`,temperature:o=.7,maxTokens:s,
|
|
101
|
+
`):null}function Pg(e,t){return e.reduceRight((e,t)=>n=>t.wrapModelCall?t.wrapModelCall(n,e):e(n),t)}function Fg(e,t){return e.reduceRight((e,t)=>n=>t.wrapToolCall?t.wrapToolCall(n,e):e(n),t)}function Ig(e){return e?/<|tool_calls|>|<||[^>]*tool_call|<invoke\s+name=|<\/?tool_call>|<function_call>/i.test(e):!1}var Lg=10,Rg=300,zg=6e3;function Bg(e,t){let n=e.reduce((e,t)=>e+(typeof t.content==`string`?t.content.length:JSON.stringify(t.content).length),0);if(n<=t)return e;let r=0,a=n-t,o=Math.max(100,Math.min(400,Math.round(t/500)));return e.map(e=>{if(r>=a||!(e instanceof i.ToolMessage))return e;let t=typeof e.content==`string`?e.content:JSON.stringify(e.content);if(t.length<=400)return e;let n=`…[已自动压缩 ${t.length} 字符,保留首 ${o}]\n`+t.slice(0,o);return r+=t.length-n.length,new i.ToolMessage({tool_call_id:e.tool_call_id,content:n})})}function Vg(e){let{apiKey:t,baseUrl:r,model:a=`gpt-3.5-turbo`,temperature:o=.7,maxTokens:s,extraBody:c,extraConfig:l,systemPrompt:u,tools:d=[],middleware:f=[],maxToolRounds:p=Lg,maxRetries:m=2,retryDelayMs:h=500,maxParallelTools:g=1,maxVerifyAttempts:_=0,onLog:v,onLlmChange:y,debug:b=!1}=e,x=Cg({model:a,contextWindow:e.contextWindow,maxOutputTokens:e.maxOutputTokens}),S=s??x.maxOutputTokens,C=Tg(x.contextWindow),w=Eg(x.contextWindow),T=fn([]);function E(e,t){let n={timestamp:Date.now(),type:e,data:t};T.value.push(n),T.value.length>Rg&&T.value.splice(0,T.value.length-Rg),hn(T),v?.(n),b&&console.log(`%c[Agent] ${e}`,`color:#667eea;font-weight:bold`,t)}let D=e=>{T.value.push(e),T.value.length>Rg&&T.value.splice(0,T.value.length-Rg),hn(T)},O=[...f.flatMap(e=>e.tools||[]),...d],k=e.llm??new n.ChatOpenAI({apiKey:t,model:a,temperature:o,maxTokens:S,configuration:{...r?{baseURL:r}:{},...l},...c?{modelKwargs:c}:{}}),A=O.length>0?k.bindTools?.(O)??k:k;function j(){A=O.length>0?k.bindTools?.(O)??k:k}let M=Dg();function N(){let e=[u||`你是一个智能助手。`];for(let t of f)if(t.augmentPrompt){let n=t.augmentPrompt(M);n&&e.push(n)}return e.join(`
|
|
102
102
|
|
|
103
|
-
`)}function
|
|
103
|
+
`)}function P(e){let t=[new i.SystemMessage(N())];for(let n of e)n.role===`user`?t.push(new i.HumanMessage(n.content)):n.role===`assistant`?t.push(new i.AIMessage(n.content)):n.role===`system`&&t.push(new i.SystemMessage(n.content));return t}function ee(e){let t=e.filter(e=>L(e)!==`system`);return[new i.SystemMessage(N()),...t]}async function F(e,t,n,r){let a=r??A;return yl(async()=>{let r=null,o=``;try{let i=await a.stream(e.messages,n?{signal:n}:void 0);for await(let e of i){r=r?r.concat(e):e;let n=typeof e.content==`string`?e.content:``;n&&t&&(o+=n,t({type:`text`,delta:n}));let i=e.additional_kwargs||{},a=i.reasoning_content||i.reasoning||``;a&&t&&t({type:`reasoning`,delta:a})}}catch(e){if(hl(e,n))return{message:r??new i.AIMessage(o),toolCalls:[],content:o,aborted:!0};throw e}let s=r;return{message:s,toolCalls:s.tool_calls||[],content:o}},{signal:n,maxRetries:m,baseDelayMs:h,onRetry:({attempt:e,error:t,waitMs:n})=>{let r=t?.message??String(t);E(`error`,{stage:`model_retry`,attempt:e,waitMs:n,error:r}),console.warn(`[Agent] 模型调用失败,第 ${e}/${m} 次重试(等 ${n}ms):${r}`)}})}async function I(e){let t=O.find(t=>t.name===e.name);if(!t)return{content:`工具 "${e.name}" 不存在`,status:`error`};try{let n=await t.invoke(e.args),r=typeof n==`string`?n:JSON.stringify(n);return r=yg(r,{files:e.state.files,vfsAvailable:O.some(e=>e.name===`vfs_read`),toolName:e.name,threshold:C,passThroughChars:w}),{content:r,status:`done`}}catch(e){return{content:`工具执行出错:${e.message}`,status:`error`}}}function L(e){return e instanceof i.HumanMessage?`human`:e instanceof i.AIMessage?`ai`:e instanceof i.SystemMessage?`system`:e instanceof i.ToolMessage?`tool`:`unknown`}function te(e,t){return Bg(e,t)}function ne(e){return e.map(e=>{let t=L(e),n={role:t===`human`?`user`:t===`ai`?`assistant`:t},r=typeof e.content==`string`?e.content:JSON.stringify(e.content);r&&(n.content=r.length>zg?r.slice(0,zg)+`…(截断 ${r.length-zg} 字符)`:r);let i=e.tool_calls;Array.isArray(i)&&i.length&&(n.tool_calls=i.map(e=>({id:e.id,type:`function`,function:{name:e.name,arguments:typeof e.args==`string`?e.args:JSON.stringify(e.args)}})));let a=e.tool_call_id;return a&&(n.tool_call_id=a),n})}async function re(e,t,n){T.value=[],M=Dg(),M.messages=e,M=await kg(f,M);let r=e;for(let e of f)if(e.compressInput){let t=await e.compressInput(r);r=Array.isArray(t)?t:t.messages,t&&!Array.isArray(t)&&t.stats&&(M={...M,lastCompression:t.stats})}let o=P(r);E(`context`,{model:a,tools:O.map(e=>e.name),middleware:f.map(e=>e.name)});let s=Pg(f,e=>F(e,t,n)),c=Fg(f,I),l=0,u=null,d=0;try{for(;l<p&&!n?.aborted;){t({type:`round_start`,round:l+1}),M=Ag(f,{messages:o,state:M}),o=ee(o),o=te(o,w),E(`llm_request`,{round:l+1,model:a,tools:O.map(e=>e.name),messages:ne(o)});let e=await s({messages:o,state:M});if(o.push(e.message),E(`llm_response`,{round:l+1,content:e.content,toolCalls:e.toolCalls}),M=jg(f,e,M),e.aborted)return t({type:`done`,content:e.content}),e.content;if(!e.toolCalls.length){if(d<2&&Ig(e.content)){d+=1,E(`middleware`,{stage:`format_retry`,attempt:d,content:e.content.slice(0,200)}),o.push(new i.HumanMessage(`⚠️ 你刚才把工具调用写成了文本(伪 XML/标签,如 <|tool_calls|>、<invoke name=...>),未被系统识别为工具调用,因此未执行,页面无变化。请直接用标准 function calling(工具调用)格式重新发起工具调用,不要在回复正文里输出这些标签或 JSON 文本。`)),l+=1;continue}if(_>0&&M.verifyAttempts<_){let t=await Ng(f,{messages:o,state:M,response:e,log:(e,t)=>E(e,t)});if(t){u=e.content,M.verifyAttempts+=1,o.push(new i.HumanMessage(`⚠️ 验证未通过,请修正:${t}`)),E(`middleware`,{stage:`verify_retry`,attempt:M.verifyAttempts,feedback:t}),l+=1;continue}}return t({type:`done`,content:e.content}),e.content}let r=e.toolCalls.map(e=>{let r=e.id||`call_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;return{id:r,call:e,ctx:{id:r,name:e.name,args:e.args,state:M,signal:n,emit:t,logSink:D}}}),p=await bg(r,g,async e=>{if(n?.aborted)return;t({type:`tool_call`,name:e.call.name,args:e.call.args}),E(`tool_call`,{round:l+1,name:e.call.name,args:e.call.args,id:e.id});let r=await c(e.ctx);return t({type:`tool_result`,name:e.call.name,result:r.content,status:r.status}),E(`tool_result`,{round:l+1,name:e.call.name,result:r.content,status:r.status}),r},n);for(let e=0;e<r.length;e++){let t=p[e];t&&o.push(new i.ToolMessage({tool_call_id:r[e].id,content:t.content}))}if(n?.aborted)break;l++}if(n?.aborted)return t({type:`done`,content:``}),``;if(u!=null)return t({type:`done`,content:u}),u;let e=o[o.length-1];if(e&&L(e)===`tool`){let e=o.filter(e=>L(e)!==`system`),r=[new i.SystemMessage(N()+`
|
|
104
104
|
|
|
105
|
-
工具调用次数已达上限,请基于已有工具结果直接给出最终回答,不要再调用工具。`),...e];
|
|
105
|
+
工具调用次数已达上限,请基于已有工具结果直接给出最终回答,不要再调用工具。`),...e];E(`llm_request`,{round:`wrap_up`,model:a,tools:[],messages:ne(r)});let s=await F({messages:r,state:M},t,n,k);if(E(`llm_response`,{round:`wrap_up`,content:s.content}),s.aborted||s.content)return t({type:`done`,content:s.content}),s.content}let r=`已达到最大工具调用轮次,请简化你的问题。`;return t({type:`done`,content:r}),r}finally{try{await Mg(f,M)}catch(e){console.warn(`[Agent] afterAgent 清理出错(已忽略):`,e)}}}async function ie(e,t){let n=``;return await re(e,e=>{e.type===`done`&&(n=e.content)},t),n}function ae(e){O=[...f.flatMap(e=>e.tools||[]),...e],j()}function oe(e){k=e,j(),y?.(e)}return{invoke:ie,stream:re,getState:()=>M,get allTools(){return O},setTools:ae,setLlm:oe,debugLogs:T}}function Hg(e){if(e.length)return[`## 当前任务清单(用 write_todos 工具管理)`,e.map((e,t)=>`${t+1}. [${e.status}] ${e.content}`).join(`
|
|
106
106
|
`),`规则:开始前用 write_todos 拆解;首个任务标 in_progress;完成一个立即标 completed(不批量);保持至少一个 in_progress 直到全部完成。`].join(`
|
|
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}:
|
|
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}:void 0});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},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(){if(await i.initDone,o){m();return}if(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 t=typeof e.container==`string`?document.querySelector(e.container):e.container;if(!t)throw Error(`createChatSdk: 挂载点未找到(${e.container})`);s=t;let a=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:a.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(t),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
|
@@ -168,6 +168,10 @@ export interface LLMConfig {
|
|
|
168
168
|
contextWindow?: number;
|
|
169
169
|
/** 模型最大输出(token);缺省按 model 名查表。maxTokens 未传时作其缺省,避免设错被截断 */
|
|
170
170
|
maxOutputTokens?: number;
|
|
171
|
+
/** 透传 ChatOpenAI 的 modelKwargs:额外请求 body 参数(如 deepseek thinking: { thinking: { type: 'enabled' } }) */
|
|
172
|
+
extraBody?: Record<string, any>;
|
|
173
|
+
/** 透传 ChatOpenAI configuration 的额外字段(如 headers/timeout/customFetch),与 baseUrl 合并 */
|
|
174
|
+
extraConfig?: Record<string, any>;
|
|
171
175
|
}
|
|
172
176
|
/** LangChain BaseChatModel 的结构形状(provider 抽离:llm 可传任意 provider 实例) */
|
|
173
177
|
export type ChatModelLike = {
|
|
@@ -409,7 +413,8 @@ export interface ChatSdkOptions {
|
|
|
409
413
|
skills?: SkillSpec[];
|
|
410
414
|
/** 用户创建 skill 的独立持久化存储(与 storage 选项分离)。默认 `{ backend: 'indexed' }`(即使 storage:false 也持久化);`false` 关闭;`id` 手动指定同一 id 可跨页面/跨 agent 复用 */
|
|
411
415
|
skillStorage?: SkillStoreConfig | false;
|
|
412
|
-
|
|
416
|
+
/** AGENTS.md 风格持久指令。支持 string 与同步/异步函数(异步函数适合加载 RAG 文档) */
|
|
417
|
+
memory?: string | (() => string | Promise<string>);
|
|
413
418
|
data?: DataConfig;
|
|
414
419
|
permissions?: PermissionRule[];
|
|
415
420
|
/** 自定义中间件(注入到内置中间件之后;可拦截/观察模型调用、工具、prompt) */
|
|
@@ -494,7 +499,9 @@ export interface DialogConfig {
|
|
|
494
499
|
}
|
|
495
500
|
|
|
496
501
|
export interface ChatSdk {
|
|
497
|
-
|
|
502
|
+
/** 渲染对话框到 container(异步:含持久化恢复);ui:false 时仅 init agent(headless)。
|
|
503
|
+
* 可选传 overrideContainer(HTMLElement | 选择器字符串)覆盖创建时 options.container —— 异步绑定:创建时可省略 container,mount 时才指定 */
|
|
504
|
+
mount(overrideContainer?: HTMLElement | string): Promise<void>;
|
|
498
505
|
/** 响应式消息数组(headless 模式自建 UI 读) */
|
|
499
506
|
messages: AgentMessage[];
|
|
500
507
|
unmount(): void;
|
|
@@ -553,8 +560,10 @@ export interface ChatSdk {
|
|
|
553
560
|
removeTool(name: string): boolean;
|
|
554
561
|
/** 运行时切换 LLM(BaseChatModel 或 LLMConfig);rebind + 重解析能力 + infoTick */
|
|
555
562
|
setLlm(llm: ChatModelLike | LLMConfig): void;
|
|
556
|
-
/** 运行时更新 memory
|
|
557
|
-
setMemory(
|
|
563
|
+
/** 运行时更新 memory;支持 string 与同步/异步函数(异步函数后台求值,下一轮 beforeAgent 前就绪) */
|
|
564
|
+
setMemory(source: string | (() => string | Promise<string>)): void;
|
|
565
|
+
/** 重新求值当前 memory 函数 source(RAG 文档更新后强制刷新);返回最新文本 */
|
|
566
|
+
refreshMemory(): Promise<string>;
|
|
558
567
|
/** 运行时替换预声明子 agent 列表(重新生成委派工具 + rebind);需创建时配 subagents:[] */
|
|
559
568
|
setSubagents(configs: SubagentConfig[]): void;
|
|
560
569
|
/** 运行时追加预声明子 agent(id 重复 warn 跳过);需创建时配 subagents:[] */
|
|
@@ -612,6 +621,8 @@ export declare function detectGarbledToolCall(content: string): boolean;
|
|
|
612
621
|
export declare function createSubagentMiddleware(opts: any): any;
|
|
613
622
|
export declare function createVerifyMiddleware(opts: VerifyMiddlewareOptions): any;
|
|
614
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>);
|
|
615
626
|
export declare const presets: Record<string, any>;
|
|
616
627
|
/** systemPrompt 辅助片段(标准化最佳实践,拼进 systemPrompt 降低写错门槛) */
|
|
617
628
|
export declare const systemPromptHelpers: {
|