aws-runtime-bridge 1.9.162 → 1.9.169
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/CHANGELOG.md +324 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +31 -3
- package/dist/adapter/AcodeSdkAdapter.js +4 -9
- package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
- package/dist/adapter/CodexSdkAdapter.js +3 -3
- package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/OpencodeSdkAdapter.js +3 -3
- package/dist/adapter/prompts.d.ts +1 -1
- package/dist/adapter/prompts.js +1 -1
- package/dist/adapter/types.d.ts +41 -4
- package/dist/adapter/types.js +1 -1
- package/dist/browser/frame-encode.d.ts +25 -0
- package/dist/browser/frame-encode.js +2 -0
- package/dist/browser/screencast-differ.d.ts +2 -3
- package/dist/browser/screencast-differ.js +1 -1
- package/dist/browser/screencast-manager.js +1 -1
- package/dist/browser/types.d.ts +5 -1
- package/dist/browser/types.js +1 -1
- package/dist/desktop/desktop-mcp-client.js +2 -2
- package/dist/routes/background-tasks.js +3 -3
- package/dist/routes/capabilities.js +1 -1
- package/dist/routes/dashboard.d.ts +2 -0
- package/dist/routes/dashboard.js +4 -4
- package/dist/routes/git.js +22 -22
- package/dist/routes/instance.js +1 -1
- package/dist/routes/launch.js +10 -10
- package/dist/routes/mcp-extra.js +2 -2
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/plugins.js +1 -1
- package/dist/routes/pty.d.ts +11 -3
- package/dist/routes/pty.js +3 -3
- package/dist/routes/runtime-binding.js +1 -1
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/sub-agents.js +8 -8
- package/dist/routes/terminal.d.ts +16 -2
- package/dist/routes/terminal.js +34 -36
- package/dist/services/agent-process-manager.js +1 -1
- package/dist/services/agent-pty-manager.js +4 -4
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/capability-config.d.ts +8 -0
- package/dist/services/capability-config.js +2 -2
- package/dist/services/desktop-mcp-manager.d.ts +3 -1
- package/dist/services/desktop-mcp-manager.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/instance-features.d.ts +10 -0
- package/dist/services/instance-features.js +1 -1
- package/dist/services/instance-init-service.js +1 -1
- package/dist/services/launch-manager.d.ts +9 -1
- package/dist/services/launch-manager.js +6 -6
- package/dist/services/launch-metrics.d.ts +1 -1
- package/dist/services/launch-metrics.js +4 -3
- package/dist/services/mcp-deploy.d.ts +4 -0
- package/dist/services/mcp-env-injector.d.ts +12 -0
- package/dist/services/mcp-env-injector.js +2 -0
- package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
- package/dist/services/mcp-launch-binding-queue.js +1 -1
- package/dist/services/orphan-monitor.js +1 -1
- package/dist/services/panel-env.d.ts +6 -2
- package/dist/services/panel-env.js +1 -1
- package/dist/services/plugin-manager.js +9 -9
- package/dist/services/process-detector.d.ts +23 -3
- package/dist/services/process-detector.js +13 -13
- package/dist/services/runtime-resources-snapshot.d.ts +3 -0
- package/dist/services/runtime-resources-snapshot.js +3 -0
- package/dist/services/session-output.d.ts +13 -0
- package/dist/services/session-output.js +4 -4
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/utils/env-safety.d.ts +15 -0
- package/dist/utils/env-safety.js +2 -0
- package/dist/utils/lifecycle-log.d.ts +2 -0
- package/dist/utils/lifecycle-log.js +3 -0
- package/dist/utils/mcp-utils.js +1 -1
- package/package/acode/dist/background-command-manager.js +4 -4
- package/package/acode/dist/built-in-file-tools.d.ts +13 -0
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
- package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
- package/package/acode/dist/compaction.d.ts +10 -0
- package/package/acode/dist/compaction.js +6 -6
- package/package/acode/dist/context-overflow.js +1 -1
- package/package/acode/dist/index.d.ts +1 -0
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/mcpToolNames.d.ts +4 -0
- package/package/acode/dist/mcpToolNames.js +1 -1
- package/package/acode/dist/runtime-environment.d.ts +2 -0
- package/package/acode/dist/runtime-environment.js +3 -2
- package/package/acode/dist/runtime.d.ts +68 -8
- package/package/acode/dist/runtime.js +28 -27
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/tool-allocation.js +1 -1
- package/package/acode/dist/tool-group-manager.d.ts +12 -0
- package/package/acode/dist/tool-group-manager.js +8 -4
- package/package/acode/dist/types.d.ts +8 -0
- package/package/acode/package.json +1 -1
- package/package/aws-client-agent-mcp/README.md +1 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +22 -8
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
- package/package/aws-client-agent-mcp/dist/logger.js +2 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +19 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.js +18 -18
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -4
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +79 -29
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
- package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
- package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +15 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +1 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +52 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import{spawn as _}from"node:child_process";import{cpSync as F,existsSync as w,lstatSync as ie,mkdirSync as
|
|
1
|
+
import{spawn as _}from"node:child_process";import{cpSync as F,existsSync as w,lstatSync as ie,mkdirSync as N,readFileSync as b,readdirSync as x,renameSync as j,rmSync as P,symlinkSync as se,writeFileSync as q}from"node:fs";import{dirname as J,join as m,resolve as Y}from"node:path";import{fileURLToPath as oe,pathToFileURL as ae}from"node:url";import{parseAcodeCommandMarkdown as le,splitQualifiedToolName as ue}from"@agentswork/acode";import{getBridgeInstancePluginsDir as ce,getBridgeTemplatePluginsDir as de,getBridgeVersion as fe}from"../config.js";import{sanitizeAgentId as I,withFileLock as W,downloadPluginZip as ge,sanitizeArchiveFileName as pe}from"../utils/file-utils.js";import{BLOCKED_ENV_KEYS as he}from"../utils/env-safety.js";import{createLogger as me}from"../utils/logger.js";import{setDeployedDefaultsProvider as ye,reconcileDefaultsFromDeployed as Se}from"./capability-config.js";import{isCapabilityEnabled as we,getAgentPluginSources as ve}from"./instance-features.js";import{PluginEventBuffer as $e}from"./plugin-event-buffer.js";import{extractPluginZip as U}from"./plugin-package.js";const f=me("plugin-manager"),k="plugin-manager",X="\u7CFB\u7EDF\u5185\u7F6E\uFF1A\u7BA1\u7406\u63D2\u4EF6\u7684\u751F\u547D\u5468\u671F\uFF08\u5B89\u88C5/\u5378\u8F7D/\u542F\u505C/\u91CD\u8F7D\uFF09\uFF1B\u5F00\u53D1\u63D2\u4EF6\u7528\u5185\u7F6E /create-plugin \u547D\u4EE4",Q=`\u300C\u63D2\u4EF6\u7BA1\u7406\u63D2\u4EF6\u300D\u7684\u751F\u547D\u5468\u671F\u5DE5\u5177\uFF1A\u7BA1\u7406\u63D2\u4EF6\uFF08\u5B89\u88C5/\u5378\u8F7D/\u91CD\u8F7D/\u542F\u505C/\u5217\u8868\uFF09\u3002\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u5B89\u88C5\u3001\u79FB\u9664\u6216\u4FEE\u590D\u63D2\u4EF6\u65F6\u4F7F\u7528\u3002
|
|
2
2
|
- action=list\uFF1A\u5217\u51FA\u5DF2\u5B89\u88C5\u63D2\u4EF6\uFF08\u72B6\u6001\u3001\u76D1\u542C\u5668\u5065\u5EB7\u3001\u5DE5\u5177\u6570\uFF09\u3002
|
|
3
3
|
- action=install\uFF1Asource \u4E3A\u63D2\u4EF6\u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u4E0D\u505A\u76EE\u5F55\u4F4D\u7F6E\u9650\u5236\uFF09\uFF1Bconfig \u4F20\u63D2\u4EF6 manifest \u91CC userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\u3002\u5B89\u88C5\u65F6\u4F1A\u5148\u628A\u8BE5\u76EE\u5F55\u79FB\u52A8\u5230\u672C agent \u52A0\u8F7D\u63D2\u4EF6\u7684\u4F4D\u7F6E\uFF0C\u518D\u52A0\u8F7D\u79FB\u52A8\u540E\u7684\u526F\u672C\uFF08\u79FB\u52A8\u540E\u6E90\u76EE\u5F55\u4E0D\u518D\u4FDD\u7559\uFF09\uFF0C\u5B89\u88C5\u540E\u7ACB\u5373\u751F\u6548\uFF1A\u4E0B\u4E00\u6B21 poll_message \u7684 pluginCatalog \u5373\u53EF\u89C1\u3002
|
|
4
4
|
- action=reload\uFF1A\u91CD\u8F7D\u6307\u5B9A\u63D2\u4EF6\uFF08\u6539\u8FC7\u63D2\u4EF6\u6587\u4EF6\u540E\u4F7F\u7528\uFF09\uFF0C\u539F\u5B50\u6362\u88C5\uFF0C\u76D1\u542C\u5668\u91CD\u542F\u3002
|
|
5
5
|
- action=enable / disable\uFF1A\u505C\u7528/\u542F\u7528\uFF08disable \u4FDD\u7559\u5B89\u88C5\u4E0E\u914D\u7F6E\uFF0C\u4EC5\u505C\u6B62\u76D1\u542C\u4E0E\u5DE5\u5177\u8C03\u7528\uFF09\u3002
|
|
6
|
-
- action=uninstall\uFF1A\u5378\u8F7D\u5E76\u5220\u9664\u63D2\u4EF6\u76EE\u5F55\uFF08\u4E0D\u53EF\u9006\uFF0C\u9700\u7528\u6237\u660E\u786E\u8981\u6C42\uFF09\u3002`,Pe={type:"object",properties:{action:{type:"string",enum:["install","uninstall","reload","enable","disable","list"],description:"\u751F\u547D\u5468\u671F\u52A8\u4F5C"},name:{type:"string",description:"\u63D2\u4EF6\u540D\uFF08uninstall/reload/enable/disable \u5FC5\u586B\uFF09"},source:{type:"string",description:'install \u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u5B89\u88C5\u65F6\u81EA\u52A8\u79FB\u52A8\u5230\u672C agent \u63D2\u4EF6\u4F4D\u7F6E\u540E\u52A0\u8F7D\uFF09'},config:{type:"object",description:"install \u65F6\u63D2\u4EF6 userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u952E\u503C\u5BF9\uFF09",additionalProperties:{type:"string"}}},required:["action"],additionalProperties:!1},$e=new Set(["install","uninstall","reload","enable","disable","list"]);function ee(){const l=fe();return l&&l!=="unknown"?l:void 0}function Ee(){return oe(new URL("./builtin-commands/",import.meta.url))}const ke=200,R=256*1024,Ae=4*1024,te=6e4,J=6e4,De=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,z=/^[a-z0-9][a-z0-9-]*$/,be=["system.","aws-","acode-"],Te=new Set(["NODE_OPTIONS","NODE_PATH","NODE_EXTRA_CA_CERTS","NODE_REPL_HISTORY","LD_PRELOAD","LD_LIBRARY_PATH","LD_AUDIT","DYLD_INSERT_LIBRARIES","DYLD_LIBRARY_PATH","DYLD_FRAMEWORK_PATH","PYTHONPATH","PYTHONSTARTUP","PYTHONHOME","PERL5LIB","PERL5OPT","RUBYOPT","RUBYLIB","BASH_ENV","ENV","SHELLOPTS","BASHOPTS","IFS","PS1","PS4","GIT_SSH","GIT_SSH_COMMAND","GIT_CONFIG","GIT_CONFIG_GLOBAL","PATH","HOME","USERPROFILE","SYSTEMROOT","COMSPEC","TEMP","TMP","LANG","TZ"]),Oe=/^[A-Za-z_][A-Za-z0-9_]*$/,Le=process.platform==="win32"?"junction":"dir",Ne=/[^\x20-\x7E]/,Ie=6e4,G=20,ne=80;function v(l){return typeof l=="object"&&l!==null&&!Array.isArray(l)}function I(l,e){let t=l;for(const n of e.split(".")){if(!v(t))return;t=t[n]}return t}function D(l,e){return l.length<=e?l:`${l.slice(0,e)}\u2026(\u622A\u65AD,\u5171 ${l.length} \u5B57\u7B26)`}async function C(l,e=8,t=200){for(let n=0;;n++)try{E(l,{recursive:!0,force:!0});return}catch(r){if(n>=e-1)throw r;await new Promise(i=>setTimeout(i,t))}}async function re(l,e){T(U(e),{recursive:!0});try{j(l,e);return}catch(t){const n=t?.code;if(!n||!["EXDEV","EPERM","EACCES","EBUSY","EINVAL"].includes(n))throw t}F(l,e,{recursive:!0,filter:t=>!/[\\/]\.git([\\/]|$)/.test(t)&&!/[\\/]node_modules([\\/]|$)/.test(t)}),await C(l)}function b(l,e){l.logs.push(`${new Date().toISOString()} ${e}`),l.logs.length>ke&&l.logs.shift()}function B(l,e,t="params"){if(!v(l))return[];const n=[],r=l.type;if(typeof r=="string"&&!Ce(r,e))return[`${t}: \u671F\u671B ${r}\uFF0C\u5B9E\u9645 ${Re(e)}`];if(Array.isArray(l.enum)&&l.enum.length>0&&(l.enum.some(s=>JSON.stringify(s)===JSON.stringify(e))||n.push(`${t}: \u503C ${JSON.stringify(e)} \u4E0D\u5728\u679A\u4E3E ${JSON.stringify(l.enum)} \u5185`)),r==="object"&&v(e)){const i=v(l.properties)?l.properties:{},s=Array.isArray(l.required)?l.required:[];for(const o of s)(!(o in e)||e[o]===void 0)&&n.push(`${t}.${o}: \u5FC5\u586B\u53C2\u6570\u7F3A\u5931`);for(const[o,a]of Object.entries(i))o in e&&e[o]!==void 0&&n.push(...B(a,e[o],`${t}.${o}`));if(l.additionalProperties===!1)for(const o of Object.keys(e))o in i||n.push(`${t}.${o}: \u4E0D\u5141\u8BB8\u7684\u672A\u77E5\u53C2\u6570\uFF08schema additionalProperties=false\uFF09`)}return r==="array"&&Array.isArray(e)&&v(l.items)&&e.forEach((i,s)=>{n.push(...B(l.items,i,`${t}[${s}]`))}),n}function Ce(l,e){switch(l){case"string":return typeof e=="string";case"number":return typeof e=="number"&&Number.isFinite(e);case"boolean":return typeof e=="boolean";case"object":return v(e);case"array":return Array.isArray(e);case"null":return e===null;default:return!0}}function Re(l){return l===null?"null":Array.isArray(l)?"array":typeof l}class Me{constructor(e={}){this.agents=new Map,this.moduleNonce=0,this.templatePullInFlight=new Set,this.backgroundTemplatePulls=new Set,this.rootDir=e.rootDir??de(),this.runtimeRootDir=e.runtimeRootDir}forAgent(e){return{listPlugins:()=>this.list(e),getCatalog:()=>this.getCatalog(e),getToolSchema:t=>this.getToolSchema(e,t),invokeTool:(t,n,r,i)=>this.invokeTool(e,t,n,r,i),manage:t=>this.manage(e,t),getCommandDirs:()=>this.getCommandDirs(e),exposePlugin:t=>this.exposePlugin(e,t)}}setOnPluginsChanged(e){this.onPluginsChanged=e}notifyPluginsChanged(e){try{this.onPluginsChanged?.(e)}catch(t){f.warn("[agent:%s] onPluginsChanged \u56DE\u8C03\u5931\u8D25: %s",e,t instanceof Error?t.message:String(t))}}async getCommandDirs(e){return[...(await this.hydrate(e)).plugins.values()].filter(n=>n.enabled&&n.commandDir).map(n=>n.commandDir)}async getPluginCommands(e){const t=await this.hydrate(e),n=[],r=Ee(),i=this.parseCommandDir($,r);i.length===0&&f.warn("[plugin-manager] \u5185\u7F6E\u547D\u4EE4\u76EE\u5F55\u4E0D\u53EF\u8BFB\u6216\u4E3A\u7A7A: %s\uFF08/create-plugin \u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u5305\u662F\u5426\u5B8C\u6574\uFF09",r),n.push(...i);for(const s of t.plugins.values())!s.enabled||!s.commandDir||n.push(...this.parsePluginCommandDir(s));return n}parsePluginCommandDir(e){return this.parseCommandDir(e.name,e.commandDir)}parseCommandDir(e,t){const n=[];if(!t)return n;try{for(const r of x(t)){if(!r.endsWith(".md"))continue;const i=m(t,r);try{const s=le(i,k(i,"utf8"));s.plugin=e,n.push(s)}catch(s){f.warn("[plugin:%s] \u547D\u4EE4\u89E3\u6790\u5931\u8D25 %s: %s",e,r,s instanceof Error?s.message:String(s))}}}catch{}return n}async list(e){const t=await this.hydrate(e),n=new Map;for(const r of t.plugins.values()){const i=this.toSummary(r);n.set(i.name,i)}n.has($)||n.set($,{name:$,version:ee(),description:X,status:"enabled",enabled:!0,source:"builtin",installedAt:new Date().toISOString(),toolCount:1,tools:[{name:"plugin-manager.manage",description:"\u63D2\u4EF6\u751F\u547D\u5468\u671F\u7BA1\u7406\uFF08install/uninstall/reload/disable/enable/list\uFF09"}],listeners:[],builtin:!0});for(const r of this.readSharedManifest()){const i=r.pluginName;if(!this.deployedPluginHealthy(i))continue;const o=n.get(i);if(o){String(o.source||"").startsWith("shared:")&&(o.enabled=this.effectiveSharedEnabled(e,r));continue}n.set(i,{name:i,version:this.deployedPluginVersion(i),status:"enabled",enabled:this.effectiveSharedEnabled(e,r),source:`shared:${r.fileName??`${i}.zip`}`,installedAt:new Date().toISOString(),toolCount:0,listeners:[]})}return[...n.values()].sort((r,i)=>r.name.localeCompare(i.name))}deployedPluginVersion(e){try{const t=JSON.parse(k(m(this.deployedPluginDir(e),"plugin.json"),"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}async getCatalog(e){const t=await this.hydrate(e),n=[];for(const r of t.plugins.values()){if(!r.enabled||r.status==="error")continue;const i=r.tools.slice(0,G).map(s=>({name:s.name,description:D(s.title||s.description,ne),requiredParams:this.requiredParamsOf(s)}));r.tools.length>G&&i.push({name:`(\u53E6\u6709 ${r.tools.length-G} \u4E2A\u5DE5\u5177\u672A\u5217\u51FA)`,description:'\u7528 function_call {action:"catalog"} \u67E5\u770B\u5168\u91CF',requiredParams:void 0}),n.push({plugin:r.name,version:r.version,description:r.description,status:r.status,tools:i})}return n.push({plugin:$,version:ee(),description:X,status:"enabled",tools:[{name:"manage",description:D(Q,ne),requiredParams:["action"]}]}),{revision:t.catalogRevision,plugins:n}}async getToolSchema(e,t){const n=ue(t);if(!n)return null;if(n.plugin===$&&n.tool==="manage")return{plugin:$,name:"manage",description:Q,inputSchema:Pe};const i=(await this.hydrate(e)).plugins.get(n.plugin);if(!i||!i.enabled)return null;const s=i.tools.find(o=>o.name===n.tool);return s?{plugin:i.name,name:s.name,title:s.title,description:s.description,inputSchema:s.inputSchema??{type:"object",properties:{}}}:null}async invokeTool(e,t,n,r,i){if(t===$&&n==="manage"){const u=this.buildManageRequest(r);if(!u)return{ok:!1,error:"plugin-manager.manage \u7F3A\u5C11 action"};const c=await this.manage(e,u);if(!c.ok)return{ok:!1,error:c.error??"\u63D2\u4EF6\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25"};const d={ok:!0};return c.plugins&&(d.plugins=c.plugins),c.summary&&(d.summary=c.summary),{ok:!0,result:d}}const s=await this.hydrate(e),o=s.plugins.get(t);if(!o)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\uFF08\u53EF\u7528\u63D2\u4EF6: ${[...s.plugins.keys()].join(", ")||"\u65E0"}\uFF09`};if(!o.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u5DF2\u505C\u7528\uFF0C\u53EF\u8BA9\u7528\u6237\u5728\u9762\u677F\u6216\u7528 plugin-manager.manage enable \u542F\u7528`};const a=o.tools.find(u=>u.name===n);if(!a)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5DE5\u5177 ${n}\uFF08\u53EF\u7528: ${o.tools.map(u=>u.name).join(", ")||"\u65E0"}\uFF09`};if(a.inputSchema){const u=B(a.inputSchema,r);if(u.length>0)return{ok:!1,error:`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${u.join("; ")}`,inputSchema:a.inputSchema}}return this.executeHandler(e,o,a,r,i)}buildManageRequest(e){const t=e.action;if(typeof t!="string"||!$e.has(t))return null;const n={action:t};if(typeof e.name=="string"&&e.name.trim()&&(n.name=e.name.trim()),typeof e.source=="string"&&e.source.trim()&&(n.source=e.source.trim()),e.config&&typeof e.config=="object"&&!Array.isArray(e.config)){const r={};for(const[i,s]of Object.entries(e.config))typeof s=="string"&&(r[i]=s);n.config=r}return n}async executeHandler(e,t,n,r,i){const s=Date.now(),o=n.handler??{type:"process"};try{return o.type==="mcp"?{ok:!1,error:"handler.type=mcp \u5C06\u5728\u540E\u7EED\u7248\u672C\u652F\u6301\uFF0C\u8BF7\u6539\u7528 process/module handler"}:o.type==="module"?{ok:!0,result:await this.invokeModuleHandler(t,o,r,e,i),durationMs:Date.now()-s}:!o.command||!o.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${n.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await this.invokeProcessHandler(t,o,r,e,i),durationMs:Date.now()-s}}catch(a){return{ok:!1,error:a instanceof Error?a.message:String(a),durationMs:Date.now()-s}}}async invokeProcessHandler(e,t,n,r,i){const s=Y(t.command??"",{params:n});if(s.length===0)throw new Error("process handler command \u4E3A\u7A7A");const o=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te,a=new AbortController,u=()=>a.abort();i?.signal?.addEventListener("abort",u,{once:!0});const c=setTimeout(()=>a.abort(),o);try{return await new Promise((d,y)=>{f.info("[plugin:%s] spawn: %s",e.name,s.join(" "));const p=_(s[0],s.slice(1),{cwd:e.dir,env:this.buildPluginEnv(e,r),shell:t.shell===!0,windowsHide:!0,signal:a.signal});let g="",h="";p.stdin?.on("error",()=>{}),p.stdout?.on("data",P=>{g.length<R&&(g+=P.toString("utf8"))}),p.stderr?.on("data",P=>{h.length<R&&(h+=P.toString("utf8"))}),p.on("error",P=>{y(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${P.message}`))}),p.on("close",P=>{const A=g.trim();if(P!==0){const O=D(h.trim()||A||"(\u65E0\u8F93\u51FA)",600);y(new Error(a.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${o}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${P}: ${O}`));return}if(!A){d({ok:!0});return}try{d(JSON.parse(A))}catch{d(A)}});try{t.stdin==="params"?p.stdin?.end(`${JSON.stringify(n)}
|
|
7
|
-
`):p.stdin?.end()}catch{}})}finally{clearTimeout(c),i?.signal?.removeEventListener("abort",u)}}async invokeModuleHandler(e,t,n,r,i){if(!t.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const s=m(e.dir,t.module);let o=e.moduleCache.get(s);o||(o=await import(`${ae(s).href}?acode_nonce=${e.importNonce}`),e.moduleCache.set(s,o));const a=t.export||"default",c=o[a];if(typeof c!="function")throw new Error(`\u6A21\u5757 ${t.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${a}`);const d=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te;let y;const p=Promise.resolve().then(()=>c(n,{agentId:r,signal:i?.signal,pluginRoot:e.dir}));try{return await Promise.race([p,new Promise((g,h)=>{y=setTimeout(()=>h(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${d}ms)`)),d)})])}finally{clearTimeout(y)}}buildPluginEnv(e,t){const n={};for(const i of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const s=process.env[i];s!==void 0&&(n[i]=s)}n.ACODE_PLUGIN_ROOT=e.dir,n.ACODE_AGENT_ID=t,n.ACODE_PLUGIN_NAME=e.name;const r=new Set((e.userConfig??[]).map(i=>i.key));for(const[i,s]of Object.entries(e.configValues))r.has(i)&&(!
|
|
8
|
-
`,"utf8")}async migrateLegacySharedIfNeeded(){try{if(w(this.deployedManifestFile()))return;const e=m(this.legacySharedDir(),"manifest.json");if(!w(e))return;const t=JSON.parse(k(e,"utf8")),n=Array.isArray(t.plugins)?t.plugins:[];if(n.length===0)return;const r=[];for(const i of n){const s=m(this.legacySharedDir(),i.zipFile);if(!(!i.pluginName||!w(s)))try{const o=await this.deployPluginZipToPersistentDir(k(s),i.pluginName);if(!o)continue;r.push(o),f.info("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u5230\u90E8\u7F72\u533A: %s",i.pluginName)}catch(o){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6 %s \u8FC1\u79FB\u5931\u8D25: %s",i.pluginName,o instanceof Error?o.message:String(o))}}r.length>0&&this.writeSharedManifest(r),E(this.legacySharedDir(),{recursive:!0,force:!0})}catch(e){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u672A\u6267\u884C\uFF08\u4E0B\u6B21\u91CD\u8BD5\uFF09: %s",e instanceof Error?e.message:String(e))}}deployedPluginHealthy(e){return w(m(this.deployedPluginDir(e),"plugin.json"))}runtimeDirFor(e){return this.runtimeRootDir?m(this.runtimeRootDir,N(e)):ce(e)}runtimeLinkPath(e,t){return m(this.runtimeDirFor(e),t)}ensureRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t),r=this.deployedPluginDir(t);if(!w(m(r,"plugin.json")))return!1;T(this.runtimeDirFor(e),{recursive:!0});try{if(w(n)){let i=!1;try{i=ie(n).isSymbolicLink()}catch{i=!1}if(i)try{return x(n),!0}catch{}E(n,{recursive:!0,force:!0})}return se(r,n,Le),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",e,n,r),!0}catch(i){return f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",e,t,r,i instanceof Error?i.message:String(i)),!1}}removeRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t);try{w(n)&&(E(n,{recursive:!0,force:!0}),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",e,t))}catch(r){f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",e,t,r instanceof Error?r.message:String(r))}}async saveSharedPlugin(e,t,n=!0,r){if(!e||e.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};await this.migrateLegacySharedIfNeeded();const i=m(this.rootDir,"tmp",`deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const s=await q(e,i),o=this.loadManifestOnly(s.pluginDir);if(!o.ok)return o;const a=o.manifest.name,u=this.readSharedManifest().find(g=>g.pluginName===a);if(u&&u.sha256===r&&this.deployedPluginHealthy(a))return{ok:!0,pluginName:a};await this.suspendDeployedPluginAcrossAgents(a),T(this.deployedDir(),{recursive:!0});const c=this.deployedPluginDir(a),d=m(this.deployedDir(),`.old-${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(w(c))try{j(c,d)}catch{E(c,{recursive:!0,force:!0})}try{F(s.pluginDir,c,{recursive:!0,filter:g=>!/[\\/]\.git([\\/]|$)/.test(g)&&!/[\\/]node_modules([\\/]|$)/.test(g)})}catch(g){throw w(d)&&(E(c,{recursive:!0,force:!0}),j(d,c)),g}w(d)&&E(d,{recursive:!0,force:!0}),await W(this.deployedManifestFile(),async()=>{const g=this.readSharedManifest().filter(h=>h.pluginName!==a);g.push({pluginName:a,zipFile:u?.zipFile??`${a}.zip`,fileName:t,defaultEnabled:n,sha256:r}),this.writeSharedManifest(g)}),f.info("[shared] \u63D2\u4EF6\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",a,t,r?`, sha256=${r.slice(0,12)}\u2026`:"");const p=(await this.applySharedToKnownAgents()).find(g=>g.installed.includes(a));return p&&f.info("[shared] \u5DF2\u540C\u6B65\u5230\u8FD0\u884C\u4E2D agent: %s",p.agentId),{ok:!0,pluginName:a}}catch(s){const o=s instanceof Error?s.message:String(s);return f.warn("[shared] \u63D2\u4EF6\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,o),{ok:!1,error:`\u63D2\u4EF6\u90E8\u7F72\u5931\u8D25: ${o}`}}finally{await C(i,3,100).catch(()=>{})}}async deployPluginZipToPersistentDir(e,t){if(!e||e.length===0)return null;const n=m(this.rootDir,"tmp",`migrate-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const r=await q(e,n),i=this.loadManifestOnly(r.pluginDir);if(!i.ok)return null;const s=i.manifest.name;if(t&&s!==t)return null;T(this.deployedDir(),{recursive:!0});const o=this.deployedPluginDir(s);return w(o)&&E(o,{recursive:!0,force:!0}),F(r.pluginDir,o,{recursive:!0,filter:a=>!/[\\/]\.git([\\/]|$)/.test(a)&&!/[\\/]node_modules([\\/]|$)/.test(a)}),{pluginName:s,zipFile:`${s}.zip`,fileName:`${s}.zip`,defaultEnabled:!0}}finally{E(n,{recursive:!0,force:!0})}}async suspendDeployedPluginAcrossAgents(e){for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e),this.bumpCatalogRevision(t),f.info("[agent:%s] \u5DF2\u6458\u9664\u63D2\u4EF6\u7B49\u5F85\u90E8\u7F72\u533A\u66F4\u65B0: %s",t.agentId,e))});t.queue=n.catch(()=>{}),await n}}async applySharedToKnownAgents(){const e=[];for(const t of this.agents.values()){if(!t.hydrated)continue;const n=await this.syncSharedIntoStateQueued(t);n.length>0&&e.push({agentId:t.agentId,installed:n})}return e}async syncSharedIntoStateQueued(e){const t=e.queue.then(()=>this.syncSharedIntoState(e));return e.queue=t.catch(()=>[]),t}effectiveSharedEnabled(e,t){return Se(e,"plugins",t.pluginName)&&(t.defaultEnabled??!0)}async pullTemplatePluginsFromCapabilities(e){const t=we(e.agentId);if(!t)return;const n=this.readSharedManifest();for(const[r,i]of Object.entries(t)){if(!i.url)continue;const s=n.find(a=>a.pluginName===r);if(!s||!s.sha256||s.sha256===i.sha256&&this.deployedPluginHealthy(r)||this.templatePullInFlight.has(r))continue;this.templatePullInFlight.add(r);const o=m(this.rootDir,"tmp",`pull-${N(e.agentId)}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{T(o,{recursive:!0});let a=`${r}.zip`;try{const y=decodeURIComponent(i.url.split("/").pop()||"");y.toLowerCase().endsWith(".zip")&&(a=pe(y,`${r}.zip`))}catch{}const u=await ge({downloadUrl:i.url,fileName:a,sha256:i.sha256},o);if(!u)continue;const c=k(u.outputPath),d=await this.saveSharedPlugin(c,u.fileName,s.defaultEnabled??!0,i.sha256);d.ok?f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u81EA\u52A8\u5BF9\u8D26\u66F4\u65B0\u6210\u529F: %s",e.agentId,d.pluginName??r):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u66F4\u65B0\u5931\u8D25: %s: %s",e.agentId,r,d.error)}catch(a){f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6 %s \u66F4\u65B0\u5931\u8D25: %s",e.agentId,r,a instanceof Error?a.message:String(a))}finally{this.templatePullInFlight.delete(r),await C(o,3,100).catch(()=>{})}}}queueTemplatePull(e){this.backgroundTemplatePulls.has(e.agentId)||(this.backgroundTemplatePulls.add(e.agentId),this.pullTemplatePluginsFromCapabilities(e).catch(t=>{f.warn("[agent:%s] \u540E\u53F0\u63D2\u4EF6\u5BF9\u8D26\u66F4\u65B0\u5931\u8D25: %s",e.agentId,t instanceof Error?t.message:String(t))}).finally(()=>{this.backgroundTemplatePulls.delete(e.agentId)}))}async syncSharedIntoState(e){this.queueTemplatePull(e);const t=this.readSharedManifest(),n=new Set,r=[];let i=0;for(const s of t)if(n.add(s.pluginName),this.effectiveSharedEnabled(e.agentId,s)){const a=e.plugins.get(s.pluginName);if(!this.ensureRuntimeLink(e.agentId,s.pluginName))continue;const u=this.runtimeLinkPath(e.agentId,s.pluginName);if(!a){const c=this.loadPluginFromDir(e,u,`shared:${s.fileName}`,new Date().toISOString(),{});c.ok?(e.plugins.set(c.plugin.name,c.plugin),r.push(c.plugin.name),f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u5DF2\u6309\u5F00\u542F\u6001\u52A0\u8F7D: %s",e.agentId,s.pluginName)):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u52A0\u8F7D\u5931\u8D25: %s: %s",e.agentId,s.pluginName,c.error)}}else{const a=e.plugins.get(s.pluginName);a&&(this.stopAllListeners(a),e.plugins.delete(s.pluginName),i++),this.removeRuntimeLink(e.agentId,s.pluginName)}return this.cleanupRuntimeDir(e,n),(r.length>0||i>0)&&this.bumpCatalogRevision(e),this.persistInstalled(e),r}cleanupRuntimeDir(e,t){const n=this.runtimeDirFor(e.agentId);try{if(!w(n))return;const r=new Set(t);for(const i of x(n))!r.has(i)&&!e.plugins.has(i)&&this.removeRuntimeLink(e.agentId,i)}catch{}}async applyCapabilities(e){const t=await this.hydrate(e);await this.pullTemplatePluginsFromCapabilities(t),await this.syncSharedIntoState(t)}exposePlugin(e,t){if(!t)return;const n=this.agentState(e);n.pendingExposed.add(t),n.exposedThisSession.add(t),f.debug("[agent:%s] \u63D2\u4EF6\u5DF2\u89E6\u53D1\u5F85\u66B4\u9732: %s",e,t)}async drainEvents(e,t={}){const n=await this.hydrate(e);this.ensureListenersRunning(n);const r=n.buffer.drain(t),i=await this.consumeExposedCatalog(n);return{revision:r.revision,events:r.events,catalog:i,compactionSeq:n.compactionSeq}}async consumeExposedCatalog(e){if(e.pendingExposed.size===0)return null;const t=await this.getCatalog(e.agentId),n=[...e.pendingExposed];e.pendingExposed.clear();const r=t.plugins.filter(i=>n.includes(i.plugin));return r.length===0?null:{revision:t.revision,plugins:r}}pushDeprecatedNotice(e,t,n){e.buffer.push({plugin:t,event:"plugin-deprecated",priority:"urgent",receivedAt:Date.now(),message:{msgId:`plugin-deprecated-${t}-${Date.now()}`,channel:"plugin-event",senderId:`plugin:${t}`,senderName:`\u63D2\u4EF6[${t}]`,receiverId:e.agentId||void 0,content:`\u3010\u7CFB\u7EDF\u63D0\u793A\u3011\u63D2\u4EF6 ${t} ${n}\uFF0C\u5176\u63D0\u4F9B\u7684\u5DE5\u5177\u4E0D\u518D\u53EF\u8C03\u7528\u3002\u5982\u4ECD\u9700\u4F7F\u7528\u8BF7\u91CD\u65B0\u5B89\u88C5/\u542F\u7528\u8BE5\u63D2\u4EF6\u3002`,requireReply:!1,role:"system",timestamp:new Date().toISOString()}})}markAgentCompacted(e){const t=this.agentState(e);t.compactionSeq++,f.debug("[agent:%s] \u4E0A\u4E0B\u6587\u538B\u7F29\u6807\u8BB0: compactionSeq=%d",e,t.compactionSeq)}async enqueueExternalEvent(e,t,n){const r=await this.hydrate(e),i=r.plugins.get(t);if(!i||!i.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`};const s=typeof n.event=="string"?n.event:"",o=i.listeners.find(a=>a.transport.type==="http-callback"&&(!s||a.event===s));return o?(this.enqueueEvent(r,i,o,n),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5339\u914D\u7684 http-callback \u76D1\u542C\u5668\uFF08event=${s||"(\u7A7A)"}\uFF09`}}bumpCatalogRevision(e){e.catalogRevision++}agentState(e){let t=this.agents.get(e);return t||(t={agentId:e,plugins:new Map,buffer:new ve(e),hydrated:!1,queue:Promise.resolve(),catalogRevision:0,eventSeq:0,compactionSeq:0,pendingExposed:new Set,exposedThisSession:new Set},this.agents.set(e,t)),t}async hydrate(e){const t=this.agentState(e);return t.hydratePromise||(t.hydratePromise=this.doHydrate(t).catch(n=>{throw t.hydratePromise=void 0,n})),await t.hydratePromise,t}async doHydrate(e){const t=e.agentId;await this.migrateLegacySharedIfNeeded();const n=this.installedFile(t);if(!w(n)){await this.syncSharedIntoState(e).catch(()=>{}),e.hydrated=!0;return}try{const r=JSON.parse(k(n,"utf8")),i=this.readSecrets(t);for(const s of r.plugins??[]){if(String(s.source||"").startsWith("shared:"))continue;const a=m(this.rootDir,"cache",N(t),s.name);if(!w(m(a,"plugin.json"))){f.warn("[agent:%s] \u5DF2\u5B89\u88C5\u63D2\u4EF6\u76EE\u5F55\u7F3A\u5931\uFF0C\u8DF3\u8FC7: %s",t,s.name);continue}const u={...s.config,...i[s.name]??{}},c=this.loadPluginFromDir(e,a,s.source,s.installedAt,u);if(c.ok){const d=c.plugin;d.enabled=s.enabled,e.plugins.set(d.name,d)}else f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25: %s: %s",t,s.name,c.error)}}catch(r){const i=r instanceof Error?r.message:String(r);f.error("[agent:%s] installed.json \u89E3\u6790\u5931\u8D25: %s",t,i)}await this.syncSharedIntoState(e).catch(r=>{f.warn("[agent:%s] \u5171\u4EAB\u63D2\u4EF6\u540C\u6B65\u5931\u8D25: %s",t,r instanceof Error?r.message:String(r))}),e.hydrated=!0}installedFile(e){return m(this.rootDir,"agents",N(e),"installed.json")}persistInstalled(e){this.persistSecrets(e);const t=this.installedFile(e.agentId);T(U(t),{recursive:!0});const n=[...e.plugins.values()].map(r=>({name:r.name,source:r.source,installedAt:r.installedAt,enabled:r.enabled,config:this.stripSensitiveValues(r)}));H(t,`${JSON.stringify({version:1,plugins:n},null,2)}
|
|
9
|
-
`,"utf8")}sensitiveKeysOf(e){return(e.userConfig??[]).filter(t=>t?.sensitive===!0&&typeof t.key=="string").map(t=>t.key)}stripSensitiveValues(e){const t=new Set(this.sensitiveKeysOf(e)),n={};for(const[r,i]of Object.entries(e.configValues))t.has(r)||(n[r]=i);return n}secretsFile(e){return m(this.rootDir,"agents",
|
|
10
|
-
`,{encoding:"utf8",mode:384})}readJsonFile(e){if(!w(e))return{ok:!0,data:{}};try{const t=JSON.parse(
|
|
6
|
+
- action=uninstall\uFF1A\u5378\u8F7D\u5E76\u5220\u9664\u63D2\u4EF6\u76EE\u5F55\uFF08\u4E0D\u53EF\u9006\uFF0C\u9700\u7528\u6237\u660E\u786E\u8981\u6C42\uFF09\u3002`,ke={type:"object",properties:{action:{type:"string",enum:["install","uninstall","reload","enable","disable","list"],description:"\u751F\u547D\u5468\u671F\u52A8\u4F5C"},name:{type:"string",description:"\u63D2\u4EF6\u540D\uFF08uninstall/reload/enable/disable \u5FC5\u586B\uFF09"},source:{type:"string",description:'install \u6765\u6E90\uFF0C\u5F53\u524D\u652F\u6301 "local:<\u4EFB\u610F\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>"\uFF08\u5B89\u88C5\u65F6\u81EA\u52A8\u79FB\u52A8\u5230\u672C agent \u63D2\u4EF6\u4F4D\u7F6E\u540E\u52A0\u8F7D\uFF09'},config:{type:"object",description:"install \u65F6\u63D2\u4EF6 userConfig \u58F0\u660E\u7684\u914D\u7F6E\u503C\uFF08\u952E\u503C\u5BF9\uFF09",additionalProperties:{type:"string"}}},required:["action"],additionalProperties:!1},Pe=new Set(["install","uninstall","reload","enable","disable","list"]);function ee(){const l=fe();return l&&l!=="unknown"?l:void 0}function be(){return oe(new URL("./builtin-commands/",import.meta.url))}const Ee=200,M=256*1024,De=4*1024,te=6e4,z=6e4,Ae=/^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/,H=/^[a-z0-9][a-z0-9-]*$/,Ne=["system.","aws-","acode-"],Ce=/^[A-Za-z_][A-Za-z0-9_]*$/,Le=process.platform==="win32"?"junction":"dir",Ie=/[^\x20-\x7E]/,Oe=6e4,V=20,ne=80;function v(l){return typeof l=="object"&&l!==null&&!Array.isArray(l)}function O(l,e){let t=l;for(const n of e.split(".")){if(!v(t))return;t=t[n]}return t}function D(l,e){return l.length<=e?l:`${l.slice(0,e)}\u2026(\u622A\u65AD,\u5171 ${l.length} \u5B57\u7B26)`}async function T(l,e=8,t=200){for(let n=0;;n++)try{P(l,{recursive:!0,force:!0});return}catch(r){if(n>=e-1)throw r;await new Promise(i=>setTimeout(i,t))}}async function re(l,e){N(J(e),{recursive:!0});try{j(l,e);return}catch(t){const n=t?.code;if(!n||!["EXDEV","EPERM","EACCES","EBUSY","EINVAL"].includes(n))throw t}F(l,e,{recursive:!0,filter:t=>!/[\\/]\.git([\\/]|$)/.test(t)&&!/[\\/]node_modules([\\/]|$)/.test(t)}),await T(l)}function A(l,e){l.logs.push(`${new Date().toISOString()} ${e}`),l.logs.length>Ee&&l.logs.shift()}function G(l,e,t="params"){if(!v(l))return[];const n=[],r=l.type;if(typeof r=="string"&&!Te(r,e))return[`${t}: \u671F\u671B ${r}\uFF0C\u5B9E\u9645 ${Me(e)}`];if(Array.isArray(l.enum)&&l.enum.length>0&&(l.enum.some(s=>JSON.stringify(s)===JSON.stringify(e))||n.push(`${t}: \u503C ${JSON.stringify(e)} \u4E0D\u5728\u679A\u4E3E ${JSON.stringify(l.enum)} \u5185`)),r==="object"&&v(e)){const i=v(l.properties)?l.properties:{},s=Array.isArray(l.required)?l.required:[];for(const o of s)(!(o in e)||e[o]===void 0)&&n.push(`${t}.${o}: \u5FC5\u586B\u53C2\u6570\u7F3A\u5931`);for(const[o,a]of Object.entries(i))o in e&&e[o]!==void 0&&n.push(...G(a,e[o],`${t}.${o}`));if(l.additionalProperties===!1)for(const o of Object.keys(e))o in i||n.push(`${t}.${o}: \u4E0D\u5141\u8BB8\u7684\u672A\u77E5\u53C2\u6570\uFF08schema additionalProperties=false\uFF09`)}return r==="array"&&Array.isArray(e)&&v(l.items)&&e.forEach((i,s)=>{n.push(...G(l.items,i,`${t}[${s}]`))}),n}function Te(l,e){switch(l){case"string":return typeof e=="string";case"number":return typeof e=="number"&&Number.isFinite(e);case"boolean":return typeof e=="boolean";case"object":return v(e);case"array":return Array.isArray(e);case"null":return e===null;default:return!0}}function Me(l){return l===null?"null":Array.isArray(l)?"array":typeof l}class Re{constructor(e={}){this.agents=new Map,this.moduleNonce=0,this.templatePullInFlight=new Set,this.backgroundTemplatePulls=new Set,this.rootDir=e.rootDir??de(),this.runtimeRootDir=e.runtimeRootDir}forAgent(e){return{listPlugins:()=>this.list(e),getCatalog:()=>this.getCatalog(e),getToolSchema:t=>this.getToolSchema(e,t),invokeTool:(t,n,r,i)=>this.invokeTool(e,t,n,r,i),manage:t=>this.manage(e,t),getCommandDirs:()=>this.getCommandDirs(e),exposePlugin:t=>this.exposePlugin(e,t)}}setOnPluginsChanged(e){this.onPluginsChanged=e}notifyPluginsChanged(e){try{this.onPluginsChanged?.(e)}catch(t){f.warn("[agent:%s] onPluginsChanged \u56DE\u8C03\u5931\u8D25: %s",e,t instanceof Error?t.message:String(t))}}async getCommandDirs(e){return[...(await this.hydrate(e)).plugins.values()].filter(n=>n.enabled&&n.commandDir).map(n=>n.commandDir)}async getPluginCommands(e){const t=await this.hydrate(e),n=[],r=be(),i=this.parseCommandDir(k,r);i.length===0&&f.warn("[plugin-manager] \u5185\u7F6E\u547D\u4EE4\u76EE\u5F55\u4E0D\u53EF\u8BFB\u6216\u4E3A\u7A7A: %s\uFF08/create-plugin \u4E0D\u53EF\u7528\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u5305\u662F\u5426\u5B8C\u6574\uFF09",r),n.push(...i);for(const s of t.plugins.values())!s.enabled||!s.commandDir||n.push(...this.parsePluginCommandDir(s));return n}parsePluginCommandDir(e){return this.parseCommandDir(e.name,e.commandDir)}parseCommandDir(e,t){const n=[];if(!t)return n;try{for(const r of x(t)){if(!r.endsWith(".md"))continue;const i=m(t,r);try{const s=le(i,b(i,"utf8"));s.plugin=e,n.push(s)}catch(s){f.warn("[plugin:%s] \u547D\u4EE4\u89E3\u6790\u5931\u8D25 %s: %s",e,r,s instanceof Error?s.message:String(s))}}}catch{}return n}async list(e){const t=await this.hydrate(e),n=new Map;for(const r of t.plugins.values()){const i=this.toSummary(r);n.set(i.name,i)}n.has(k)||n.set(k,{name:k,version:ee(),description:X,status:"enabled",enabled:!0,source:"builtin",installedAt:new Date().toISOString(),toolCount:1,tools:[{name:"plugin-manager.manage",description:"\u63D2\u4EF6\u751F\u547D\u5468\u671F\u7BA1\u7406\uFF08install/uninstall/reload/disable/enable/list\uFF09"}],listeners:[],builtin:!0});for(const r of this.readSharedManifest()){const i=r.pluginName;if(!this.deployedPluginHealthy(i))continue;const o=n.get(i);if(o){String(o.source||"").startsWith("shared:")&&(o.enabled=this.effectiveSharedEnabled(e,r));continue}n.set(i,{name:i,version:this.deployedPluginVersion(i),status:"enabled",enabled:this.effectiveSharedEnabled(e,r),source:`shared:${r.fileName??`${i}.zip`}`,installedAt:new Date().toISOString(),toolCount:0,listeners:[]})}return[...n.values()].sort((r,i)=>r.name.localeCompare(i.name))}deployedPluginVersion(e){try{const t=JSON.parse(b(m(this.deployedPluginDir(e),"plugin.json"),"utf8"));return typeof t.version=="string"?t.version:void 0}catch{return}}async getCatalog(e){const t=await this.hydrate(e),n=[];for(const r of t.plugins.values()){if(!r.enabled||r.status==="error")continue;const i=r.tools.slice(0,V).map(s=>({name:s.name,description:D(s.title||s.description,ne),requiredParams:this.requiredParamsOf(s)}));r.tools.length>V&&i.push({name:`(\u53E6\u6709 ${r.tools.length-V} \u4E2A\u5DE5\u5177\u672A\u5217\u51FA)`,description:'\u7528 function_call {action:"catalog"} \u67E5\u770B\u5168\u91CF',requiredParams:void 0}),n.push({plugin:r.name,version:r.version,description:r.description,status:r.status,tools:i})}return n.push({plugin:k,version:ee(),description:X,status:"enabled",tools:[{name:"manage",description:D(Q,ne),requiredParams:["action"]}]}),{revision:t.catalogRevision,plugins:n}}async getToolSchema(e,t){const n=ue(t);if(!n)return null;if(n.plugin===k&&n.tool==="manage")return{plugin:k,name:"manage",description:Q,inputSchema:ke};const i=(await this.hydrate(e)).plugins.get(n.plugin);if(!i||!i.enabled)return null;const s=i.tools.find(o=>o.name===n.tool);return s?{plugin:i.name,name:s.name,title:s.title,description:s.description,inputSchema:s.inputSchema??{type:"object",properties:{}}}:null}async invokeTool(e,t,n,r,i){if(t===k&&n==="manage"){const u=this.buildManageRequest(r);if(!u)return{ok:!1,error:"plugin-manager.manage \u7F3A\u5C11 action"};const c=await this.manage(e,u);if(!c.ok)return{ok:!1,error:c.error??"\u63D2\u4EF6\u7BA1\u7406\u64CD\u4F5C\u5931\u8D25"};const d={ok:!0};return c.plugins&&(d.plugins=c.plugins),c.summary&&(d.summary=c.summary),{ok:!0,result:d}}const s=await this.hydrate(e),o=s.plugins.get(t);if(!o)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\uFF08\u53EF\u7528\u63D2\u4EF6: ${[...s.plugins.keys()].join(", ")||"\u65E0"}\uFF09`};if(!o.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u5DF2\u505C\u7528\uFF0C\u53EF\u8BA9\u7528\u6237\u5728\u9762\u677F\u6216\u7528 plugin-manager.manage enable \u542F\u7528`};const a=o.tools.find(u=>u.name===n);if(!a)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5DE5\u5177 ${n}\uFF08\u53EF\u7528: ${o.tools.map(u=>u.name).join(", ")||"\u65E0"}\uFF09`};if(a.inputSchema){const u=G(a.inputSchema,r);if(u.length>0)return{ok:!1,error:`\u53C2\u6570\u6821\u9A8C\u5931\u8D25: ${u.join("; ")}`,inputSchema:a.inputSchema}}return this.executeHandler(e,o,a,r,i)}buildManageRequest(e){const t=e.action;if(typeof t!="string"||!Pe.has(t))return null;const n={action:t};if(typeof e.name=="string"&&e.name.trim()&&(n.name=e.name.trim()),typeof e.source=="string"&&e.source.trim()&&(n.source=e.source.trim()),e.config&&typeof e.config=="object"&&!Array.isArray(e.config)){const r={};for(const[i,s]of Object.entries(e.config))typeof s=="string"&&(r[i]=s);n.config=r}return n}async executeHandler(e,t,n,r,i){const s=Date.now(),o=n.handler??{type:"process"};try{return o.type==="mcp"?{ok:!1,error:"handler.type=mcp \u5C06\u5728\u540E\u7EED\u7248\u672C\u652F\u6301\uFF0C\u8BF7\u6539\u7528 process/module handler"}:o.type==="module"?{ok:!0,result:await this.invokeModuleHandler(t,o,r,e,i),durationMs:Date.now()-s}:!o.command||!o.command.trim()?{ok:!1,error:`\u5DE5\u5177 ${n.name} \u7684 process handler \u7F3A\u5C11 command`}:{ok:!0,result:await this.invokeProcessHandler(t,o,r,e,i),durationMs:Date.now()-s}}catch(a){return{ok:!1,error:a instanceof Error?a.message:String(a),durationMs:Date.now()-s}}}async invokeProcessHandler(e,t,n,r,i){const s=K(t.command??"",{params:n});if(s.length===0)throw new Error("process handler command \u4E3A\u7A7A");const o=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te,a=new AbortController,u=()=>a.abort();i?.signal?.addEventListener("abort",u,{once:!0});const c=setTimeout(()=>a.abort(),o);try{return await new Promise((d,y)=>{f.info("[plugin:%s] spawn: %s",e.name,s.join(" "));const p=_(s[0],s.slice(1),{cwd:e.dir,env:this.buildPluginEnv(e,r),shell:t.shell===!0,windowsHide:!0,signal:a.signal});let g="",h="";p.stdin?.on("error",()=>{}),p.stdout?.on("data",$=>{g.length<M&&(g+=$.toString("utf8"))}),p.stderr?.on("data",$=>{h.length<M&&(h+=$.toString("utf8"))}),p.on("error",$=>{y(new Error(`\u63D2\u4EF6\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${$.message}`))}),p.on("close",$=>{const E=g.trim();if($!==0){const C=D(h.trim()||E||"(\u65E0\u8F93\u51FA)",600);y(new Error(a.signal.aborted?`\u63D2\u4EF6\u8FDB\u7A0B\u8D85\u65F6(${o}ms)\u6216\u88AB\u4E2D\u6B62`:`\u63D2\u4EF6\u8FDB\u7A0B\u9000\u51FA\u7801 ${$}: ${C}`));return}if(!E){d({ok:!0});return}try{d(JSON.parse(E))}catch{d(E)}});try{t.stdin==="params"?p.stdin?.end(`${JSON.stringify(n)}
|
|
7
|
+
`):p.stdin?.end()}catch{}})}finally{clearTimeout(c),i?.signal?.removeEventListener("abort",u)}}async invokeModuleHandler(e,t,n,r,i){if(!t.module)throw new Error("module handler \u7F3A\u5C11 module \u8DEF\u5F84");const s=m(e.dir,t.module);let o=e.moduleCache.get(s);o||(o=await import(`${ae(s).href}?acode_nonce=${e.importNonce}`),e.moduleCache.set(s,o));const a=t.export||"default",c=o[a];if(typeof c!="function")throw new Error(`\u6A21\u5757 ${t.module} \u672A\u5BFC\u51FA\u51FD\u6570 ${a}`);const d=typeof t.timeoutMs=="number"&&t.timeoutMs>0?t.timeoutMs:te;let y;const p=Promise.resolve().then(()=>c(n,{agentId:r,signal:i?.signal,pluginRoot:e.dir}));try{return await Promise.race([p,new Promise((g,h)=>{y=setTimeout(()=>h(new Error(`\u63D2\u4EF6\u6A21\u5757\u6267\u884C\u8D85\u65F6(${d}ms)`)),d)})])}finally{clearTimeout(y)}}buildPluginEnv(e,t){const n={};for(const i of["PATH","HOME","USERPROFILE","SystemRoot","COMSPEC","TEMP","TMP","LANG","TZ"]){const s=process.env[i];s!==void 0&&(n[i]=s)}n.ACODE_PLUGIN_ROOT=e.dir,n.ACODE_AGENT_ID=t,n.ACODE_PLUGIN_NAME=e.name;const r=new Set((e.userConfig??[]).map(i=>i.key));for(const[i,s]of Object.entries(e.configValues))r.has(i)&&(!Ce.test(i)||he.has(i.toUpperCase())||(n[i]=s));return n}async manage(e,t){const n=this.agentState(e),r=n.queue.then(async()=>{const i=await this.hydrate(e);return this.doManage(i,t)});return n.queue=r.catch(()=>{}),r}async doManage(e,t){if(t.name===k&&(t.action==="uninstall"||t.action==="disable"||t.action==="enable"||t.action==="reload"))return{ok:!1,error:`\u5185\u7F6E\u7CFB\u7EDF\u63D2\u4EF6 ${k} \u4E0D\u53EF${t.action==="uninstall"?"\u5378\u8F7D":t.action==="reload"?"\u91CD\u8F7D":"\u505C\u7528/\u542F\u7528"}`};switch(t.action){case"list":return{ok:!0,plugins:await this.list(e.agentId)};case"install":return this.installPlugin(e,t);case"uninstall":return this.uninstallPlugin(e,t);case"reload":return this.reloadPlugin(e,t);case"enable":case"disable":return this.setEnabled(e,t,t.action==="enable");default:return{ok:!1,error:`\u672A\u77E5 action: ${String(t.action)}`}}}async installPlugin(e,t){const n=(t.source??"").trim();if(!n)return{ok:!1,error:"install \u9700\u8981 source\uFF08\u5F53\u524D\u652F\u6301 local:<\u63D2\u4EF6\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84>\uFF09"};const r=n.split(":",1)[0];if(r!=="local")return{ok:!1,error:`\u6682\u4E0D\u652F\u6301\u63D2\u4EF6\u6765\u6E90 "${r}:"\uFF08npm:/git: \u5728\u8DEF\u7EBF\u56FE\u4E2D\uFF1Bzip \u5305\u8BF7\u7528\u9762\u677F\u5BFC\u5165\u6216 POST /runtime/plugins/:agentId/upload\uFF09`};const i=n.slice(6).trim();return!i||!w(m(i,"plugin.json"))?{ok:!1,error:`\u63D2\u4EF6\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u7F3A\u5C11 plugin.json: ${i}`}:this.installFromDirectory(e,i,n,t.config)}async installFromZip(e,t,n,r){if(!t||t.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};const i=this.agentState(e),s=i.queue.then(async()=>{await this.hydrate(e);const o=m(this.rootDir,"tmp",`upload-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const a=await U(t,o);return w(m(a.pluginDir,"plugin.json"))?(f.info("[agent:%s] zip \u5BFC\u5165: %s\uFF08%d \u4E2A\u6587\u4EF6\uFF09",e,n,a.fileCount),await this.installFromDirectory(i,a.pluginDir,`upload:${n}`,r)):{ok:!1,error:"zip \u5185\u672A\u627E\u5230 plugin.json\uFF08\u8BF7\u6253\u5305\u63D2\u4EF6\u76EE\u5F55\uFF0C\u4E14 zip \u5185\u8DEF\u5F84\u4F7F\u7528\u82F1\u6587\uFF09"}}catch(a){const u=a instanceof Error?a.message:String(a);return f.warn("[agent:%s] zip \u5BFC\u5165\u5931\u8D25: %s",e,u),{ok:!1,error:`zip \u5BFC\u5165\u5931\u8D25: ${u}`}}finally{await T(o,3,100).catch(()=>{})}});return i.queue=s.catch(()=>{}),s}async installFromDirectory(e,t,n,r){const i=this.loadManifestOnly(t);if(!i.ok)return i;const s=i.manifest,o=s.name;if(o===k)return{ok:!1,error:`\u63D2\u4EF6\u540D ${o} \u4E3A\u7CFB\u7EDF\u4FDD\u7559\u540D\u79F0\uFF0C\u4E0D\u5141\u8BB8\u5B89\u88C5\u540C\u540D\u63D2\u4EF6`};const a=this.validateUserConfigValues(s,r??{});if(a)return{ok:!1,error:a};const u=this.loadPluginFromDir(e,t,n,new Date().toISOString(),r??{});if(!u.ok)return f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u6821\u9A8C\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,u.error),u;const c=m(this.rootDir,"cache",I(e.agentId),o),d=t===c,y=e.plugins.get(o);if(y&&this.stopAllListeners(y),!d)try{await T(c),await re(t,c)}catch(h){const $=h instanceof Error?h.message:String(h);return f.warn("[agent:%s] \u63D2\u4EF6\u79FB\u52A8\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,$),y&&this.startAllListeners(e,y),{ok:!1,error:`\u63D2\u4EF6\u79FB\u52A8\u5931\u8D25: ${$}`}}const p=this.loadPluginFromDir(e,c,n,new Date().toISOString(),r??{});if(!p.ok){if(f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25\uFF08%s\uFF09: %s",e.agentId,n,p.error),!d)try{await re(c,t)}catch(h){f.warn("[agent:%s] \u88C5\u8F7D\u5931\u8D25\u540E\u65E0\u6CD5\u79FB\u56DE\u6E90\u76EE\u5F55\uFF08%s\uFF09\uFF0C\u5DF2\u4FDD\u7559\u7F13\u5B58\u526F\u672C",e.agentId,h instanceof Error?h.message:String(h))}if(y)try{this.startAllListeners(e,y)}catch(h){f.warn("[agent:%s] \u6062\u590D\u65E7\u5B9E\u4F8B\u76D1\u542C\u5931\u8D25: %s",e.agentId,h instanceof Error?h.message:String(h))}return p}const g=p.plugin;return e.plugins.set(g.name,g),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,g),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5B89\u88C5: %s@%s",e.agentId,g.name,g.version??"?"),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(g)}}async uninstallPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);return r?(this.stopAllListeners(r),e.plugins.delete(n),e.pendingExposed.delete(n),e.exposedThisSession.has(n)&&this.pushDeprecatedNotice(e,n,"\u5DF2\u88AB\u5378\u8F7D"),this.bumpCatalogRevision(e),this.readSharedManifest().some(s=>s.pluginName===n)&&this.removeRuntimeLink(e.agentId,n),this.persistInstalled(e),await T(r.dir),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u5378\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`}}async reloadPlugin(e,t){const n=(t.name??"").trim(),r=e.plugins.get(n);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${n} \u672A\u5B89\u88C5`};const i=this.loadPluginFromDir(e,r.dir,r.source,r.installedAt,r.configValues);if(!i.ok)return{ok:!1,error:`\u91CD\u8F7D\u5931\u8D25\uFF08\u4FDD\u7559\u65E7\u7248\u672C\u8FD0\u884C\uFF09: ${i.error}`};const s=i.plugin;return this.stopAllListeners(r),e.plugins.set(n,s),this.bumpCatalogRevision(e),this.persistInstalled(e),this.startAllListeners(e,s),f.info("[agent:%s] \u63D2\u4EF6\u5DF2\u91CD\u8F7D: %s",e.agentId,n),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(s)}}async setEnabled(e,t,n){const r=(t.name??"").trim(),i=e.plugins.get(r);return i?(i.enabled=n,this.bumpCatalogRevision(e),n?this.startAllListeners(e,i):(e.pendingExposed.delete(r),e.exposedThisSession.has(r)&&this.pushDeprecatedNotice(e,r,"\u5DF2\u505C\u7528"),this.stopAllListeners(i)),this.persistInstalled(e),this.notifyPluginsChanged(e.agentId),{ok:!0,summary:this.toSummary(i)}):{ok:!1,error:`\u63D2\u4EF6 ${r} \u672A\u5B89\u88C5`}}deployedDir(){return m(this.rootDir,"deployed")}deployedManifestFile(){return m(this.deployedDir(),"manifest.json")}deployedPluginDir(e){if(!B(e))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${H}\uFF09: ${JSON.stringify(e)}`);const t=m(this.deployedDir(),e),n=Y(this.deployedDir());if(Y(t)!==m(n,e))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u8D8A\u51FA\u90E8\u7F72\u533A: ${e}`);return t}legacySharedDir(){return m(this.rootDir,"shared")}readSharedManifest(){try{const e=JSON.parse(b(this.deployedManifestFile(),"utf8"));return Array.isArray(e.plugins)?e.plugins.filter(t=>t&&B(t.pluginName)):[]}catch{return[]}}writeSharedManifest(e){N(this.deployedDir(),{recursive:!0}),q(this.deployedManifestFile(),`${JSON.stringify({version:2,plugins:e},null,2)}
|
|
8
|
+
`,"utf8")}async migrateLegacySharedIfNeeded(){try{if(w(this.deployedManifestFile()))return;const e=m(this.legacySharedDir(),"manifest.json");if(!w(e))return;const t=JSON.parse(b(e,"utf8")),n=Array.isArray(t.plugins)?t.plugins:[];if(n.length===0)return;const r=[];for(const i of n){const s=m(this.legacySharedDir(),i.zipFile);if(!(!i.pluginName||!w(s)))try{const o=await this.deployPluginZipToPersistentDir(b(s),i.pluginName);if(!o)continue;r.push(o),f.info("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u5230\u90E8\u7F72\u533A: %s",i.pluginName)}catch(o){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6 %s \u8FC1\u79FB\u5931\u8D25: %s",i.pluginName,o instanceof Error?o.message:String(o))}}r.length>0&&this.writeSharedManifest(r),P(this.legacySharedDir(),{recursive:!0,force:!0})}catch(e){f.warn("[shared] \u65E7\u5171\u4EAB\u63D2\u4EF6\u8FC1\u79FB\u672A\u6267\u884C\uFF08\u4E0B\u6B21\u91CD\u8BD5\uFF09: %s",e instanceof Error?e.message:String(e))}}deployedPluginHealthy(e){return w(m(this.deployedPluginDir(e),"plugin.json"))}runtimeDirFor(e){return this.runtimeRootDir?m(this.runtimeRootDir,I(e)):ce(e)}runtimeLinkPath(e,t){return m(this.runtimeDirFor(e),t)}ensureRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t),r=this.deployedPluginDir(t);if(!w(m(r,"plugin.json")))return!1;N(this.runtimeDirFor(e),{recursive:!0});try{if(w(n)){let i=!1;try{i=ie(n).isSymbolicLink()}catch{i=!1}if(i)try{return x(n),!0}catch{}P(n,{recursive:!0,force:!0})}return se(r,n,Le),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u5EFA\u7ACB: %s \u2192 %s",e,n,r),!0}catch(i){return f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5931\u8D25\uFF08%s \u2192 %s\uFF09: %s",e,t,r,i instanceof Error?i.message:String(i)),!1}}removeRuntimeLink(e,t){const n=this.runtimeLinkPath(e,t);try{w(n)&&(P(n,{recursive:!0,force:!0}),f.info("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u5DF2\u79FB\u9664: %s",e,t))}catch(r){f.warn("[agent:%s] \u63D2\u4EF6\u8FD0\u884C\u65F6\u94FE\u63A5\u79FB\u9664\u5931\u8D25\uFF08%s\uFF09: %s",e,t,r instanceof Error?r.message:String(r))}}async saveSharedPlugin(e,t,n=!0,r){if(!e||e.length===0)return{ok:!1,error:"zip \u5305\u5185\u5BB9\u4E3A\u7A7A"};await this.migrateLegacySharedIfNeeded();const i=m(this.rootDir,"tmp",`deploy-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const s=await U(e,i),o=this.loadManifestOnly(s.pluginDir);if(!o.ok)return o;const a=o.manifest.name,u=this.readSharedManifest().find(g=>g.pluginName===a);if(u&&u.sha256===r&&this.deployedPluginHealthy(a))return{ok:!0,pluginName:a};await this.suspendDeployedPluginAcrossAgents(a),N(this.deployedDir(),{recursive:!0});const c=this.deployedPluginDir(a),d=m(this.deployedDir(),`.old-${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);if(w(c))try{j(c,d)}catch{P(c,{recursive:!0,force:!0})}try{F(s.pluginDir,c,{recursive:!0,filter:g=>!/[\\/]\.git([\\/]|$)/.test(g)&&!/[\\/]node_modules([\\/]|$)/.test(g)})}catch(g){throw w(d)&&(P(c,{recursive:!0,force:!0}),j(d,c)),g}w(d)&&P(d,{recursive:!0,force:!0}),await W(this.deployedManifestFile(),async()=>{const g=this.readSharedManifest().filter(h=>h.pluginName!==a);g.push({pluginName:a,zipFile:u?.zipFile??`${a}.zip`,fileName:t,defaultEnabled:n,sha256:r}),this.writeSharedManifest(g)}),f.info("[shared] \u63D2\u4EF6\u5DF2\u90E8\u7F72\u5230 bridge: %s\uFF08\u6765\u6E90 %s%s\uFF09",a,t,r?`, sha256=${r.slice(0,12)}\u2026`:"");const p=(await this.applySharedToKnownAgents()).find(g=>g.installed.includes(a));return p&&f.info("[shared] \u5DF2\u540C\u6B65\u5230\u8FD0\u884C\u4E2D agent: %s",p.agentId),{ok:!0,pluginName:a}}catch(s){const o=s instanceof Error?s.message:String(s);return f.warn("[shared] \u63D2\u4EF6\u90E8\u7F72\u5931\u8D25\uFF08%s\uFF09: %s",t,o),{ok:!1,error:`\u63D2\u4EF6\u90E8\u7F72\u5931\u8D25: ${o}`}}finally{await T(i,3,100).catch(()=>{})}}async deployPluginZipToPersistentDir(e,t){if(!e||e.length===0)return null;const n=m(this.rootDir,"tmp",`migrate-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{const r=await U(e,n),i=this.loadManifestOnly(r.pluginDir);if(!i.ok)return null;const s=i.manifest.name;if(t&&s!==t)return null;N(this.deployedDir(),{recursive:!0});const o=this.deployedPluginDir(s);return w(o)&&P(o,{recursive:!0,force:!0}),F(r.pluginDir,o,{recursive:!0,filter:a=>!/[\\/]\.git([\\/]|$)/.test(a)&&!/[\\/]node_modules([\\/]|$)/.test(a)}),{pluginName:s,zipFile:`${s}.zip`,fileName:`${s}.zip`,defaultEnabled:!0}}finally{P(n,{recursive:!0,force:!0})}}async suspendDeployedPluginAcrossAgents(e){for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e),this.bumpCatalogRevision(t),f.info("[agent:%s] \u5DF2\u6458\u9664\u63D2\u4EF6\u7B49\u5F85\u90E8\u7F72\u533A\u66F4\u65B0: %s",t.agentId,e))});t.queue=n.catch(()=>{}),await n}}async applySharedToKnownAgents(){const e=[];for(const t of this.agents.values()){if(!t.hydrated)continue;const n=await this.syncSharedIntoStateQueued(t);n.length>0&&e.push({agentId:t.agentId,installed:n})}return e}async syncSharedIntoStateQueued(e){const t=e.queue.then(()=>this.syncSharedIntoState(e));return e.queue=t.catch(()=>[]),t}effectiveSharedEnabled(e,t){return we(e,"plugins",t.pluginName)&&(t.defaultEnabled??!0)}async pullTemplatePluginsFromCapabilities(e){const t=ve(e.agentId);if(!t)return;const n=this.readSharedManifest();for(const[r,i]of Object.entries(t)){if(!i.url)continue;const s=n.find(a=>a.pluginName===r);if(!s||!s.sha256||s.sha256===i.sha256&&this.deployedPluginHealthy(r)||this.templatePullInFlight.has(r))continue;this.templatePullInFlight.add(r);const o=m(this.rootDir,"tmp",`pull-${I(e.agentId)}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`);try{N(o,{recursive:!0});let a=`${r}.zip`;try{const y=decodeURIComponent(i.url.split("/").pop()||"");y.toLowerCase().endsWith(".zip")&&(a=pe(y,`${r}.zip`))}catch{}const u=await ge({downloadUrl:i.url,fileName:a,sha256:i.sha256},o);if(!u)continue;const c=b(u.outputPath),d=await this.saveSharedPlugin(c,u.fileName,s.defaultEnabled??!0,i.sha256);d.ok?f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u81EA\u52A8\u5BF9\u8D26\u66F4\u65B0\u6210\u529F: %s",e.agentId,d.pluginName??r):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u66F4\u65B0\u5931\u8D25: %s: %s",e.agentId,r,d.error)}catch(a){f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6 %s \u66F4\u65B0\u5931\u8D25: %s",e.agentId,r,a instanceof Error?a.message:String(a))}finally{this.templatePullInFlight.delete(r),await T(o,3,100).catch(()=>{})}}}queueTemplatePull(e){this.backgroundTemplatePulls.has(e.agentId)||(this.backgroundTemplatePulls.add(e.agentId),this.pullTemplatePluginsFromCapabilities(e).catch(t=>{f.warn("[agent:%s] \u540E\u53F0\u63D2\u4EF6\u5BF9\u8D26\u66F4\u65B0\u5931\u8D25: %s",e.agentId,t instanceof Error?t.message:String(t))}).finally(()=>{this.backgroundTemplatePulls.delete(e.agentId)}))}async syncSharedIntoState(e){this.queueTemplatePull(e);const t=this.readSharedManifest(),n=new Set,r=[];let i=0;for(const s of t)if(n.add(s.pluginName),this.effectiveSharedEnabled(e.agentId,s)){const a=e.plugins.get(s.pluginName);if(!this.ensureRuntimeLink(e.agentId,s.pluginName))continue;const u=this.runtimeLinkPath(e.agentId,s.pluginName);if(!a){const c=this.loadPluginFromDir(e,u,`shared:${s.fileName}`,new Date().toISOString(),{});c.ok?(e.plugins.set(c.plugin.name,c.plugin),r.push(c.plugin.name),f.info("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u5DF2\u6309\u5F00\u542F\u6001\u52A0\u8F7D: %s",e.agentId,s.pluginName)):f.warn("[agent:%s] \u5DF2\u90E8\u7F72\u63D2\u4EF6\u52A0\u8F7D\u5931\u8D25: %s: %s",e.agentId,s.pluginName,c.error)}}else{const a=e.plugins.get(s.pluginName);a&&(this.stopAllListeners(a),e.plugins.delete(s.pluginName),i++),this.removeRuntimeLink(e.agentId,s.pluginName)}return this.cleanupRuntimeDir(e,n),(r.length>0||i>0)&&this.bumpCatalogRevision(e),this.persistInstalled(e),r}cleanupRuntimeDir(e,t){const n=this.runtimeDirFor(e.agentId);try{if(!w(n))return;const r=new Set(t);for(const i of x(n))!r.has(i)&&!e.plugins.has(i)&&this.removeRuntimeLink(e.agentId,i)}catch{}}async applyCapabilities(e){const t=await this.hydrate(e);await this.pullTemplatePluginsFromCapabilities(t),await this.syncSharedIntoState(t)}exposePlugin(e,t){if(!t)return;const n=this.agentState(e);n.pendingExposed.add(t),n.exposedThisSession.add(t),f.debug("[agent:%s] \u63D2\u4EF6\u5DF2\u89E6\u53D1\u5F85\u66B4\u9732: %s",e,t)}async drainEvents(e,t={}){const n=await this.hydrate(e);this.ensureListenersRunning(n);const r=n.buffer.drain(t),i=await this.consumeExposedCatalog(n);return{revision:r.revision,events:r.events,catalog:i,compactionSeq:n.compactionSeq}}async consumeExposedCatalog(e){if(e.pendingExposed.size===0)return null;const t=await this.getCatalog(e.agentId),n=[...e.pendingExposed];e.pendingExposed.clear();const r=t.plugins.filter(i=>n.includes(i.plugin));return r.length===0?null:{revision:t.revision,plugins:r}}pushDeprecatedNotice(e,t,n){e.buffer.push({plugin:t,event:"plugin-deprecated",priority:"urgent",receivedAt:Date.now(),message:{msgId:`plugin-deprecated-${t}-${Date.now()}`,channel:"plugin-event",senderId:`plugin:${t}`,senderName:`\u63D2\u4EF6[${t}]`,receiverId:e.agentId||void 0,content:`\u3010\u7CFB\u7EDF\u63D0\u793A\u3011\u63D2\u4EF6 ${t} ${n}\uFF0C\u5176\u63D0\u4F9B\u7684\u5DE5\u5177\u4E0D\u518D\u53EF\u8C03\u7528\u3002\u5982\u4ECD\u9700\u4F7F\u7528\u8BF7\u91CD\u65B0\u5B89\u88C5/\u542F\u7528\u8BE5\u63D2\u4EF6\u3002`,requireReply:!1,role:"system",timestamp:new Date().toISOString()}})}markAgentCompacted(e){const t=this.agentState(e);t.compactionSeq++,f.debug("[agent:%s] \u4E0A\u4E0B\u6587\u538B\u7F29\u6807\u8BB0: compactionSeq=%d",e,t.compactionSeq)}async enqueueExternalEvent(e,t,n){const r=await this.hydrate(e),i=r.plugins.get(t);if(!i||!i.enabled)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5\u6216\u5DF2\u505C\u7528`};const s=typeof n.event=="string"?n.event:"",o=i.listeners.find(a=>a.transport.type==="http-callback"&&(!s||a.event===s));return o?(this.enqueueEvent(r,i,o,n),{ok:!0}):{ok:!1,error:`\u63D2\u4EF6 ${t} \u65E0\u5339\u914D\u7684 http-callback \u76D1\u542C\u5668\uFF08event=${s||"(\u7A7A)"}\uFF09`}}bumpCatalogRevision(e){e.catalogRevision++}agentState(e){let t=this.agents.get(e);return t||(t={agentId:e,plugins:new Map,buffer:new $e(e),hydrated:!1,queue:Promise.resolve(),catalogRevision:0,eventSeq:0,compactionSeq:0,pendingExposed:new Set,exposedThisSession:new Set},this.agents.set(e,t)),t}async hydrate(e){const t=this.agentState(e);return t.hydratePromise||(t.hydratePromise=this.doHydrate(t).catch(n=>{throw t.hydratePromise=void 0,n})),await t.hydratePromise,t}async doHydrate(e){const t=e.agentId;await this.migrateLegacySharedIfNeeded();const n=this.installedFile(t);if(!w(n)){await this.syncSharedIntoState(e).catch(()=>{}),e.hydrated=!0;return}try{const r=JSON.parse(b(n,"utf8")),i=this.readSecrets(t);for(const s of r.plugins??[]){if(String(s.source||"").startsWith("shared:"))continue;const a=m(this.rootDir,"cache",I(t),s.name);if(!w(m(a,"plugin.json"))){f.warn("[agent:%s] \u5DF2\u5B89\u88C5\u63D2\u4EF6\u76EE\u5F55\u7F3A\u5931\uFF0C\u8DF3\u8FC7: %s",t,s.name);continue}const u={...s.config,...i[s.name]??{}},c=this.loadPluginFromDir(e,a,s.source,s.installedAt,u);if(c.ok){const d=c.plugin;d.enabled=s.enabled,e.plugins.set(d.name,d)}else f.warn("[agent:%s] \u63D2\u4EF6\u88C5\u8F7D\u5931\u8D25: %s: %s",t,s.name,c.error)}}catch(r){const i=r instanceof Error?r.message:String(r);f.error("[agent:%s] installed.json \u89E3\u6790\u5931\u8D25: %s",t,i)}await this.syncSharedIntoState(e).catch(r=>{f.warn("[agent:%s] \u5171\u4EAB\u63D2\u4EF6\u540C\u6B65\u5931\u8D25: %s",t,r instanceof Error?r.message:String(r))}),e.hydrated=!0}installedFile(e){return m(this.rootDir,"agents",I(e),"installed.json")}persistInstalled(e){this.persistSecrets(e);const t=this.installedFile(e.agentId);N(J(t),{recursive:!0});const n=[...e.plugins.values()].map(r=>({name:r.name,source:r.source,installedAt:r.installedAt,enabled:r.enabled,config:this.stripSensitiveValues(r)}));q(t,`${JSON.stringify({version:1,plugins:n},null,2)}
|
|
9
|
+
`,"utf8")}sensitiveKeysOf(e){return(e.userConfig??[]).filter(t=>t?.sensitive===!0&&typeof t.key=="string").map(t=>t.key)}stripSensitiveValues(e){const t=new Set(this.sensitiveKeysOf(e)),n={};for(const[r,i]of Object.entries(e.configValues))t.has(r)||(n[r]=i);return n}secretsFile(e){return m(this.rootDir,"agents",I(e),"secrets.json")}readSecrets(e){try{const t=JSON.parse(b(this.secretsFile(e),"utf8"));if(!v(t)||!v(t.secrets))return{};const n={};for(const[r,i]of Object.entries(t.secrets)){if(!v(i))continue;const s={};for(const[o,a]of Object.entries(i))typeof a=="string"&&(s[o]=a);n[r]=s}return n}catch{return{}}}persistSecrets(e){const t={};for(const r of e.plugins.values()){const i={};for(const s of this.sensitiveKeysOf(r)){const o=r.configValues[s];typeof o=="string"&&o.length>0&&(i[s]=o)}Object.keys(i).length>0&&(t[r.name]=i)}const n=this.secretsFile(e.agentId);if(Object.keys(t).length===0){try{P(n,{force:!0})}catch{}return}N(J(n),{recursive:!0}),q(n,`${JSON.stringify({version:1,secrets:t},null,2)}
|
|
10
|
+
`,{encoding:"utf8",mode:384})}readJsonFile(e){if(!w(e))return{ok:!0,data:{}};try{const t=JSON.parse(b(e,"utf8"));return v(t)?{ok:!0,data:t}:{ok:!1,error:`${e}: \u6839\u8282\u70B9\u987B\u4E3A\u5BF9\u8C61`}}catch(t){const n=t instanceof Error?t.message:String(t);return{ok:!1,error:`${e}: JSON \u89E3\u6790\u5931\u8D25: ${n}`}}}loadManifestOnly(e){const t=this.readJsonFile(m(e,"plugin.json"));if(!t.ok)return t;const n=t.data,r=_e(n);return r?{ok:!1,error:r}:{ok:!0,manifest:n}}validateUserConfigValues(e,t){const n=Array.isArray(e.userConfig)?e.userConfig:[],r={...t};for(const i of n){if(!i||typeof i.key!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i.key))return"plugin.json: userConfig.key \u975E\u6CD5\uFF08\u987B\u4E3A\u73AF\u5883\u53D8\u91CF\u540D\uFF09";if(!(typeof r[i.key]=="string"&&r[i.key].length>0)&&i.required){const o=i.default!==void 0&&typeof i.default=="string"?i.default:"";if(!o)return`\u7F3A\u5C11\u5FC5\u9700\u914D\u7F6E ${i.key}${i.description?`\uFF08${i.description}\uFF09`:""}\uFF0C\u5B89\u88C5\u65F6\u8BF7\u5728 config \u4E2D\u63D0\u4F9B`;r[i.key]=o}}return null}loadPluginFromDir(e,t,n,r,i){const s=this.loadManifestOnly(t);if(!s.ok)return s;const o=s.manifest,a=m(t,o.tools??"tools/tools.json"),u=this.readJsonFile(a);if(!u.ok)return u;const c=[],d=Array.isArray(u.data.tools)?u.data.tools:[];for(const S of d){const L=Fe(S);if(L)return{ok:!1,error:`${o.tools??"tools/tools.json"}: ${L}`};c.push(S)}const y=m(t,o.listeners??"listeners/listeners.json"),p=this.readJsonFile(y);if(!p.ok)return p;const g=[],h=Array.isArray(p.data.listeners)?p.data.listeners:[];for(const S of h){const L=xe(S);if(L)return{ok:!1,error:`${o.listeners??"listeners/listeners.json"}: ${L}`};g.push(S)}const $=Array.isArray(o.userConfig)?o.userConfig:[],E=this.validateUserConfigValues(o,i);if(E)return{ok:!1,error:E};const C={...i};for(const S of $){if(!S||typeof S.key!="string")continue;!(typeof C[S.key]=="string"&&C[S.key].length>0)&&S.required&&S.default!==void 0&&typeof S.default=="string"&&(C[S.key]=S.default)}const R=o.commands;let Z;if(typeof R=="string"&&R.trim()){const S=m(t,R.trim());w(S)&&(Z=S)}return{ok:!0,plugin:{name:o.name,version:typeof o.version=="string"?o.version:void 0,description:typeof o.description=="string"?o.description:void 0,source:n,installedAt:r,dir:t,enabled:!0,tools:c,listeners:g,commandDir:Z,userConfig:$,configValues:C,status:"enabled",runtimes:g.map(S=>({def:S,stopping:!1,restarts:0,logs:[]})),moduleCache:new Map,importNonce:++this.moduleNonce}}}ensureListenersRunning(e){for(const t of e.plugins.values())if(t.enabled)for(const n of t.runtimes)!n.child&&!n.timer&&!n.backoffTimer&&!n.stopping&&this.startListener(e,t,n)}startAllListeners(e,t){for(const n of t.runtimes)this.stopListener(n),t.enabled&&this.startListener(e,t,n)}stopAllListeners(e){for(const t of e.runtimes)this.stopListener(t)}startListener(e,t,n){const r=n.def.transport??{type:"command-stream"};if(r.type==="http-callback"){n.stopping=!1;return}if(r.type==="poll-command"){const i=Math.max(5e3,r.intervalMs??3e4);n.stopping=!1,n.timer=setInterval(()=>{this.pollListenerOnce(e,t,n)},i),this.pollListenerOnce(e,t,n);return}if(!r.command){n.lastError="command-stream \u7F3A\u5C11 command",A(n,`ERROR ${n.lastError}`);return}n.stopping=!1,this.spawnListenerChild(e,t,n)}spawnListenerChild(e,t,n){const i=n.def.transport?.command??"",s=K(i,{});try{A(n,`spawn: ${s.join(" ")}`);const o=_(s[0],s.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"]});n.child=o,n.lastError=void 0;let a="";o.stdout?.on("data",u=>{a+=u.toString("utf8");let c=a.indexOf(`
|
|
11
11
|
`);for(;c>=0;){const d=a.slice(0,c).trim();a=a.slice(c+1),d&&this.handleListenerLine(e,t,n,d),c=a.indexOf(`
|
|
12
|
-
`)}a.length>1024*1024&&(a=a.slice(-4096))}),o.stderr?.on("data",u=>{
|
|
13
|
-
`)){const c=u.trim();c&&this.handleListenerLine(e,t,n,c)}}catch(a){const u=a instanceof Error?a.message:String(a);n.lastError=u,
|
|
12
|
+
`)}a.length>1024*1024&&(a=a.slice(-4096))}),o.stderr?.on("data",u=>{A(n,`stderr: ${D(u.toString("utf8").trimEnd(),400)}`)}),o.on("error",u=>{n.lastError=`\u8FDB\u7A0B\u542F\u52A8\u5931\u8D25: ${u.message}`,A(n,`ERROR ${n.lastError}`)}),o.on("close",u=>{n.child=void 0,!n.stopping&&(n.lastError=`\u76D1\u542C\u8FDB\u7A0B\u9000\u51FA\uFF08code=${u??"signal"}\uFF09`,A(n,`exit code=${u??"signal"}\uFF0C\u51C6\u5907\u91CD\u542F`),this.scheduleListenerRestart(e,t,n))})}catch(o){const a=o instanceof Error?o.message:String(o);n.lastError=a,A(n,`ERROR spawn: ${a}`),this.scheduleListenerRestart(e,t,n)}}scheduleListenerRestart(e,t,n){if(n.stopping)return;const r=Math.max(500,n.def.transport?.restartBackoffMs??2e3),i=Math.min(Oe,r*2**Math.min(n.restarts,6));n.restarts++,A(n,`restart #${n.restarts} in ${i}ms`),n.backoffTimer=setTimeout(()=>{n.backoffTimer=void 0,n.stopping||this.spawnListenerChild(e,t,n)},i)}async pollListenerOnce(e,t,n){if(n.polling)return;const r=n.def.transport?.command??"",i=K(r,{});if(i.length===0)return;n.polling=!0;const s=new AbortController,o=setTimeout(()=>s.abort(),z);try{const a=await new Promise((u,c)=>{const d=_(i[0],i.slice(1),{cwd:t.dir,env:this.buildPluginEnv(t,e.agentId),shell:!1,windowsHide:!0,stdio:["ignore","pipe","pipe"],signal:s.signal});let y="",p="";d.stdout?.on("data",h=>{y.length<M&&(y+=h.toString("utf8"))}),d.stderr?.on("data",h=>{p.length<M&&(p+=h.toString("utf8"))});const g=()=>s.signal.aborted;d.on("error",h=>{c(g()?new Error(`poll \u8D85\u65F6(${z}ms)`):h)}),d.on("close",h=>{g()?c(new Error(`poll \u8D85\u65F6(${z}ms)`)):h===0?u(y):c(new Error(`exit ${h}: ${D(p||y,300)}`))})});n.lastError=void 0;for(const u of a.split(`
|
|
13
|
+
`)){const c=u.trim();c&&this.handleListenerLine(e,t,n,c)}}catch(a){const u=a instanceof Error?a.message:String(a);n.lastError=u,A(n,`poll \u5931\u8D25: ${u}`)}finally{clearTimeout(o),n.polling=!1}}stopListener(e){if(e.stopping=!0,e.restarts=0,e.child){try{e.child.kill()}catch{}e.child=void 0}e.timer&&(clearInterval(e.timer),e.timer=void 0),e.backoffTimer&&(clearTimeout(e.backoffTimer),e.backoffTimer=void 0)}handleListenerLine(e,t,n,r){A(n,`event: ${D(r,300)}`);let i;try{i=JSON.parse(r)}catch{n.lastError="\u4E8B\u4EF6\u884C\u4E0D\u662F\u5408\u6CD5 JSON\uFF08\u8981\u6C42 JSONL\uFF09";return}if(!v(i))return;const s=typeof i.event=="string"?i.event:n.def.event,o=s===n.def.event?n.def:t.listeners.find(a=>a.event===s);o&&(o.delivery&&o.delivery!=="poll"&&f.debug("[plugin:%s] delivery=%s \u6682\u6309 poll \u4EA4\u4ED8",t.name,o.delivery),this.enqueueEvent(e,t,o,i))}enqueueEvent(e,t,n,r){for(const[p,g]of Object.entries(n.matcher??{})){const h=O(r,p);if(!(Array.isArray(g)?g:[g]).some(E=>JSON.stringify(E)===JSON.stringify(h)))return}let i;if(n.dedupKey){const p=O(r,n.dedupKey);p!=null&&(i=D(String(p),256))}e.eventSeq++;const s=D(qe(r.data??r),De),o=n.promptTemplate?je(n.promptTemplate,r):`\u3010\u63D2\u4EF6\u4E8B\u4EF6\u3011${t.name} \xB7 ${n.event}${n.description?`
|
|
14
14
|
${n.description}`:""}`,a=(n.toolHints??[]).join(","),u=`${o}
|
|
15
|
-
[plugin-event] plugin=${t.name} event=${n.event}`+(a?` toolHints=${a}`:"")+` payload=${s}`,c={msgId:D(i?`plugin-event-${t.name}-${i}`:`plugin-event-${t.name}-${n.event}-${e.eventSeq}`,512),channel:"plugin-event",senderId:`plugin:${t.name}`,senderName:`\u63D2\u4EF6[${t.name}]`,receiverId:e.agentId||void 0,content:u,requireReply:!1,role:"system",timestamp:new Date().toISOString()},d=n.priority??"normal";e.buffer.push({plugin:t.name,event:n.event,priority:d,dedupKey:i,receivedAt:Date.now(),message:c})&&this.exposePlugin(e.agentId,t.name)}requiredParamsOf(e){const t=e.inputSchema;if(!(!t||!Array.isArray(t.required)))return t.required.filter(n=>typeof n=="string")}toSummary(e){return{name:e.name,version:e.version,description:e.description,status:e.status,enabled:e.enabled,source:e.source,installedAt:e.installedAt,toolCount:e.tools.length,tools:e.tools.map(t=>({name:t.name,title:t.title,description:t.description})),listeners:e.runtimes.map(t=>({event:t.def.event,delivery:t.def.delivery??"poll",running:!!(t.child||t.timer)||t.def.transport?.type==="http-callback",error:t.lastError})),running:e.runtimes.some(t=>!!(t.child||t.timer)||t.def.transport?.type==="http-callback"),error:e.error}}async getLogs(e,t){const n=await this.hydrate(e);if(t
|
|
15
|
+
[plugin-event] plugin=${t.name} event=${n.event}`+(a?` toolHints=${a}`:"")+` payload=${s}`,c={msgId:D(i?`plugin-event-${t.name}-${i}`:`plugin-event-${t.name}-${n.event}-${e.eventSeq}`,512),channel:"plugin-event",senderId:`plugin:${t.name}`,senderName:`\u63D2\u4EF6[${t.name}]`,receiverId:e.agentId||void 0,content:u,requireReply:!1,role:"system",timestamp:new Date().toISOString()},d=n.priority??"normal";e.buffer.push({plugin:t.name,event:n.event,priority:d,dedupKey:i,receivedAt:Date.now(),message:c})&&this.exposePlugin(e.agentId,t.name)}requiredParamsOf(e){const t=e.inputSchema;if(!(!t||!Array.isArray(t.required)))return t.required.filter(n=>typeof n=="string")}toSummary(e){return{name:e.name,version:e.version,description:e.description,status:e.status,enabled:e.enabled,source:e.source,installedAt:e.installedAt,toolCount:e.tools.length,tools:e.tools.map(t=>({name:t.name,title:t.title,description:t.description})),listeners:e.runtimes.map(t=>({event:t.def.event,delivery:t.def.delivery??"poll",running:!!(t.child||t.timer)||t.def.transport?.type==="http-callback",error:t.lastError})),running:e.runtimes.some(t=>!!(t.child||t.timer)||t.def.transport?.type==="http-callback"),error:e.error}}async getLogs(e,t){const n=await this.hydrate(e);if(t===k)return{ok:!0,logs:[`\u2500\u2500 ${k} \u4E3A\u7CFB\u7EDF\u5185\u7F6E\u63D2\u4EF6\uFF08\u65E0\u9700\u5B89\u88C5\uFF09\uFF0C\u65E0\u72EC\u7ACB\u76D1\u542C\u5668\u8FD0\u884C\u65E5\u5FD7\u3002`,"\u5176\u751F\u547D\u5468\u671F\u64CD\u4F5C\uFF08install/reload/disable/enable/list\uFF09\u7531 bridge plugin-manager \u5904\u7406\uFF0C\u53EF\u901A\u8FC7\u300C\u91CD\u8F7D/\u542F\u7528/\u505C\u7528\u300D\u6309\u94AE\u89C2\u5BDF\u72B6\u6001\u53D8\u5316\u3002"]};const r=n.plugins.get(t);if(!r)return{ok:!1,error:`\u63D2\u4EF6 ${t} \u672A\u5B89\u88C5`,logs:[]};const i=[];for(const s of r.runtimes)i.push(`\u2500\u2500 listener ${s.def.event} (${s.def.transport?.type}) ${s.lastError?`[error: ${s.lastError}]`:""}`),i.push(...s.logs);return{ok:!0,logs:i}}async stopAgent(e){const t=this.agents.get(e);if(t){for(const n of t.plugins.values())this.stopAllListeners(n);this.agents.delete(e)}}async stopAll(){for(const e of[...this.agents.keys()])await this.stopAgent(e)}async listDeployed(){await this.migrateLegacySharedIfNeeded();const e=this.readSharedManifest(),t=[];for(const n of e){const r=this.deployedPluginDir(n.pluginName),i=this.deployedPluginHealthy(n.pluginName);let s;if(i)try{const o=JSON.parse(b(m(r,"plugin.json"),"utf8"));typeof o.version=="string"&&(s=o.version)}catch{}t.push({pluginName:n.pluginName,version:s,fileName:n.fileName??`${n.pluginName}.zip`,defaultEnabled:n.defaultEnabled!==!1,sha256:n.sha256,deployed:i})}return t}deployedDefaultEnabled(){const e=this.readSharedManifest(),t={};for(const n of e)t[n.pluginName]=n.defaultEnabled!==!1;return t}async removeDeployedPlugin(e){if(!B(e))return{ok:!1,error:"pluginName \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF0C1~64 \u5B57\u7B26\uFF09"};await this.migrateLegacySharedIfNeeded();for(const t of[...this.agents.values()]){if(!t.hydrated)continue;const n=t.queue.then(async()=>{const r=t.plugins.get(e);r&&(this.stopAllListeners(r),t.plugins.delete(e)),this.removeRuntimeLink(t.agentId,e),this.persistInstalled(t)});t.queue=n.catch(()=>{}),await n}await W(this.deployedManifestFile(),async()=>{const t=this.readSharedManifest().filter(n=>n.pluginName!==e);this.writeSharedManifest(t)});try{P(this.deployedPluginDir(e),{recursive:!0,force:!0})}catch(t){return{ok:!1,error:`\u90E8\u7F72\u76EE\u5F55\u6E05\u7406\u5931\u8D25: ${t instanceof Error?t.message:String(t)}`}}return f.info("[shared] \u63D2\u4EF6\u5DF2\u4ECE bridge \u79FB\u9664\u90E8\u7F72: %s",e),{ok:!0}}}function B(l){return typeof l=="string"&&l.length>0&&l.length<=64&&H.test(l)}function _e(l){const e=l.name;if(typeof e!="string"||!H.test(e))return`plugin.json: name \u975E\u6CD5\uFF08\u987B\u4E3A kebab-case\uFF09: ${String(e)}`;if(e.length>64)return"plugin.json: name \u8FC7\u957F\uFF08\u226464\uFF09";for(const t of Ne)if(e===t.replace(/\.$/,"")||e.startsWith(t))return`plugin.json: name \u4F7F\u7528\u4E86\u4FDD\u7559\u524D\u7F00 ${t}`;return Ie.test(e)?"plugin.json: name \u542B\u975E ASCII \u5B57\u7B26\uFF08\u540C\u5F62\u5B57\u9632\u62A4\uFF09":l.version!==void 0&&typeof l.version!="string"?"plugin.json: version \u987B\u4E3A\u5B57\u7B26\u4E32":l.userConfig!==void 0&&!Array.isArray(l.userConfig)?"plugin.json: userConfig \u987B\u4E3A\u6570\u7EC4":null}function Fe(l){if(!v(l))return"\u5DE5\u5177\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";const e=l.name;if(typeof e!="string"||!Ae.test(e))return`\u5DE5\u5177 name \u975E\u6CD5: ${String(e)}`;if(typeof l.description!="string"||!l.description.trim())return`\u5DE5\u5177 ${e} \u7F3A\u5C11 description`;const t=l.handler;if(!v(t))return`\u5DE5\u5177 ${e} \u7F3A\u5C11 handler`;const n=t.type;return n!=="process"&&n!=="module"&&n!=="mcp"?`\u5DE5\u5177 ${e} handler.type \u975E\u6CD5: ${String(n)}`:n==="process"&&typeof t.command!="string"?`\u5DE5\u5177 ${e} \u7684 process handler \u7F3A\u5C11 command`:n==="module"&&typeof t.module!="string"?`\u5DE5\u5177 ${e} \u7684 module handler \u7F3A\u5C11 module`:l.inputSchema!==void 0&&!v(l.inputSchema)?`\u5DE5\u5177 ${e} inputSchema \u987B\u4E3A\u5BF9\u8C61`:null}function xe(l){if(!v(l))return"\u76D1\u542C\u5668\u6761\u76EE\u987B\u4E3A\u5BF9\u8C61";if(typeof l.event!="string"||!l.event.trim())return"\u76D1\u542C\u5668\u7F3A\u5C11 event";const e=l.transport;if(!v(e))return`\u76D1\u542C\u5668 ${String(l.event)} \u7F3A\u5C11 transport`;const t=e.type;if(t!=="command-stream"&&t!=="poll-command"&&t!=="http-callback")return`\u76D1\u542C\u5668 ${String(l.event)} transport.type \u975E\u6CD5: ${String(t)}`;if((t==="command-stream"||t==="poll-command")&&typeof e.command!="string")return`\u76D1\u542C\u5668 ${String(l.event)} \u7684 ${t} transport \u7F3A\u5C11 command`;const n=l.delivery;return n!==void 0&&n!=="poll"&&n!=="force"&&n!=="wake"?`\u76D1\u542C\u5668 ${String(l.event)} delivery \u975E\u6CD5: ${String(n)}`:null}function K(l,e){return l.trim().split(/\s+/).map(t=>{const n=/^\{\{(.+)\}\}$/.exec(t);if(n){const r=O(e,n[1].trim());return r==null?"":typeof r=="string"?r:JSON.stringify(r)}return t.replace(/\{\{(.+?)\}\}/g,(r,i)=>{const s=O(e,i.trim());return s==null?"":typeof s=="string"?s:JSON.stringify(s)})}).filter(t=>t!=="")}function je(l,e){return l.replace(/\{\{(.+?)\}\}/g,(t,n)=>{let r=O(e,n.trim());return r===void 0&&!n.trim().startsWith("params.")&&(r=O(e,`data.${n.trim()}`)),r==null?"":typeof r=="string"?r:JSON.stringify(r)})}function qe(l){try{return JSON.stringify(l)??"null"}catch{return"(\u4E0D\u53EF\u5E8F\u5217\u5316\u7684\u4E8B\u4EF6\u8D1F\u8F7D)"}}const Je=new Re;ye("plugins",()=>Je.deployedDefaultEnabled());const nt=()=>Se("plugins");export{X as BUILTIN_PLUGIN_DESCRIPTION,Q as BUILTIN_PLUGIN_MANAGE_DESC,k as BUILTIN_PLUGIN_NAME,Re as PluginManager,be as getBuiltinCommandDir,B as isValidPluginName,Je as pluginManager,nt as reconcilePluginsDefaultsFromDeployed,K as renderCommandArgv,G as validateAgainstSchema,_e as validateManifest};
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
export declare function isProcessRunningAsync(pid: number): Promise<boolean>;
|
|
4
4
|
|
|
5
|
-
export declare function isProcessRunning(pid: number): boolean
|
|
5
|
+
export declare function isProcessRunning(pid: number): Promise<boolean>;
|
|
6
6
|
|
|
7
7
|
export interface ProcessInfo {
|
|
8
8
|
pid: number;
|
|
@@ -16,6 +16,25 @@ export declare function findClaudeCodeProcesses(): Promise<ProcessInfo[]>;
|
|
|
16
16
|
|
|
17
17
|
export declare function findOrphanProcessByAgentId(agentId: string): Promise<ProcessInfo | undefined>;
|
|
18
18
|
|
|
19
|
+
interface ProcEntry {
|
|
20
|
+
processId: number;
|
|
21
|
+
parentProcessId: number;
|
|
22
|
+
name: string;
|
|
23
|
+
commandLine: string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ProcessSnapshotEntry extends ProcEntry {
|
|
27
|
+
creationDate?: string | null;
|
|
28
|
+
workingSetSize?: number | null;
|
|
29
|
+
handleCount?: number | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ProcessSnapshot {
|
|
33
|
+
entries: ProcessSnapshotEntry[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export declare function captureProcessSnapshot(): Promise<ProcessSnapshot | undefined>;
|
|
37
|
+
|
|
19
38
|
export declare function findOrphanProcessByWorkspace(workspacePath: string): Promise<ProcessInfo | undefined>;
|
|
20
39
|
|
|
21
40
|
export declare function terminateProcess(pid: number): boolean;
|
|
@@ -32,7 +51,7 @@ export declare function detectOrphanProcesses(persistedSessions: Array<{
|
|
|
32
51
|
pid?: number;
|
|
33
52
|
workspacePath?: string;
|
|
34
53
|
command?: string;
|
|
35
|
-
}
|
|
54
|
+
}>, snapshot?: ProcessSnapshot): Promise<Array<{
|
|
36
55
|
agentId: string;
|
|
37
56
|
process: ProcessInfo;
|
|
38
57
|
sessionInfo: {
|
|
@@ -56,7 +75,7 @@ export declare function checkProcessHealth(pid: number, agentId: string): Promis
|
|
|
56
75
|
export declare function checkAllSessionsHealth(sessions: Array<{
|
|
57
76
|
agentId: string;
|
|
58
77
|
pid?: number;
|
|
59
|
-
}
|
|
78
|
+
}>, snapshot?: ProcessSnapshot): Promise<Map<string, ProcessHealthStatus>>;
|
|
60
79
|
|
|
61
80
|
export type ProcessManagementStatus = 'managed' | 'orphan' | 'unknown';
|
|
62
81
|
|
|
@@ -73,3 +92,4 @@ export declare function discoverAllProcessesFull(registryExport: Array<{
|
|
|
73
92
|
agentId: string;
|
|
74
93
|
pid: number;
|
|
75
94
|
}>): Promise<DiscoveredProcessInfo[]>;
|
|
95
|
+
export {};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`);let
|
|
3
|
-
`).filter(
|
|
4
|
-
`).filter(
|
|
1
|
+
import{exec as O}from"child_process";import h from"os";import{promisify as A}from"util";const g=A(O);import{createLogger as F}from"../utils/logger.js";const d=F("process-detector");async function l(n,r=15e3){const e=Buffer.from(n,"utf16le").toString("base64"),{stdout:t}=await g(`powershell -NoProfile -NonInteractive -EncodedCommand ${e}`,{encoding:"utf8",timeout:r,windowsHide:!0,maxBuffer:10*1024*1024});return t.replace(/#\s*<\s*CLIXML[\s\S]*?(?=#<\s*CLIXML|$)/g,"").trim()}async function P(n){try{if(h.platform()==="win32"){const{stdout:r}=await g(`tasklist /FI "PID eq ${n}" /NH /FO CSV`,{encoding:"utf8",timeout:5e3,windowsHide:!0});return r.includes(String(n))}else return process.kill(n,0),!0}catch{return!1}}function Z(n){return P(n)}async function w(){const n=h.platform(),r=[];try{n==="win32"?r.push(...await N()):r.push(...await W())}catch(s){d.debug("Failed to list processes:",s)}return r}async function N(){const n=[];try{const s=await l(`Get-CimInstance Win32_Process -Filter "Name LIKE '%node%' OR Name LIKE '%claude%' OR Name LIKE '%opencode%' OR Name LIKE '%python%'" | Select-Object ProcessId, CommandLine | ConvertTo-Json -Compress`,1e4);if(!s||!s.trim())return n;let e;try{const t=JSON.parse(s);e=Array.isArray(t)?t:[t]}catch{return n}for(const t of e){if(!t.ProcessId||!t.CommandLine)continue;const o=t.CommandLine;if(y(o)){const i=$(o);n.push({pid:t.ProcessId,command:o,agentId:i})}}}catch(r){d.debug("PowerShell process query failed, trying wmic fallback:",r),n.push(...await T())}return n}async function T(){const n=[];try{const{stdout:r}=await g(`wmic process where "name like '%node%' or name like '%claude%' or name like '%opencode%'" get processid,commandline /format:list`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),s=r.split(`
|
|
2
|
+
`);let e=null,t=null;for(const o of s){const i=o.trim();if(i.startsWith("CommandLine=")?t=i.substring(12):i.startsWith("ProcessId=")&&(e=i.substring(10)),e&&t){if(y(t)){const a=$(t);n.push({pid:parseInt(e,10),command:t,agentId:a})}e=null,t=null}}}catch(r){d.debug("wmic process query failed:",r)}return n}async function W(){const n=[];try{const{stdout:r}=await g('ps aux | grep -E "claude|claude-code|opencode" | grep -v grep',{encoding:"utf8",timeout:5e3}),s=r.split(`
|
|
3
|
+
`).filter(e=>e.trim());for(const e of s){const t=e.trim().split(/\s+/);if(t.length>=2){const o=parseInt(t[1],10),i=t.slice(10).join(" ");if(y(i)){const a=$(i);n.push({pid:o,command:i,agentId:a})}}}}catch(r){d.debug("ps process query failed:",r)}return n}function y(n){if(!n)return!1;const r=n.toLowerCase();return!!(r.includes("claude")||r.includes("@anthropic-ai/claude-code")||r.includes("opencode")||r.includes("open-code")||r.includes("opencode.exe")||r.includes("opencode.cmd")||r.includes("aws-client-agent-mcp")||r.includes("aws-client-agent")||r.includes("acode")&&r.includes("sdk")||r.includes("cc-switch-sdk")||r.includes("cc-switch"))}function $(n){if(!n)return;const r=n.match(/AWS_AGENT_ID=(\S+)/);if(r)return C(r[1]);const s=n.match(/--agent-id[=\s]+(\S+)/);if(s)return C(s[1]);const e=n.match(/--id[=\s]+(\S+)/);if(e)return C(e[1])}function C(n){if(!n)return n;const r=n[0],s=n[n.length-1];return(r==='"'||r==="'")&&r===s?n.slice(1,-1):n}async function x(n){const s=(await w()).find(e=>e.agentId===n);if(s)return s;if(h.platform()==="win32"){const e=await B(n);if(e)return e;const t=await R(n);if(t)return t}}async function B(n){try{const r=`$targetId = '${n}'; $procs = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*') }; foreach ($proc in $procs) { if ($proc.CommandLine -like "*$targetId*") { @{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine; AgentId=$targetId} | ConvertTo-Json -Compress } }`,s=await l(r,1e4);if(!s||!s.trim())return;const e=s.trim().split(`
|
|
4
|
+
`).filter(t=>t.trim());for(const t of e)try{const o=JSON.parse(t.trim());if(o.ProcessId)return{pid:o.ProcessId,command:o.CommandLine||"",agentId:o.AgentId||n}}catch{}}catch(r){d.debug("PowerShell env var query failed:",r)}}async function R(n){try{const s=await l("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine | ConvertTo-Json -Compress",15e3);return!s||!s.trim()?void 0:await E(s.trim(),n)}catch(r){d.debug("[findOrphanByAncestorEnvSearch] Failed:",r)}}async function ee(){if(h.platform()!=="win32")return;const r=await l("Get-CimInstance Win32_Process | Select-Object ProcessId, ParentProcessId, Name, CommandLine, CreationDate, WorkingSetSize, HandleCount | ConvertTo-Json -Compress",15e3);if(!r||!r.trim())throw new Error("empty Win32_Process snapshot output");const s=r.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),e=M(s),t=JSON.parse(e),o=Array.isArray(t)?t:[t],i=[];for(const a of o){const c=Number(a?.ProcessId);!Number.isFinite(c)||c<=0||i.push({processId:c,parentProcessId:Number(a?.ParentProcessId)||0,name:String(a?.Name??""),commandLine:a?.CommandLine??null,creationDate:a?.CreationDate??null,workingSetSize:a?.WorkingSetSize??null,handleCount:a?.HandleCount??null})}return{entries:i}}function L(n,r){return n.entries.some(s=>s.processId===r)}function _(n){const r=[];for(const s of n.entries){const e=s.commandLine;if(!s.processId||!e)continue;const t=s.name.toLowerCase();!t.includes("node")&&!t.includes("claude")&&!t.includes("opencode")&&!t.includes("python")||y(e)&&r.push({pid:s.processId,command:e,agentId:$(e)})}return r}function v(n,r){const s=r.toLowerCase();for(const e of n.entries){const t=e.commandLine;if(!t)continue;const o=e.name.toLowerCase();if(!(!o.includes("node")&&!o.includes("claude")&&!o.includes("opencode"))&&t.toLowerCase().includes(s))return{pid:e.processId,command:t,agentId:r}}}async function E(n,r){let s;try{const e=n.replace(/#\s*<\s*CLIXML[\s\S]*?(?=\{|\[|$)/g,"").trim(),t=M(e),o=JSON.parse(t);s=Array.isArray(o)?o:[o]}catch(e){d.debug(`[searchOrphanInProcessTree] JSON parse failed, raw length=${n.length}`,e);return}return k(s,r,e=>G(e,r))}async function k(n,r,s){if(!n.length)return;const e=new Map;for(const c of n)c.processId&&e.set(c.processId,c);function t(c){const u=c.name.toLowerCase(),p=(c.commandLine||"").toLowerCase();return!!(u.includes("claude")||p.includes("claude")||p.includes("@anthropic-ai/claude-code")||p.includes("cli.js")||u.includes("opencode")||p.includes("opencode")||p.includes("serve")&&p.includes("--port"))}function o(c){const u=c.toLowerCase();return u==="powershell.exe"||u==="cmd.exe"||u==="pwsh.exe"||u==="bash.exe"}function i(c){let u=c;const p=10;for(let I=0;I<p;I++){const m=e.get(u);if(!m)break;if(o(m.name)){const f=e.get(m.parentProcessId);if(f&&f.name.toLowerCase()==="node.exe"){const S=(f.commandLine||"").toLowerCase();if(S.includes("runtime-bridge")||S.includes("agentswork"))return d.debug(`[searchOrphanInProcessTree] Found bridge ancestor chain: agent(${c}) -> shell(${m.processId}) -> node(${f.processId})`),{shellPid:m.processId,shellCmd:m.commandLine||""}}}if(u=m.parentProcessId,u<=0)break}return null}for(const c of n){if(!t(c))continue;const u=i(c.processId);if(u){if(u.shellCmd.toLowerCase().includes(r.toLowerCase()))return d.info(`[searchOrphanInProcessTree] Found orphan by tree search (agentId verified): agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r};const m=n.filter(f=>t(f)&&i(f.processId));if(m.length===1)return d.info(`[searchOrphanInProcessTree] Found orphan by tree search (single candidate): agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r};d.debug(`[searchOrphanInProcessTree] Multiple candidates found (${m.length}), cannot determine which belongs to agentId=${r}`)}}const a=n.filter(c=>t(c)&&!i(c.processId));for(const c of a)if(await s(c.processId))return d.info(`[searchOrphanInProcessTree] Found orphan by env verification: agentId=${r}, pid=${c.processId}, name=${c.name}`),{pid:c.processId,command:c.commandLine||"",agentId:r}}function H(n,r){const s=r.toLowerCase(),e=new Map;for(const t of n.entries)t.processId&&e.set(t.processId,t);return t=>{const o=e.get(t);if(o&&(o.commandLine||"").toLowerCase().includes(s))return!0;const i=o?e.get(o.parentProcessId):void 0;if(i&&(i.commandLine||"").toLowerCase().includes(s))return!0;const a=i?e.get(i.parentProcessId):void 0;return!!(a&&(a.commandLine||"").toLowerCase().includes(s))}}async function D(n,r,s){const e=s.find(o=>o.agentId===n);if(e)return e;const t=v(r,n);return t||await k(r.entries,n,H(r,n))}function M(n){const r=n.indexOf("["),s=n.indexOf("{");let e=-1;return r>=0&&s>=0?e=Math.min(r,s):r>=0?e=r:s>=0&&(e=s),e<0?n:n.substring(e)}async function G(n,r){try{const s=`
|
|
5
5
|
try {
|
|
6
6
|
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
7
|
-
if ($proc -and $proc.CommandLine -like '*${
|
|
7
|
+
if ($proc -and $proc.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
|
|
8
8
|
} catch { 'ERROR' }
|
|
9
|
-
`;if((await
|
|
9
|
+
`;if((await l(s,5e3)).trim()==="MATCH")return!0;const t=`
|
|
10
10
|
try {
|
|
11
11
|
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
12
12
|
if ($proc) {
|
|
13
13
|
$parentPid = $proc.ParentProcessId
|
|
14
14
|
$parent = Get-CimInstance Win32_Process -Filter "ProcessId = $parentPid" -ErrorAction SilentlyContinue
|
|
15
|
-
if ($parent -and $parent.CommandLine -like '*${
|
|
15
|
+
if ($parent -and $parent.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
|
|
16
16
|
} else { 'NOPROC' }
|
|
17
17
|
} catch { 'ERROR' }
|
|
18
|
-
`;if((await
|
|
18
|
+
`;if((await l(t,5e3)).trim()==="MATCH")return!0;const i=`
|
|
19
19
|
try {
|
|
20
20
|
$proc = Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" -ErrorAction SilentlyContinue
|
|
21
21
|
if ($proc) {
|
|
@@ -24,11 +24,11 @@ import{execSync as O,exec as k}from"child_process";import h from"os";import{prom
|
|
|
24
24
|
if ($parent) {
|
|
25
25
|
$grandParentPid = $parent.ParentProcessId
|
|
26
26
|
$grandParent = Get-CimInstance Win32_Process -Filter "ProcessId = $grandParentPid" -ErrorAction SilentlyContinue
|
|
27
|
-
if ($grandParent -and $grandParent.CommandLine -like '*${
|
|
27
|
+
if ($grandParent -and $grandParent.CommandLine -like '*${r}*') { 'MATCH' } else { 'NOMATCH' }
|
|
28
28
|
} else { 'NOPARENT' }
|
|
29
29
|
} else { 'NOPROC' }
|
|
30
30
|
} catch { 'ERROR' }
|
|
31
|
-
`;return(await
|
|
31
|
+
`;return(await l(i,5e3)).trim()==="MATCH"}catch(s){return d.debug(`[verifyProcessAgentId] Failed for pid=${n}, agentId=${r}:`,s),!1}}async function ne(n){if(n)try{const r=await w(),s=n.replace(/\\/g,"/").toLowerCase();for(const e of r)if(e.command.replace(/\\/g,"/").toLowerCase().includes(s))return d.info(`[findOrphanProcessByWorkspace] Found process by workspace: pid=${e.pid}, workspace=${n}`),e;if(h.platform()==="win32"){const t=`
|
|
32
32
|
$targetPath = '${n.replace(/'/g,"''")}'.ToLower().Replace('\\', '/')
|
|
33
33
|
$procs = Get-CimInstance Win32_Process | Where-Object {
|
|
34
34
|
$_.CommandLine -and ($_.Name -like '*node*' -or $_.Name -like '*claude*' -or $_.Name -like '*opencode*')
|
|
@@ -39,7 +39,7 @@ import{execSync as O,exec as k}from"child_process";import h from"os";import{prom
|
|
|
39
39
|
@{ProcessId=$proc.ProcessId; CommandLine=$proc.CommandLine} | ConvertTo-Json -Compress
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
`,
|
|
43
|
-
`).filter(
|
|
44
|
-
`).filter(Boolean).map(Number),
|
|
42
|
+
`,o=await l(t,1e4);if(o&&o.trim()){const i=o.trim().split(`
|
|
43
|
+
`).filter(a=>a.trim());for(const a of i)try{const c=JSON.parse(a.trim());if(c.ProcessId)return d.info(`[findOrphanProcessByWorkspace] Found process by PowerShell workspace search: pid=${c.ProcessId}`),{pid:c.ProcessId,command:c.CommandLine||""}}catch{}}}}catch(r){d.debug("[findOrphanProcessByWorkspace] Failed:",r)}}function J(n){try{return process.kill(n,"SIGTERM"),!0}catch(r){return d.warn(`Failed to terminate process ${n}:`,r),!1}}async function j(n){const r={terminated:0,failed:0};if(h.platform()==="win32")try{await g(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3,windowsHide:!0}),r.terminated++,d.info(`Terminated process tree for pid=${n}`)}catch(s){const e=s;d.warn(`Failed to terminate process tree for pid=${n}:`,e.message),r.failed++}else{const s=await b(n);d.debug(`Found ${s.length} child processes for pid=${n}`);for(const e of s){const t=await j(e);r.terminated+=t.terminated,r.failed+=t.failed}J(n)?r.terminated++:r.failed++}return r}async function b(n){try{const{stdout:r}=await g(`pgrep -P ${n}`,{encoding:"utf8",timeout:3e3}),s=r.trim().split(`
|
|
44
|
+
`).filter(Boolean).map(Number),e=[];for(const t of s)e.push(t),e.push(...await b(t));return e}catch{return[]}}async function te(n,r=5e3){const s=Date.now();for(;Date.now()-s<r;){if(!await P(n))return!0;const e=Math.min(100,r-(Date.now()-s));e>0&&await new Promise(t=>setTimeout(t,e))}return!1}async function re(n,r){if(r)return await z(n,r);const s=[];for(const e of n)if(e.pid&&await P(e.pid)){const o=(await w()).find(i=>i.pid===e.pid);o?(s.push({agentId:e.agentId,process:o,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by PID: agentId=${e.agentId}, pid=${e.pid}`)):(s.push({agentId:e.agentId,process:{pid:e.pid,command:e.command||"(unknown - persisted session)",agentId:e.agentId},sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by PID (no cmd match): agentId=${e.agentId}, pid=${e.pid}`))}for(const e of n)if(!e.pid&&e.agentId){const t=await x(e.agentId);t&&!s.some(o=>o.agentId===e.agentId)&&(s.push({agentId:e.agentId,process:t,sessionInfo:{workspacePath:e.workspacePath,command:e.command}}),d.info(`Found orphan process by agentId: agentId=${e.agentId}, pid=${t.pid}`))}return s}async function z(n,r){const s=[],e=_(r);for(const t of n)if(t.pid&&L(r,t.pid)){const o=e.find(i=>i.pid===t.pid);o?(s.push({agentId:t.agentId,process:o,sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by PID: agentId=${t.agentId}, pid=${t.pid}`)):(s.push({agentId:t.agentId,process:{pid:t.pid,command:t.command||"(unknown - persisted session)",agentId:t.agentId},sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by PID (no cmd match): agentId=${t.agentId}, pid=${t.pid}`))}for(const t of n)if(!t.pid&&t.agentId){const o=await D(t.agentId,r,e);o&&!s.some(i=>i.agentId===t.agentId)&&(s.push({agentId:t.agentId,process:o,sessionInfo:{workspacePath:t.workspacePath,command:t.command}}),d.info(`Found orphan process by agentId: agentId=${t.agentId}, pid=${o.pid}`))}return s}async function U(n,r){const s={pid:n,agentId:r,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};try{if(!await P(n))return s.status="dead",d.debug(`Process ${n} is not running`),s;s.alive=!0;const{cpu:e,memoryMB:t}=await q(n);return s.cpu=e,s.memoryMB=t,t>2048?s.status="high_memory":e>100?s.status="high_cpu":s.status="healthy",d.debug(`Process ${n} health: CPU=${e}%, Memory=${t}MB, Status=${s.status}`),s}catch(e){return d.warn(`Failed to check health for process ${n}:`,e),s.status="dead",s}}async function q(n){if(h.platform()==="win32"){const s=`Get-CimInstance Win32_Process -Filter "ProcessId=${n}" | Select-Object @{Name='CPU';Expression={$_.WorkingSetSize/1MB}}, @{Name='Mem';Expression={$_.WorkingSetSize/1MB}} | ConvertTo-Json -Compress`;try{const e=await l(s,5e3);if(!e||!e.trim())return{cpu:0,memoryMB:0};const t=JSON.parse(e);return{cpu:0,memoryMB:Math.round((t.WorkingSetSize||0)/1024/1024)}}catch{return{cpu:0,memoryMB:0}}}else try{const{stdout:s}=await g(`ps -p ${n} -o %cpu=,rss=`,{encoding:"utf8",timeout:5e3}),e=s.trim().split(/\s+/);if(e.length>=2)return{cpu:parseFloat(e[0])||0,memoryMB:Math.round(parseInt(e[1],10)/1024)}}catch{return{cpu:0,memoryMB:0}}return{cpu:0,memoryMB:0}}async function se(n,r){const s=new Map;if(r){for(const t of n)t.pid&&s.set(t.agentId,K(t.pid,t.agentId,r));return s}const e=n.filter(t=>t.pid).map(async t=>{const o=await U(t.pid,t.agentId);s.set(t.agentId,o)});return await Promise.all(e),s}function K(n,r,s){const e={pid:n,agentId:r,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date};return L(s,n)?(e.alive=!0,e.cpu=0,e.memoryMB=0,e.status="healthy",d.debug(`Process ${n} health: CPU=0%, Memory=0MB, Status=healthy`),e):(e.status="dead",d.debug(`Process ${n} is not running`),e)}async function oe(n=new Set,r=new Set){const s=[],e=await w();for(const t of e){const o=n.has(t.pid),i=t.agentId?r.has(t.agentId):!1;s.push({...t,isRunning:!0,managementStatus:o||i?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}return s}async function ce(n){const r=new Set(n.map(a=>a.pid)),s=new Set(n.map(a=>a.agentId)),e=new Map(n.map(a=>[a.pid,a])),t=[],o=new Set,i=await w();for(const a of i){o.add(a.pid);const c=r.has(a.pid),u=a.agentId?s.has(a.agentId):!1,p=e.get(a.pid),I=a.agentId||p?.agentId;t.push({...a,agentId:I,isRunning:!0,managementStatus:c||u?"managed":"orphan",sessionId:void 0,lastSeen:new Date().toISOString()})}for(const a of n)!o.has(a.pid)&&!await P(a.pid)&&t.push({pid:a.pid,command:"(process exited)",agentId:a.agentId,isRunning:!1,managementStatus:"unknown",lastSeen:void 0});return t}export{ee as captureProcessSnapshot,se as checkAllSessionsHealth,U as checkProcessHealth,re as detectOrphanProcesses,oe as discoverAllProcesses,ce as discoverAllProcessesFull,w as findClaudeCodeProcesses,x as findOrphanProcessByAgentId,ne as findOrphanProcessByWorkspace,Z as isProcessRunning,P as isProcessRunningAsync,J as terminateProcess,j as terminateProcessTree,te as waitForProcessExit};
|
|
45
45
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import d from"axios";import{getBrowserPool as m}from"../browser/browser-pool.js";import{getAcodeBgManager as f}from"./acode-bg-manager.js";import{resolveSchedulerBaseUrl as g}from"../config.js";import{ptySessions as p}from"../routes/pty.js";import{getRuntimeAccessToken as l}from"./runtime-binding.js";import{subAgentManager as h}from"./sub-agent-manager-instance.js";import{createLogger as $}from"../utils/logger.js";const c=$("runtime-resources"),w=3e3,i=20;function s(r,e){const t=String(r??"").replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e)}\u2026`:t}function b(r){if(typeof r!="number"||!Number.isFinite(r)||r<=0)return"";const e=new Date(r),t=n=>String(n).padStart(2,"0");return`${t(e.getHours())}:${t(e.getMinutes())}`}async function k(r){try{const e=await f();return e?.listTasksWithReconcile?(await e.listTasksWithReconcile(r,"running")).filter(n=>n.status==="running").slice(0,i).map(n=>{const o=b(n.startedAt),a=n.description?s(n.description,60):s(n.commandPreview||n.command,80);return{kind:"background commands",text:`${n.taskId} \`${a}\`${o?` (since ${o})`:""}`}}):[]}catch(e){return c.warn(`collect background commands failed: ${e?.message}`),[]}}function y(r){try{const e=[];for(const t of p.values()){if(t.ownerUserId!==r||t.status!=="running")continue;if(e.length>=i)break;const n=s(t.title||t.shell,60);e.push({kind:"terminals",text:`${t.id} ${n} (running)`})}return e}catch(e){return c.warn(`collect terminals failed: ${e?.message}`),[]}}function S(r){try{return h.listActiveByParent(r).slice(0,i).map(t=>({kind:"sub-agents",text:`${t.subId} ${t.subagentType} "${s(t.description,60)}" (running)`}))}catch(e){return c.warn(`collect sub-agents failed: ${e?.message}`),[]}}function v(r){try{return m().listSessions(r).slice(0,i).map(t=>{const n=s(t.title||t.browserId,40),o=s(t.currentUrl,80);return{kind:"browsers",text:`"${n}"${o?` ${o}`:""}`}})}catch(e){return c.warn(`collect browsers failed: ${e?.message}`),[]}}function u(r,e){if(!Array.isArray(e))return[];const t=[];for(const n of e){if(t.length>=i)break;const o=s(String(n?.name??n?.docId??""),60);if(!o)continue;const a=String(n?.permission??"").trim();t.push({kind:r,text:`${o}${a?` (${a})`:""}`})}return t}async function x(r){try{const{url:e}=g();if(!e)return[];const t=l(e)||l();if(!t)return[];const o=(await d.get(`${e}/api/runtime/agent-resources`,{params:{agentId:r},headers:{"X-Runtime-Token":t},timeout:w})).data??{};return[...u("office docs",o.officeDocs),...u("pencil docs",o.pencilDocs),...u("draw docs",o.drawDocs)]}catch(e){return c.warn(`collect java docs failed (office/pencil/draw omitted): agentId=${r}, error=${e?.message}`),[]}}function A(r){const e=new Map;for(const n of r){const o=e.get(n.kind);o?o.push(n.text):e.set(n.kind,[n.text])}const t=["[Runtime resources \u2014 live snapshot taken after context compaction.]","These already exist and are still running/available. Reuse them instead of creating duplicates","(do not start another dev server, open another browser, or redraw an existing document).","Details (output, page content, document body) are not included \u2014 query them when needed."];for(const[n,o]of e)t.push(`- ${n} (${o.length}): ${o.join("; ")}`);return t.join(`
|
|
2
|
+
`)}async function j(r){if(!r)return null;try{const[e,t]=await Promise.all([k(r),x(r)]),n=[...e,...y(r),...S(r),...v(r),...t];return n.length===0?null:A(n)}catch(e){return c.warn(`build snapshot failed: ${e?.message}`),null}}export{j as buildRuntimeResourcesSnapshot};
|
|
3
|
+
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { type AxiosResponse } from "axios";
|
|
3
|
+
import type { RuntimeToolBatchMetrics } from "../adapter/types.js";
|
|
3
4
|
import type { Session } from "../types.js";
|
|
4
5
|
import { RingBuffer, type RingBufferEntry, type RingBufferSlice } from "./ring-buffer.js";
|
|
5
6
|
|
|
@@ -19,7 +20,13 @@ export interface BridgeEventPayload {
|
|
|
19
20
|
readonly actionInput?: string;
|
|
20
21
|
readonly actionResult?: string;
|
|
21
22
|
readonly actionId?: string;
|
|
23
|
+
|
|
24
|
+
readonly actionError?: string;
|
|
22
25
|
readonly parentId?: string;
|
|
26
|
+
|
|
27
|
+
readonly batchId?: string;
|
|
28
|
+
|
|
29
|
+
readonly batchMetrics?: RuntimeToolBatchMetrics;
|
|
23
30
|
readonly inputTokens?: number;
|
|
24
31
|
readonly outputTokens?: number;
|
|
25
32
|
|
|
@@ -46,7 +53,13 @@ interface RuntimeStatusActionInfo {
|
|
|
46
53
|
actionResult?: string;
|
|
47
54
|
actionId?: string;
|
|
48
55
|
|
|
56
|
+
actionError?: string;
|
|
57
|
+
|
|
49
58
|
parentId?: string;
|
|
59
|
+
|
|
60
|
+
batchId?: string;
|
|
61
|
+
|
|
62
|
+
batchMetrics?: RuntimeToolBatchMetrics;
|
|
50
63
|
}
|
|
51
64
|
export interface RuntimeCallbackAuthOptions {
|
|
52
65
|
runtimeAccessToken?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import h from"axios";import{resolveSchedulerBaseUrlFrom as
|
|
2
|
-
${
|
|
3
|
-
[AgentsWorkStudio: omitted ${
|
|
4
|
-
`,u=Math.max(0,
|
|
1
|
+
import h from"axios";import{resolveSchedulerBaseUrlFrom as H}from"../config.js";import{requestRuntimeAccessTokenRefreshForServer as C}from"../services/auto-register.js";import{logger as f}from"../utils/logger.js";import{agentEventStore as S}from"./agent-event-store.js";import{scheduleEventPush as $}from"./event-delta-pusher.js";import{RingBuffer as P}from"./ring-buffer.js";import{getRuntimeAccessToken as _}from"./runtime-binding.js";const B=new P(2e3);function m(t,r=y(t)){const c=t?.runtimeAccessToken||_(r)||_();return c?{"X-Runtime-Token":c}:void 0}function x(t){if(t)return{schedulerBaseUrl:t.schedulerBaseUrl}}function y(t){return H(t?.schedulerBaseUrl).url}const O=100;function w(t){if(typeof t!="object"||t===null)return;const r=t.response;if(typeof r!="object"||r===null)return;const c=r.status;return typeof c=="number"?c:void 0}let L=null;async function R(t){if(L)return L;L=(async()=>{try{const r=await C(t);return r.success&&r.runtimeAccessToken?(f.info("[session-output] Runtime token refreshed after 401"),!0):(f.warn("[session-output] Runtime token refresh failed",{error:r.error}),!1)}catch(r){return f.warn("[session-output] Runtime token refresh threw",{error:r}),!1}})();try{return await L}finally{L=null}}const E=8e3,M=64*1024,g=32*1024,A=15e3,U=new Map;async function J(t,r,c,e,i,o,u,s){const n={agentId:t,sessionId:r,status:c};u!==void 0&&(n.timestamp=u),e&&(e.actionType&&(n.actionType=e.actionType),e.actionLabel&&(n.actionLabel=e.actionLabel),e.actionDetail&&(n.actionDetail=e.actionDetail),e.actionInput&&(n.actionInput=e.actionInput),e.actionResult&&(n.actionResult=e.actionResult),e.actionError&&(n.actionError=e.actionError),e.actionId&&(n.actionId=e.actionId),e.parentId&&(n.parentId=e.parentId),e.batchId&&(n.batchId=e.batchId),e.batchMetrics&&(n.batchMetrics=e.batchMetrics)),i&&(n.inputTokens=i.inputTokens,n.outputTokens=i.outputTokens,i.contextLimit&&(n.contextLimit=i.contextLimit),i.maxOutput&&(n.maxOutput=i.maxOutput),i.inputLimit&&(n.inputLimit=i.inputLimit),i.compactionThreshold&&(n.compactionThreshold=i.compactionThreshold),i.cacheHitTokens!==void 0&&(n.cacheHitTokens=i.cacheHitTokens),i.cacheMissTokens!==void 0&&(n.cacheMissTokens=i.cacheMissTokens)),s&&(n.sourceEventType=s),process.env.ACODE_TOKEN_DEBUG==="1"&&(n.inputTokens!==void 0||n.outputTokens!==void 0||n.cacheHitTokens!==void 0||n.cacheMissTokens!==void 0)&&console.log(`[TokenDebug][SendStatus] status=${c} inputTokens=${n.inputTokens??"(none)"} outputTokens=${n.outputTokens??"(none)"} cacheHitTokens=${n.cacheHitTokens??"(none)"} cacheMissTokens=${n.cacheMissTokens??"(none)"} contextLimit=${n.contextLimit??"(none)"} actionType=${n.actionType??"(none)"}`);const a=y(o),k=m(o,a);if(!k){f.warn("Skip runtime status callback because runtime token is missing",{agentId:t,sessionId:r,status:c,schedulerBaseUrl:a});return}const p=e?.actionType==="context_compaction";p&&f.info("[compaction-diag] sendStatus enter",{agentId:t,sessionId:r,status:c,actionId:e?.actionId,parentId:e?.parentId,actionLabel:e?.actionLabel});try{const l=await h.post(`${a}/api/runtime/callback/status`,n,{headers:k,timeout:15e3});if(p){const d=l?.data;f.info("[compaction-diag] sendStatus success",{agentId:t,actionId:e?.actionId,actionLabel:e?.actionLabel,httpStatus:l?.status,ignored:d?.ignored,responseBody:d})}return l}catch(l){if(w(l)===401&&await R(a)){const T=m(x(o),a);if(T)try{const b=await h.post(`${a}/api/runtime/callback/status`,n,{headers:T,timeout:15e3});if(p){const v=b?.data;f.info("[compaction-diag] sendStatus retry success",{agentId:t,actionId:e?.actionId,actionLabel:e?.actionLabel,httpStatus:b?.status,ignored:v?.ignored})}return b}catch(b){f.warn("Runtime status callback retry failed after token refresh",{agentId:t,sessionId:r,status:c,error:b});return}}f.warn("Runtime status callback failed",{agentId:t,sessionId:r,status:c,schedulerBaseUrl:a,error:l});return}finally{const l={category:"status",agentId:t,sessionId:r,status:c,actionType:e?.actionType,actionLabel:e?.actionLabel,actionDetail:e?.actionDetail,actionInput:e?.actionInput,actionResult:e?.actionResult,actionError:e?.actionError,actionId:e?.actionId,parentId:e?.parentId,batchId:e?.batchId,batchMetrics:e?.batchMetrics,inputTokens:i?.inputTokens,outputTokens:i?.outputTokens,cacheHitTokens:i?.cacheHitTokens,cacheMissTokens:i?.cacheMissTokens,sourceEventType:s};B.append(l);const d=S.append(t,l);$(t,d,o)}}async function D(t,r,c,e,i,o,u){const s=y(o);try{const n=m(o,s);if(!n){f.warn("Skip runtime output callback because runtime token is missing",{agentId:t,sessionId:c,schedulerBaseUrl:s});return}const a={headers:n,timeout:A};u&&(a.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:t,output:r,sessionId:c,seq:e,...i},a)}catch(n){if(u?.aborted||n?.name==="AbortError"||n?.code==="ERR_CANCELED")throw n;if(w(n)===401&&await R(s)){const k=m(x(o),s);if(k)try{const p={headers:k,timeout:A};u&&(p.signal=u),await h.post(`${s}/api/runtime/callback/output`,{agentId:t,output:r,sessionId:c,seq:e,...i},p);return}catch{}}throw f.warn("Runtime output callback failed",{agentId:t,sessionId:c,error:n}),n}finally{const n=r.length>E?`...(truncated)
|
|
2
|
+
${r.slice(-E)}`:r,a={category:"output",agentId:t,sessionId:c,output:n,seq:e,sourceEventType:i?.sourceEventType,logLevel:i?.logLevel,logCategory:i?.logCategory};B.appendOrMerge(a,p=>{const l=p.data;if(l.category!=="output"||l.sessionId!==c||l.sourceEventType!==i?.sourceEventType||Date.now()-p.timestamp>1e4)return!1;const d=(l.output||"").length,T=(a.output||"").length;return d+T<=E},(p,l)=>{const d=p.output||"",T=l.output||"";return d.includes(T)?p:{...p,output:`${d}${T}`}});const k=S.appendOrMergeOutput(t,a);$(t,k,o)}}async function V(t,r,c,e,i){const o=y(e),u={agentId:t,sessionId:r,questions:c,...i?{toolCallId:i}:{}};try{const s=m(e,o);if(!s)return;await h.post(`${o}/api/runtime/callback/question`,u,{headers:s})}catch(s){if(w(s)===401&&await R(o)){const a=m(x(e),o);if(a)try{await h.post(`${o}/api/runtime/callback/question`,u,{headers:a});return}catch{}}}finally{const s={category:"question",agentId:t,sessionId:r,...i?{toolCallId:i}:{},questions:c};B.append(s);const n=S.append(t,s);$(t,n,e)}}async function Y(t,r,c,e){const i=y(e),o={agentId:t,sessionId:r,...c};try{const u=m(e,i);if(!u)return;await h.post(`${i}/api/runtime/callback/tool-auth`,o,{headers:u})}catch(u){if(w(u)===401&&await R(i)){const n=m(x(e),i);if(n)try{await h.post(`${i}/api/runtime/callback/tool-auth`,o,{headers:n});return}catch{}}}}async function Z(t){const r=y();try{const c=m(void 0,r);if(!c)return;await h.post(`${r}/api/runtime/callback/file-changed`,t,{headers:c})}catch(c){if(w(c)===401&&await R(r)){const i=m(void 0,r);if(i)try{await h.post(`${r}/api/runtime/callback/file-changed`,t,{headers:i});return}catch{}}}finally{const c={category:"file_changed",agentId:"",sessionId:null,workspacePath:t.workspacePath,filePath:t.filePath,eventType:t.eventType,size:t.size};B.append(c)}}function I(t,r){const c=U.get(t);if(!c||!r)return;const e=`${c.outputBuffer}${r}`;if(e.length<=M){c.outputBuffer=e;return}const o=`\r
|
|
3
|
+
[AgentsWorkStudio: omitted ${e.length-M} chars of old terminal output]\r
|
|
4
|
+
`,u=Math.max(0,M-o.length);c.outputBuffer=`${o}${e.slice(-u)}`}function F(t){const r=U.get(t);r&&(r.flushTimer||(r.flushTimer=setTimeout(()=>{r.flushTimer=null,q(t).catch(()=>{})},O)))}async function q(t){const r=U.get(t);if(!r||r.flushInFlight||!r.outputBuffer)return;const c=r.outputBuffer.slice(0,g);r.outputBuffer=r.outputBuffer.slice(g);const e=(async()=>{const i=r.seq+1;r.seq=i,await D(r.agentId,c,t,i),U.get(t)?.outputBuffer&&F(t)})();r.flushInFlight=e;try{await e}finally{const i=U.get(t);i&&(i.flushInFlight=null)}}export{I as appendSessionOutput,B as bridgeEventBuffer,q as flushSessionOutput,F as scheduleOutputFlush,Z as sendFileChanged,D as sendOutput,V as sendQuestionRequest,J as sendStatus,Y as sendToolAuthRequest,U as sessions};
|
|
5
5
|
|