aws-runtime-bridge 1.9.146 → 1.9.147

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.
Files changed (32) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +6 -1
  2. package/dist/adapter/AcodeSdkAdapter.js +5 -5
  3. package/dist/browser/browser-pool.d.ts +4 -0
  4. package/dist/browser/browser-pool.js +1 -1
  5. package/dist/desktop/built-in-desktop-tools.d.ts +6 -0
  6. package/dist/desktop/built-in-desktop-tools.js +1 -1
  7. package/dist/routes/background-tasks.js +4 -4
  8. package/dist/routes/instance.js +1 -1
  9. package/dist/routes/terminal.js +19 -19
  10. package/dist/services/builtin-commands/create-plugin.md +44 -0
  11. package/dist/services/changelog.d.ts +8 -0
  12. package/dist/services/changelog.js +17 -0
  13. package/dist/services/instance-features.d.ts +2 -0
  14. package/dist/services/instance-features.js +1 -1
  15. package/dist/services/plugin-manager.js +1 -1
  16. package/dist/utils/npm-version.d.ts +2 -0
  17. package/dist/utils/npm-version.js +1 -1
  18. package/package/acode/dist/background-command-manager.d.ts +4 -0
  19. package/package/acode/dist/background-command-manager.js +2 -2
  20. package/package/acode/dist/background-command-store.d.ts +2 -0
  21. package/package/acode/dist/built-in-file-tools.js +2 -2
  22. package/package/acode/dist/image-utils.d.ts +30 -1
  23. package/package/acode/dist/image-utils.js +1 -1
  24. package/package/acode/dist/runtime-environment.d.ts +3 -0
  25. package/package/acode/dist/runtime-environment.js +3 -0
  26. package/package/acode/dist/runtime.js +14 -14
  27. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +16 -0
  28. package/package/aws-client-agent-mcp/dist/mcp-server.js +20 -20
  29. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +16 -0
  30. package/package/aws-client-agent-mcp/dist/mcp-tools.js +7 -7
  31. package/package/aws-client-agent-mcp/dist/types.d.ts +10 -1
  32. package/package.json +2 -2
@@ -1,10 +1,10 @@
1
- import{spawn as Ge}from"node:child_process";import{promises as q}from"node:fs";import Qe from"node:os";import B from"node:path";import{TextDecoder as ee}from"node:util";import be from"axios";import{Router as Ve}from"express";import{v4 as Je}from"uuid";import{adapterRegistry as b,getToolActionInfo as ye,isTransientClipboardPasteFilePath as we,redactTransientClipboardPastePaths as v,registerSdkProviders as Ye,resolveSdkProviderIdByCommand as Ze}from"../adapter/index.js";import{MESSAGE_POLLING_IDLE_PROMPT as _e}from"../adapter/prompts.js";import{getActiveBridgeHttpPort as et,getAcodeDataHome as Ce}from"../config.js";import{validateToken as I}from"../middleware/auth.js";import{getAgentProcessManager as he}from"../services/agent-process-manager.js";import{createAiConfigService as tt}from"../services/ai-config-service.js";import{resolveSchedulerBaseUrlFromToken as $e}from"../services/auto-register.js";import{setChangeCacheRetentionDays as nt}from"../services/change-cache-retention.js";import{getAllPushStats as rt,startHeartbeatScheduler as ot}from"../services/event-delta-pusher.js";import{prepareAcodeInstanceConfig as st,redactForLog as te}from"../services/instance-ai-config-service.js";import{setAgentFeatures as it,setAgentCapabilities as at,getAgentFeatures as ct,isFeatureEnabled as De,LAUNCH_ITEM_FEATURE_KEY as ut,HIRE_FEATURE_KEY as dt}from"../services/instance-features.js";import{enqueueMcpLaunchBinding as lt}from"../services/mcp-launch-binding-queue.js";import{setPanelEnvVars as mt}from"../services/panel-env.js";import{findClaudeCodeProcesses as ft,isProcessRunning as pt}from"../services/process-detector.js";import{forgetSession as F,onSdkToolUseEnd as gt,onSdkToolUseStart as yt}from"../services/sdk-tool-file-change-recorder.js";import{bridgeEventBuffer as Re,sendOutput as G,sendQuestionRequest as ht,sendToolAuthRequest as It,sendStatus as C}from"../services/session-output.js";import{findPersistedSessionByAgentId as St,removePersistedSession as K,savePersistedSessions as At,updatePersistedSessionAutoCommands as Tt,updatePersistedSessionRuntimeState as kt,upsertPersistedSession as bt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as wt}from"../utils/instance-ai-config-debug-logger.js";import{logger as m}from"../utils/logger.js";const S=Ve();function Pe(e){const n=e.header("X-Runtime-Token");return n&&n.trim()?n.trim():(e.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||void 0}const p=new Map,_t=45e3,ne=new Map;function Ct(e){if(ne.has(e))return;const n=setInterval(()=>{const t=p.get(e);if(!t){L(e);return}const r=t.currentRuntimeStatus;if(r!=="thinking"&&r!=="tool_using"&&r!=="compacting"){L(e);return}C(t.agentId,e,r,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},_t);ne.set(e,n)}function L(e){const n=ne.get(e);n&&(clearInterval(n),ne.delete(e))}const Ee=4e3,$t=`
1
+ import{spawn as Ge}from"node:child_process";import{promises as q}from"node:fs";import Qe from"node:os";import B from"node:path";import{TextDecoder as ee}from"node:util";import we from"axios";import{Router as Ve}from"express";import{v4 as Je}from"uuid";import{adapterRegistry as b,getToolActionInfo as ye,isTransientClipboardPasteFilePath as _e,redactTransientClipboardPastePaths as v,registerSdkProviders as Ye,resolveSdkProviderIdByCommand as Ze}from"../adapter/index.js";import{MESSAGE_POLLING_IDLE_PROMPT as Ce}from"../adapter/prompts.js";import{getActiveBridgeHttpPort as et,getAcodeDataHome as $e}from"../config.js";import{validateToken as I}from"../middleware/auth.js";import{getAgentProcessManager as he}from"../services/agent-process-manager.js";import{createAiConfigService as tt}from"../services/ai-config-service.js";import{resolveSchedulerBaseUrlFromToken as De}from"../services/auto-register.js";import{setChangeCacheRetentionDays as nt}from"../services/change-cache-retention.js";import{getAllPushStats as rt,startHeartbeatScheduler as ot}from"../services/event-delta-pusher.js";import{prepareAcodeInstanceConfig as st,redactForLog as te}from"../services/instance-ai-config-service.js";import{setAgentFeatures as it,setAgentCapabilities as at,getAgentFeatures as ct,isFeatureEnabled as Ie,LAUNCH_ITEM_FEATURE_KEY as ut,HIRE_FEATURE_KEY as dt,PENCIL_FEATURE_KEY as lt}from"../services/instance-features.js";import{enqueueMcpLaunchBinding as mt}from"../services/mcp-launch-binding-queue.js";import{setPanelEnvVars as ft}from"../services/panel-env.js";import{findClaudeCodeProcesses as pt,isProcessRunning as gt}from"../services/process-detector.js";import{forgetSession as F,onSdkToolUseEnd as yt,onSdkToolUseStart as ht}from"../services/sdk-tool-file-change-recorder.js";import{bridgeEventBuffer as Re,sendOutput as G,sendQuestionRequest as It,sendToolAuthRequest as St,sendStatus as C}from"../services/session-output.js";import{findPersistedSessionByAgentId as At,removePersistedSession as K,savePersistedSessions as Tt,updatePersistedSessionAutoCommands as kt,updatePersistedSessionRuntimeState as bt,upsertPersistedSession as wt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as _t}from"../utils/instance-ai-config-debug-logger.js";import{logger as m}from"../utils/logger.js";const S=Ve();function Pe(e){const n=e.header("X-Runtime-Token");return n&&n.trim()?n.trim():(e.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||void 0}const p=new Map,Ct=45e3,ne=new Map;function $t(e){if(ne.has(e))return;const n=setInterval(()=>{const t=p.get(e);if(!t){L(e);return}const r=t.currentRuntimeStatus;if(r!=="thinking"&&r!=="tool_using"&&r!=="compacting"){L(e);return}C(t.agentId,e,r,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},Ct);ne.set(e,n)}function L(e){const n=ne.get(e);n&&(clearInterval(n),ne.delete(e))}const Ee=4e3,Dt=`
2
2
 
3
3
  \u8BF7\u6C42\u4F53:
4
- `;function Me(e){if(e==null||typeof e!="object"||Array.isArray(e))return;const n=e,t={};return typeof n.model=="string"&&n.model.trim()&&(t.model=n.model.trim()),typeof n.baseURL=="string"&&n.baseURL.trim()&&(t.baseURL=n.baseURL.trim()),typeof n.apiKey=="string"&&n.apiKey.trim()&&(t.apiKey=n.apiKey.trim()),typeof n.effort=="string"&&n.effort.trim()&&(t.effort=n.effort.trim()),t}const Dt=`
4
+ `;function Me(e){if(e==null||typeof e!="object"||Array.isArray(e))return;const n=e,t={};return typeof n.model=="string"&&n.model.trim()&&(t.model=n.model.trim()),typeof n.baseURL=="string"&&n.baseURL.trim()&&(t.baseURL=n.baseURL.trim()),typeof n.apiKey=="string"&&n.apiKey.trim()&&(t.apiKey=n.apiKey.trim()),typeof n.effort=="string"&&n.effort.trim()&&(t.effort=n.effort.trim()),t}const Rt=`
5
5
 
6
6
  \u8BF7\u6C42\u5934:
7
- `,z=new Set;async function Rt(e,n){const t=[],r=[],o=B.join(e,".agentswork","memory");try{const c=(await q.readdir(o)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await q.readFile(B.join(o,u),"utf-8");return JSON.parse(l)}catch{return m.warn("[loadAgentStartupMemories] Failed to parse memory file: %s",B.join(o,u)),null}}));for(const u of d)if(u?.by_uri)for(const l of Object.values(u.by_uri)){const f=l.memory_type||"memory",g=(l.content||"").trim();g&&(f==="recently_memory"?t.push({title:l.title,content:g,uri:l.uri||""}):f==="agent_memory"&&r.push({title:l.title,content:g,uri:l.uri||""}))}}catch{m.debug("[loadAgentStartupMemories] \u65E0\u6CD5\u8BFB\u53D6\u8BB0\u5FC6\u76EE\u5F55: %s",o)}if(t.length===0&&r.length===0&&n?.schedulerBaseUrl&&n?.runtimeAccessToken&&n?.agentId){const a=`${n.schedulerBaseUrl.replace(/\/+$/,"")}/mcp/call`,c={"Content-Type":"application/json","X-Runtime-Token":n.runtimeAccessToken,Authorization:`Bearer ${n.runtimeAccessToken}`},d=["recently_memory","agent_memory"],u=await Promise.allSettled(d.map(l=>fetch(a,{method:"POST",headers:c,body:JSON.stringify({tool:"list_memories",arguments:{agentId:n.agentId,memory_type:l}})}).then(f=>{if(!f.ok)throw new Error(`Server returned ${f.status}`);return f.json()})));for(let l=0;l<u.length;l++){const f=u[l];if(f.status!=="fulfilled")continue;const g=f.value;if(!Array.isArray(g))continue;const T=d[l]==="recently_memory"?t:r;for(const h of g){const y=(h.content||"").trim();y&&T.push({title:h.title,content:y,uri:h.uri||""})}}(t.length>0||r.length>0)&&m.info(`[loadAgentStartupMemories] Loaded ${t.length} task(s) and ${r.length} memory(s) from server for ${n.agentId}`)}const s=10;t.sort((a,c)=>c.uri.localeCompare(a.uri)),r.sort((a,c)=>c.uri.localeCompare(a.uri));const i=[];if(t.length>0){const c=t.slice(0,s).map((d,u)=>`${d.title?`\u3010${d.title}\u3011`:`\u6761\u76EE ${u+1}`}
7
+ `,z=new Set;async function Pt(e,n){const t=[],r=[],o=B.join(e,".agentswork","memory");try{const c=(await q.readdir(o)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await q.readFile(B.join(o,u),"utf-8");return JSON.parse(l)}catch{return m.warn("[loadAgentStartupMemories] Failed to parse memory file: %s",B.join(o,u)),null}}));for(const u of d)if(u?.by_uri)for(const l of Object.values(u.by_uri)){const f=l.memory_type||"memory",g=(l.content||"").trim();g&&(f==="recently_memory"?t.push({title:l.title,content:g,uri:l.uri||""}):f==="agent_memory"&&r.push({title:l.title,content:g,uri:l.uri||""}))}}catch{m.debug("[loadAgentStartupMemories] \u65E0\u6CD5\u8BFB\u53D6\u8BB0\u5FC6\u76EE\u5F55: %s",o)}if(t.length===0&&r.length===0&&n?.schedulerBaseUrl&&n?.runtimeAccessToken&&n?.agentId){const a=`${n.schedulerBaseUrl.replace(/\/+$/,"")}/mcp/call`,c={"Content-Type":"application/json","X-Runtime-Token":n.runtimeAccessToken,Authorization:`Bearer ${n.runtimeAccessToken}`},d=["recently_memory","agent_memory"],u=await Promise.allSettled(d.map(l=>fetch(a,{method:"POST",headers:c,body:JSON.stringify({tool:"list_memories",arguments:{agentId:n.agentId,memory_type:l}})}).then(f=>{if(!f.ok)throw new Error(`Server returned ${f.status}`);return f.json()})));for(let l=0;l<u.length;l++){const f=u[l];if(f.status!=="fulfilled")continue;const g=f.value;if(!Array.isArray(g))continue;const T=d[l]==="recently_memory"?t:r;for(const h of g){const y=(h.content||"").trim();y&&T.push({title:h.title,content:y,uri:h.uri||""})}}(t.length>0||r.length>0)&&m.info(`[loadAgentStartupMemories] Loaded ${t.length} task(s) and ${r.length} memory(s) from server for ${n.agentId}`)}const s=10;t.sort((a,c)=>c.uri.localeCompare(a.uri)),r.sort((a,c)=>c.uri.localeCompare(a.uri));const i=[];if(t.length>0){const c=t.slice(0,s).map((d,u)=>`${d.title?`\u3010${d.title}\u3011`:`\u6761\u76EE ${u+1}`}
8
8
  ${d.content}`);i.push(`\u3010\u77ED\u671F\u8BB0\u5FC6\u3011
9
9
  ${c.join(`
10
10
 
@@ -14,23 +14,23 @@ ${c.join(`
14
14
 
15
15
  `)}`),r.length>s&&i.push(`... \u53CA\u53E6\u5916 ${r.length-s} \u6761 agent \u8BA4\u77E5`)}if(i.length!==0)return i.join(`
16
16
 
17
- `)}function Pt(e,n){return e!=="acode"?{supported:!1,statusCode:400,error:"context reset without restart is only supported by ACode"}:n?{supported:!0}:{supported:!1,statusCode:500,error:"ACode adapter does not expose resetContext"}}function Et(e){return e!=="acode"}function Mt(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function re(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,r=Number.isFinite(n.outputTokens)?n.outputTokens:0;if(t<=0&&r<=0&&!n.contextLimit&&!n.maxOutput&&!n.inputLimit&&!n.compactionThreshold)return;const o={inputTokens:t,outputTokens:r,...n.contextLimit?{contextLimit:n.contextLimit}:{},...n.maxOutput?{maxOutput:n.maxOutput}:{},...n.inputLimit?{inputLimit:n.inputLimit}:{},...n.compactionThreshold?{compactionThreshold:n.compactionThreshold}:{},...n.cacheHitTokens?{cacheHitTokens:n.cacheHitTokens}:{},...n.cacheMissTokens?{cacheMissTokens:n.cacheMissTokens}:{}};return process.env.ACODE_TOKEN_DEBUG==="1"&&(o.inputTokens>0||o.outputTokens>0||o.cacheHitTokens!==void 0||o.cacheMissTokens!==void 0)&&m.info(`[TokenDebug][Terminal] resolveStatusChangeUsage: input=${o.inputTokens} output=${o.outputTokens} cacheHit=${o.cacheHitTokens??"(none)"} cacheMiss=${o.cacheMissTokens??"(none)"} actionType=${e?.actionType??"(none)"}`),o}function Lt(e,n){const t=String(e||"").trim().toLowerCase(),r=String(n?.actionType||"").trim().toLowerCase();return t==="tool_using"&&r==="idle"?n?{status:"waiting_input",actionInfo:n}:{status:"waiting_input"}:n?{status:e,actionInfo:n}:{status:e}}const Q=new Map,xt="utf-8",Le="utf-8",xe=300,Ue=6e4;function V(e){return String(e).padStart(2,"0")}function Ut(e,n=new Date){const t=n.getFullYear(),r=V(n.getMonth()+1),o=V(n.getDate()),s=V(n.getHours()),i=V(n.getMinutes()),a=`${t}${r}${o}-${s}${i}${V(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return B.join(Ce(),"cmd-dist",e,`${t}-${r}-${o}`,s,i,`${a}-cmd.out`)}function jt(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
17
+ `)}function Et(e,n){return e!=="acode"?{supported:!1,statusCode:400,error:"context reset without restart is only supported by ACode"}:n?{supported:!0}:{supported:!1,statusCode:500,error:"ACode adapter does not expose resetContext"}}function Mt(e){return e!=="acode"}function Lt(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function re(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,r=Number.isFinite(n.outputTokens)?n.outputTokens:0;if(t<=0&&r<=0&&!n.contextLimit&&!n.maxOutput&&!n.inputLimit&&!n.compactionThreshold)return;const o={inputTokens:t,outputTokens:r,...n.contextLimit?{contextLimit:n.contextLimit}:{},...n.maxOutput?{maxOutput:n.maxOutput}:{},...n.inputLimit?{inputLimit:n.inputLimit}:{},...n.compactionThreshold?{compactionThreshold:n.compactionThreshold}:{},...n.cacheHitTokens?{cacheHitTokens:n.cacheHitTokens}:{},...n.cacheMissTokens?{cacheMissTokens:n.cacheMissTokens}:{}};return process.env.ACODE_TOKEN_DEBUG==="1"&&(o.inputTokens>0||o.outputTokens>0||o.cacheHitTokens!==void 0||o.cacheMissTokens!==void 0)&&m.info(`[TokenDebug][Terminal] resolveStatusChangeUsage: input=${o.inputTokens} output=${o.outputTokens} cacheHit=${o.cacheHitTokens??"(none)"} cacheMiss=${o.cacheMissTokens??"(none)"} actionType=${e?.actionType??"(none)"}`),o}function xt(e,n){const t=String(e||"").trim().toLowerCase(),r=String(n?.actionType||"").trim().toLowerCase();return t==="tool_using"&&r==="idle"?n?{status:"waiting_input",actionInfo:n}:{status:"waiting_input"}:n?{status:e,actionInfo:n}:{status:e}}const Q=new Map,Ut="utf-8",Le="utf-8",xe=300,Ue=6e4;function V(e){return String(e).padStart(2,"0")}function jt(e,n=new Date){const t=n.getFullYear(),r=V(n.getMonth()+1),o=V(n.getDate()),s=V(n.getHours()),i=V(n.getMinutes()),a=`${t}${r}${o}-${s}${i}${V(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return B.join($e(),"cmd-dist",e,`${t}-${r}-${o}`,s,i,`${a}-cmd.out`)}function Bt(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
18
18
  `).replace(/\r/g,`
19
19
  `),t=n.endsWith(`
20
20
  `)?n.slice(0,-1):n;return t?t.split(`
21
- `).length:1}function Bt(e,n=xe){return`\r
21
+ `).length:1}function Ot(e,n=xe){return`\r
22
22
  [ACode] \u547D\u4EE4\u8F93\u51FA\u8D85\u8FC7 ${n} \u884C\uFF0C\u5B8C\u6574\u8F93\u51FA\u5DF2\u5199\u5165: ${e}\r
23
23
  [ACode] Agent \u53EF\u81EA\u884C\u8BFB\u53D6\u8BE5\u6587\u4EF6\uFF0C\u6216\u5728\u8BE5\u6587\u4EF6\u4E2D\u641C\u7D22\u9700\u8981\u7684\u5185\u5BB9\u3002\r
24
- `}function Ot(e=Ue){return`\r
24
+ `}function Nt(e=Ue){return`\r
25
25
  [ACode] \u547D\u4EE4\u8D85\u8FC7 ${Math.round(e/1e3)} \u79D2\u6CA1\u6709\u65B0\u7684\u8F93\u51FA\uFF0C\u5DF2\u505C\u6B62\u6267\u884C\u5E76\u4FDD\u7559\u6B64\u524D\u8F93\u51FA\u3002\r
26
- `}async function je(e){const n=e.outputPath||Ut(e.agentId,e.startedAt);return e.outputPath=n,await q.mkdir(B.dirname(n),{recursive:!0}),await q.writeFile(n,e.chunks.join(""),"utf-8"),n}function Nt(e){return String(e??"").replace(/\r/g,`
27
- `).trim()}function qt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?xt:Le)}function Be(e=qt()){if(e!=="utf-8")try{return new ee(e,{fatal:!1})}catch{return new ee(Le,{fatal:!1})}return vt()}function vt(){let e=null,n=null,t=null;const r=[];function o(s){try{return new ee(s,{fatal:!1})}catch{return new ee("utf-8",{fatal:!1})}}return{decode(s,i){if(s!=null&&r.push(s instanceof ArrayBuffer?Buffer.from(s):Buffer.isBuffer(s)?s:Buffer.from(s.buffer,s.byteOffset,s.byteLength)),t==="gb18030")return n||(n=o("gb18030")),n.decode(s,i);e||(e=o("utf-8"));const a=e.decode(s,i);if(t===null&&a.includes("\uFFFD")){t="gb18030",n=o("gb18030");const c=Buffer.concat(r);return n.decode(c)}return t===null&&!i?.stream&&(t="utf-8"),a}}}function oe(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function Ft(e){const n=e.trim().match(/^cd(?:\s+(.*))?$/i);if(!n)return;const t=n[1]?.trim();if(!t)return null;const r=t.replace(/^\/d\s+/i,"").trim();return r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function Kt(e){const n=Q.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return Q.set(e.sessionId,t),t}function Oe(e){for(const n of p.values())if(n.agentId===e)return n}async function zt(e){const n=b.get(e.providerId||"claude-code"),t=se(n.getSessionStatus(e.sessionId),e.currentRuntimeStatus,e.currentRuntimeActionType);return{sessionId:e.sessionId,status:t,runtimeStatus:t,runtimeActionType:e.currentRuntimeActionType,runtimeActionLabel:e.currentRuntimeActionLabel,runtimeActionDetail:e.currentRuntimeActionDetail,agentId:e.agentId,workspacePath:e.workspacePath,command:e.config.command,mode:"sdk",providerSessionId:n.getProviderSessionId(e.sessionId),reused:!0}}function se(e,n,t){const r=String(e||"").trim();if(r){const s=String(n||"").trim(),i=String(t||"").trim().toLowerCase();return r.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&i==="idle"?s:r}return String(n||"").trim()||"running"}function Ht(e,n=pt){return e.pid?n(e.pid)?ze(e.command)==="acode"?{reusable:!1,reason:"in-process-provider"}:{reusable:!0,reason:"active-pid"}:{reusable:!1,reason:"dead-pid"}:{reusable:!1,reason:"missing-pid"}}function nr(e){const n=Oe(e);if(!n)m.info(`[cleanupSdkSessionByAgentId] No active SDK session found for agentId=${e}, cleaning residual state anyway`);else{const t=n.sessionId;return m.info(`[cleanupSdkSessionByAgentId] Cleaning up SDK session for agentId=${e}, sessionId=${t}`),L(t),p.delete(t),F(t),ie(t),K(t).catch(r=>{m.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${r}`)}),t}z.has(e)&&(z.delete(e),m.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ie(e){const n=Q.get(e);if(!n?.runningProcess){Q.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,Q.delete(e)}}function w(e,n){n&&(e.seq+=1,G(e.agentId,n,e.sessionId,e.seq,void 0,{runtimeAccessToken:e.runtimeAccessToken,schedulerBaseUrl:e.schedulerBaseUrl}).catch(()=>{}))}function Ie(e){return`\x1B[36m${e}>\x1B[0m `}function Wt(e,n){return n==="~"?Qe.homedir():B.resolve(e,n)}async function Xt(e,n,t){const r=Ft(t);if(r===void 0)return!1;if(r===null)return w(e,`${n.currentDirectory}\r
28
- `),!0;const o=Wt(n.currentDirectory,r);try{return(await q.stat(o)).isDirectory()?(n.currentDirectory=o,w(e,`${n.currentDirectory}\r
26
+ `}async function je(e){const n=e.outputPath||jt(e.agentId,e.startedAt);return e.outputPath=n,await q.mkdir(B.dirname(n),{recursive:!0}),await q.writeFile(n,e.chunks.join(""),"utf-8"),n}function qt(e){return String(e??"").replace(/\r/g,`
27
+ `).trim()}function vt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?Ut:Le)}function Be(e=vt()){if(e!=="utf-8")try{return new ee(e,{fatal:!1})}catch{return new ee(Le,{fatal:!1})}return Ft()}function Ft(){let e=null,n=null,t=null;const r=[];function o(s){try{return new ee(s,{fatal:!1})}catch{return new ee("utf-8",{fatal:!1})}}return{decode(s,i){if(s!=null&&r.push(s instanceof ArrayBuffer?Buffer.from(s):Buffer.isBuffer(s)?s:Buffer.from(s.buffer,s.byteOffset,s.byteLength)),t==="gb18030")return n||(n=o("gb18030")),n.decode(s,i);e||(e=o("utf-8"));const a=e.decode(s,i);if(t===null&&a.includes("\uFFFD")){t="gb18030",n=o("gb18030");const c=Buffer.concat(r);return n.decode(c)}return t===null&&!i?.stream&&(t="utf-8"),a}}}function oe(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function Kt(e){const n=e.trim().match(/^cd(?:\s+(.*))?$/i);if(!n)return;const t=n[1]?.trim();if(!t)return null;const r=t.replace(/^\/d\s+/i,"").trim();return r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function zt(e){const n=Q.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return Q.set(e.sessionId,t),t}function Oe(e){for(const n of p.values())if(n.agentId===e)return n}async function Ht(e){const n=b.get(e.providerId||"claude-code"),t=se(n.getSessionStatus(e.sessionId),e.currentRuntimeStatus,e.currentRuntimeActionType);return{sessionId:e.sessionId,status:t,runtimeStatus:t,runtimeActionType:e.currentRuntimeActionType,runtimeActionLabel:e.currentRuntimeActionLabel,runtimeActionDetail:e.currentRuntimeActionDetail,agentId:e.agentId,workspacePath:e.workspacePath,command:e.config.command,mode:"sdk",providerSessionId:n.getProviderSessionId(e.sessionId),reused:!0}}function se(e,n,t){const r=String(e||"").trim();if(r){const s=String(n||"").trim(),i=String(t||"").trim().toLowerCase();return r.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&i==="idle"?s:r}return String(n||"").trim()||"running"}function Wt(e,n=gt){return e.pid?n(e.pid)?ze(e.command)==="acode"?{reusable:!1,reason:"in-process-provider"}:{reusable:!0,reason:"active-pid"}:{reusable:!1,reason:"dead-pid"}:{reusable:!1,reason:"missing-pid"}}function rr(e){const n=Oe(e);if(!n)m.info(`[cleanupSdkSessionByAgentId] No active SDK session found for agentId=${e}, cleaning residual state anyway`);else{const t=n.sessionId;return m.info(`[cleanupSdkSessionByAgentId] Cleaning up SDK session for agentId=${e}, sessionId=${t}`),L(t),p.delete(t),F(t),ie(t),K(t).catch(r=>{m.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${r}`)}),t}z.has(e)&&(z.delete(e),m.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ie(e){const n=Q.get(e);if(!n?.runningProcess){Q.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,Q.delete(e)}}function w(e,n){n&&(e.seq+=1,G(e.agentId,n,e.sessionId,e.seq,void 0,{runtimeAccessToken:e.runtimeAccessToken,schedulerBaseUrl:e.schedulerBaseUrl}).catch(()=>{}))}function Se(e){return`\x1B[36m${e}>\x1B[0m `}function Xt(e,n){return n==="~"?Qe.homedir():B.resolve(e,n)}async function Gt(e,n,t){const r=Kt(t);if(r===void 0)return!1;if(r===null)return w(e,`${n.currentDirectory}\r
28
+ `),!0;const o=Xt(n.currentDirectory,r);try{return(await q.stat(o)).isDirectory()?(n.currentDirectory=o,w(e,`${n.currentDirectory}\r
29
29
  `),!0):(w(e,`cd: not a directory: ${o}\r
30
30
  `),!0)}catch(s){const i=s instanceof Error?s.message:String(s);return w(e,`cd: ${i}\r
31
- `),!0}}async function Gt(e,n){const t=p.get(e);if(!t)throw new Error("SDK session not found");const r=Nt(n),o=Kt(t);if(!r)return{started:!1,cwd:o.currentDirectory};if(o.runningProcess)throw new Error("A terminal command is already running for this session");const s=v(r);if(w(t,`${Ie(o.currentDirectory)}${s}\r
32
- `),we(r))return w(t,`[Terminal Warning] \u68C0\u6D4B\u5230\u526A\u8D34\u677F\u4E34\u65F6 paste \u6587\u4EF6\u8DEF\u5F84\uFF0C\u5DF2\u8DF3\u8FC7\u6267\u884C\u3002\u8BF7\u7C98\u8D34\u6587\u4EF6\u5185\u5BB9\u6216\u4F7F\u7528\u663E\u5F0F\u8BFB\u53D6\u547D\u4EE4\u3002\r
33
- `),w(t,Ie(o.currentDirectory)),{started:!1,cwd:o.currentDirectory};if(await Xt(t,o,r))return{started:!1,cwd:o.currentDirectory};await C(t.agentId,e,"tool_using",{actionType:"bash",actionLabel:"\u7EC8\u7AEF\u547D\u4EE4",actionDetail:s},void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl});const a=Ge(r,{cwd:o.currentDirectory,shell:!0,env:Ne(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});o.runningProcess=a;const c=Be(),d=Be(),u=t.providerId==="acode",l={agentId:t.agentId,startedAt:new Date,chunks:[],spilled:!1};let f;const g=()=>{f&&(clearTimeout(f),f=void 0)},T=()=>{g(),f=setTimeout(()=>{o.runningProcess===a&&(w(t,Ot()),a.kill())},Ue)},h=(y,_=!0)=>{if(y&&(u&&l.chunks.push(y),u&&_&&T(),!(u&&l.spilled))){if(u&&jt(l.chunks.join(""))>xe){l.spilled=!0,je(l).then($=>{w(t,Bt($))}).catch($=>{const M=$ instanceof Error?$.message:String($);w(t,`\r
31
+ `),!0}}async function Qt(e,n){const t=p.get(e);if(!t)throw new Error("SDK session not found");const r=qt(n),o=zt(t);if(!r)return{started:!1,cwd:o.currentDirectory};if(o.runningProcess)throw new Error("A terminal command is already running for this session");const s=v(r);if(w(t,`${Se(o.currentDirectory)}${s}\r
32
+ `),_e(r))return w(t,`[Terminal Warning] \u68C0\u6D4B\u5230\u526A\u8D34\u677F\u4E34\u65F6 paste \u6587\u4EF6\u8DEF\u5F84\uFF0C\u5DF2\u8DF3\u8FC7\u6267\u884C\u3002\u8BF7\u7C98\u8D34\u6587\u4EF6\u5185\u5BB9\u6216\u4F7F\u7528\u663E\u5F0F\u8BFB\u53D6\u547D\u4EE4\u3002\r
33
+ `),w(t,Se(o.currentDirectory)),{started:!1,cwd:o.currentDirectory};if(await Gt(t,o,r))return{started:!1,cwd:o.currentDirectory};await C(t.agentId,e,"tool_using",{actionType:"bash",actionLabel:"\u7EC8\u7AEF\u547D\u4EE4",actionDetail:s},void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl});const a=Ge(r,{cwd:o.currentDirectory,shell:!0,env:Ne(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});o.runningProcess=a;const c=Be(),d=Be(),u=t.providerId==="acode",l={agentId:t.agentId,startedAt:new Date,chunks:[],spilled:!1};let f;const g=()=>{f&&(clearTimeout(f),f=void 0)},T=()=>{g(),f=setTimeout(()=>{o.runningProcess===a&&(w(t,Nt()),a.kill())},Ue)},h=(y,_=!0)=>{if(y&&(u&&l.chunks.push(y),u&&_&&T(),!(u&&l.spilled))){if(u&&Bt(l.chunks.join(""))>xe){l.spilled=!0,je(l).then($=>{w(t,Ot($))}).catch($=>{const M=$ instanceof Error?$.message:String($);w(t,`\r
34
34
  [ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${M}\r
35
35
  `)});return}w(t,y)}};return u&&T(),a.stdout.on("data",y=>{h(oe(c,y))}),a.stderr.on("data",y=>{h(oe(d,y))}),a.on("error",y=>{w(t,`\r
36
36
  [Terminal Error] ${y.message}\r
@@ -40,15 +40,15 @@ ${c.join(`
40
40
  [exit ${y}]\r
41
41
  `):_&&w(t,`\r
42
42
  [signal ${_}]\r
43
- `),w(t,Ie(o.currentDirectory)),C(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:o.currentDirectory}}function Ne(e,n,t,r){const o={};for(const[s,i]of Object.entries(t))i!==void 0&&(o[s]=i);if(n&&(o.AWS_WORKSPACE_PATH=String(n)),r)for(const[s,i]of Object.entries(r)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(o[a]=c)}return o.AWS_AGENT_ID=String(e),o.AWS_MCP_CLAIM_LAUNCH_BINDING="true",o.AWS_RUNTIME_BRIDGE_BASE_URL=`http://127.0.0.1:${et()}`,String(o.ACODE_HOME||"").trim()||(o.ACODE_HOME=Ce()),De(e,ut)&&(o.AWS_LAUNCH_CONFIG_TOOLS="1"),De(e,dt)&&(o.AWS_HIRE_TOOLS="1"),o}function Qt(e){const n=e.trim(),t=n[0],r=n[n.length-1];return(t==='"'||t==="'")&&t===r?n.slice(1,-1):n}async function Vt(e){const n=String(e);if(!we(n))return n;const t=Qt(n);return B.isAbsolute(t)?q.readFile(t,"utf-8"):n}function qe(e,n){const t={};for(const o of[e?.env,n])if(o)for(const[s,i]of Object.entries(o)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(t[a]=c)}const r=t.ANTHROPIC_MODEL?.trim()||t.CODEX_MODEL?.trim()||void 0;return{envOverrides:t,model:r}}async function Jt(){try{return await tt().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function Yt(e){if(e==null)return;const t=(typeof e=="string"?e:JSON.stringify(e,null,2)).trim();if(t)return t.length<=Ee?t:`${t.slice(0,Ee)}
44
- ...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function Zt(e){try{const n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return["directMessages","groupMessages","messages"].some(t=>Array.isArray(n[t])&&n[t].length>0)}catch{}return e.trim().length>0}function en(e){if(e.data.actionType==="mcp")return!0;const t=String(e.data.toolName||"").toLowerCase();return t.startsWith("mcp__")||t.includes("-mcp__")||t.includes("mcp_")}function tn(e){if(e.type!=="tool_use_end")return;const n=Yt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionType||t.actionType;if(r==="idle"){const o=String(e.data.rawToolName||e.data.toolName||"").toLowerCase();if((o.includes("poll_message")||o.includes("get_message"))&&!Zt(n))return}return r==="mcp"&&en(e)?{actionType:"mcp",actionLabel:"MCP\u8FD4\u56DE",actionDetail:e.data.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}:{actionType:r,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:e.data.actionDetail||t.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}}function nn(e){if(e.type==="ai_request"){const n=e.data.model?` ${e.data.model}`:"",t=e.data.lastUserMessagePreview?`\uFF1A${e.data.lastUserMessagePreview}`:"";return`\r
43
+ `),w(t,Se(o.currentDirectory)),C(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:o.currentDirectory}}function Ne(e,n,t,r){const o={};for(const[s,i]of Object.entries(t))i!==void 0&&(o[s]=i);if(n&&(o.AWS_WORKSPACE_PATH=String(n)),r)for(const[s,i]of Object.entries(r)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(o[a]=c)}return o.AWS_AGENT_ID=String(e),o.AWS_MCP_CLAIM_LAUNCH_BINDING="true",o.AWS_RUNTIME_BRIDGE_BASE_URL=`http://127.0.0.1:${et()}`,String(o.ACODE_HOME||"").trim()||(o.ACODE_HOME=$e()),Ie(e,ut)&&(o.AWS_LAUNCH_CONFIG_TOOLS="1"),Ie(e,dt)&&(o.AWS_HIRE_TOOLS="1"),Ie(e,lt)&&(o.AWS_PENCIL_TOOLS="1"),o}function Vt(e){const n=e.trim(),t=n[0],r=n[n.length-1];return(t==='"'||t==="'")&&t===r?n.slice(1,-1):n}async function Jt(e){const n=String(e);if(!_e(n))return n;const t=Vt(n);return B.isAbsolute(t)?q.readFile(t,"utf-8"):n}function qe(e,n){const t={};for(const o of[e?.env,n])if(o)for(const[s,i]of Object.entries(o)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(t[a]=c)}const r=t.ANTHROPIC_MODEL?.trim()||t.CODEX_MODEL?.trim()||void 0;return{envOverrides:t,model:r}}async function Yt(){try{return await tt().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function Zt(e){if(e==null)return;const t=(typeof e=="string"?e:JSON.stringify(e,null,2)).trim();if(t)return t.length<=Ee?t:`${t.slice(0,Ee)}
44
+ ...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function en(e){try{const n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return["directMessages","groupMessages","messages"].some(t=>Array.isArray(n[t])&&n[t].length>0)}catch{}return e.trim().length>0}function tn(e){if(e.data.actionType==="mcp")return!0;const t=String(e.data.toolName||"").toLowerCase();return t.startsWith("mcp__")||t.includes("-mcp__")||t.includes("mcp_")}function nn(e){if(e.type!=="tool_use_end")return;const n=Zt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionType||t.actionType;if(r==="idle"){const o=String(e.data.rawToolName||e.data.toolName||"").toLowerCase();if((o.includes("poll_message")||o.includes("get_message"))&&!en(n))return}return r==="mcp"&&tn(e)?{actionType:"mcp",actionLabel:"MCP\u8FD4\u56DE",actionDetail:e.data.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}:{actionType:r,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:e.data.actionDetail||t.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}}function rn(e){if(e.type==="ai_request"){const n=e.data.model?` ${e.data.model}`:"",t=e.data.lastUserMessagePreview?`\uFF1A${e.data.lastUserMessagePreview}`:"";return`\r
45
45
  [ACode] \u6B63\u5728\u8BF7\u6C42\u6A21\u578B${n}${t}\r
46
46
  `}if(e.type==="text_delta"||e.type==="thinking"||e.type==="command_output")return e.data.text||void 0;if(e.type==="error")return e.data.text?`\r
47
47
  [SDK Error] ${e.data.text}\r
48
- `:void 0}function rn(e){const n=an(e);return{sourceEventType:e.type,logCategory:"acode",...sn(e),...n?{logLevel:on(e),logMessage:n}:{}}}function on(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function sn(e){return e.type!=="command_output"?{}:{...typeof e.data.stream=="string"?{stream:e.data.stream}:{},...typeof e.data.sequence=="number"?{sequence:e.data.sequence}:{},...typeof e.data.cwd=="string"?{cwd:e.data.cwd}:{},...typeof e.data.commandFilePath=="string"?{commandFilePath:e.data.commandFilePath}:{},...typeof e.data.commandLineCount=="number"?{commandLineCount:e.data.commandLineCount}:{}}}function an(e){if(e.type==="ai_request"){const n=e.data.model||"unknown-model",t=e.data.endpoint?` @ ${e.data.endpoint}`:"",r=typeof e.data.toolCount=="number"?`, tools=${e.data.toolCount}`:"";return`AI request started: ${n}${t}${r}`}if(e.type==="tool_use_start")return ve(e,"\u5F00\u59CB");if(e.type==="tool_use_end")return ve(e,"\u5B8C\u6210");if(e.type==="command_output")return dn(e);if(e.type==="turn_complete")return`Turn completed${e.data.finishReason?`, finish=${e.data.finishReason}`:""}`;if(e.type==="session_complete")return`Session completed: exitCode=${e.data.exitCode??0}`;if(e.type==="error")return e.data.text||"ACode runtime error"}const cn=/\x1b\[[0-9;?]*[a-zA-Z]/g;function un(e){return e.replace(cn,"")}function dn(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",r=un(String(e.data.text||"")).replace(/\s+/g," ").trim(),o=r.length>240?`${r.slice(0,240)}...`:r;return`\u547D\u4EE4\u8F93\u51FA(${n}${t}): ${o||"(empty)"}`}function ve(e,n){const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionLabel||t.actionLabel||"\u8C03\u7528\u5DE5\u5177",o=Fe(e,t);return o?`${n}${r}: ${o}`:`${n}${r}: ${e.data.actionDetail||e.data.toolName||"tool"}`}function Fe(e,n){const t=e.data.toolInput;return n.actionType==="bash"?ln(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?mn(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function ln(e){const n=Se(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(r=>String(r??"").trim()).filter(Boolean).join(" ");return t?v(t):void 0}return Se(e?.args)}function mn(e){const n=Ke(e?.paths);return n.length>0?n.length===1?n[0]:`${n.length}\u4E2A\u6587\u4EF6: ${n.join(", ")}`:Se(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)}function Se(...e){for(const n of e){if(typeof n=="string"&&n.trim())return v(n.trim());if(Array.isArray(n)){const t=Ke(n)[0];if(t)return t}}}function Ke(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>v(n)):[]}function fn(e){if(!(!e||Object.keys(e).length===0))try{const n=v(JSON.stringify(e,null,2));return n.length>8e3?`${n.slice(0,8e3)}
49
- ...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function pn(e){const n=[e.model?`\u6A21\u578B: ${e.model}`:void 0,e.endpoint||e.requestUrl?`\u63A5\u53E3: ${e.endpoint||e.requestUrl}`:void 0,e.requestMethod?`\u65B9\u6CD5: ${e.requestMethod}`:void 0,typeof e.stream=="boolean"?`\u6D41\u5F0F: ${e.stream?"\u662F":"\u5426"}`:void 0,typeof e.messageCount=="number"?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${e.messageCount}`:void 0,typeof e.toolCount=="number"?`\u53EF\u7528\u5DE5\u5177: ${e.toolCount}`:void 0,e.lastUserMessagePreview?`\u6700\u540E\u8BF7\u6C42: ${e.lastUserMessagePreview}`:void 0].filter(i=>!!i),t=gn(e.requestHeaders),r=n.join(`
50
- `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",o=t.length>0?`${Dt}${t.join(`
51
- `)}`:"",s=e.requestBody?`${$t}${e.requestBody}`:"";return`${r}${o}${s}`}function gn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function yn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function hn(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],r=Number(t);if(Number.isFinite(r)&&r>0)return r}}function In(e,n){if(!yn(e,n)){if(e.type==="ai_request"){const t=hn(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:pn(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),r=Fe(e,t),o=fn(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const x=new Map,ae=new Map,ce=new Map,J=new Map,Sn=20,An=500,Tn=3e4;async function ue(e,n=Tn,t=2){for(let r=0;r<=t;r++){const o=new AbortController;let s;try{const i=e(o.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{o.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(r<t){const c=1e3*(r+1);m.warn(`sendOutput attempt ${r+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}m.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let r,o;if(t)r=J.get(t),o=t;else{const g=[];for(const[T,h]of J)T.startsWith(e+":")&&h.buffer&&g.push(h.sourceEventType);for(const T of g)de(e,T);return}if(!r||!r.buffer)return;r.timer=null;const s=r.buffer,i=r.seq,a=r.entry,c=r.sourceEventType;r.buffer="",o&&J.delete(o);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},f=(x.get(e)??Promise.resolve()).then(()=>ue(g=>G(a.agentId,s,e,i,d,u,g)),()=>ue(g=>G(a.agentId,s,e,i,d,u,g)));x.set(e,f),f.finally(()=>{x.get(e)===f&&x.delete(e)})}function kn(e,n){const t=nn(e);if(!t)return;n.seq+=1;const r=n.seq,o=rn(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<Sn){const c=`${e.sessionId}:${e.type}`;let d=J.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=r,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),An)}J.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)),()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function ze(e){return Ze(e)}let He=!1;function bn(){He||(Ye(b,wn),ot(),He=!0)}function wn(e,n){e.on("event",t=>{const r=p.get(t.sessionId);if(r){if(t.type==="tool_use_start"?yt(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&gt(t,{sessionId:r.sessionId,agentId:r.agentId,workspacePath:r.workspacePath,providerId:r.providerId}),m.info(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(r.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=In(t,r.currentRuntimeStatus);i&&C(r.agentId,t.sessionId,i.status,i.actionInfo,re(i.actionInfo),{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}kn(t,r);const s=tn(t);if(s){const i={runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,r,o)=>{const s=p.get(t);if(s){de(t),r==="thinking"||r==="tool_using"||r==="compacting"?Ct(t):L(t);const i=Lt(r,o);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),m.info(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),kt(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const g=(ae.get(t)??Promise.resolve()).then(async()=>{for(let h=0;h<=2;h++){if(await C(s.agentId,t,i.status,l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;h<2&&(m.warn(`[${n.displayName}] compaction sendStatus attempt ${h+1} failed (HTTP), retrying in ${1e3*(h+1)}ms...`),await new Promise(_=>setTimeout(_,1e3*(h+1))))}m.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{m.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,g),g.finally(()=>{ae.get(t)===g&&ae.delete(t)})}else{const f=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const h=(ce.get(t)??Promise.resolve()).then(async()=>{for(let _=0;_<=2;_++){if(await C(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;_<2&&await new Promise(M=>setTimeout(M,1e3*(_+1)))}m.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(y=>{m.warn(`[${n.displayName}] idle status chain error:`,y)});ce.set(t,h),h.finally(()=>{ce.get(t)===h&&ce.delete(t)})}else C(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const f=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,m.info(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),C(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:f},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const r=p.get(t.sessionId);r&&(m.info(`[${n.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),ht(r.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.toolCallId))}),e.on("tool-permission-request",t=>{const r=p.get(t.sessionId);r&&t.requestId&&(m.info(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${r.agentId}`),It(r.agentId,t.sessionId,{requestId:t.requestId,capability:t.capability,...t.detail||{}},{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}))}),e.on("permission-request",t=>{const r=p.get(t.sessionId);if(r){m.info(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${r.agentId}`);const o=t.toolInput?v(JSON.stringify(t.toolInput).slice(0,400)):void 0;C(r.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:o||t.toolName},void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl})}})}S.post("/start",I,async(e,n)=>{const{agentId:t,workspacePath:r,mode:o="sdk"}=e.body||{};if(!t||!r){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||$e(Pe(e))||void 0;lt({agentId:String(t),workspacePath:String(r),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!==null&&e.body?.runtimeFeatures!==void 0&&(it(String(t),e.body.runtimeFeatures),m.info(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(ct(String(t)))}`)),e.body?.capabilities!==void 0&&at(String(t),e.body.capabilities),e.body?.envVars!==null&&e.body?.envVars!==void 0&&typeof e.body.envVars=="object"&&(mt(e.body.envVars),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(nt(e.body.changeCacheRetentionDays),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),o&&o!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${o}" requested for agent ${t}; starting SDK session instead.`),await _n(e,n)});async function _n(e,n){const{agentId:t,workspacePath:r,command:o,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:f,envOverrides:g,idleInputAutoCommand:T,nonInputAutoCommand:h,model:y,instanceAiConfig:_,subAgentModel:$,subAgentEffort:M,scopeKey:Ae,browserAllowPrivate:Te}=e.body||{},H=wt();H.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:_?te(_):null,perAgentModel:y??null}});let D=null;const A=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,O=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||$e(Pe(e))||void 0;O?m.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${O} (agentId=${A})`):m.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(bn(),!A){n.status(400).json({error:"agentId is required"});return}const N=Oe(A);if(N){n.json(await zt(N));return}const k=await St(A);if(k){const R=Ht(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${k.sessionId}, reason=${R.reason}`),await K(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(z.has(A)){n.status(409).json({error:"SDK session is already starting for this agent"});return}z.add(A);const E=ze(o),We=b.get(E);D=Je();const Xe=E==="claude-code"?await Jt():null,Y=qe(E==="claude-code"?Xe:null,g),W=E==="acode"?y?String(y).trim():void 0:(()=>{const R=y?String(y).trim():void 0,P=Y.model?String(Y.model).trim():void 0;return R||P})();H.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:D??void 0,details:{perAgentModel:y??null,globalModel:Y.model??null,resolvedModel:W??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...Y.envOverrides};W&&(me.ANTHROPIC_MODEL=W,me.CODEX_MODEL=W);let X,fe=l;if(E==="acode"){const R=_||{},P=await st({apiOverrides:Me(R)??void 0,agentId:A,sessionId:D??void 0,runtimeBridgeBaseUrl:O});X=P.instanceConfig.config,fe=P.perInstanceConfigPath,H.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:D??void 0,details:{sanitizedApiOverrides:(()=>{const j=Me(R);return j?te(j):null})(),resolvedInstanceAiConfig:X?te(X):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let ke=a||void 0,pe,ge,Z;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Z=u.trim();else{const R=await Rt(r,{schedulerBaseUrl:O,runtimeAccessToken:le,agentId:A});R&&(Z=R,m.info(`[startSdkSession] Auto-loaded memories for ACode agent ${A}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(j=>typeof j=="string"&&j.trim().length>0).map(j=>j.trim());ke=P.length>0?P.join(`
48
+ `:void 0}function on(e){const n=cn(e);return{sourceEventType:e.type,logCategory:"acode",...an(e),...n?{logLevel:sn(e),logMessage:n}:{}}}function sn(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function an(e){return e.type!=="command_output"?{}:{...typeof e.data.stream=="string"?{stream:e.data.stream}:{},...typeof e.data.sequence=="number"?{sequence:e.data.sequence}:{},...typeof e.data.cwd=="string"?{cwd:e.data.cwd}:{},...typeof e.data.commandFilePath=="string"?{commandFilePath:e.data.commandFilePath}:{},...typeof e.data.commandLineCount=="number"?{commandLineCount:e.data.commandLineCount}:{}}}function cn(e){if(e.type==="ai_request"){const n=e.data.model||"unknown-model",t=e.data.endpoint?` @ ${e.data.endpoint}`:"",r=typeof e.data.toolCount=="number"?`, tools=${e.data.toolCount}`:"";return`AI request started: ${n}${t}${r}`}if(e.type==="tool_use_start")return ve(e,"\u5F00\u59CB");if(e.type==="tool_use_end")return ve(e,"\u5B8C\u6210");if(e.type==="command_output")return ln(e);if(e.type==="turn_complete")return`Turn completed${e.data.finishReason?`, finish=${e.data.finishReason}`:""}`;if(e.type==="session_complete")return`Session completed: exitCode=${e.data.exitCode??0}`;if(e.type==="error")return e.data.text||"ACode runtime error"}const un=/\x1b\[[0-9;?]*[a-zA-Z]/g;function dn(e){return e.replace(un,"")}function ln(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",r=dn(String(e.data.text||"")).replace(/\s+/g," ").trim(),o=r.length>240?`${r.slice(0,240)}...`:r;return`\u547D\u4EE4\u8F93\u51FA(${n}${t}): ${o||"(empty)"}`}function ve(e,n){const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionLabel||t.actionLabel||"\u8C03\u7528\u5DE5\u5177",o=Fe(e,t);return o?`${n}${r}: ${o}`:`${n}${r}: ${e.data.actionDetail||e.data.toolName||"tool"}`}function Fe(e,n){const t=e.data.toolInput;return n.actionType==="bash"?mn(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?fn(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function mn(e){const n=Ae(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(r=>String(r??"").trim()).filter(Boolean).join(" ");return t?v(t):void 0}return Ae(e?.args)}function fn(e){const n=Ke(e?.paths);return n.length>0?n.length===1?n[0]:`${n.length}\u4E2A\u6587\u4EF6: ${n.join(", ")}`:Ae(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)}function Ae(...e){for(const n of e){if(typeof n=="string"&&n.trim())return v(n.trim());if(Array.isArray(n)){const t=Ke(n)[0];if(t)return t}}}function Ke(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>v(n)):[]}function pn(e){if(!(!e||Object.keys(e).length===0))try{const n=v(JSON.stringify(e,null,2));return n.length>8e3?`${n.slice(0,8e3)}
49
+ ...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function gn(e){const n=[e.model?`\u6A21\u578B: ${e.model}`:void 0,e.endpoint||e.requestUrl?`\u63A5\u53E3: ${e.endpoint||e.requestUrl}`:void 0,e.requestMethod?`\u65B9\u6CD5: ${e.requestMethod}`:void 0,typeof e.stream=="boolean"?`\u6D41\u5F0F: ${e.stream?"\u662F":"\u5426"}`:void 0,typeof e.messageCount=="number"?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${e.messageCount}`:void 0,typeof e.toolCount=="number"?`\u53EF\u7528\u5DE5\u5177: ${e.toolCount}`:void 0,e.lastUserMessagePreview?`\u6700\u540E\u8BF7\u6C42: ${e.lastUserMessagePreview}`:void 0].filter(i=>!!i),t=yn(e.requestHeaders),r=n.join(`
50
+ `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",o=t.length>0?`${Rt}${t.join(`
51
+ `)}`:"",s=e.requestBody?`${Dt}${e.requestBody}`:"";return`${r}${o}${s}`}function yn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function hn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function In(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],r=Number(t);if(Number.isFinite(r)&&r>0)return r}}function Sn(e,n){if(!hn(e,n)){if(e.type==="ai_request"){const t=In(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:gn(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),r=Fe(e,t),o=pn(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const x=new Map,ae=new Map,ce=new Map,J=new Map,An=20,Tn=500,kn=3e4;async function ue(e,n=kn,t=2){for(let r=0;r<=t;r++){const o=new AbortController;let s;try{const i=e(o.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{o.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(r<t){const c=1e3*(r+1);m.warn(`sendOutput attempt ${r+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}m.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let r,o;if(t)r=J.get(t),o=t;else{const g=[];for(const[T,h]of J)T.startsWith(e+":")&&h.buffer&&g.push(h.sourceEventType);for(const T of g)de(e,T);return}if(!r||!r.buffer)return;r.timer=null;const s=r.buffer,i=r.seq,a=r.entry,c=r.sourceEventType;r.buffer="",o&&J.delete(o);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},f=(x.get(e)??Promise.resolve()).then(()=>ue(g=>G(a.agentId,s,e,i,d,u,g)),()=>ue(g=>G(a.agentId,s,e,i,d,u,g)));x.set(e,f),f.finally(()=>{x.get(e)===f&&x.delete(e)})}function bn(e,n){const t=rn(e);if(!t)return;n.seq+=1;const r=n.seq,o=on(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<An){const c=`${e.sessionId}:${e.type}`;let d=J.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=r,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),Tn)}J.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)),()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function ze(e){return Ze(e)}let He=!1;function wn(){He||(Ye(b,_n),ot(),He=!0)}function _n(e,n){e.on("event",t=>{const r=p.get(t.sessionId);if(r){if(t.type==="tool_use_start"?ht(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&yt(t,{sessionId:r.sessionId,agentId:r.agentId,workspacePath:r.workspacePath,providerId:r.providerId}),m.info(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(r.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=Sn(t,r.currentRuntimeStatus);i&&C(r.agentId,t.sessionId,i.status,i.actionInfo,re(i.actionInfo),{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}bn(t,r);const s=nn(t);if(s){const i={runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):C(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,r,o)=>{const s=p.get(t);if(s){de(t),r==="thinking"||r==="tool_using"||r==="compacting"?$t(t):L(t);const i=xt(r,o);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),m.info(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),bt(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const g=(ae.get(t)??Promise.resolve()).then(async()=>{for(let h=0;h<=2;h++){if(await C(s.agentId,t,i.status,l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;h<2&&(m.warn(`[${n.displayName}] compaction sendStatus attempt ${h+1} failed (HTTP), retrying in ${1e3*(h+1)}ms...`),await new Promise(_=>setTimeout(_,1e3*(h+1))))}m.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{m.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,g),g.finally(()=>{ae.get(t)===g&&ae.delete(t)})}else{const f=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const h=(ce.get(t)??Promise.resolve()).then(async()=>{for(let _=0;_<=2;_++){if(await C(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;_<2&&await new Promise(M=>setTimeout(M,1e3*(_+1)))}m.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(y=>{m.warn(`[${n.displayName}] idle status chain error:`,y)});ce.set(t,h),h.finally(()=>{ce.get(t)===h&&ce.delete(t)})}else C(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const f=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,m.info(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),C(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:f},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const r=p.get(t.sessionId);r&&(m.info(`[${n.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),It(r.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.toolCallId))}),e.on("tool-permission-request",t=>{const r=p.get(t.sessionId);r&&t.requestId&&(m.info(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${r.agentId}`),St(r.agentId,t.sessionId,{requestId:t.requestId,capability:t.capability,...t.detail||{}},{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}))}),e.on("permission-request",t=>{const r=p.get(t.sessionId);if(r){m.info(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${r.agentId}`);const o=t.toolInput?v(JSON.stringify(t.toolInput).slice(0,400)):void 0;C(r.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:o||t.toolName},void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl})}})}S.post("/start",I,async(e,n)=>{const{agentId:t,workspacePath:r,mode:o="sdk"}=e.body||{};if(!t||!r){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;mt({agentId:String(t),workspacePath:String(r),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!==null&&e.body?.runtimeFeatures!==void 0&&(it(String(t),e.body.runtimeFeatures),m.info(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(ct(String(t)))}`)),e.body?.capabilities!==void 0&&at(String(t),e.body.capabilities),e.body?.envVars!==null&&e.body?.envVars!==void 0&&typeof e.body.envVars=="object"&&(ft(e.body.envVars),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(nt(e.body.changeCacheRetentionDays),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),o&&o!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${o}" requested for agent ${t}; starting SDK session instead.`),await Cn(e,n)});async function Cn(e,n){const{agentId:t,workspacePath:r,command:o,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:f,envOverrides:g,idleInputAutoCommand:T,nonInputAutoCommand:h,model:y,instanceAiConfig:_,subAgentModel:$,subAgentEffort:M,scopeKey:Te,browserAllowPrivate:ke}=e.body||{},H=_t();H.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:_?te(_):null,perAgentModel:y??null}});let D=null;const A=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,O=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;O?m.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${O} (agentId=${A})`):m.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(wn(),!A){n.status(400).json({error:"agentId is required"});return}const N=Oe(A);if(N){n.json(await Ht(N));return}const k=await At(A);if(k){const R=Wt(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${k.sessionId}, reason=${R.reason}`),await K(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(z.has(A)){n.status(409).json({error:"SDK session is already starting for this agent"});return}z.add(A);const E=ze(o),We=b.get(E);D=Je();const Xe=E==="claude-code"?await Yt():null,Y=qe(E==="claude-code"?Xe:null,g),W=E==="acode"?y?String(y).trim():void 0:(()=>{const R=y?String(y).trim():void 0,P=Y.model?String(Y.model).trim():void 0;return R||P})();H.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:D??void 0,details:{perAgentModel:y??null,globalModel:Y.model??null,resolvedModel:W??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...Y.envOverrides};W&&(me.ANTHROPIC_MODEL=W,me.CODEX_MODEL=W);let X,fe=l;if(E==="acode"){const R=_||{},P=await st({apiOverrides:Me(R)??void 0,agentId:A,sessionId:D??void 0,runtimeBridgeBaseUrl:O});X=P.instanceConfig.config,fe=P.perInstanceConfigPath,H.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:D??void 0,details:{sanitizedApiOverrides:(()=>{const j=Me(R);return j?te(j):null})(),resolvedInstanceAiConfig:X?te(X):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let be=a||void 0,pe,ge,Z;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Z=u.trim();else{const R=await Pt(r,{schedulerBaseUrl:O,runtimeAccessToken:le,agentId:A});R&&(Z=R,m.info(`[startSdkSession] Auto-loaded memories for ACode agent ${A}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(j=>typeof j=="string"&&j.trim().length>0).map(j=>j.trim());be=P.length>0?P.join(`
52
52
 
53
- `):void 0}const U={command:o||"acode",workingDirectory:r,agentId:A,...Ae?{scopeKey:Ae}:{},...typeof Te=="boolean"?{browserAllowPrivate:Te}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:ke,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Z!==void 0?{memory:Z}:{},model:W,mcpConfigPath:fe,...X?{instanceAiConfig:X}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:f||{},envOverrides:Ne(String(t),String(r),process.env,me)};H.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await H.flush(),p.set(D,{agentId:A,workspacePath:r,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:O}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:r,command:U.command,mode:"sdk"}),Cn({sessionId:D,agentId:A,config:U,adapter:We,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:h,runtimeAccessToken:le,requestedSchedulerBaseUrl:O})}catch(N){if(D&&(L(D),p.delete(D),F(D)),A&&z.delete(A),!n.headersSent){const k=N instanceof Error?N.message:String(N);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function Cn(e){const{sessionId:n,agentId:t,config:r,adapter:o,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await o.startSession(n,r),o.setIdleCommands?.(n,{idleInputCommand:i||_e,nonInputCommand:a||""});let u;if(Et(s))try{if(await new Promise(f=>setTimeout(f,500)),u=o.getSessionPid?.(n),!u){const g=(await ft()).find(T=>T.agentId===t||T.cwd===r.workingDirectory||T.command.includes(r.workingDirectory));g&&(u=g.pid,m.info(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(f){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,f)}const l=se(o.getSessionStatus(n),p.get(n)?.currentRuntimeStatus,p.get(n)?.currentRuntimeActionType);await bt({sessionId:n,agentId:t,workspacePath:r.workingDirectory,command:r.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:o.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await $n({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(n),p.delete(n),F(n),await K(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await Dn({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{z.delete(t)}}async function $n(e){const{agentId:n,sessionId:t,sdkPid:r,status:o,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){m.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(a,{agentId:n,sessionId:t,status:o,pid:r},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${o}`)}catch(c){const d=c instanceof Error?c.message:String(c);m.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function Dn(e){const{agentId:n,sessionId:t,schedulerBaseUrl:r,runtimeAccessToken:o}=e;if(!r||!o)return;const s=`${r.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":o,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);m.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}S.post("/sdk/message",I,async(e,n)=>{const{sessionId:t,message:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and message are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendMessage(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/answer",I,async(e,n)=>{const{sessionId:t,answers:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and answers are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code",i=b.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/tool-auth/answer",I,async(e,n)=>{const{sessionId:t,requestId:r,allowed:o}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and requestId are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(!a.submitToolPermissionDecision){n.status(400).json({error:"adapter does not support tool authorization"});return}const c=a.submitToolPermissionDecision(t,String(r),!!o);n.json({ok:!0,existed:c})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.get("/tool-auth/pending/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingToolAuthRequests?.(t)??[];n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingRequests:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/confirm",I,async(e,n)=>{const{sessionId:t,accept:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendConfirmation(t,!!r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/abort",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code";await b.get(o).abortCurrentTurn(t),n.json({ok:!0})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.json({ok:!0,status:"stopped"});return}try{const o=r.providerId||"claude-code",s=b.get(o);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(r.agentId),await C(r.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/status/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",s=b.get(o),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:r.agentId,workspacePath:r.workspacePath,messageCount:a.length})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/capabilities/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,capabilities:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/pending-questions/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/command",I,async(e,n)=>{const{sessionId:t,command:r}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and command are required"});return}try{const o=await Gt(String(t),r);n.json({ok:!0,mode:"terminal",...o})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/input",I,async(e,n)=>{const{sessionId:t,input:r,mode:o}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and input are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(o==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(r)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Vt(r)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.post("/update-auto-commands",I,async(e,n)=>{const{agentId:t,idleInputAutoCommand:r="",nonInputAutoCommand:o=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...p.values()].find(c=>c.agentId===s),a={idleInputCommand:String(r||"").trim()||_e,nonInputCommand:String(o||"")};try{let c=!1;i&&(b.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await Tt(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),S.post("/resize",I,(e,n)=>{const{sessionId:t,cols:r,rows:o}=e.body||{};if(!t||!r||!o){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!p.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(r),rows:Number(o)})}),S.post("/reset-context",I,async(e,n)=>{const{sessionId:t,reason:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}const s=o.providerId||"claude-code",i=b.get(s),a=i.resetContext?.bind(i),c=Pt(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),o.currentRuntimeStatus,o.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:o.agentId,mode:"sdk",providerId:s,reason:typeof r=="string"&&r.trim()?r.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),S.post("/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{},r=Mt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){await K(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const s=o.agentId;try{m.info(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=o.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(s),r.statusNotified?await C(s,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}):m.info(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${r.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:r.statusNotified,reason:r.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),S.post("/stop-all",I,async(e,n)=>{const t=[],r=[];for(const[o,s]of p.entries())try{const i=s.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(o).catch(()=>{}),await a.terminateSession(o),L(o),p.delete(o),F(o),ie(o),t.push(o),await C(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);r.push(`SDK ${o}: ${a}`)}try{await At([]),m.info("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(o){const s=o instanceof Error?o.message:String(o);r.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:r.length>0?r:void 0})}),S.get("/events/last/:n",I,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const r=Re.getLastN(t);n.json({ok:!0,count:r.length,entries:r})}),S.get("/events/since/:index",I,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const r=Re.getSinceIndex(t);n.json({ok:!0,entries:r.entries,nextIndex:r.nextIndex,oldestIndex:r.oldestIndex,dataLoss:r.oldestIndex>t+1})}),S.get("/events/push-stats",I,(e,n)=>{const t=rt();n.json({ok:!0,count:t.length,agents:t})});export{Ut as buildAcodeCommandOutputPath,qe as buildClaudeCodeLaunchConfig,Ne as buildRuntimeEnv,rn as buildSdkOutputMetadata,tn as buildToolResultTimelineActionInfo,nr as cleanupSdkSessionByAgentId,jt as countTerminalOutputLines,Be as createTerminalOutputDecoder,oe as decodeTerminalOutputChunk,Ht as evaluatePersistedSessionReuse,Ot as formatCommandInactivityTimeoutNotice,Bt as formatCommandOutputSpilloverNotice,nn as formatSdkOutputEvent,Ie as formatTerminalPrompt,Nt as normalizeTerminalCommandInput,Mt as parseRuntimeStopOptions,Ft as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Pt as resolveRuntimeContextResetSupport,In as resolveRuntimeStatusFromProviderEvent,Vt as resolveSdkInputMessage,ze as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,Lt as resolveStatusChangeRuntimeState,re as resolveStatusChangeUsage,qt as resolveTerminalOutputEncoding,p as sdkSessions,Et as shouldProbeSdkProcessPid,S as terminalRouter};
53
+ `):void 0}const U={command:o||"acode",workingDirectory:r,agentId:A,...Te?{scopeKey:Te}:{},...typeof ke=="boolean"?{browserAllowPrivate:ke}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:be,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Z!==void 0?{memory:Z}:{},model:W,mcpConfigPath:fe,...X?{instanceAiConfig:X}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:f||{},envOverrides:Ne(String(t),String(r),process.env,me)};H.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await H.flush(),p.set(D,{agentId:A,workspacePath:r,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:O}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:r,command:U.command,mode:"sdk"}),$n({sessionId:D,agentId:A,config:U,adapter:We,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:h,runtimeAccessToken:le,requestedSchedulerBaseUrl:O})}catch(N){if(D&&(L(D),p.delete(D),F(D)),A&&z.delete(A),!n.headersSent){const k=N instanceof Error?N.message:String(N);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function $n(e){const{sessionId:n,agentId:t,config:r,adapter:o,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await o.startSession(n,r),o.setIdleCommands?.(n,{idleInputCommand:i||Ce,nonInputCommand:a||""});let u;if(Mt(s))try{if(await new Promise(f=>setTimeout(f,500)),u=o.getSessionPid?.(n),!u){const g=(await pt()).find(T=>T.agentId===t||T.cwd===r.workingDirectory||T.command.includes(r.workingDirectory));g&&(u=g.pid,m.info(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(f){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,f)}const l=se(o.getSessionStatus(n),p.get(n)?.currentRuntimeStatus,p.get(n)?.currentRuntimeActionType);await wt({sessionId:n,agentId:t,workspacePath:r.workingDirectory,command:r.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:o.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await Dn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(n),p.delete(n),F(n),await K(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await Rn({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{z.delete(t)}}async function Dn(e){const{agentId:n,sessionId:t,sdkPid:r,status:o,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){m.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(a,{agentId:n,sessionId:t,status:o,pid:r},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${o}`)}catch(c){const d=c instanceof Error?c.message:String(c);m.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function Rn(e){const{agentId:n,sessionId:t,schedulerBaseUrl:r,runtimeAccessToken:o}=e;if(!r||!o)return;const s=`${r.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":o,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);m.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}S.post("/sdk/message",I,async(e,n)=>{const{sessionId:t,message:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and message are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendMessage(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/answer",I,async(e,n)=>{const{sessionId:t,answers:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and answers are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code",i=b.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/tool-auth/answer",I,async(e,n)=>{const{sessionId:t,requestId:r,allowed:o}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and requestId are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(!a.submitToolPermissionDecision){n.status(400).json({error:"adapter does not support tool authorization"});return}const c=a.submitToolPermissionDecision(t,String(r),!!o);n.json({ok:!0,existed:c})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.get("/tool-auth/pending/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingToolAuthRequests?.(t)??[];n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingRequests:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/confirm",I,async(e,n)=>{const{sessionId:t,accept:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendConfirmation(t,!!r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/abort",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code";await b.get(o).abortCurrentTurn(t),n.json({ok:!0})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.json({ok:!0,status:"stopped"});return}try{const o=r.providerId||"claude-code",s=b.get(o);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(r.agentId),await C(r.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/status/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",s=b.get(o),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:r.agentId,workspacePath:r.workspacePath,messageCount:a.length})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/capabilities/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,capabilities:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/pending-questions/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/command",I,async(e,n)=>{const{sessionId:t,command:r}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and command are required"});return}try{const o=await Qt(String(t),r);n.json({ok:!0,mode:"terminal",...o})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/input",I,async(e,n)=>{const{sessionId:t,input:r,mode:o}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and input are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(o==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(r)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Jt(r)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.post("/update-auto-commands",I,async(e,n)=>{const{agentId:t,idleInputAutoCommand:r="",nonInputAutoCommand:o=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...p.values()].find(c=>c.agentId===s),a={idleInputCommand:String(r||"").trim()||Ce,nonInputCommand:String(o||"")};try{let c=!1;i&&(b.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await kt(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),S.post("/resize",I,(e,n)=>{const{sessionId:t,cols:r,rows:o}=e.body||{};if(!t||!r||!o){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!p.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(r),rows:Number(o)})}),S.post("/reset-context",I,async(e,n)=>{const{sessionId:t,reason:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}const s=o.providerId||"claude-code",i=b.get(s),a=i.resetContext?.bind(i),c=Et(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),o.currentRuntimeStatus,o.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:o.agentId,mode:"sdk",providerId:s,reason:typeof r=="string"&&r.trim()?r.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),S.post("/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{},r=Lt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){await K(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const s=o.agentId;try{m.info(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=o.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(s),r.statusNotified?await C(s,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}):m.info(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${r.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:r.statusNotified,reason:r.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),S.post("/stop-all",I,async(e,n)=>{const t=[],r=[];for(const[o,s]of p.entries())try{const i=s.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(o).catch(()=>{}),await a.terminateSession(o),L(o),p.delete(o),F(o),ie(o),t.push(o),await C(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);r.push(`SDK ${o}: ${a}`)}try{await Tt([]),m.info("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(o){const s=o instanceof Error?o.message:String(o);r.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:r.length>0?r:void 0})}),S.get("/events/last/:n",I,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const r=Re.getLastN(t);n.json({ok:!0,count:r.length,entries:r})}),S.get("/events/since/:index",I,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const r=Re.getSinceIndex(t);n.json({ok:!0,entries:r.entries,nextIndex:r.nextIndex,oldestIndex:r.oldestIndex,dataLoss:r.oldestIndex>t+1})}),S.get("/events/push-stats",I,(e,n)=>{const t=rt();n.json({ok:!0,count:t.length,agents:t})});export{jt as buildAcodeCommandOutputPath,qe as buildClaudeCodeLaunchConfig,Ne as buildRuntimeEnv,on as buildSdkOutputMetadata,nn as buildToolResultTimelineActionInfo,rr as cleanupSdkSessionByAgentId,Bt as countTerminalOutputLines,Be as createTerminalOutputDecoder,oe as decodeTerminalOutputChunk,Wt as evaluatePersistedSessionReuse,Nt as formatCommandInactivityTimeoutNotice,Ot as formatCommandOutputSpilloverNotice,rn as formatSdkOutputEvent,Se as formatTerminalPrompt,qt as normalizeTerminalCommandInput,Lt as parseRuntimeStopOptions,Kt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Et as resolveRuntimeContextResetSupport,Sn as resolveRuntimeStatusFromProviderEvent,Jt as resolveSdkInputMessage,ze as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,xt as resolveStatusChangeRuntimeState,re as resolveStatusChangeUsage,vt as resolveTerminalOutputEncoding,p as sdkSessions,Mt as shouldProbeSdkProcessPid,S as terminalRouter};
54
54
 
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: create-plugin
3
+ description: 引导 Agent 开发一个新的 ACode 插件(获取开发规范、生成脚手架;$ARGUMENTS 传插件名与用途)
4
+ ---
5
+
6
+ # 创建 ACode 插件(内置 /create-plugin 命令)
7
+
8
+ 用户要求创建插件时执行本流程。插件名/用途:$ARGUMENTS(未给出时先向用户确认)。
9
+
10
+ ## 1. 开发规范(权威)
11
+ 完整规范见仓库 `docs/plugin-development-guide.md`,先读取它。要点:
12
+
13
+ - 插件 = 一个目录 + 四类声明文件,零框架依赖:
14
+ - `plugin.json`(必需):`name`(kebab-case,保留前缀 `system.`/`aws-`/`acode-` 不可用)、`version`、`description`、`tools`、`listeners`、`commands`、`userConfig`(安装时向用户要的配置)。
15
+ - `tools/tools.json`(可选):注入给 agent 的工具目录;handler 支持 `process`(跑命令)/ `module`(JS 函数)/ `mcp`(预留)。
16
+ - `listeners/listeners.json`(可选):事件监听器,对接 poll_message 的 `[plugin-event]`。
17
+ - `commands/`(可选):斜杠命令 markdown,如 `mycmd.md` 定义 `/mycmd`。
18
+ - 未知清单字段会被剥离而非报错。
19
+
20
+ ## 2. 生成脚手架
21
+ 用文件工具在当前工作区创建插件目录,推荐结构:
22
+
23
+ ```
24
+ <插件名>/
25
+ ├── plugin.json
26
+ ├── tools/tools.json # 如无工具可省略
27
+ ├── listeners/listeners.json # 如无监听可省略
28
+ └── commands/ # 如无斜杠命令可省略
29
+ ```
30
+
31
+ `plugin.json` 最小示例:
32
+
33
+ ```json
34
+ {
35
+ "name": "<插件名>",
36
+ "version": "0.1.0",
37
+ "description": "<一句话描述>"
38
+ }
39
+ ```
40
+
41
+ ## 3. 校验并安装生效
42
+ - 目录就绪后校验:确认 `plugin.json` 存在且 `name` 合法、各引用文件存在、JSON 语法正确。
43
+ - 安装:经 `function_call` 调用内置插件 plugin-manager 的 manage 工具,`function_call { "tool": "plugin-manager.manage", "params": { "action": "install", "source": "local:<插件目录绝对路径>" } }`(插件管理默认可用,无需额外能力开关)。
44
+ - 安装后:下一次 poll_message 的 `pluginCatalog` 可见新插件工具;监听器开始向 poll_message 投递 `[plugin-event]`。
@@ -0,0 +1,8 @@
1
+
2
+ export declare function readChangelog(version: string): Promise<{
3
+ found: boolean;
4
+ content: string;
5
+ path: string;
6
+ }>;
7
+
8
+ export declare function appendChangelogSection(version: string, body: string): Promise<void>;
@@ -0,0 +1,17 @@
1
+ import g from"node:fs/promises";import s from"node:path";import{fileURLToPath as E}from"node:url";import{getRuntimeHomeDir as v}from"../config.js";import{createLogger as S}from"../utils/logger.js";const l=S("changelog");function h(){const e=String(process.env.AWS_BRIDGE_CHANGELOG_PATH||"").trim();if(e)return[e];const r=s.resolve(s.dirname(E(import.meta.url)),"..","..");return[s.join(r,"CHANGELOG.md"),s.join(v(),".aws-bridge","CHANGELOG.md")]}const $=256*1024,d="<!-- append-new-version-above -->";function A(e){return/^v?\d+\.\d+\.\d+/.test(e.trim())}function w(e){const r=e.trim();return r.startsWith("v")?r:`v${r}`}async function I(e){const r=w(e);for(const t of h())try{const c=await g.readFile(t,{encoding:"utf8"}),i=String(c),n=x(i,r);return n!==null?{found:!0,content:n.trimEnd(),path:t}:{found:!1,content:i.length>$?i.slice(-$):i,path:t}}catch(c){const i=c;if(i.code==="ENOENT")continue;l.warn(`[changelog] read failed for ${t}: ${i.message}`)}return{found:!1,content:"",path:h()[0]}}function x(e,r){const t=e.split(/\r?\n/);let c=-1;for(let n=0;n<t.length;n++){const o=t[n];if(/^##\s+/.test(o.trim())){const a=o.trim().replace(/^##\s+/,"");if(a===r||a===r.replace(/^v/,"")){c=n;break}}}if(c===-1)return null;let i=t.length;for(let n=c+1;n<t.length;n++)if(/^##\s+/.test(t[n].trim())||t[n].includes(d)){i=n;break}return t.slice(c,i).join(`
2
+ `)}async function R(e,r){const t=w(e);if(!A(e)){l.warn(`[changelog] skip append: invalid version "${e}"`);return}const c=h(),i=[];for(const n of c)try{let o="";try{o=await g.readFile(n,{encoding:"utf8"})}catch(p){if(p.code!=="ENOENT")throw p;o=`# Changelog
3
+
4
+ \u672C\u6587\u4EF6\u8BB0\u5F55 aws-runtime-bridge \u5404\u7248\u672C\u7684\u53D1\u5E03\u8BF4\u660E\u3002
5
+
6
+ ${d}
7
+ `}if(N(o,t)){l.info(`[changelog] ${t} \u6BB5\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u8FFD\u52A0`);return}const a=new Date().toISOString().slice(0,10),u=`
8
+ ## ${t}
9
+
10
+ _\u53D1\u5E03\u65E5\u671F\uFF1A${a}_
11
+
12
+ ${r.trim()}
13
+ `,m=C(o);let f;m>=0?f=`${o.slice(0,m).replace(/\s*$/,"")}
14
+ ${u}${o.slice(m)}`:o.includes(d)?f=o.replace(d,`${u}
15
+ ${d}`):f=`${o.replace(/\s*$/,"")}
16
+ ${u}`,await g.mkdir(s.dirname(n),{recursive:!0}),await g.writeFile(n,f,{encoding:"utf8"}),l.info(`[changelog] \u5DF2\u8FFD\u52A0 ${t} \u6BB5\u5230 ${n}`);return}catch(o){const a=o;i.push(`${n}: ${a.message}`)}l.warn(`[changelog] \u8FFD\u52A0\u5931\u8D25\uFF08\u5DF2\u5FFD\u7565\uFF09\uFF1A${i.join("; ")}`)}function N(e,r){return x(e,r)!==null}function C(e){return e.match(/^[ \t]*##\s+v?\d+\.\d+\.\d+.*$/m)?.index??-1}export{R as appendChangelogSection,I as readChangelog};
17
+
@@ -8,6 +8,8 @@ export declare const LAUNCH_ITEM_FEATURE_KEY = "agentSys.launchItem";
8
8
 
9
9
  export declare const HIRE_FEATURE_KEY = "agentSys.hire";
10
10
 
11
+ export declare const PENCIL_FEATURE_KEY = "pencil";
12
+
11
13
  export declare function setAgentFeatures(agentId: string, features: unknown): void;
12
14
 
13
15
  export declare function getAgentFeatures(agentId: string): Record<string, boolean>;
@@ -1,2 +1,2 @@
1
- import{getEffective as _,hasAnyDefault as x}from"./capability-config.js";const E={},C="desktop",F="browser",D="agentSys.launchItem",N="agentSys.hire",h=new Set([F]),O=new Set,y=new Map,c=new Map,R=["fileReadOutside","commandExecution","fileModification"],P=new Set(["allow","ask","deny"]);function M(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of R){const s=t[r];typeof s=="string"&&P.has(s)?(n[r]=s,o=!0):n[r]="allow"}return o?n:null}function j(e){if(e==null)return{...E};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...E};const n={};for(const[o,r]of Object.entries(t))O.has(o)||typeof r=="boolean"&&(n[o]=r);return n}function z(e,t){if(!e)return;y.set(e,j(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=M(n.toolPermissions);o?c.set(e,o):c.delete(e)}else c.delete(e)}function L(e){return y.get(e)??{...E}}function Y(e,t){const n=L(e)[t];return n!==void 0?n:h.has(t)}function K(e){y.delete(e),c.delete(e),u.delete(e),A.delete(e)}function k(e){return c.get(e)??null}function H(e){return c.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow"}}const U=["skills","mcp","plugins"],u=new Map,A=new Map;function v(e){if(typeof e!="object"||e===null||Array.isArray(e))return;const t={};for(const[n,o]of Object.entries(e))n.trim()&&typeof o=="boolean"&&(t[n.trim()]=o);return t}function J(e,t){if(!e)return;if(t==null){u.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){u.delete(e);return}const o=n,r={};let s=!1;for(const a of U){const i=v(o[a]);i&&(r[a]=i,s=!0)}s?u.set(e,r):u.delete(e);const f=o.plugins,d={};let g=!1;if(typeof f=="object"&&f!==null&&!Array.isArray(f))for(const[a,i]of Object.entries(f)){const p=a.trim();if(p){if(typeof i=="boolean"){const l=r.plugins??{};l[p]=i,r.plugins=l,s=!0;continue}if(i!==null&&typeof i=="object"&&!Array.isArray(i)){const l=i,S=l.enabled!==!1,b=typeof l.url=="string"?l.url:void 0,T=typeof l.sha256=="string"?l.sha256:void 0,m=r.plugins??{};m[p]=S,r.plugins=m,s=!0,b&&(d[p]={url:b,sha256:T},g=!0)}}}g?A.set(e,d):A.delete(e)}function V(e){return u.get(e)??null}function W(e){return A.get(e)??null}function q(e,t,n){if(x(t))return _(e,t,n);const o=u.get(e);if(!o)return!0;const r=o[t];if(!r)return!0;const s=r[n];return s===void 0?!0:s}function w(){return y.size}export{F as BROWSER_FEATURE_KEY,U as CAPABILITY_TYPES,C as DESKTOP_FEATURE_KEY,N as HIRE_FEATURE_KEY,D as LAUNCH_ITEM_FEATURE_KEY,K as clearAgentFeatures,V as getAgentCapabilities,L as getAgentFeatures,W as getAgentPluginSources,k as getAgentToolPermissions,w as instanceFeaturesCacheSize,q as isCapabilityEnabled,Y as isFeatureEnabled,H as resolveAgentToolPermissions,J as setAgentCapabilities,z as setAgentFeatures};
1
+ import{getEffective as T,hasAnyDefault as x}from"./capability-config.js";const E={},C="desktop",F="browser",D="agentSys.launchItem",N="agentSys.hire",Y="pencil",h=new Set([F]),O=new Set,A=new Map,c=new Map,R=["fileReadOutside","commandExecution","fileModification"],P=new Set(["allow","ask","deny"]);function L(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of R){const s=t[r];typeof s=="string"&&P.has(s)?(n[r]=s,o=!0):n[r]="allow"}return o?n:null}function M(e){if(e==null)return{...E};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...E};const n={};for(const[o,r]of Object.entries(t))O.has(o)||typeof r=="boolean"&&(n[o]=r);return n}function z(e,t){if(!e)return;A.set(e,M(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=L(n.toolPermissions);o?c.set(e,o):c.delete(e)}else c.delete(e)}function j(e){return A.get(e)??{...E}}function K(e,t){const n=j(e)[t];return n!==void 0?n:h.has(t)}function k(e){A.delete(e),c.delete(e),u.delete(e),y.delete(e)}function H(e){return c.get(e)??null}function J(e){return c.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow"}}const U=["skills","mcp","plugins"],u=new Map,y=new Map;function v(e){if(typeof e!="object"||e===null||Array.isArray(e))return;const t={};for(const[n,o]of Object.entries(e))n.trim()&&typeof o=="boolean"&&(t[n.trim()]=o);return t}function V(e,t){if(!e)return;if(t==null){u.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){u.delete(e);return}const o=n,r={};let s=!1;for(const a of U){const i=v(o[a]);i&&(r[a]=i,s=!0)}s?u.set(e,r):u.delete(e);const f=o.plugins,d={};let g=!1;if(typeof f=="object"&&f!==null&&!Array.isArray(f))for(const[a,i]of Object.entries(f)){const p=a.trim();if(p){if(typeof i=="boolean"){const l=r.plugins??{};l[p]=i,r.plugins=l,s=!0;continue}if(i!==null&&typeof i=="object"&&!Array.isArray(i)){const l=i,S=l.enabled!==!1,b=typeof l.url=="string"?l.url:void 0,_=typeof l.sha256=="string"?l.sha256:void 0,m=r.plugins??{};m[p]=S,r.plugins=m,s=!0,b&&(d[p]={url:b,sha256:_},g=!0)}}}g?y.set(e,d):y.delete(e)}function W(e){return u.get(e)??null}function q(e){return y.get(e)??null}function w(e,t,n){if(x(t))return T(e,t,n);const o=u.get(e);if(!o)return!0;const r=o[t];if(!r)return!0;const s=r[n];return s===void 0?!0:s}function G(){return A.size}export{F as BROWSER_FEATURE_KEY,U as CAPABILITY_TYPES,C as DESKTOP_FEATURE_KEY,N as HIRE_FEATURE_KEY,D as LAUNCH_ITEM_FEATURE_KEY,Y as PENCIL_FEATURE_KEY,k as clearAgentFeatures,W as getAgentCapabilities,j as getAgentFeatures,q as getAgentPluginSources,H as getAgentToolPermissions,G as instanceFeaturesCacheSize,w as isCapabilityEnabled,K as isFeatureEnabled,J as resolveAgentToolPermissions,V as setAgentCapabilities,z as setAgentFeatures};
2
2
 
@@ -3,7 +3,7 @@ import{spawn as _}from"node:child_process";import{cpSync as F,existsSync as w,ls
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=[];n.push(...this.parseCommandDir($,Ee()));for(const r of t.plugins.values())!r.enabled||!r.commandDir||n.push(...this.parsePluginCommandDir(r));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)}
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
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)&&(!Oe.test(i)||Te.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===$&&(t.action==="uninstall"||t.action==="disable"||t.action==="enable"||t.action==="reload"))return{ok:!1,error:`\u5185\u7F6E\u7CFB\u7EDF\u63D2\u4EF6 ${$} \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 q(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 C(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===$)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",N(e.agentId),o),d=t===c,y=e.plugins.get(o);if(y&&this.stopAllListeners(y),!d)try{await C(c),await re(t,c)}catch(h){const P=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,P),y&&this.startAllListeners(e,y),{ok:!1,error:`\u63D2\u4EF6\u79FB\u52A8\u5931\u8D25: ${P}`}}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 C(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(!V(e))throw new Error(`\u975E\u6CD5\u63D2\u4EF6\u540D\uFF08\u4EC5\u5141\u8BB8 ${z}\uFF09: ${JSON.stringify(e)}`);const t=m(this.deployedDir(),e),n=Z(this.deployedDir());if(Z(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(k(this.deployedManifestFile(),"utf8"));return Array.isArray(e.plugins)?e.plugins.filter(t=>t&&V(t.pluginName)):[]}catch{return[]}}writeSharedManifest(e){T(this.deployedDir(),{recursive:!0}),H(this.deployedManifestFile(),`${JSON.stringify({version:2,plugins:e},null,2)}
8
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
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",N(e),"secrets.json")}readSecrets(e){try{const t=JSON.parse(k(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{E(n,{force:!0})}catch{}return}T(U(n),{recursive:!0}),H(n,`${JSON.stringify({version:1,secrets:t},null,2)}
@@ -1,4 +1,6 @@
1
1
 
2
+ export declare function compareVersions(a: string, b: string): number;
3
+
2
4
  export declare function fetchLatestNpmVersion(): Promise<string>;
3
5
 
4
6
  export declare function checkBridgeUpdate(): Promise<{
@@ -1,2 +1,2 @@
1
- import s from"axios";import{getBridgeVersion as n}from"../config.js";import{createLogger as o}from"./logger.js";const a=o("npm-version"),i=3e5;let r=null;async function c(){return(await s.get("https://registry.npmjs.org/aws-runtime-bridge/latest",{timeout:1e4,responseType:"json"})).data?.version||"unknown"}async function m(){try{let e;r&&Date.now()-r.ts<i?e=r.latestVersion:(e=await c(),r={latestVersion:e,ts:Date.now()});const t=n();return{ok:!0,hasUpdate:e!=="unknown"&&t!=="unknown"&&e!==t,currentVersion:t,latestVersion:e}}catch(e){const t=e;return a.warn("[check-update] Failed to query npm registry:",t.message),{ok:!1,hasUpdate:!1,currentVersion:n(),latestVersion:null,error:t.message||"failed to check for updates"}}}export{m as checkBridgeUpdate,c as fetchLatestNpmVersion};
1
+ import l from"axios";import{getBridgeVersion as c}from"../config.js";import{createLogger as u}from"./logger.js";const m=u("npm-version"),d=3e5;let s=null;function f(e,t){const o=r=>r.trim().replace(/^v/i,"").split(/[-+]/)[0].split(".").map(n=>Number.parseInt(n,10)||0),a=o(e),i=o(t),p=Math.max(a.length,i.length);for(let r=0;r<p;r++){const n=(a[r]??0)-(i[r]??0);if(n!==0)return n>0?1:-1}return 0}async function g(){return(await l.get("https://registry.npmjs.org/aws-runtime-bridge/latest",{timeout:1e4,responseType:"json"})).data?.version||"unknown"}async function V(){try{let e;s&&Date.now()-s.ts<d?e=s.latestVersion:(e=await g(),s={latestVersion:e,ts:Date.now()});const t=c();return{ok:!0,hasUpdate:e!=="unknown"&&t!=="unknown"&&f(e,t)>0,currentVersion:t,latestVersion:e}}catch(e){const t=e;return m.warn("[check-update] Failed to query npm registry:",t.message),{ok:!1,hasUpdate:!1,currentVersion:c(),latestVersion:null,error:t.message||"failed to check for updates"}}}export{V as checkBridgeUpdate,f as compareVersions,g as fetchLatestNpmVersion};
2
2
 
@@ -44,6 +44,8 @@ export interface StartCommandInput {
44
44
  agentId: string;
45
45
  workspaceRoot: string;
46
46
  cwd: string;
47
+
48
+ description?: string;
47
49
  timeoutMs?: number;
48
50
 
49
51
  inactivityTimeoutMs?: number;
@@ -72,6 +74,8 @@ export interface TaskSummary {
72
74
  status: BackgroundTaskStatus;
73
75
  command: string;
74
76
  commandPreview: string;
77
+
78
+ description?: string;
75
79
  cwd: string;
76
80
  startedAt: number;
77
81
  finishedAt: number | null;