aws-runtime-bridge 1.9.153 → 1.9.162

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 (78) hide show
  1. package/CHANGELOG.md +462 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +29 -6
  3. package/dist/adapter/AcodeSdkAdapter.js +6 -5
  4. package/dist/adapter/prompts.d.ts +1 -1
  5. package/dist/adapter/prompts.js +1 -1
  6. package/dist/adapter/types.d.ts +0 -16
  7. package/dist/routes/acode-todos.js +1 -1
  8. package/dist/routes/ltr.js +1 -1
  9. package/dist/routes/sessions.d.ts +18 -74
  10. package/dist/routes/sessions.js +1 -1
  11. package/dist/routes/terminal.d.ts +8 -0
  12. package/dist/routes/terminal.js +24 -24
  13. package/dist/services/instance-features.d.ts +16 -2
  14. package/dist/services/instance-features.js +1 -1
  15. package/dist/services/workspace-files.js +1 -1
  16. package/dist/services/workspace-watch.js +1 -1
  17. package/package/acode/dist/ask-user-question-tool.js +1 -1
  18. package/package/acode/dist/await-complete-tool.js +1 -1
  19. package/package/acode/dist/background-command-manager.js +1 -1
  20. package/package/acode/dist/background-command-tools.js +1 -1
  21. package/package/acode/dist/built-in-file-tools.d.ts +18 -2
  22. package/package/acode/dist/built-in-file-tools.js +2 -2
  23. package/package/acode/dist/built-in-symbols-tool.js +1 -1
  24. package/package/acode/dist/context-overflow.d.ts +19 -0
  25. package/package/acode/dist/context-overflow.js +2 -0
  26. package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
  27. package/package/acode/dist/index.d.ts +3 -1
  28. package/package/acode/dist/index.js +1 -1
  29. package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
  30. package/package/acode/dist/parsers/ast-cache.js +1 -1
  31. package/package/acode/dist/parsers/language-queries.js +1 -1
  32. package/package/acode/dist/parsers/symbol-extractor.js +2 -2
  33. package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
  34. package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
  35. package/package/acode/dist/plugin-types.d.ts +5 -0
  36. package/package/acode/dist/plugin-types.js +1 -0
  37. package/package/acode/dist/read-file-state.d.ts +48 -0
  38. package/package/acode/dist/read-file-state.js +2 -0
  39. package/package/acode/dist/runtime.d.ts +63 -9
  40. package/package/acode/dist/runtime.js +30 -27
  41. package/package/acode/dist/skill-tool.js +3 -3
  42. package/package/acode/dist/sub-agent-manager.js +1 -1
  43. package/package/acode/dist/sub-agent-tools.js +5 -5
  44. package/package/acode/dist/todo-tool.js +3 -3
  45. package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
  46. package/package/acode/dist/tool-concurrency/index.js +2 -0
  47. package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
  48. package/package/acode/dist/tool-concurrency/observability.js +3 -0
  49. package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
  50. package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
  51. package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
  52. package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
  53. package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
  54. package/package/acode/dist/tool-concurrency/types.js +2 -0
  55. package/package/acode/dist/tool-group-manager.d.ts +116 -0
  56. package/package/acode/dist/tool-group-manager.js +14 -0
  57. package/package/acode/dist/types.d.ts +12 -2
  58. package/package/acode/package.json +2 -2
  59. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +3 -27
  60. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  61. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +46 -8
  62. package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -30
  63. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +29 -3
  64. package/package/aws-client-agent-mcp/dist/mcp-tools.js +146 -21
  65. package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
  66. package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
  67. package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
  68. package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
  69. package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +25 -0
  70. package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
  71. package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
  72. package/package/aws-client-agent-mcp/dist/types.d.ts +6 -2
  73. package/package/aws-client-agent-mcp/package.json +2 -1
  74. package/package.json +1 -1
  75. package/package/acode/dist/capability-prompt.d.ts +0 -16
  76. package/package/acode/dist/capability-prompt.js +0 -3
  77. package/package/acode/dist/plugin-tools.d.ts +0 -14
  78. package/package/acode/dist/plugin-tools.js +0 -9
@@ -1,11 +1,12 @@
1
- import{EventEmitter as X}from"node:events";import V from"node:fs/promises";import U from"node:path";import{fileURLToPath as Z,pathToFileURL as tt}from"node:url";import{v4 as v}from"uuid";import{getBridgeInstancePluginsDir as et,getBridgeInstanceSkillsDir as st,getBridgeTemplateConfigFile as x,getBridgeTemplateSkillsDir as ot}from"../config.js";import{getReleasedAcodeEntryPath as it}from"../services/acode-package.js";import{syncAgentSkillFarm as F}from"../services/agent-capability-sync.js";import{agentPtyManager as at}from"../services/agent-pty-manager.js";import{getBrowserTools as L,closeBrowserSession as nt,registerListenerWakeHook as rt,unregisterListenerWakeHook as q}from"../services/browser-session-manager.js";import{getDesktopTools as P,getDesktopToolsIfReady as lt}from"../services/desktop-mcp-manager.js";import{redactForLog as B}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as W,DESKTOP_FEATURE_KEY as D,getAgentToolPermissions as ut,getFeatureState as O,isFeatureEnabled as dt,resolveAgentToolPermissions as ct}from"../services/instance-features.js";import{pluginManager as $}from"../services/plugin-manager.js";import{subAgentManager as mt}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as pt}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as E}from"../utils/instance-ai-config-debug-logger.js";import{isMessagePollingIdleCommand as M,isPollMessageToolDescriptor as gt}from"./acode-tool-names.js";import{IdlePollLoop as ft}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as ht}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as Tt}from"./prompts.js";import{getCanonicalMcpDetail as N,getToolActionInfo as At}from"./types.js";const yt=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...d){yt&&console.log(...d)}const bt=process.env.ACODE_TOKEN_DEBUG==="1";function k(...d){bt&&console.log("[TokenDebug][Adapter]",...d)}const St=["Continue the AgentsWork message loop now.","You MUST call the exact MCP tool named aws-mcp__poll_message as your next action and wait for the next assigned message or task.","Do not answer in plain text before calling aws-mcp__poll_message.","After handling any received work, reply through the appropriate aws-mcp messaging tool, then continue listening again."].join(" "),_t=5e3;function R(d,t){const e=process.env[d];if(e===void 0||e.trim()==="")return t;const s=Number(e.trim());return Number.isFinite(s)&&s>=0?Math.floor(s):t}const K=R("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Ct=5*6e4,kt=R("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),wt=250,H=[0,3e3,1e4,4e4],j=R("ACODE_SUBMIT_TIMEOUT_MS",12e4),Q=3e3,Pt=Tt;function $t(){return U.resolve(it())}function Lt(d){return tt(U.resolve(d)).href}const G=128e3,w={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function xt(d){if(!d)return G;const t=d.toLowerCase().trim(),e=w[t];if(e)return e.contextLimit;const s=Object.keys(w).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?w[s[0]]:void 0;return o?o.contextLimit:G}const J=4096;function Dt(d){if(!d)return J;const t=d.toLowerCase().trim(),e=w[t];if(e)return e.maxOutput;const s=Object.keys(w).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?w[s[0]]:void 0;return o?o.maxOutput:J}function Ot(d){if(!d||typeof d!="object")return;const t=d,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),s=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&s===0)return;let o=h(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=h(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(o===0&&a===0){const r=h(t.cache_read_input_tokens),n=h(t.cache_creation_input_tokens);r>0||n>0?(o=r,a=n+h(t.input_tokens),i=!0):(o=h(t.cache_hit_tokens),a=h(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(o===0&&a===0){const r=h(t.prompt_tokens_details?.cached_tokens);r>0&&(o=r,a=e>r?e-r:0,i=!0)}return{inputTokens:e,outputTokens:s,...o>0||a>0?{cacheHitTokens:o,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function h(...d){for(const t of d){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function z(d){return h(d.estimatedContextTokens,d.contextTokens,d.context_tokens,d.contextUsedTokens,d.context_used_tokens)}function Et(d){return d==="stderr"||d==="mixed"?d:"stdout"}function Mt(d){if(!d||typeof d!="object"||Array.isArray(d))return;const t={};for(const[e,s]of Object.entries(d))typeof s=="string"&&(t[e]=s);return Object.keys(t).length>0?t:void 0}function Rt(d){return d.failed===!0}function Y(d,t,e){if(!d)return e?`${t}/${e}`:t;const s=`${t}__`;return d.startsWith(s)?N(`${t}__${d.slice(s.length)}`):N(d.replace("/","__"))}function It(d){return d==="read_file"||d==="edit_file"||d==="write_file"||d==="bash"}function Ut(d){const t=vt(d);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof d=="string"&&d.trim().length>0}function vt(d){if(d&&typeof d=="object"&&!Array.isArray(d))return d;if(!(typeof d!="string"||!d.trim()))try{const t=JSON.parse(d);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class ne extends X{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.dispatchableCapabilityTools=new Map,this.listenerWakeHooks=new Map,$.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await $.getPluginCommands(t);for(const s of this.sessions.values())s.config.agentId===t&&s.runtime.addPluginCommands?.(e)}catch(e){l(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const s=e.mcpConfigPath||x(),{resolved:o,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,s),r=o.model,n=a??xt(r),c=Dt(r),u={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:n,maxOutput:c,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:u,config:e,runtime:await this.createRuntime(t,r,e,o,i),autoPollActive:!1,retryAttempt:0,retryActive:!1}),this.emit("status-change",t,"starting");const m=this.sessions.get(t);if(!m)throw new Error("ACode session was not initialized");const p=()=>{const g=this.sessions.get(t);g&&this.getIdlePollLoop(g).start()};this.listenerWakeHooks.set(t,p),rt(e.agentId,p);try{await m.runtime.start(),u.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:m.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(g){u.status="error",this.emitRuntimeErrorEvent(t,g),this.emit("status-change",t,"error");const f=this.sessions.get(t);throw f?.capabilitiesFallbackTimer&&clearTimeout(f.capabilitiesFallbackTimer),this.sessions.delete(t),this.expandedBuiltInCapabilities.delete(t),this.pruneDispatchableCapabilityTools(e.agentId),q(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),g}}async sendMessage(t,e){const s=Date.now();l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l("[ACode] \u25B6\uFE0F sendMessage STARTED"),l(`[ACode] Session: ${t}`),l(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const o=this.requireSession(t),a=o.adapterSession.status;l(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(o),o.failedTurnRecoveryScheduled=!1,o.idlePollLoop?.stop(),this.cancelRequestRetry(o),o.retryAttempt=0;const i={id:v(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};o.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${a} \u2192 thinking`),o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),o.lastSubmittedPrompt=e,this.startSubmitTimeoutDetection(t,o,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const r=Date.now();await o.runtime.submit(e);const n=Date.now()-r;this.cancelSubmitTimeoutDetection(o),l(`[ACode] \u2705 runtime.submit() completed in ${n}ms`),l(`[ACode] Current status after submit: ${o.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${o.adapterSession.status}`);const c=Date.now()-s;l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),l(`[ACode] \u2705 sendMessage COMPLETED in ${c}ms`),l("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}catch(r){const n=Date.now()-s;console.error(`[ACode] \u274C sendMessage FAILED after ${n}ms:`,r instanceof Error?r.message:String(r)),this.cancelSubmitTimeoutDetection(o),l("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,r),this.scheduleRequestRetry(t,"sendMessage"),l(`[ACode] Status after failure: ${o.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,s){const o=this.sessions.get(t);if(!o)return!1;o.pendingToolAuthRequests?.delete(e);const a=o.runtime.submitToolPermissionDecision?.(e,s)??!1;return a&&this.startSubmitTimeoutDetection(t,o,"submitToolPermissionDecision"),a}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([s,o])=>({requestId:s,capability:o.capability,detail:o.detail,requestedAt:o.requestedAt})):[]}async sendQuestionAnswer(t,e){const s=this.sessions.get(t);if(!s)return;const o=s.pendingQuestionToolCallId;if(!o){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}s.pendingQuestionToolCallId=void 0,s.pendingQuestions=void 0,s.runtime.submitQuestionAnswer&&s.runtime.submitQuestionAnswer(o,e),this.startSubmitTimeoutDetection(t,s,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const s=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:s.contextLimit,maxOutput:s.maxOutput,inputLimit:s.inputLimit,compactionThreshold:s.compactionThreshold,cacheHitTokens:s.cacheHitTokens,cacheMissTokens:s.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const s=e.config.agentId;s&&(q(s,this.listenerWakeHooks.get(t)),nt(s)),this.listenerWakeHooks.delete(t),this.expandedBuiltInCapabilities.delete(t),this.pruneDispatchableCapabilityTools(s),e.adapterSession.status="terminated",this.sessions.delete(t),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(i=>i.config.agentId===t);if(!e)return;const s=e.config.mcpConfigPath||x(),{resolved:o,supportsImage:a}=await this.resolveAcodeProvider(e.config,s);return o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=F(t);if(e)return e}catch(e){l(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return st(t)}return ot()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,D),s=this.shouldInjectCapabilityTools(t,W);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const r=i.runtime,n=e,c=s;try{if(n){const u=await P(t,await this.resolveAgentAiInfo(t)),m=r.addBuiltInTools?.(u)??0;m>0&&l(`[acode-adapter] session ${a}: ${m} desktop tools hot-added for agent ${t}`)}else{const u=r.removeBuiltInToolsByPrefix?.("desktop_")??0;u>0&&l(`[acode-adapter] session ${a}: ${u} desktop tools hot-removed for agent ${t}`)}}catch(u){l(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,u.message)}if(c)try{const u=await L(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),m=r.addBuiltInTools?.(u)??0;m>0&&l(`[acode-adapter] session ${a}: ${m} browser tools hot-added for agent ${t}`)}catch(u){l(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,u.message)}else{const u=r.removeBuiltInToolsByPrefix?.("browser_")??0;u>0&&l(`[acode-adapter] session ${a}: ${u} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{F(t)}catch(a){l(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await $.applyCapabilities(t)}catch(a){l(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,a.message)}const o=ct(t);for(const[a,i]of this.sessions)if(i.config.agentId===t)try{i.runtime.setToolPermissionPolicy?.(o)}catch(r){l(`[acode-adapter] session ${a}: tool permission policy hot-sync failed for agent ${t}:`,r.message)}}syncMcpToolsForAgent(t){if(t){for(const[e,s]of this.sessions)if(s.config.agentId===t)try{s.runtime.requestMcpToolsRefresh?.()}catch(o){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,o.message)}}}async setBuiltInCapabilityTools(t,e,s){if(!t)return{sessions:0,tools:0};const o=e==="browser"?"browser_":e==="desktop"?"desktop_":void 0;if(!o)return{sessions:0,tools:0};let a=0,i=0,r;const n=this.dispatchableCapabilityTools.get(t)?.get(e)?.length??0;let c=0;for(const[u,m]of this.sessions)if(m.config.agentId===t)try{if(s==="collapse"){const A=this.expandedBuiltInCapabilities.get(u)?.delete(e)??!1,y=m.runtime.removeBuiltInToolsByPrefix?.(o)??0;c+=y,(A||y>0)&&(a+=1,i+=y,l(`[acode-adapter] session ${u}: collapsed ${e} capability for agent ${t}`));continue}const p=e==="browser"?await L(t,m.config.scopeKey,typeof m.config.browserAllowPrivate=="boolean"?{allowPrivate:m.config.browserAllowPrivate}:void 0):await P(t,await this.resolveAgentAiInfo(t));if(!this.sessions.has(u))continue;let g=this.dispatchableCapabilityTools.get(t);g||(g=new Map,this.dispatchableCapabilityTools.set(t,g)),g.set(e,[...p]);let f=this.expandedBuiltInCapabilities.get(u);f||(f=new Set,this.expandedBuiltInCapabilities.set(u,f)),f.add(e),a+=1,i=p.length,r=p.map(A=>({name:A.toolName,description:A.description,inputSchema:A.inputSchema})),l(`[acode-adapter] session ${u}: ${p.length} ${e} tools dispatchable for agent ${t}`)}catch(p){l(`[acode-adapter] session ${u}: ${e} ${s} failed for agent ${t}:`,p.message)}return s==="collapse"?(this.dispatchableCapabilityTools.get(t)?.delete(e),{sessions:a,tools:n>0?n:c,manifests:r}):{sessions:a,tools:i,manifests:r}}async callBuiltInCapabilityTool(t,e,s,o){if(!t)return{ok:!1,error:"\u7F3A\u5C11 agentId"};if(e!=="browser"&&e!=="desktop")return{ok:!1,error:`\u672A\u77E5\u6865\u63A5\u80FD\u529B\u300C${e}\u300D`};if(!s.startsWith(`${e}_`))return{ok:!1,error:`\u5DE5\u5177\u300C${s}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(O(t,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u672A\u5F00\u542F\uFF08\u5DF2\u7981\u7528\uFF0C\u8BF7\u5148\u5728\u80FD\u529B\u914D\u7F6E\u4E2D\u5F00\u542F\uFF09\u3002`};if(![...this.expandedBuiltInCapabilities.entries()].some(([n,c])=>c.has(e)&&this.sessions.get(n)?.config.agentId===t))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools({ group: "${e}" })\u3002`};let i=this.dispatchableCapabilityTools.get(t)?.get(e);if(!i||i.length===0)try{const n=[...this.sessions.values()].find(u=>u.config.agentId===t);i=e==="browser"?await L(t,n?.config.scopeKey,typeof n?.config.browserAllowPrivate=="boolean"?{allowPrivate:n.config.browserAllowPrivate}:void 0):await P(t,await this.resolveAgentAiInfo(t));let c=this.dispatchableCapabilityTools.get(t);c||(c=new Map,this.dispatchableCapabilityTools.set(t,c)),c.set(e,[...i])}catch(n){return{ok:!1,error:`\u6865\u63A5\u80FD\u529B\u5DE5\u5177\u6784\u5EFA\u5931\u8D25\uFF1A${n instanceof Error?n.message:String(n)}`}}const r=i.find(n=>n.toolName===s);if(!r)return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u4E0B\u4E0D\u5B58\u5728\u5DE5\u5177\u300C${s}\u300D`};try{return{ok:!0,result:await r.execute(o)}}catch(n){return{ok:!1,error:n instanceof Error?n.message:String(n)}}}pruneDispatchableCapabilityTools(t){if(!t)return;[...this.sessions.values()].some(s=>s.config.agentId===t)||this.dispatchableCapabilityTools.delete(t)}shouldInjectCapabilityTools(t,e){return t?O(t,e)==="expanded":!0}getPendingQuestion(t){const e=this.sessions.get(t);if(e?.pendingQuestionToolCallId)return{toolCallId:e.pendingQuestionToolCallId,questions:e.pendingQuestions??[]}}cleanup(){for(const t of this.sessions.keys())this.terminateSession(t)}setIdleCommands(t,e){const s=this.sessions.get(t);if(s){if(s.idleCommands=e,this.cancelScheduledAutoPoll(s),e.idleInputCommand&&M(e.idleInputCommand)){this.getIdlePollLoop(s).start();return}s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(s).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await V.readFile(t,"utf-8"),s=JSON.parse(e),a=s.provider?.default,i=a?.options,r=h(s.contextLimit),n={},c={},u=a?.models;if(u&&typeof u=="object"){for(const[m,p]of Object.entries(u))if(p&&typeof p=="object"){const g=h(p.contextLimit);g>0&&(n[m.trim()]=g);const f=p.modalities?.input,A=Array.isArray(f)&&f.includes("image")||p.supportsImageInput===!0;c[m.trim()]=A===!0}}return{...a?.model?{model:a.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...r>0?{contextLimit:r}:{},...Object.keys(n).length>0?{modelContextLimits:n}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const s=e instanceof Error?e.message:String(e);return E().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${s}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const s=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,o=E();o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?B(t.instanceAiConfig):null,configPath:e}});const a={...t.instanceAiConfig?.model?{model:t.instanceAiConfig.model}:{},...t.instanceAiConfig?.baseURL?{baseURL:t.instanceAiConfig.baseURL}:{},...t.instanceAiConfig?.apiKey?{apiKey:t.instanceAiConfig.apiKey}:{},...t.instanceAiConfig?.effort?{effort:t.instanceAiConfig.effort}:{},...s?{model:s}:{}},i=await this.loadAcodeProviderSection(e);let r=i.contextLimit;if(!r&&i.modelContextLimits){const c=s||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(r=i.modelContextLimits[c])}const n=ht(a,i,"acode-default");return o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:B(a),globalConfigModel:i?.model??null,resolvedModel:n.model,resolvedBaseURL:n.baseURL??null,resolvedApiKey:n.apiKey?"[set]":null,configContextLimit:r,resolvedSource:n.source}}),{resolved:n,configPath:e,perSessionModel:s,configContextLimit:r,supportsImage:i.modelImageSupport?.[n.model]===!0}}async createRuntime(t,e,s,o,a){const i=await this.loadRuntimeConstructor(),r=s.mcpConfigPath||x();let n=[];try{n=await L(s.agentId,s.scopeKey,typeof s.browserAllowPrivate=="boolean"?{allowPrivate:s.browserAllowPrivate}:void 0)}catch(p){l(`[acode-adapter] browser tools injection skipped for agent ${s.agentId}:`,p.message)}let c=[];if(this.shouldInjectCapabilityTools(s.agentId??"",W)&&(c=n),s.agentId&&this.shouldInjectCapabilityTools(s.agentId,D))try{const p=o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0,g=await P(s.agentId,p);g.length>0&&(c=[...c,...g])}catch(p){l(`[acode-adapter] desktop tools injection skipped for agent ${s.agentId}:`,p.message)}const u=new i({sessionId:t,agentId:s.agentId,workingDirectory:s.workingDirectory,configPath:r,skillsDir:this.resolveAgentSkillsDir(s.agentId),pluginsDir:s.agentId?et(s.agentId):void 0,model:e,systemPrompt:typeof s.systemPrompt=="string"?s.systemPrompt:void 0,globalPrompt:typeof s.globalPrompt=="string"?s.globalPrompt:void 0,rolePrompt:typeof s.rolePrompt=="string"?s.rolePrompt:void 0,memory:typeof s.memory=="string"?s.memory:void 0,env:s.envOverrides,subAgentManager:mt,terminalManager:at,capabilityState:p=>O(s.agentId??"",p),pluginBridge:s.agentId?$.forAgent(s.agentId):void 0,commandDirs:[Z(new URL("../services/builtin-commands/",import.meta.url))],...s.subAgentModel?{subAgentModel:s.subAgentModel}:{},...s.subAgentEffort?{subAgentEffort:s.subAgentEffort}:{},...s.instanceAiConfig?.effort?{effort:s.instanceAiConfig.effort}:{},onFileChange:p=>pt({...p,agentId:s.agentId,workspacePath:s.workingDirectory}),extraBuiltInTools:c,...s.agentId?{toolPermissionPolicy:ut(s.agentId)??void 0}:{},subAgentSuiteTools:n,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(s.agentId)});return E().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:s.instanceAiConfig?.model||null,perInstanceBaseURL:s.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:s.instanceAiConfig?.apiKey?"[set]":null,configPath:r}}),u.on("event",p=>this.forwardAcodeEvent(p)),u}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!dt(t,D))return[];if(e.length===0)return lt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const o=await this.resolveAgentAiInfo(t);return P(t,o)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=$t(),e=await import(Lt(t));if(!e.ACodeRuntime)throw new Error(`ACode runtime export not found: ${t}`);return this.runtimeConstructor=e.ACodeRuntime,this.runtimeConstructor}requireSession(t){const e=this.sessions.get(t);if(!e)throw new Error("ACode session not found");return e}startInitialPromptTurn(t,e){const s=this.sessions.get(t);s&&(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),s.lastSubmittedPrompt=e,this.startSubmitTimeoutDetection(t,s,"startInitialPromptTurn"),s.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(s),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(o=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),this.emitRuntimeErrorEvent(t,o),this.scheduleRequestRetry(t,"startInitialPromptTurn"))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const s=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:v(),sessionId:t.sessionId,role:"assistant",content:s,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:s});return}if(t.type==="thinking_delta"){const s=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:s});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:Et(t.data.stream),sequence:typeof t.data.sequence=="number"?t.data.sequence:void 0,cwd:typeof t.data.cwd=="string"?t.data.cwd:void 0,commandLineCount:typeof t.data.commandLineCount=="number"?t.data.commandLineCount:void 0,commandFilePath:typeof t.data.commandFilePath=="string"?t.data.commandFilePath:void 0});return}if(t.type==="background_command_completed"){this.emitProviderEvent(t,"background_command_completed",t.data);return}if(t.type==="ai_request"){const s=z(t.data),o=t.data.lastUsage,a=h(o?.inputTokens),i=h(o?.outputTokens),r=h(o?.cacheHitTokens),n=h(o?.cacheMissTokens),c=!!(o&&(a>0||i>0));let u;if(c&&(a>0&&(e.adapterSession.totalUsage.inputTokens=a),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(o?.cacheHitTokens!==void 0||o?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=r,e.adapterSession.totalUsage.cacheMissTokens=n),u={...e.adapterSession.totalUsage},k(`ai_request lastUsage applied: ${JSON.stringify(o)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&s>0){const g=e.adapterSession.totalUsage.inputTokens;g>0?e.adapterSession.totalUsage.inputTokens=Math.min(s,Math.floor(g*1.5)):e.adapterSession.totalUsage.inputTokens=s,u={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const p={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};u&&(p.usage=u),k(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(u??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,p),this.startDataFlowWatchdog(t.sessionId,e),e.adapterSession.status==="thinking"&&e.watchdogSubmitStartTime&&(e.watchdogSubmitStartTime=Date.now()),this.emitProviderEvent(t,"ai_request",{model:typeof t.data.model=="string"?t.data.model:void 0,endpoint:typeof t.data.endpoint=="string"?t.data.endpoint:void 0,requestMethod:typeof t.data.requestMethod=="string"?t.data.requestMethod:void 0,requestUrl:typeof t.data.requestUrl=="string"?t.data.requestUrl:void 0,requestHeaders:Mt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0,requestBody:typeof t.data.requestBody=="string"?t.data.requestBody:void 0});return}if(t.type==="turn_complete"){const s=Ot(t.data.usage);if(s){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&s.inputTokens<Math.floor(a*.2)&&!s.hasCache;k(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(s)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?s.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=s.outputTokens):(e.adapterSession.totalUsage.inputTokens=s.inputTokens,e.adapterSession.totalUsage.outputTokens=s.outputTokens),(s.cacheHitTokens||s.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=s.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=s.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${s.cacheHitTokens||0}, miss=${s.cacheMissTokens||0})`)),k(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else k(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const o=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${o}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),Rt(t.data)){l(`[ACode] Scheduling retry from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&(e.autoPollActive||e.retryActive||e.retryTimer)){l(`[ACode] Scheduling retry from aborted turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(this.cancelDataFlowWatchdog(e),this.emitProviderEvent(t,"turn_complete",{usage:e.adapterSession.totalUsage,responseBody:typeof t.data.responseBody=="string"?t.data.responseBody:void 0,finishReason:typeof t.data.finishReason=="string"?t.data.finishReason:void 0}),e.adapterSession.status="waiting_input",this.emit("status-change",t.sessionId,"waiting_input",{usage:e.adapterSession.totalUsage}),k(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),l(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",o=Array.isArray(t.data.questions)?t.data.questions:[];s&&(e.pendingQuestionToolCallId=s,e.pendingQuestions=o),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:s||void 0,questions:o});return}if(t.type==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.requestId=="string"?t.data.requestId:"";s&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(s,{capability:String(t.data.capability||""),detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation},requestedAt:Date.now()})),this.emit("tool-permission-request",{sessionId:t.sessionId,requestId:s,capability:String(t.data.capability||""),agentId:e.config.agentId,detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation}});return}if(t.type==="error"){if(t.data.nonFatal){this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")});return}this.cancelDataFlowWatchdog(e),e.adapterSession.status="error",this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const f=t.data.tools;f.some(T=>gt(T))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const y=Array.isArray(t.data.servers)?t.data.servers:[],S=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),_={kind:"mcp",mcpServers:y,mcpTools:S};e.cachedMcpCapabilities=_,e.lastMcpCapabilities=_,e.lastCombinedCapabilities={kind:"combined",mcpServers:y,mcpTools:S,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${y.length} servers, ${S.length} tools`,{sessionId:t.sessionId,servers:y,toolNames:S.map(T=>T.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const T=e.cachedMcpCapabilities;if(!T)return;const C={...T,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:C,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(C)}),l(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${Q}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},Q);return}const s=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${s}, server=${typeof t.data.server=="string"?t.data.server:"?"}, tool=${typeof t.data.tool=="string"?t.data.tool:"?"}, toolUseId=${typeof t.data.toolUseId=="string"?t.data.toolUseId.slice(0,16)+"\u2026":"none"}, failed=${t.data.failed===!0}, session=${t.sessionId}, status=${e.adapterSession.status}`);const o=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=o&&a?`${o}__${a}`:a||o,r=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,n=At(i,r);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,n.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=It(n.actionType)?n.actionDetail||Y(void 0,o,a):Y(n.actionDetail,o,a),u=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=r?JSON.stringify(r,null,2):void 0,p={toolName:c,rawToolName:i,actionType:n.actionType,actionLabel:n.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...r?{toolInput:r}:{},...u?{toolUseId:u,actionId:u}:{},metadata:{mcpServer:o}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...p,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=n.actionType==="idle"&&!Ut(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,n.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const A=n.actionType==="idle";this.emit("status-change",t.sessionId,f,A||f==="thinking"?void 0:p);return}const g=n.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=g,n.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),g==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...p}),this.emitProviderEvent(t,"tool_use_start",p),this.emit("status-change",t.sessionId,g,p);return}if(t.type==="skill_status"){const o=(Array.isArray(t.data.skills)?t.data.skills:[]).map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,r=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const p=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:p.map(g=>({name:String(g.name??""),description:typeof g.description=="string"?g.description:void 0,directory:typeof g.directory=="string"?g.directory:void 0})).filter(g=>g.name)}}).filter(m=>m.dir),n=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,u={kind:"combined",mcpServers:n?.mcpServers??[],mcpTools:n?.mcpTools??[],skills:o,skillsDir:a,skillGroups:r};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:u,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(u)}),e.lastCombinedCapabilities=u,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(n?.mcpTools??[]).length} MCP tools, ${o.length} skills`,{sessionId:t.sessionId,mcpServers:n?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){l(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){l(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const s=z(t.data),o=h(t.data.contextLimit)||void 0,a=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,r=h(t.data.compactionThreshold)||void 0;let n=!1;s>0&&(e.adapterSession.totalUsage.inputTokens=s,e.adapterSession.totalUsage.outputTokens=0,n=!0),o!==void 0&&(e.adapterSession.totalUsage.contextLimit=o,n=!0),a!==void 0&&(e.adapterSession.totalUsage.maxOutput=a,n=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,n=!0),r!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=r,n=!0),n&&this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:e.adapterSession.totalUsage});return}if(t.type==="exit_plan_mode"){e.adapterSession.status="waiting_input";const s=typeof t.data.plan=="string"?t.data.plan:void 0;this.emitProviderEvent(t,"exit_plan_mode",{toolInput:t.data.toolInput&&typeof t.data.toolInput=="object"?t.data.toolInput:void 0,text:s||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:s||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const s=t.data,o=s.action,a=o==="start",i=o==="end",r=o==="phase",n=s.parentId,c=s.compactionId;let u,m;if(a){const g=String(s.sizeKB??s.sizeBeforeKB??"?"),f=String(s.messageCount??s.messageCountBefore??"?"),A=s.estimatedTokens,y=s.actualInputTokens?`input=${s.actualInputTokens}`:"",S=s.actualOutputTokens?`output=${s.actualOutputTokens}`:"",_=s.trigger?`, \u89E6\u53D1: ${s.trigger}`:"";u="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",A!==void 0?m=`\u538B\u7F29\u524D: ~${A} tokens, \u6D88\u606F: ${f}\u6761`+(y?`, \u5B9E\u9645 tokens: ${y} ${S}`:"")+_:m=`\u538B\u7F29\u524D: ${g}KB, \u6D88\u606F: ${f}\u6761`+(y?`, \u5B9E\u9645 tokens: ${y} ${S}`:"")+_}else if(r)u=String(s.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(s.phaseDetail??"");else{const g=s.tokensBefore,f=s.tokensAfter,A=s.freedTokens,y=String(s.sizeBeforeKB??"?"),S=String(s.sizeAfterKB??"?"),_=String(s.freedKB??"?"),T=String(s.strategy??"?"),C=Number(s.prunedToolMessages??0),b=Number(s.summarizedMessages??0);u="\u538B\u7F29\u5B8C\u6210",g!==void 0&&f!==void 0?m=`\u91CA\u653E: ${A??g-f} tokens, ${g} tokens \u2192 ${f} tokens, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(b?`, \u6458\u8981\u5316: ${b}\u6761`:""):m=`\u91CA\u653E: ${_}KB, ${y}KB \u2192 ${S}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(b?`, \u6458\u8981\u5316: ${b}\u6761`:"")}a&&(e.adapterSession.status="compacting");const p={actionType:"context_compaction",actionLabel:u,actionDetail:m};if(a&&c)p.actionId=c;else if((r||i)&&c)if(p.parentId=c,r){const g=String(s.phase??"unknown");p.actionId=`${c}-phase-${g}`}else p.actionId=`${c}-end`;r&&n&&!p.parentId&&(p.parentId=n),i&&(e.adapterSession.totalUsage.inputTokens=h(s.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,e.config.agentId&&$.markAgentCompacted(e.config.agentId),p.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",p),this.emit("status-change",t.sessionId,"compacting",p);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,s){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:s})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new ft({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:s=>M(s),preDispatchHook:()=>null,dispatchPollingPrompt:(s,o)=>this.submitAutoPollPrompt(e,o?s:Pt,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:s=>this.submitAutoPollPrompt(e,s)}),t.idlePollLoop}submitAutoPollPrompt(t,e,s){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;const a=(o.autoPollToken??0)+1;o.autoPollToken=a,o.autoPollActive=!0,o.autoPollObservedPollingTool=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.stopAutoPollAfterCurrentTurn=!1,o.autoPollQueuedAt=Date.now(),o.autoPollLastActivityAt=Date.now(),o.idleToolActiveAt=void 0,o.lastSubmittedPrompt=e,s?.keepWaitingStatus||(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,o,"submitAutoPollPrompt"),o.runtime.submit(e).catch(i=>{this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){l(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${a}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e=wt){const s=this.sessions.get(t);!s||s.autoPollActive||s.autoPollTimer||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=setTimeout(()=>{const o=this.sessions.get(t);!o||o.autoPollActive||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=void 0,this.submitAutoPollPrompt(t,St,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status)||s.retryActive||s.retryTimer)return;if(!s.lastSubmittedPrompt){s.adapterSession.status="error",this.emit("status-change",t,"error");return}s.retryAttempt+=1,s.retryActive=!0,this.cancelScheduledAutoPoll(s),s.idlePollLoop?.stop();const o=H[Math.min(s.retryAttempt-1,H.length-1)];s.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${s.retryAttempt}\u6B21 \xB7 ${Math.round(o/1e3)}s\u540E`}),l(`[ACode] scheduleRequestRetry(${e}): attempt=${s.retryAttempt} delay=${o}ms`),s.retryTimer=setTimeout(()=>{s.retryTimer=void 0,this.retryFailedRequest(t,e)},o)}retryFailedRequest(t,e){const s=this.sessions.get(t);if(!s)return;if(s.retryTimer=void 0,this.isTerminalStatus(s.adapterSession.status)||!s.lastSubmittedPrompt){s.retryActive=!1;return}s.retryActive=!1;const o=s.lastSubmittedPrompt;l(`[ACode] retryFailedRequest(${e}): attempt=${s.retryAttempt} re-submitting...`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:s.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,s,"retryFailedRequest"),s.runtime.submit(o).then(()=>{const a=this.sessions.get(t);!a||a.retryTimer||(this.cancelSubmitTimeoutDetection(a),a.retryAttempt=0,a.retryActive=!1,this.recoverResolvedTurnWithoutTerminalEvent(t))}).catch(a=>{const i=this.sessions.get(t);i&&(this.cancelSubmitTimeoutDetection(i),this.emitRuntimeErrorEvent(t,a),this.scheduleRequestRetry(t,`retry#${i.retryAttempt+1}`))})}cancelRequestRetry(t){t.retryTimer&&(clearTimeout(t.retryTimer),t.retryTimer=void 0),t.retryActive=!1}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeErrorEvent(t,e){const s=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:s,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(s=>s.role==="assistant").map(s=>s.content).join("");return Math.max(0,Math.round(e.length/4))}recoverTurnFailure(t,e){if(this.isTerminalStatus(e.adapterSession.status))return;if(e.idleToolActiveAt=void 0,e.pendingToolAuthRequests?.size&&e.pendingToolAuthRequests.clear(),e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const o=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${o.toolName??"unknown"}) \u5173\u95ED\u65F6\u95F4\u7EBF\u6761\u76EE\uFF0C\u907F\u514D\u6C38\u4E45\u5361\u5728\u5DE5\u5177\u6267\u884C\u72B6\u6001`),this.emit("event",{type:"tool_use_end",sessionId:t,timestamp:new Date().toISOString(),data:{...o,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const s=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(s>0){const o=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=s,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${o} -> ${s} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){l(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){l(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(l(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){l(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),l("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand,a=!!(s&&M(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;this.emit("status-change",t,"waiting_input",a),l(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),this.armIdleLoopOrAutoPoll(t),l("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,s){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.cancelSubmitTimeoutDetection(e);return}const a=o.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(o.autoPollActive&&o.autoPollLastActivityAt&&o.idleToolActiveAt===void 0&&i-o.autoPollLastActivityAt>=kt){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-o.autoPollLastActivityAt)/1e3)}s (source: ${s}, session: ${t}): submit queued but no runtime events and no active poll_message tool. Forcing recovery (runtime force-settle will unblock submitQueue).`),this.executeWatchdogRecovery(t,o,s,"stuck_autopoll",i-o.autoPollLastActivityAt);return}o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(a==="tool_using"){const c=i-(o.watchdogLastDataFlowTime||i);if(c>=Ct){const u=String(o.pendingToolEventData?.rawToolName??"");if((o.pendingToolAuthRequests?.size??0)>0){const m=o.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but ${m} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(u.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${u}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${s}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),o.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${u} to background (session: ${t}); waiting for the real tool_result to continue the turn`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,o,s,"tool_using_slow",c);return}o.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const r=i-(o.watchdogSubmitStartTime||i),n=i-(o.watchdogLastDataFlowTime||i);if(K>0&&n>=K){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(n/1e3)}s (source: ${s}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,o,s,"data_flow",n);return}if(j>0&&r>=j){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(r/1e3)}s (source: ${s}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,o,s,"submit_timeout",r);return}},_t)}executeWatchdogRecovery(t,e,s,o,a){l(`[ACode] Watchdog (${o}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${o}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}formatAiRequestActionDetail(t){const e=`
1
+ import{EventEmitter as st}from"node:events";import ot from"node:fs/promises";import N from"node:path";import{fileURLToPath as it,pathToFileURL as at}from"node:url";import{v4 as H}from"uuid";import{getBridgeInstancePluginsDir as nt,getBridgeInstanceSkillsDir as rt,getBridgeTemplateConfigFile as R,getBridgeTemplateSkillsDir as lt}from"../config.js";import{getReleasedAcodeEntryPath as ut}from"../services/acode-package.js";import{syncAgentSkillFarm as K}from"../services/agent-capability-sync.js";import{agentPtyManager as dt}from"../services/agent-pty-manager.js";import{getBrowserTools as U,closeBrowserSession as ct,registerListenerWakeHook as mt,unregisterListenerWakeHook as j}from"../services/browser-session-manager.js";import{getDesktopTools as E,getDesktopToolsIfReady as pt}from"../services/desktop-mcp-manager.js";import{redactForLog as G}from"../services/instance-ai-config-service.js";import{BROWSER_FEATURE_KEY as x,DESKTOP_FEATURE_KEY as w,getAgentToolPermissions as gt,getFeatureState as v,isFeatureEnabled as ft,resolveAgentToolPermissions as ht,resolveGroupFeatureKey as Tt}from"../services/instance-features.js";import{pluginManager as L}from"../services/plugin-manager.js";import{subAgentManager as yt}from"../services/sub-agent-manager-instance.js";import{recordAgentFileChange as At}from"../services/workspaceTaskChangeWatcher.js";import{getInstanceAiConfigDebugLogger as F}from"../utils/instance-ai-config-debug-logger.js";import{isMessagePollingIdleCommand as q,isPollMessageToolDescriptor as St}from"./acode-tool-names.js";import{IdlePollLoop as bt}from"./idle-poll-loop.js";import{resolveAcodeProviderConfig as _t}from"./instance-ai-config-resolver.js";import{MESSAGE_POLLING_IDLE_PROMPT as Ct}from"./prompts.js";import{getCanonicalMcpDetail as Q,getToolActionInfo as kt}from"./types.js";const wt=process.env.ACODE_COMPACTION_DEBUG==="1";function r(...d){wt&&console.log(...d)}const Pt=process.env.ACODE_TOKEN_DEBUG==="1";function k(...d){Pt&&console.log("[TokenDebug][Adapter]",...d)}const $t=["Continue the AgentsWork message loop now.","You MUST call the exact MCP tool named aws-mcp__poll_message as your next action and wait for the next assigned message or task.","Do not answer in plain text before calling aws-mcp__poll_message.","After handling any received work, reply through the appropriate aws-mcp messaging tool, then continue listening again."].join(" "),xt=5e3;function B(d,t){const e=process.env[d];if(e===void 0||e.trim()==="")return t;const s=Number(e.trim());return Number.isFinite(s)&&s>=0?Math.floor(s):t}const z=B("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),Lt=5*6e4,Ot=B("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),Et=250,J=[0,3e3,1e4,4e4];function Dt(d){const t=d.toLowerCase();return/tool[_ ]?call/.test(t)||t.includes("invalid_request")?!0:/\b(400|401|403|404|422)\b/.test(t)}const W={[x]:"browser_",[w]:"desktop_"};function Mt(d){if(!d||typeof d!="object")return;const t=d,e=typeof t.exposedName=="string"&&t.exposedName||typeof t.toolName=="string"&&t.toolName||typeof t.name=="string"&&t.name||"";if(!e)return;const s=typeof t.execute=="function"?t.execute:void 0;return{name:e,...typeof t.description=="string"?{description:t.description}:{},...t.inputSchema!==void 0?{inputSchema:t.inputSchema}:{},definition:t,...s?{execute:s}:{}}}const Y=B("ACODE_SUBMIT_TIMEOUT_MS",12e4),X=3e3,It=Ct;function Rt(){return N.resolve(ut())}function Ut(d){return at(N.resolve(d)).href}const V=128e3,P={"claude-4":{contextLimit:2e5,maxOutput:8192},"claude-sonnet-4":{contextLimit:2e5,maxOutput:8192},"claude-3-5-sonnet":{contextLimit:2e5,maxOutput:8192},"claude-3-opus":{contextLimit:2e5,maxOutput:8192},"claude-3-haiku":{contextLimit:2e5,maxOutput:8192},"claude-2":{contextLimit:1e5,maxOutput:4096},"gpt-4o":{contextLimit:128e3,maxOutput:16384},"gpt-4-turbo":{contextLimit:128e3,maxOutput:4096},"gpt-4":{contextLimit:8192,maxOutput:4096},"gpt-3.5-turbo":{contextLimit:16384,maxOutput:4096},o1:{contextLimit:2e5,maxOutput:1e5},"o3-mini":{contextLimit:2e5,maxOutput:1e5},"gemini-2.0-flash":{contextLimit:1048576,maxOutput:8192},"gemini-2.5-pro":{contextLimit:1048576,maxOutput:8192},"gemini-1.5-pro":{contextLimit:2097152,maxOutput:8192},"gemini-1.5-flash":{contextLimit:1048576,maxOutput:8192},deepseek:{contextLimit:64e3,maxOutput:8192},"deepseek-chat":{contextLimit:64e3,maxOutput:8192},"deepseek-reasoner":{contextLimit:64e3,maxOutput:8192},"qwen-max":{contextLimit:32e3,maxOutput:8192},"qwen-plus":{contextLimit:128e3,maxOutput:8192},"qwen-turbo":{contextLimit:1e6,maxOutput:8192},"glm-4":{contextLimit:128e3,maxOutput:4096},"yi-":{contextLimit:2e5,maxOutput:4096},"llama-3":{contextLimit:8192,maxOutput:4096},"llama-2":{contextLimit:4096,maxOutput:4096},mistral:{contextLimit:32e3,maxOutput:4096},mixtral:{contextLimit:32e3,maxOutput:4096},codestral:{contextLimit:256e3,maxOutput:8192},grok:{contextLimit:131072,maxOutput:4096},"nova-":{contextLimit:2e5,maxOutput:8192}};function vt(d){if(!d)return V;const t=d.toLowerCase().trim(),e=P[t];if(e)return e.contextLimit;const s=Object.keys(P).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?P[s[0]]:void 0;return o?o.contextLimit:V}const Z=4096;function Ft(d){if(!d)return Z;const t=d.toLowerCase().trim(),e=P[t];if(e)return e.maxOutput;const s=Object.keys(P).filter(a=>t.startsWith(a)).sort((a,i)=>i.length-a.length),o=s[0]!==void 0?P[s[0]]:void 0;return o?o.maxOutput:Z}function tt(d){if(!d||typeof d!="object")return;const t=d,e=T(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),s=T(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&s===0)return;let o=T(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),a=T(t.cacheMissTokens,t.promptCacheMissTokens,t.prompt_cache_miss_tokens),i=t.cacheHitTokens!==void 0||t.cacheMissTokens!==void 0||t.promptCacheHitTokens!==void 0||t.promptCacheMissTokens!==void 0||t.prompt_cache_hit_tokens!==void 0||t.prompt_cache_miss_tokens!==void 0;if(o===0&&a===0){const n=T(t.cache_read_input_tokens),c=T(t.cache_creation_input_tokens);n>0||c>0?(o=n,a=c+T(t.input_tokens),i=!0):(o=T(t.cache_hit_tokens),a=T(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(o===0&&a===0){const n=T(t.prompt_tokens_details?.cached_tokens);n>0&&(o=n,a=e>n?e-n:0,i=!0)}return{inputTokens:e,outputTokens:s,...o>0||a>0?{cacheHitTokens:o,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function T(...d){for(const t of d){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function qt(d){return d==="stderr"||d==="mixed"?d:"stdout"}function Bt(d){if(!d||typeof d!="object"||Array.isArray(d))return;const t={};for(const[e,s]of Object.entries(d))typeof s=="string"&&(t[e]=s);return Object.keys(t).length>0?t:void 0}function Wt(d){return d.failed===!0}function et(d,t,e){if(!d)return e?`${t}/${e}`:t;const s=`${t}__`;return d.startsWith(s)?Q(`${t}__${d.slice(s.length)}`):Q(d.replace("/","__"))}function Nt(d){return d==="read_file"||d==="edit_file"||d==="write_file"||d==="bash"}function Ht(d){const t=Kt(d);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof d=="string"&&d.trim().length>0}function Kt(d){if(d&&typeof d=="object"&&!Array.isArray(d))return d;if(!(typeof d!="string"||!d.trim()))try{const t=JSON.parse(d);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class pe extends st{constructor(){super(),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.expandedBuiltInCapabilities=new Map,this.builtInCapabilityToolCache=new Map,this.listenerWakeHooks=new Map,L.setOnPluginsChanged(t=>{this.syncPluginCommands(t)})}async syncPluginCommands(t){try{const e=await L.getPluginCommands(t);for(const s of this.sessions.values())s.config.agentId===t&&s.runtime.addPluginCommands?.(e)}catch(e){r(`[acode-adapter] syncPluginCommands failed for agent ${t}:`,e.message)}}async startSession(t,e){const s=e.mcpConfigPath||R(),{resolved:o,configContextLimit:a,supportsImage:i}=await this.resolveAcodeProvider(e,s),n=o.model,c=a??vt(n),l=Ft(n),p={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:c,maxOutput:l,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:p,config:e,runtime:await this.createRuntime(t,n,e,o,i),autoPollActive:!1,retryAttempt:0,retryActive:!1}),this.emit("status-change",t,"starting");const m=this.sessions.get(t);if(!m)throw new Error("ACode session was not initialized");const u=()=>{const g=this.sessions.get(t);g&&this.getIdlePollLoop(g).start()};this.listenerWakeHooks.set(t,u),mt(e.agentId,u);try{await m.runtime.start(),p.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:m.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(g){p.status="error",this.emitRuntimeErrorEvent(t,g),this.emit("status-change",t,"error");const f=this.sessions.get(t);throw f?.capabilitiesFallbackTimer&&clearTimeout(f.capabilitiesFallbackTimer),this.sessions.delete(t),j(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),g}}async sendMessage(t,e){const s=Date.now();r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),r("[ACode] \u25B6\uFE0F sendMessage STARTED"),r(`[ACode] Session: ${t}`),r(`[ACode] Message: ${e.slice(0,100)}${e.length>100?"...":""}`),r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");const o=this.requireSession(t),a=o.adapterSession.status;r(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(o),o.failedTurnRecoveryScheduled=!1,o.idlePollLoop?.stop(),this.cancelRequestRetry(o),o.retryAttempt=0;const i={id:H(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};o.adapterSession.messages.push(i),this.emit("conversation-message",t,i),r(`[ACode] Changing status: ${a} \u2192 thinking`),o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.autoPollObservedPollingTool=!1,o.lastSubmittedPrompt=e,o.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,o,"sendMessage");try{r("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const n=Date.now();await o.runtime.submit(e);const c=Date.now()-n;this.cancelSubmitTimeoutDetection(o),r(`[ACode] \u2705 runtime.submit() completed in ${c}ms`),r(`[ACode] Current status after submit: ${o.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),r(`[ACode] Status after recovery: ${o.adapterSession.status}`);const l=Date.now()-s;r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"),r(`[ACode] \u2705 sendMessage COMPLETED in ${l}ms`),r("[ACode] \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")}catch(n){const c=Date.now()-s;console.error(`[ACode] \u274C sendMessage FAILED after ${c}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(o),r("[ACode] \u25B6\uFE0F sendMessage failed, scheduling request retry..."),this.emitRuntimeErrorEvent(t,n),this.scheduleRequestRetry(t,"sendMessage"),r(`[ACode] Status after failure: ${o.adapterSession.status}`)}}async sendConfirmation(t,e){}submitToolPermissionDecision(t,e,s){const o=this.sessions.get(t);if(!o)return!1;o.pendingToolAuthRequests?.delete(e);const a=o.runtime.submitToolPermissionDecision?.(e,s)??!1;return a&&this.startSubmitTimeoutDetection(t,o,"submitToolPermissionDecision"),a}getPendingToolAuthRequests(t){const e=this.sessions.get(t);return e?.pendingToolAuthRequests?Array.from(e.pendingToolAuthRequests.entries()).map(([s,o])=>({requestId:s,capability:o.capability,detail:o.detail,requestedAt:o.requestedAt})):[]}async sendQuestionAnswer(t,e){const s=this.sessions.get(t);if(!s)return;const o=s.pendingQuestionToolCallId;if(!o){r(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}s.pendingQuestionToolCallId=void 0,s.pendingQuestions=void 0,s.runtime.submitQuestionAnswer&&s.runtime.submitQuestionAnswer(o,e),this.startSubmitTimeoutDetection(t,s,"sendQuestionAnswer")}async abortCurrentTurn(t){await this.requireSession(t).runtime.abort()}async resetContext(t){const e=this.requireSession(t);if(this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.autoPollActive=!1,e.autoPollObservedPollingTool=!1,e.autoPollObservedAssistantText=!1,e.autoPollObservedAnyTool=!1,e.stopAutoPollAfterCurrentTurn=!1,e.idlePollLoop?.stop(),!e.runtime.resetContext)throw new Error("ACode runtime does not support context reset");await e.runtime.resetContext(),e.adapterSession.messages=[];const s=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:s.contextLimit,maxOutput:s.maxOutput,inputLimit:s.inputLimit,compactionThreshold:s.compactionThreshold,cacheHitTokens:s.cacheHitTokens,cacheMissTokens:s.cacheMissTokens},e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),e.config.initialPrompt?.trim()){this.startInitialPromptTurn(t,e.config.initialPrompt);return}this.armIdleLoopOrAutoPoll(t)}async terminateSession(t){const e=this.sessions.get(t);if(!e)return;this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),this.cancelRequestRetry(e),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const s=e.config.agentId;s&&(j(s,this.listenerWakeHooks.get(t)),ct(s)),this.listenerWakeHooks.delete(t),e.adapterSession.status="terminated",this.sessions.delete(t),s&&![...this.sessions.values()].some(o=>o.config.agentId===s)&&(this.expandedBuiltInCapabilities.delete(s),this.builtInCapabilityToolCache.delete(s)),this.emit("status-change",t,"terminated")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.has(t)?t:void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}notifyForceMessage(t){const e=this.sessions.get(t);return e?.runtime?.notifyForceMessage?(e.runtime.notifyForceMessage(),!0):!1}getCapabilities(t){return this.sessions.get(t)?.lastCombinedCapabilities}async resolveAgentAiInfo(t){try{const e=[...this.sessions.values()].find(i=>i.config.agentId===t);if(!e)return;const s=e.config.mcpConfigPath||R(),{resolved:o,supportsImage:a}=await this.resolveAcodeProvider(e.config,s);return o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0}catch{return}}resolveAgentSkillsDir(t){if(t){try{const e=K(t);if(e)return e}catch(e){r(`[acode-adapter] skill farm sync failed for agent ${t}:`,e.message)}return rt(t)}return lt()}async applyAgentFeatures(t){if(!t)return;const e=this.shouldInjectCapabilityTools(t,w),s=this.shouldInjectCapabilityTools(t,x);for(const[a,i]of this.sessions){if(i.config.agentId!==t)continue;const n=i.runtime,c=e,l=s;try{if(c){const p=await E(t,await this.resolveAgentAiInfo(t)),m=n.addBuiltInTools?.(p)??0;m>0&&r(`[acode-adapter] session ${a}: ${m} desktop tools hot-added for agent ${t}`)}else{const p=n.removeBuiltInToolsByPrefix?.("desktop_")??0;p>0&&r(`[acode-adapter] session ${a}: ${p} desktop tools hot-removed for agent ${t}`)}}catch(p){r(`[acode-adapter] session ${a}: desktop feature hot-sync failed for agent ${t}:`,p.message)}if(l)try{const p=await U(t,i.config.scopeKey,typeof i.config.browserAllowPrivate=="boolean"?{allowPrivate:i.config.browserAllowPrivate}:void 0),m=n.addBuiltInTools?.(p)??0;m>0&&r(`[acode-adapter] session ${a}: ${m} browser tools hot-added for agent ${t}`)}catch(p){r(`[acode-adapter] session ${a}: browser feature hot-sync failed for agent ${t}:`,p.message)}else{const p=n.removeBuiltInToolsByPrefix?.("browser_")??0;p>0&&r(`[acode-adapter] session ${a}: ${p} browser tools hot-removed for agent ${t}`)}}this.syncMcpToolsForAgent(t);try{K(t)}catch(a){r(`[acode-adapter] skill farm hot-sync failed for agent ${t}:`,a.message)}try{await L.applyCapabilities(t)}catch(a){r(`[acode-adapter] plugin capability hot-sync failed for agent ${t}:`,a.message)}const o=ht(t);for(const[a,i]of this.sessions)if(i.config.agentId===t)try{i.runtime.setToolPermissionPolicy?.(o)}catch(n){r(`[acode-adapter] session ${a}: tool permission policy hot-sync failed for agent ${t}:`,n.message)}}syncMcpToolsForAgent(t){if(t){for(const[e,s]of this.sessions)if(s.config.agentId===t)try{s.runtime.requestMcpToolsRefresh?.()}catch(o){r(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,o.message)}}}shouldInjectCapabilityTools(t,e){return t?v(t,e)==="expanded":!0}resolveCapabilityToolPrefix(t){return W[String(t??"").trim()]}async loadCapabilityToolsForSession(t,e,s){const o=t===x?await U(e,s.config.scopeKey,typeof s.config.browserAllowPrivate=="boolean"?{allowPrivate:s.config.browserAllowPrivate}:void 0):await E(e,await this.resolveAgentAiInfo(e)),a=[];for(const i of o){const n=Mt(i);n&&a.push(n)}return a}async setBuiltInCapabilityTools(t,e,s){const o=String(t??"").trim(),a=this.resolveCapabilityToolPrefix(e);if(!o||!a)return{sessions:0,tools:0};const i=[...this.sessions.entries()].filter(([,l])=>l.config.agentId===o);if(i.length===0)return{sessions:0,tools:0};if(s==="collapse"){let l=0;for(const[p,m]of i){const u=m.runtime.removeBuiltInToolsByPrefix?.(a)??0;l+=u,u>0&&r(`[acode-adapter] session ${p}: ${u} ${e} tools removed on collapse (agent ${o})`)}return this.expandedBuiltInCapabilities.get(o)?.delete(e),this.builtInCapabilityToolCache.get(o)?.delete(e),r(`[acode-adapter] capability collapse: agent=${o} capability=${e} sessions=${i.length} removedTools=${l}`),{sessions:i.length,tools:l}}const n=new Map;for(const[l,p]of i){let m;try{m=await this.loadCapabilityToolsForSession(e,o,p)}catch(u){throw r(`[acode-adapter] session ${l}: capability ${e} tool load failed for agent ${o}:`,u.message),u}for(const u of m)n.has(u.name)||n.set(u.name,u)}const c=this.expandedBuiltInCapabilities.get(o)??new Set;return c.add(e),this.expandedBuiltInCapabilities.set(o,c),this.builtInCapabilityToolCache.set(o,n),r(`[acode-adapter] capability expand: agent=${o} capability=${e} sessions=${i.length} tools=${n.size} (manifests only, no session tool injection)`),{sessions:i.length,tools:n.size,manifests:[...n.values()].map(l=>({name:l.name,...l.description!==void 0?{description:l.description}:{},...l.inputSchema!==void 0?{inputSchema:l.inputSchema}:{}}))}}async callBuiltInCapabilityTool(t,e,s,o){const a=String(t??"").trim(),i=this.resolveCapabilityToolPrefix(e);if(!i)return{ok:!1,error:`\u672A\u77E5\u80FD\u529B\u300C${String(e)}\u300D\uFF1A\u4EC5\u652F\u6301 browser / desktop`};const n=String(s??"").trim();if(!n)return{ok:!1,error:"\u5DE5\u5177\u540D\u7F3A\u5931"};if(!n.startsWith(i))return{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u5C5E\u4E8E\u80FD\u529B\u300C${e}\u300D`};if(a&&v(a,e)==="disabled")return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5DF2\u7981\u7528\uFF0C\u65E0\u6CD5\u8C03\u5EA6\u8BE5\u5DE5\u5177`};if(!(this.expandedBuiltInCapabilities.get(a)?.has(e)??!1))return{ok:!1,error:`\u80FD\u529B\u300C${e}\u300D\u5C1A\u672A\u5C55\u5F00\uFF0C\u8BF7\u5148\u8C03\u7528 expand_tools \u5C55\u5F00\u540E\u518D\u8C03\u5EA6\u8BE5\u5DE5\u5177`};const l=this.builtInCapabilityToolCache.get(a)?.get(n);return l?typeof l.execute!="function"?{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u4E0D\u53EF\u8C03\u5EA6\uFF08\u7F3A\u5C11 execute \u5B9E\u73B0\uFF09`}:{ok:!0,result:await l.execute.call(l.definition,o??{})}:{ok:!1,error:`\u5DE5\u5177\u300C${n}\u300D\u65E0\u7F13\u5B58\u5B9A\u4E49\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528 expand_tools \u5237\u65B0`}}getPendingQuestion(t){const e=this.sessions.get(t);if(e?.pendingQuestionToolCallId)return{toolCallId:e.pendingQuestionToolCallId,questions:e.pendingQuestions??[]}}cleanup(){for(const t of this.sessions.keys())this.terminateSession(t)}setIdleCommands(t,e){const s=this.sessions.get(t);if(s){if(s.idleCommands=e,this.cancelScheduledAutoPoll(s),e.idleInputCommand&&q(e.idleInputCommand)){this.getIdlePollLoop(s).start();return}s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(s).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await ot.readFile(t,"utf-8"),s=JSON.parse(e),a=s.provider?.default,i=a?.options,n=T(s.contextLimit),c={},l={},p=a?.models;if(p&&typeof p=="object"){for(const[m,u]of Object.entries(p))if(u&&typeof u=="object"){const g=T(u.contextLimit);g>0&&(c[m.trim()]=g);const f=u.modalities?.input,A=Array.isArray(f)&&f.includes("image")||u.supportsImageInput===!0;l[m.trim()]=A===!0}}return{...a?.model?{model:a.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...n>0?{contextLimit:n}:{},...Object.keys(c).length>0?{modelContextLimits:c}:{},...Object.keys(l).length>0?{modelImageSupport:l}:{}}}catch(e){const s=e instanceof Error?e.message:String(e);return F().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${s}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const s=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,o=F();o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?G(t.instanceAiConfig):null,configPath:e}});const a={...t.instanceAiConfig?.model?{model:t.instanceAiConfig.model}:{},...t.instanceAiConfig?.baseURL?{baseURL:t.instanceAiConfig.baseURL}:{},...t.instanceAiConfig?.apiKey?{apiKey:t.instanceAiConfig.apiKey}:{},...t.instanceAiConfig?.effort?{effort:t.instanceAiConfig.effort}:{},...s?{model:s}:{}},i=await this.loadAcodeProviderSection(e);let n=i.contextLimit;if(!n&&i.modelContextLimits){const l=s||t.instanceAiConfig?.model||i.model;l&&i.modelContextLimits[l]&&(n=i.modelContextLimits[l])}const c=_t(a,i,"acode-default");return o.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:G(a),globalConfigModel:i?.model??null,resolvedModel:c.model,resolvedBaseURL:c.baseURL??null,resolvedApiKey:c.apiKey?"[set]":null,configContextLimit:n,resolvedSource:c.source}}),{resolved:c,configPath:e,perSessionModel:s,configContextLimit:n,supportsImage:i.modelImageSupport?.[c.model]===!0}}async createRuntime(t,e,s,o,a){const i=await this.loadRuntimeConstructor(),n=s.mcpConfigPath||R();let c=[];try{c=await U(s.agentId,s.scopeKey,typeof s.browserAllowPrivate=="boolean"?{allowPrivate:s.browserAllowPrivate}:void 0)}catch(u){r(`[acode-adapter] browser tools injection skipped for agent ${s.agentId}:`,u.message)}let l=[];if(this.shouldInjectCapabilityTools(s.agentId??"",x)&&(l=c),s.agentId&&this.shouldInjectCapabilityTools(s.agentId,w))try{const u=o?.model?{model:o.model,supportsImage:a===!0,...o.baseURL?{baseURL:o.baseURL}:{},...o.apiKey?{apiKey:o.apiKey}:{}}:void 0,g=await E(s.agentId,u);g.length>0&&(l=[...l,...g])}catch(u){r(`[acode-adapter] desktop tools injection skipped for agent ${s.agentId}:`,u.message)}const p=new i({sessionId:t,agentId:s.agentId,workingDirectory:s.workingDirectory,configPath:n,skillsDir:this.resolveAgentSkillsDir(s.agentId),pluginsDir:s.agentId?nt(s.agentId):void 0,model:e,systemPrompt:typeof s.systemPrompt=="string"?s.systemPrompt:void 0,globalPrompt:typeof s.globalPrompt=="string"?s.globalPrompt:void 0,rolePrompt:typeof s.rolePrompt=="string"?s.rolePrompt:void 0,memory:typeof s.memory=="string"?s.memory:void 0,env:s.envOverrides,subAgentManager:yt,terminalManager:dt,capabilityState:u=>v(s.agentId??"",Tt(u)),capabilityToolRelay:s.agentId?{handlesGroup:u=>this.resolveCapabilityToolPrefix(u)!==void 0,handlesTool:u=>Object.values(W).some(g=>u.startsWith(g)),expand:async u=>(await this.setBuiltInCapabilityTools(s.agentId??"",u,"expand")).manifests??[],collapse:async u=>{await this.setBuiltInCapabilityTools(s.agentId??"",u,"collapse")},call:async(u,g)=>{const f=u.startsWith(W[w]??"desktop_")?w:x;return this.callBuiltInCapabilityTool(s.agentId??"",f,u,g)}}:void 0,pluginBridge:s.agentId?L.forAgent(s.agentId):void 0,commandDirs:[it(new URL("../services/builtin-commands/",import.meta.url))],...s.subAgentModel?{subAgentModel:s.subAgentModel}:{},...s.subAgentEffort?{subAgentEffort:s.subAgentEffort}:{},...s.instanceAiConfig?.effort?{effort:s.instanceAiConfig.effort}:{},onFileChange:u=>At({...u,agentId:s.agentId,workspacePath:s.workingDirectory}),extraBuiltInTools:l,...s.agentId?{toolPermissionPolicy:gt(s.agentId)??void 0}:{},subAgentSuiteTools:c,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(s.agentId)});return F().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:s.instanceAiConfig?.model||null,perInstanceBaseURL:s.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:s.instanceAiConfig?.apiKey?"[set]":null,configPath:n}}),p.on("event",u=>this.forwardAcodeEvent(u)),p}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!ft(t,w))return[];if(e.length===0)return pt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const o=await this.resolveAgentAiInfo(t);return E(t,o)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=Rt(),e=await import(Ut(t));if(!e.ACodeRuntime)throw new Error(`ACode runtime export not found: ${t}`);return this.runtimeConstructor=e.ACodeRuntime,this.runtimeConstructor}requireSession(t){const e=this.sessions.get(t);if(!e)throw new Error("ACode session not found");return e}startInitialPromptTurn(t,e){const s=this.sessions.get(t);s&&(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.autoPollObservedPollingTool=!1,s.lastSubmittedPrompt=e,s.turnModelRequestSucceeded=!1,this.startSubmitTimeoutDetection(t,s,"startInitialPromptTurn"),s.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(s),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(o=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),a.lastErrorText=o instanceof Error?o.message:String(o),this.emitRuntimeErrorEvent(t,o),this.scheduleRequestRetry(t,"startInitialPromptTurn"))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const s=typeof t.data.text=="string"?t.data.text:"";e.turnModelRequestSucceeded=!0,e.autoPollObservedAssistantText=!0,e.adapterSession.messages.push({id:H(),sessionId:t.sessionId,role:"assistant",content:s,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:s});return}if(t.type==="thinking_delta"){const s=typeof t.data.text=="string"?t.data.text:"";e.turnModelRequestSucceeded=!0,this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:s});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:qt(t.data.stream),sequence:typeof t.data.sequence=="number"?t.data.sequence:void 0,cwd:typeof t.data.cwd=="string"?t.data.cwd:void 0,commandLineCount:typeof t.data.commandLineCount=="number"?t.data.commandLineCount:void 0,commandFilePath:typeof t.data.commandFilePath=="string"?t.data.commandFilePath:void 0});return}if(t.type==="background_command_completed"){this.emitProviderEvent(t,"background_command_completed",t.data);return}if(t.type==="ai_request"){const s=t.data.lastUsage,o=T(s?.inputTokens),a=T(s?.outputTokens),i=T(s?.cacheHitTokens),n=T(s?.cacheMissTokens),c=!!(s&&(o>0||a>0));let l;c&&(o>0&&(e.adapterSession.totalUsage.inputTokens=o),a>0&&(e.adapterSession.totalUsage.outputTokens=a),(s?.cacheHitTokens!==void 0||s?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=i,e.adapterSession.totalUsage.cacheMissTokens=n),l={...e.adapterSession.totalUsage},k(`ai_request lastUsage applied: ${JSON.stringify(s)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const m={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};l&&(m.usage=l),k(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(l??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,m),this.startDataFlowWatchdog(t.sessionId,e),e.adapterSession.status==="thinking"&&e.watchdogSubmitStartTime&&(e.watchdogSubmitStartTime=Date.now()),this.emitProviderEvent(t,"ai_request",{model:typeof t.data.model=="string"?t.data.model:void 0,endpoint:typeof t.data.endpoint=="string"?t.data.endpoint:void 0,requestMethod:typeof t.data.requestMethod=="string"?t.data.requestMethod:void 0,requestUrl:typeof t.data.requestUrl=="string"?t.data.requestUrl:void 0,requestHeaders:Bt(t.data.requestHeaders),stream:typeof t.data.stream=="boolean"?t.data.stream:void 0,messageCount:typeof t.data.messageCount=="number"?t.data.messageCount:void 0,toolCount:typeof t.data.toolCount=="number"?t.data.toolCount:void 0,lastUserMessagePreview:typeof t.data.lastUserMessagePreview=="string"?t.data.lastUserMessagePreview:void 0,requestBody:typeof t.data.requestBody=="string"?t.data.requestBody:void 0});return}if(t.type==="iteration_usage"){const s=tt(t.data);s&&(e.adapterSession.totalUsage.inputTokens=s.inputTokens,e.adapterSession.totalUsage.outputTokens=s.outputTokens,s.hasCache&&(e.adapterSession.totalUsage.cacheHitTokens=s.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=s.cacheMissTokens),k(`iteration_usage applied: raw=${JSON.stringify(t.data)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:{...e.adapterSession.totalUsage}}));return}if(t.type==="turn_complete"){const s=tt(t.data.usage);if(s){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&s.inputTokens<Math.floor(a*.2)&&!s.hasCache;k(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(s)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?s.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=s.outputTokens):(e.adapterSession.totalUsage.inputTokens=s.inputTokens,e.adapterSession.totalUsage.outputTokens=s.outputTokens),(s.cacheHitTokens||s.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=s.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=s.cacheMissTokens,r(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${s.cacheHitTokens||0}, miss=${s.cacheMissTokens||0})`)),k(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else k(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const o=e.adapterSession.status;if(r(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${o}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),Wt(t.data)){r(`[ACode] Scheduling retry from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&(e.autoPollActive||e.retryActive||e.retryTimer)){r(`[ACode] Scheduling retry from aborted turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(this.cancelDataFlowWatchdog(e),this.emitProviderEvent(t,"turn_complete",{usage:e.adapterSession.totalUsage,responseBody:typeof t.data.responseBody=="string"?t.data.responseBody:void 0,finishReason:typeof t.data.finishReason=="string"?t.data.finishReason:void 0}),e.adapterSession.status="waiting_input",this.emit("status-change",t.sessionId,"waiting_input",{usage:e.adapterSession.totalUsage}),k(`status-change emitted (waiting_input after turn_complete): usage=${JSON.stringify(e.adapterSession.totalUsage)}`),r(`[ACode] Status changed to waiting_input after turn_complete (session: ${t.sessionId})`),e.autoPollActive&&e.autoPollObservedAssistantText&&!e.autoPollObservedPollingTool&&!e.autoPollObservedAnyTool){e.stopAutoPollAfterCurrentTurn=!0,console.warn(`[${this.displayName}] Auto-poll turn produced assistant text without calling any tool; stopping auto-poll rearm for session ${t.sessionId}`);return}if(!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; skipping idle prompt dispatch for this turn (session: ${t.sessionId})`);return}this.armIdleLoopOrAutoPoll(t.sessionId);return}if(t.type==="session_complete"){this.cancelDataFlowWatchdog(e),this.cancelScheduledAutoPoll(e),e.failedTurnRecoveryScheduled=!1,e.idlePollLoop?.stop(),e.adapterSession.status="completed",this.emitProviderEvent(t,"session_complete",{exitCode:Number(t.data.exitCode)||0}),this.emit("status-change",t.sessionId,"completed");return}if(t.type==="question_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",o=Array.isArray(t.data.questions)?t.data.questions:[];s&&(e.pendingQuestionToolCallId=s,e.pendingQuestions=o),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:s||void 0,questions:o});return}if(t.type==="tool_permission_request"){this.cancelDataFlowWatchdog(e),this.cancelSubmitTimeoutDetection(e);const s=typeof t.data.requestId=="string"?t.data.requestId:"";s&&(e.pendingToolAuthRequests||(e.pendingToolAuthRequests=new Map),e.pendingToolAuthRequests.set(s,{capability:String(t.data.capability||""),detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation},requestedAt:Date.now()})),this.emit("tool-permission-request",{sessionId:t.sessionId,requestId:s,capability:String(t.data.capability||""),agentId:e.config.agentId,detail:{path:t.data.path,command:t.data.command,cwd:t.data.cwd,operation:t.data.operation}});return}if(t.type==="error"){if(t.data.nonFatal){this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")});return}this.cancelDataFlowWatchdog(e),e.adapterSession.status="error",e.lastErrorText=String(t.data.message||""),this.emitProviderEvent(t,"error",{text:String(t.data.message||"ACode runtime error")}),this.emit("status-change",t.sessionId,"error"),e.autoPollActive||this.recoverTurnFailure(t.sessionId,e);return}if(t.type==="mcp_status"){if(!t.data.action&&Array.isArray(t.data.tools)){const f=t.data.tools;f.some(h=>St(h))||console.warn(`[${this.displayName}] ACode runtime is not exposing a poll_message tool. The LLM cannot call poll_message. Please configure an MCP server that provides poll_message (e.g. aws-mcp) in the dashboard panel for this runtime.`);const S=Array.isArray(t.data.servers)?t.data.servers:[],C=f.map(h=>({name:String(h.name??""),source:String(h.source??""),description:String(h.description??"")})).filter(h=>h.name),b={kind:"mcp",mcpServers:S,mcpTools:C};e.cachedMcpCapabilities=b,e.lastMcpCapabilities=b,e.lastCombinedCapabilities={kind:"combined",mcpServers:S,mcpTools:C,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},r(`[cap-diag] MCP capabilities cached: ${S.length} servers, ${C.length} tools`,{sessionId:t.sessionId,servers:S,toolNames:C.map(h=>h.name)}),e.capabilitiesFallbackTimer&&clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=setTimeout(()=>{const h=e.cachedMcpCapabilities;if(!h)return;const _={...h,skills:[],skillGroups:[]};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:_,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(_)}),r(`[cap-diag] MCP capabilities emitted via fallback (skill_status not received within ${X}ms)`,{sessionId:t.sessionId,mcpServers:h.mcpServers,mcpToolsCount:h.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},X);return}const s=String(t.data.action??"");r(`[ACode] \u{1F4E1} mcp_status event: action=${s}, server=${typeof t.data.server=="string"?t.data.server:"?"}, tool=${typeof t.data.tool=="string"?t.data.tool:"?"}, toolUseId=${typeof t.data.toolUseId=="string"?t.data.toolUseId.slice(0,16)+"\u2026":"none"}, failed=${t.data.failed===!0}, session=${t.sessionId}, status=${e.adapterSession.status}`);const o=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=o&&a?`${o}__${a}`:a||o,n=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,c=kt(i,n);e.autoPollObservedAnyTool=!0,c.actionType==="idle"&&(e.autoPollObservedPollingTool=!0);const l=Nt(c.actionType)?c.actionDetail||et(void 0,o,a):et(c.actionDetail,o,a),p=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=n?JSON.stringify(n,null,2):void 0,u={toolName:l,rawToolName:i,actionType:c.actionType,actionLabel:c.actionLabel,actionDetail:l,...m?{actionInput:m}:{},...n?{toolInput:n}:{},...p?{toolUseId:p,actionId:p}:{},metadata:{mcpServer:o}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...u,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=c.actionType==="idle"&&!Ht(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,c.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const A=c.actionType==="idle";this.emit("status-change",t.sessionId,f,A||f==="thinking"?void 0:u);return}const g=c.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=g,c.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),g==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...u}),this.emitProviderEvent(t,"tool_use_start",u),this.emit("status-change",t.sessionId,g,u);return}if(t.type==="skill_status"){const o=(Array.isArray(t.data.skills)?t.data.skills:[]).map(m=>({name:String(m.name??""),description:typeof m.description=="string"?m.description:void 0,directory:typeof m.directory=="string"?m.directory:void 0})).filter(m=>m.name),a=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,n=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const u=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:u.map(g=>({name:String(g.name??""),description:typeof g.description=="string"?g.description:void 0,directory:typeof g.directory=="string"?g.directory:void 0})).filter(g=>g.name)}}).filter(m=>m.dir),c=e.cachedMcpCapabilities??e.lastMcpCapabilities,l=e.cachedMcpCapabilities!==void 0,p={kind:"combined",mcpServers:c?.mcpServers??[],mcpTools:c?.mcpTools??[],skills:o,skillsDir:a,skillGroups:n};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:p,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(p)}),e.lastCombinedCapabilities=p,r(`[cap-diag] Combined capabilities emitted ${l?"(startup merge)":"(runtime refresh)"}: ${(c?.mcpTools??[]).length} MCP tools, ${o.length} skills`,{sessionId:t.sessionId,mcpServers:c?.mcpServers??[],skillsDir:a}),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),e.cachedMcpCapabilities=void 0;return}if(t.type==="startup_phase"){r(`[ACode] \u{1F680} startup_phase swallowed: ${String(t.data.phase??"unknown")}`,{sessionId:t.sessionId});return}if(t.type==="command_status"){if(t.data.action==="commands_loaded"){r(`[ACode] \u{1F4CB} command_status commands_loaded swallowed: ${typeof t.data.installedCommandCount=="number"?t.data.installedCommandCount:"?"} commands`,{sessionId:t.sessionId});return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)});return}if(t.type==="session_started"){const s=T(t.data.contextLimit)||void 0,o=T(t.data.maxOutput)||void 0,a=T(t.data.inputLimit)||void 0,i=T(t.data.compactionThreshold)||void 0;let n=!1;s!==void 0&&(e.adapterSession.totalUsage.contextLimit=s,n=!0),o!==void 0&&(e.adapterSession.totalUsage.maxOutput=o,n=!0),a!==void 0&&(e.adapterSession.totalUsage.inputLimit=a,n=!0),i!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=i,n=!0),n&&this.emit("status-change",t.sessionId,e.adapterSession.status,{usage:e.adapterSession.totalUsage});return}if(t.type==="exit_plan_mode"){e.adapterSession.status="waiting_input";const s=typeof t.data.plan=="string"?t.data.plan:void 0;this.emitProviderEvent(t,"exit_plan_mode",{toolInput:t.data.toolInput&&typeof t.data.toolInput=="object"?t.data.toolInput:void 0,text:s||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:s||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const s=t.data,o=s.action,a=o==="start",i=o==="end",n=o==="phase",c=s.parentId,l=s.compactionId;let p,m;if(a){const g=String(s.sizeKB??s.sizeBeforeKB??"?"),f=String(s.messageCount??s.messageCountBefore??"?"),A=s.estimatedTokens,S=s.actualInputTokens?`input=${s.actualInputTokens}`:"",C=s.actualOutputTokens?`output=${s.actualOutputTokens}`:"",b=s.trigger;p=b==="provider_overflow_error"?"\u68C0\u6D4B\u5230\u6A21\u578B\u8FD4\u56DE\u4E0A\u4E0B\u6587\u8D85\u9650\u4FE1\u53F7":"\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB";const _=b?`, \u89E6\u53D1: ${b}`:"";A!==void 0?m=`\u538B\u7F29\u524D: ~${A} tokens, \u6D88\u606F: ${f}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${C}`:"")+_:m=`\u538B\u7F29\u524D: ${g}KB, \u6D88\u606F: ${f}\u6761`+(S?`, \u5B9E\u9645 tokens: ${S} ${C}`:"")+_}else if(n){const g=String(s.phase??""),f=String(s.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),A=String(s.phaseDetail??"");g==="detect"?(p="\u5F00\u59CB\u89E6\u53D1\u54CD\u5E94\u5F0F\u538B\u7F29",m=A||"\u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u8D85\u9650\uFF0C\u5373\u5C06\u5F00\u59CB\u538B\u7F29..."):(p=f,m=A)}else{const g=s.tokensBefore,f=s.tokensAfter,A=s.freedTokens,S=String(s.sizeBeforeKB??"?"),C=String(s.sizeAfterKB??"?"),b=String(s.freedKB??"?"),h=String(s.strategy??"?"),_=Number(s.prunedToolMessages??0),y=Number(s.summarizedMessages??0);p="\u538B\u7F29\u5B8C\u6210",g!==void 0&&f!==void 0?m=`\u91CA\u653E: ${A??g-f} tokens, ${g} tokens \u2192 ${f} tokens, \u7B56\u7565: ${h}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(y?`, \u6458\u8981\u5316: ${y}\u6761`:""):m=`\u91CA\u653E: ${b}KB, ${S}KB \u2192 ${C}KB, \u7B56\u7565: ${h}`+(_?`, \u88C1\u526A\u5DE5\u5177: ${_}\u6761`:"")+(y?`, \u6458\u8981\u5316: ${y}\u6761`:"")}a&&(e.adapterSession.status="compacting");const u={actionType:"context_compaction",actionLabel:p,actionDetail:m};if(a&&l)u.actionId=l;else if((n||i)&&l)if(u.parentId=l,n){const g=String(s.phase??"unknown");u.actionId=`${l}-phase-${g}`}else u.actionId=`${l}-end`;n&&c&&!u.parentId&&(u.parentId=c),i&&(e.adapterSession.totalUsage.inputTokens=T(s.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,e.config.agentId&&L.markAgentCompacted(e.config.agentId),u.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",u),this.emit("status-change",t.sessionId,"compacting",u);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,s){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:s})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(this.cancelRequestRetry(e),e.retryAttempt=0,e.idleCommands?.idleInputCommand){this.getIdlePollLoop(e).start();return}this.scheduleAutoPoll(t)}}getIdlePollLoop(t){if(t.idlePollLoop)return t.idlePollLoop;const e=t.adapterSession.sessionId;return t.idlePollLoop=new bt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:s=>q(s),preDispatchHook:()=>null,dispatchPollingPrompt:(s,o)=>this.submitAutoPollPrompt(e,o?s:It,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:s=>this.submitAutoPollPrompt(e,s)}),t.idlePollLoop}submitAutoPollPrompt(t,e,s){const o=this.sessions.get(t);if(!o||this.isTerminalStatus(o.adapterSession.status))return;const a=(o.autoPollToken??0)+1;o.autoPollToken=a,o.autoPollActive=!0,o.autoPollObservedPollingTool=!1,o.autoPollObservedAssistantText=!1,o.autoPollObservedAnyTool=!1,o.stopAutoPollAfterCurrentTurn=!1,o.autoPollQueuedAt=Date.now(),o.autoPollLastActivityAt=Date.now(),o.idleToolActiveAt=void 0,o.lastSubmittedPrompt=e,o.turnModelRequestSucceeded=!1,s?.keepWaitingStatus||(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,o,"submitAutoPollPrompt"),o.runtime.submit(e).catch(i=>{this.emitRuntimeErrorEvent(t,i),this.scheduleRequestRetry(t,"submitAutoPollPrompt")}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==a){r(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${a}, current=${i.autoPollToken}), skipping cleanup \u2014 newer turn has taken over`);return}if(this.cancelSubmitTimeoutDetection(i),i.autoPollActive=!1,i.failedTurnRecoveryScheduled||i.autoPollTimer){i.failedTurnRecoveryScheduled=!1;return}if(i.stopAutoPollAfterCurrentTurn){i.stopAutoPollAfterCurrentTurn=!1,i.autoPollObservedPollingTool=!1,i.autoPollObservedAssistantText=!1,i.autoPollObservedAnyTool=!1;return}if(i.adapterSession.status==="error"){this.recoverTurnFailure(t,i);return}if(i.adapterSession.status==="thinking"||i.adapterSession.status==="tool_using"){this.recoverResolvedTurnWithoutTerminalEvent(t);return}i.adapterSession.status==="waiting_input"&&this.armIdleLoopOrAutoPoll(t)}})}scheduleAutoPoll(t,e=Et){const s=this.sessions.get(t);!s||s.autoPollActive||s.autoPollTimer||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=setTimeout(()=>{const o=this.sessions.get(t);!o||o.autoPollActive||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=void 0,this.submitAutoPollPrompt(t,$t,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}scheduleRequestRetry(t,e){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status)||s.retryActive||s.retryTimer)return;if(!s.lastSubmittedPrompt){s.adapterSession.status="error",this.emit("status-change",t,"error");return}if(s.turnModelRequestSucceeded&&(s.turnModelRequestSucceeded=!1,s.retryAttempt=0),s.lastErrorText&&Dt(s.lastErrorText)){r(`[ACode] scheduleRequestRetry(${e}): non-retryable provider error, giving up retry: ${s.lastErrorText.slice(0,200)}`),this.cancelRequestRetry(s),s.retryAttempt=0,s.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry_aborted",actionLabel:"\u8BF7\u6C42\u65E0\u6548",actionDetail:"Provider \u8FD4\u56DE 4xx \u8BF7\u6C42\u9519\u8BEF\uFF08\u539F\u6837\u91CD\u8BD5\u5FC5\u7136\u5931\u8D25\uFF09\uFF0C\u5DF2\u505C\u6B62\u81EA\u52A8\u91CD\u8BD5\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u914D\u7F6E\u6216\u91CD\u542F\u4F1A\u8BDD\u3002"});return}s.retryAttempt+=1,s.retryActive=!0,this.cancelScheduledAutoPoll(s),s.idlePollLoop?.stop();const o=J[Math.min(s.retryAttempt-1,J.length-1)];s.adapterSession.status="error",this.emit("status-change",t,"error",{actionType:"retry",actionLabel:"\u91CD\u8BD5\u4E2D",actionDetail:`\u7B2C${s.retryAttempt}\u6B21 \xB7 ${Math.round(o/1e3)}s\u540E`}),r(`[ACode] scheduleRequestRetry(${e}): attempt=${s.retryAttempt} delay=${o}ms`),s.retryTimer=setTimeout(()=>{s.retryTimer=void 0,this.retryFailedRequest(t,e)},o)}retryFailedRequest(t,e){const s=this.sessions.get(t);if(!s)return;if(s.retryTimer=void 0,this.isTerminalStatus(s.adapterSession.status)||!s.lastSubmittedPrompt){s.retryActive=!1;return}s.retryActive=!1;const o=s.lastSubmittedPrompt;r(`[ACode] retryFailedRequest(${e}): attempt=${s.retryAttempt} re-submitting...`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking",{usage:s.adapterSession.totalUsage}),this.startSubmitTimeoutDetection(t,s,"retryFailedRequest");try{s.runtime.markSkipNextCompaction?.()}catch{}s.runtime.submit(o,{skipProactiveCompaction:!0,resume:!0}).then(()=>{const a=this.sessions.get(t);!a||a.retryTimer||(this.cancelSubmitTimeoutDetection(a),a.retryAttempt=0,a.retryActive=!1,this.recoverResolvedTurnWithoutTerminalEvent(t))}).catch(a=>{const i=this.sessions.get(t);i&&(this.cancelSubmitTimeoutDetection(i),i.lastErrorText=a instanceof Error?a.message:String(a),this.emitRuntimeErrorEvent(t,a),this.scheduleRequestRetry(t,`retry#${i.retryAttempt+1}`))})}cancelRequestRetry(t){t.retryTimer&&(clearTimeout(t.retryTimer),t.retryTimer=void 0),t.retryActive=!1}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeErrorEvent(t,e){const s=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:s,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(s=>s.role==="assistant").map(s=>s.content).join("");return Math.max(0,Math.round(e.length/4))}recoverTurnFailure(t,e){if(this.isTerminalStatus(e.adapterSession.status))return;if(e.idleToolActiveAt=void 0,e.pendingToolAuthRequests?.size&&e.pendingToolAuthRequests.clear(),e.adapterSession.status==="tool_using"&&e.pendingToolEventData){const o=e.pendingToolEventData;r(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${o.toolName??"unknown"}) \u5173\u95ED\u65F6\u95F4\u7EBF\u6761\u76EE\uFF0C\u907F\u514D\u6C38\u4E45\u5361\u5728\u5DE5\u5177\u6267\u884C\u72B6\u6001`),this.emit("event",{type:"tool_use_end",sessionId:t,timestamp:new Date().toISOString(),data:{...o,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const s=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(s>0){const o=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=s,r(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${o} -> ${s} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}this.cancelScheduledAutoPoll(e),this.scheduleRequestRetry(t,"recoverTurnFailure")}recoverResolvedTurnWithoutTerminalEvent(t){r(`[ACode] \u25B6\uFE0F recoverResolvedTurnWithoutTerminalEvent called for session ${t}`);const e=this.sessions.get(t);if(!e||this.isTerminalStatus(e.adapterSession.status)){r(`[ACode] Skipping recovery: entry=${!!e}, isTerminal=${e?this.isTerminalStatus(e.adapterSession.status):"N/A"}`);return}if(r(`[ACode] Current status: ${e.adapterSession.status}`),e.adapterSession.status!=="thinking"&&e.adapterSession.status!=="tool_using"){r(`[ACode] Skipping recovery: status is ${e.adapterSession.status} (not thinking/tool_using)`);return}console.warn(`[ACode] \u26A0\uFE0F Detected stuck state: ${e.adapterSession.status} after submit resolved! Recovering to waiting_input. If runtime.submit() is still pending (e.g., built-in tool execution not interruptible by abort()), the submitQueue is deadlocked and subsequent auto-poll/user submits will never execute.`),r("[ACode] Recovering to waiting_input..."),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand,a=!!(s&&q(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(this.emit("status-change",t,"waiting_input",a),r(`[ACode] \u2705 Recovery complete, status now: ${e.adapterSession.status}`),r("[ACode] \u25B6\uFE0F Arming idle loop or auto-poll..."),!e.autoPollActive&&e.autoPollObservedAnyTool&&!e.autoPollObservedPollingTool){r(`[ACode] User-message turn called work tools; skipping idle prompt dispatch in recoverResolvedTurnWithoutTerminalEvent (session: ${t})`);return}this.armIdleLoopOrAutoPoll(t),r("[ACode] \u2705 Idle loop armed, recovery process complete")}startSubmitTimeoutDetection(t,e,s){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const o=this.sessions.get(t);if(!o){this.cancelSubmitTimeoutDetection(e);return}const a=o.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(o.autoPollActive&&o.autoPollLastActivityAt&&o.idleToolActiveAt===void 0&&i-o.autoPollLastActivityAt>=Ot){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-o.autoPollLastActivityAt)/1e3)}s (source: ${s}, session: ${t}): submit queued but no runtime events and no active poll_message tool. Forcing recovery (runtime force-settle will unblock submitQueue).`),this.executeWatchdogRecovery(t,o,s,"stuck_autopoll",i-o.autoPollLastActivityAt);return}o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(a==="tool_using"){const l=i-(o.watchdogLastDataFlowTime||i);if(l>=Lt){const p=String(o.pendingToolEventData?.rawToolName??"");if((o.pendingToolAuthRequests?.size??0)>0){const m=o.pendingToolAuthRequests?.size??0;console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but ${m} tool permission request(s) awaiting user decision (session: ${t}), skipping recovery`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(p.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(l/1e3)}s but await_complete is running (session: ${t}, tool: ${p}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(l/1e3)}s (source: ${s}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),o.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(l/1e3)}s): detached tool ${p} to background (session: ${t}); waiting for the real tool_result to continue the turn`),o.watchdogSubmitStartTime=i,o.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,o,s,"tool_using_slow",l);return}o.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const n=i-(o.watchdogSubmitStartTime||i),c=i-(o.watchdogLastDataFlowTime||i);if(z>0&&c>=z){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(c/1e3)}s (source: ${s}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,o,s,"data_flow",c);return}if(Y>0&&n>=Y){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(n/1e3)}s (source: ${s}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,o,s,"submit_timeout",n);return}},xt)}executeWatchdogRecovery(t,e,s,o,a){r(`[ACode] Watchdog (${o}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),r(`[ACode] Watchdog (${o}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${o}) recovery complete. If abort() could not cancel the underlying operation, submitQueue may still be deadlocked.`)}cancelSubmitTimeoutDetection(t){t.watchdogTimer&&(clearInterval(t.watchdogTimer),t.watchdogTimer=void 0),t.watchdogSubmitStartTime=void 0,t.watchdogLastDataFlowTime=void 0}resetDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now(),e.watchdogSubmitStartTime=Date.now()}startDataFlowWatchdog(t,e){e.watchdogLastDataFlowTime=Date.now()}cancelDataFlowWatchdog(t){t.watchdogLastDataFlowTime=Date.now()}formatAiRequestActionDetail(t){const e=`
2
2
 
3
3
  \u8BF7\u6C42\u5934:
4
4
  `,s=`
5
5
 
6
6
  \u8BF7\u6C42\u4F53:
7
- `,a=typeof t.model=="string"?t.model:"",i=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",r=typeof t.requestMethod=="string"?t.requestMethod:"",n=typeof t.stream=="boolean"?t.stream:void 0,c=typeof t.messageCount=="number"?t.messageCount:void 0,u=typeof t.toolCount=="number"?t.toolCount:void 0,m=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",p=[a?`\u6A21\u578B: ${a}`:void 0,i?`\u63A5\u53E3: ${i}`:void 0,r?`\u65B9\u6CD5: ${r}`:void 0,n!==void 0?`\u6D41\u5F0F: ${n?"\u662F":"\u5426"}`:void 0,c!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${c}`:void 0,u!==void 0?`\u53EF\u7528\u5DE5\u5177: ${u}`:void 0,m?`\u6700\u540E\u8BF7\u6C42: ${m}`:void 0].filter(b=>!!b),g=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,f=t.requestHeaders,A=f?Object.entries(f).filter(([b])=>!g.test(b)).map(([b,I])=>`${b}: ${I}`).filter(b=>b.trim().length>0):[],y=p.join(`
8
- `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",S=A.length>0?`${e}${A.join(`
9
- `)}`:"",_=typeof t.requestBody=="string"?t.requestBody:"",T=_.length>6e4?`${_.slice(0,6e4)}
10
- ...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:_,C=T?`${s}${T}`:"";return`${y}${S}${C}`}}export{ne as AcodeSdkAdapter,Rt as isFailedAcodeTurnComplete,Lt as toAcodeEsmImportSpecifier};
7
+ `,a=typeof t.model=="string"?t.model:"",i=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",n=typeof t.requestMethod=="string"?t.requestMethod:"",c=typeof t.stream=="boolean"?t.stream:void 0,l=typeof t.messageCount=="number"?t.messageCount:void 0,p=typeof t.toolCount=="number"?t.toolCount:void 0,m=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",u=[a?`\u6A21\u578B: ${a}`:void 0,i?`\u63A5\u53E3: ${i}`:void 0,n?`\u65B9\u6CD5: ${n}`:void 0,c!==void 0?`\u6D41\u5F0F: ${c?"\u662F":"\u5426"}`:void 0,l!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${l}`:void 0,p!==void 0?`\u53EF\u7528\u5DE5\u5177: ${p}`:void 0,m?`\u6700\u540E\u8BF7\u6C42: ${m}`:void 0].filter(y=>!!y),g=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,f=t.requestHeaders,A=f?Object.entries(f).filter(([y])=>!g.test(y)).map(([y,D])=>`${y}: ${D}`).filter(y=>y.trim().length>0):[],S=u.join(`
8
+ `)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",C=A.length>0?`${e}${A.join(`
9
+ `)}`:"",b=typeof t.requestBody=="string"?t.requestBody:"";let h=b;if(b.length>6e4)try{const y=JSON.parse(b);if(Array.isArray(y.messages)&&y.messages.length>0){const O=y.messages,$=[],M=O.length;M<=5?$.push(...O):($.push(...O.slice(0,2)),$.push({role:"system",content:`[\u4E2D\u95F4 ${M-5} \u6761\u6D88\u606F\u5DF2\u7701\u7565\uFF0C\u5171 ${M} \u6761]`}),$.push(...O.slice(-3))),y.messages=$;const I=JSON.stringify(y,null,2);h=I.length>6e4?`${I.slice(0,6e4)}
10
+ ...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:I}}catch{h=`${b.slice(0,6e4)}
11
+ ...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`}const _=h?`${s}${h}`:"";return`${S}${C}${_}`}}export{pe as AcodeSdkAdapter,Wt as isFailedAcodeTurnComplete,Ut as toAcodeEsmImportSpecifier};
11
12
 
@@ -1,2 +1,2 @@
1
1
 
2
- export declare const MESSAGE_POLLING_IDLE_PROMPT = "\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";
2
+ export declare const MESSAGE_POLLING_IDLE_PROMPT = "\u3010\u7A7A\u95F2\u76D1\u542C\u6307\u4EE4\u3011\u6B64\u6307\u4EE4\u4EC5\u5728\u5F53\u524D\u6CA1\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\u65F6\u751F\u6548\u3002\u82E5\u4F60\u4ECD\u5728\u5904\u7406\u4EFB\u52A1\uFF08\u5305\u62EC\u591A\u8F6E\u5DE5\u5177\u8C03\u7528\u3001\u7B49\u5F85\u5DE5\u5177\u7ED3\u679C\u3001\u9636\u6BB5\u6027\u601D\u8003\u8F93\u51FA\u7B49\uFF09\uFF0C\u8BF7\u5FFD\u7565\u672C\u6307\u4EE4\u5E76\u7EE7\u7EED\u6267\u884C\u4EFB\u52A1\u3002\u4EC5\u5F53\u786E\u8BA4\u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u8FDB\u884C\u4E2D\u6216\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u65F6\uFF0C\u624D\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";
@@ -1,2 +1,2 @@
1
- const s="\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";export{s as MESSAGE_POLLING_IDLE_PROMPT};
1
+ const s="\u3010\u7A7A\u95F2\u76D1\u542C\u6307\u4EE4\u3011\u6B64\u6307\u4EE4\u4EC5\u5728\u5F53\u524D\u6CA1\u6709\u672A\u5B8C\u6210\u4EFB\u52A1\u65F6\u751F\u6548\u3002\u82E5\u4F60\u4ECD\u5728\u5904\u7406\u4EFB\u52A1\uFF08\u5305\u62EC\u591A\u8F6E\u5DE5\u5177\u8C03\u7528\u3001\u7B49\u5F85\u5DE5\u5177\u7ED3\u679C\u3001\u9636\u6BB5\u6027\u601D\u8003\u8F93\u51FA\u7B49\uFF09\uFF0C\u8BF7\u5FFD\u7565\u672C\u6307\u4EE4\u5E76\u7EE7\u7EED\u6267\u884C\u4EFB\u52A1\u3002\u4EC5\u5F53\u786E\u8BA4\u5F53\u524D\u6CA1\u6709\u4EFB\u4F55\u8FDB\u884C\u4E2D\u6216\u672A\u5B8C\u6210\u7684\u4EFB\u52A1\u65F6\uFF0C\u624D\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002";export{s as MESSAGE_POLLING_IDLE_PROMPT};
2
2
 
@@ -334,22 +334,6 @@ export declare abstract class BaseProviderAdapter extends EventEmitter {
334
334
 
335
335
  abstract applyAgentFeatures?(agentId: string): Promise<void>;
336
336
 
337
- abstract setBuiltInCapabilityTools?(agentId: string, capability: string, action: "expand" | "collapse"): Promise<{
338
- sessions: number;
339
- tools: number;
340
- manifests?: Array<{
341
- name: string;
342
- description?: string;
343
- inputSchema?: unknown;
344
- }>;
345
- }>;
346
-
347
- abstract callBuiltInCapabilityTool?(agentId: string, capability: string, toolName: string, args: Record<string, unknown>): Promise<{
348
- ok: boolean;
349
- result?: unknown;
350
- error?: string;
351
- }>;
352
-
353
337
  abstract resetContext?(sessionId: string): Promise<void>;
354
338
 
355
339
  abstract terminateSession(sessionId: string): Promise<void>;
@@ -1,2 +1,2 @@
1
- import{promises as c}from"node:fs";import g from"node:path";import{Router as u}from"express";import{getAcodeDataHome as f}from"../config.js";import{validateToken as p}from"../middleware/auth.js";import{createLogger as m}from"../utils/logger.js";const i=m("acode-todos"),l=u();function A(r){return String(r).replace(/[^a-zA-Z0-9_-]/g,"_")}function y(r){return g.join(f(),"todos",`${A(r)}.json`)}l.get("/acode-todos/:agentId",p,async(r,n)=>{const s=r.params.agentId,e=Array.isArray(s)?s[0]:s;if(!e||!String(e).trim()){n.status(400).json({ok:!1,error:"agentId is required"});return}const d=y(String(e));try{const t=await c.readFile(d,"utf-8"),o=JSON.parse(t),a=Array.isArray(o.todos)?o.todos:[];n.json({ok:!0,agentId:String(e),updatedAt:typeof o.updatedAt=="string"?o.updatedAt:null,background:typeof o.background=="string"?o.background:"",todos:a})}catch(t){if((typeof t=="object"&&t!==null?Reflect.get(t,"code"):void 0)==="ENOENT"){n.json({ok:!0,agentId:String(e),updatedAt:null,todos:[]});return}if(t instanceof SyntaxError){i.warn("[acode-todos] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",d),n.json({ok:!0,agentId:String(e),updatedAt:null,todos:[]});return}const a=t;i.error("[acode-todos] \u8BFB\u53D6\u5931\u8D25: %s",a.message),n.status(500).json({ok:!1,error:a.message})}});export{l as acodeTodosRouter};
1
+ import{promises as c}from"node:fs";import l from"node:path";import{Router as m}from"express";import{getAcodeDataHome as p}from"../config.js";import{validateToken as g}from"../middleware/auth.js";import{createLogger as I}from"../utils/logger.js";const i=I("acode-todos"),u=m();function y(n){return String(n).replace(/[^a-zA-Z0-9_-]/g,"_")}function f(n){return l.join(p(),"todos",`${y(n)}.json`)}u.get("/acode-todos/:agentId",g,async(n,e)=>{const a=n.params.agentId,t=Array.isArray(a)?a[0]:a;if(!t||!String(t).trim()){e.status(400).json({ok:!1,error:"agentId is required"});return}const d=f(String(t));try{const o=await c.readFile(d,"utf-8"),r=JSON.parse(o),s=Array.isArray(r.todos)?r.todos:[];e.json({ok:!0,agentId:String(t),updatedAt:typeof r.updatedAt=="string"?r.updatedAt:null,background:typeof r.background=="string"?r.background:"",todos:s})}catch(o){if((typeof o=="object"&&o!==null?Reflect.get(o,"code"):void 0)==="ENOENT"){e.json({ok:!0,agentId:String(t),updatedAt:null,todos:[]});return}if(o instanceof SyntaxError){i.warn("[acode-todos] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",d),e.json({ok:!0,agentId:String(t),updatedAt:null,todos:[]});return}const s=o;i.error("[acode-todos] \u8BFB\u53D6\u5931\u8D25: %s",s.message),e.status(500).json({ok:!1,error:s.message})}}),u.delete("/acode-todos/:agentId",g,async(n,e)=>{const a=n.params.agentId,t=Array.isArray(a)?a[0]:a;if(!t||!String(t).trim()){e.status(400).json({ok:!1,error:"agentId is required"});return}const d=f(String(t));try{await c.unlink(d),i.info("[acode-todos] \u5DF2\u91CD\u7F6E todo: agentId=%s, file=%s",t,d),e.json({ok:!0,agentId:String(t),removed:!0})}catch(o){if((typeof o=="object"&&o!==null?Reflect.get(o,"code"):void 0)==="ENOENT"){e.json({ok:!0,agentId:String(t),removed:!1});return}const s=o;i.error("[acode-todos] \u91CD\u7F6E\u5931\u8D25: %s",s.message),e.status(500).json({ok:!1,error:s.message})}});export{u as acodeTodosRouter};
2
2
 
@@ -1,2 +1,2 @@
1
- import{randomUUID as m}from"node:crypto";import{promises as i}from"node:fs";import p from"node:os";import n from"node:path";import{Router as l}from"express";import{validateToken as u}from"../middleware/auth.js";import{createLogger as d}from"../utils/logger.js";const s=d("ltr"),w=l(),c=n.join(p.tmpdir(),"aw-temp","LTR"),y=7,f=512*1024;function g(o=new Date){const e=o.getFullYear(),t=String(o.getMonth()+1).padStart(2,"0"),r=String(o.getDate()).padStart(2,"0");return n.join(c,`${e}${t}${r}`)}async function h(){const o=Date.now()-y*24*60*60*1e3;try{const e=await i.readdir(c,{withFileTypes:!0});for(const t of e){if(!t.isDirectory())continue;const r=n.join(c,t.name);try{(await i.stat(r)).mtimeMs<o&&(await i.rm(r,{recursive:!0,force:!0}),s.info(`[ltr] removed expired temp dir: ${r}`))}catch{}}}catch(e){const t=e;t.code!=="ENOENT"&&s.warn("[ltr] cleanup expired dirs failed:",t)}}async function T(o){const e=String(o??"");if(!e.trim())throw new Error("ltr content is empty");const t=Buffer.byteLength(e,"utf8");if(t>f)throw new Error(`ltr content too large: ${t} bytes, max ${f} bytes`);const r=g();await i.mkdir(r,{recursive:!0});const a=n.join(r,`${m()}.txt`);return await i.writeFile(a,e,"utf8"),h(),a}w.post("/upload",u,async(o,e)=>{try{const{content:t}=o.body||{},r=await T(String(t??""));e.json({path:r})}catch(t){const r=t;s.error("[ltr] failed to write temp text file:",r),e.status(400).json({error:r.message})}});export{c as LTR_ROOT,w as ltrRouter};
1
+ import{randomUUID as u}from"node:crypto";import{promises as i}from"node:fs";import p from"node:os";import n from"node:path";import{Router as w}from"express";import{validateToken as f}from"../middleware/auth.js";import{createLogger as y}from"../utils/logger.js";const a=y("ltr"),d=w(),c=n.join(p.tmpdir(),"aw-temp","LTR"),h=7,l=512*1024;function g(o=new Date){const e=o.getFullYear(),r=String(o.getMonth()+1).padStart(2,"0"),t=String(o.getDate()).padStart(2,"0");return n.join(c,`${e}${r}${t}`)}async function T(){const o=Date.now()-h*24*60*60*1e3;try{const e=await i.readdir(c,{withFileTypes:!0});for(const r of e){if(!r.isDirectory())continue;const t=n.join(c,r.name);try{(await i.stat(t)).mtimeMs<o&&(await i.rm(t,{recursive:!0,force:!0}),a.info(`[ltr] removed expired temp dir: ${t}`))}catch{}}}catch(e){const r=e;r.code!=="ENOENT"&&a.warn("[ltr] cleanup expired dirs failed:",r)}}async function j(o){const e=String(o??"");if(!e.trim())throw new Error("ltr content is empty");const r=Buffer.byteLength(e,"utf8");if(r>l)throw new Error(`ltr content too large: ${r} bytes, max ${l} bytes`);const t=g();await i.mkdir(t,{recursive:!0});const s=n.join(t,`${u()}.txt`);return await i.writeFile(s,e,"utf8"),T(),s}d.post("/upload",f,async(o,e)=>{try{const{content:r}=o.body||{},t=await j(String(r??""));e.json({path:t})}catch(r){const t=r;a.error("[ltr] failed to write temp text file:",t),e.status(400).json({error:t.message})}}),d.post("/read",f,async(o,e)=>{try{const{path:r}=o.body||{};if(!r||typeof r!="string"||!r.trim()){e.status(400).json({error:"filePath is required"});return}const t=n.resolve(String(r).trim()),s=n.resolve(c);if(!t.startsWith(s+n.sep)&&t!==s){a.warn("[ltr] read attempted outside LTR root:",t),e.status(403).json({error:"access denied: file is not within LTR temp directory"});return}if(!(await i.stat(t)).isFile()){e.status(400).json({error:"path is not a file"});return}const m=await i.readFile(t,{encoding:"utf8",flag:"r"});e.json({content:m})}catch(r){const t=r;if(t.code==="ENOENT"){e.status(404).json({error:"LTR file not found"});return}a.error("[ltr] failed to read temp text file:",t),e.status(500).json({error:t.message})}});export{c as LTR_ROOT,d as ltrRouter};
2
2
 
@@ -1,91 +1,35 @@
1
1
 
2
2
  export declare const sessionsRouter: import("express-serve-static-core").Router;
3
-
4
- export declare function handleCapabilityToolsRequest(input: {
3
+ export interface HandleCapabilityToolsRequestInput {
5
4
  agentId: string;
6
5
  capability: string;
7
- action: unknown;
8
-
9
- resolveSession?: () => {
6
+ action: string | null | undefined;
7
+ resolveSession: () => {
10
8
  agentId: string;
11
9
  providerId: string;
12
10
  } | undefined;
13
- resolveAdapter?: (providerId: string) => {
14
- setBuiltInCapabilityTools?: (agentId: string, capability: string, action: 'expand' | 'collapse') => Promise<{
15
- sessions: number;
16
- tools: number;
17
- manifests?: Array<{
18
- name: string;
19
- description?: string;
20
- inputSchema?: unknown;
21
- }>;
22
- }>;
23
- };
24
- }): Promise<{
25
- status: 400;
26
- body: {
27
- ok: false;
28
- error: string;
29
- };
30
- } | {
31
- status: 200;
32
- body: {
33
- ok: true;
34
- changed: {
35
- sessions: number;
36
- tools: number;
37
- };
38
- manifests?: Array<{
39
- name: string;
40
- description?: string;
41
- inputSchema?: unknown;
42
- }>;
43
- message?: string;
44
- };
45
- } | {
46
- status: 500;
47
- body: {
48
- ok: false;
49
- error: string;
50
- };
51
- }>;
11
+ resolveAdapter?: (providerId: string) => unknown;
12
+ }
52
13
 
53
- export declare function handleCapabilityToolCallRequest(input: {
14
+ export declare function handleCapabilityToolsRequest(input: HandleCapabilityToolsRequestInput): Promise<{
15
+ status: number;
16
+ body: Record<string, unknown>;
17
+ }>;
18
+ export interface HandleCapabilityToolCallRequestInput {
54
19
  agentId: string;
55
20
  capability: string;
56
21
  tool: string;
57
- args: Record<string, unknown>;
58
-
59
- resolveSession?: () => {
22
+ args?: Record<string, unknown> | null;
23
+ resolveSession: () => {
60
24
  agentId: string;
61
25
  providerId: string;
62
26
  } | undefined;
63
- resolveAdapter?: (providerId: string) => {
64
- callBuiltInCapabilityTool?: (agentId: string, capability: string, toolName: string, args: Record<string, unknown>) => Promise<{
65
- ok: boolean;
66
- result?: unknown;
67
- error?: string;
68
- }>;
69
- };
70
- }): Promise<{
71
- status: 400;
72
- body: {
73
- ok: false;
74
- error: string;
75
- };
76
- } | {
77
- status: 200;
78
- body: {
79
- ok: boolean;
80
- result?: unknown;
81
- error?: string;
82
- };
83
- } | {
84
- status: 500;
85
- body: {
86
- ok: false;
87
- error: string;
88
- };
27
+ resolveAdapter?: (providerId: string) => unknown;
28
+ }
29
+
30
+ export declare function handleCapabilityToolCallRequest(input: HandleCapabilityToolCallRequestInput): Promise<{
31
+ status: number;
32
+ body: Record<string, unknown>;
89
33
  }>;
90
34
 
91
35
  export declare function resolveActiveSdkSessionSnapshotStatus(adapterStatus?: string, currentRuntimeStatus?: string, currentRuntimeActionType?: string): string;
@@ -1,2 +1,2 @@
1
- import{execSync as T}from"node:child_process";import{Router as R}from"express";import{adapterRegistry as y}from"../adapter/index.js";import{validateToken as I,validateTokenOrLoopback as P}from"../middleware/auth.js";import{isProcessRunning as b,findOrphanProcessByAgentId as A,findOrphanProcessByWorkspace as C}from"../services/process-detector.js";import{findPersistedSessionByAgentId as S,loadPersistedSessions as F,removePersistedSession as w}from"../services/terminal-persistence.js";import{createLogger as K}from"../utils/logger.js";import{sdkSessions as m,cleanupSdkSessionByAgentId as E}from"./terminal.js";const u=K("sessions"),h=R();h.post("/sessions/:agentId/notify-force-message",P,(i,t)=>{const e=String(i.params.agentId??"").trim();if(!e){t.status(400).json({ok:!1,error:"agentId is required"});return}const n=Array.from(m.entries()).find(([,c])=>c.agentId===e);if(!n){t.json({ok:!0,notified:!1,message:"No active SDK session for this agentId"});return}const[r,s]=n,o=y.get(s.providerId||"claude-code");if(typeof o.notifyForceMessage=="function"){const c=o.notifyForceMessage(r);t.json({ok:!0,notified:c})}else t.json({ok:!0,notified:!1,message:"Adapter does not support force message notification"})});async function x(i){const t=String(i.agentId??"").trim(),e=String(i.capability??"").trim(),n=i.action==="expand"||i.action==="collapse"?i.action:void 0;if(!t)return{status:400,body:{ok:!1,error:"agentId is required"}};if(e!=="browser"&&e!=="desktop")return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};if(n!=="expand"&&n!=="collapse")return{status:400,body:{ok:!1,error:'action must be "expand" or "collapse"'}};const s=(i.resolveSession??(()=>{const a=Array.from(m.entries()).find(([,d])=>d.agentId===t);return a?{agentId:a[1].agentId,providerId:a[1].providerId}:void 0}))();if(!s)return{status:200,body:{ok:!0,changed:{sessions:0,tools:0},message:"No active SDK session for this agentId"}};const o=i.resolveAdapter??(a=>y.get(a));let c;try{c=o(s.providerId||"claude-code")}catch(a){return{status:500,body:{ok:!1,error:a?.message||"adapter resolution failed"}}}if(typeof c.setBuiltInCapabilityTools!="function")return{status:200,body:{ok:!0,changed:{sessions:0,tools:0},message:"Adapter does not support built-in capability tool switching"}};try{const a=await c.setBuiltInCapabilityTools(t,e,n),{manifests:d,...l}=a;return{status:200,body:{ok:!0,changed:l,...d&&d.length>0?{manifests:d}:{}}}}catch(a){return u.error("[sessions] capability-tools \u6267\u884C\u5931\u8D25",{agentId:t,capability:e,action:n,error:a?.message||String(a)}),{status:500,body:{ok:!1,error:a?.message||"failed"}}}}async function L(i){const t=String(i.agentId??"").trim(),e=String(i.capability??"").trim(),n=String(i.tool??"").trim(),r=i.args&&typeof i.args=="object"&&!Array.isArray(i.args)?i.args:{};if(!t)return{status:400,body:{ok:!1,error:"agentId is required"}};if(e!=="browser"&&e!=="desktop")return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};if(!n)return{status:400,body:{ok:!1,error:"tool is required"}};const o=(i.resolveSession??(()=>{const d=Array.from(m.entries()).find(([,l])=>l.agentId===t);return d?{agentId:d[1].agentId,providerId:d[1].providerId}:void 0}))();if(!o)return{status:200,body:{ok:!1,error:"No active SDK session for this agentId"}};const c=i.resolveAdapter??(d=>y.get(d));let a;try{a=c(o.providerId||"claude-code")}catch(d){return{status:500,body:{ok:!1,error:d?.message||"adapter resolution failed"}}}if(typeof a.callBuiltInCapabilityTool!="function")return{status:200,body:{ok:!1,error:"Adapter does not support built-in capability tool dispatch"}};try{return{status:200,body:await a.callBuiltInCapabilityTool(t,e,n,r)}}catch(d){return u.error("[sessions] capability-tools/call \u6267\u884C\u5931\u8D25",{agentId:t,capability:e,tool:n,error:d?.message||String(d)}),{status:500,body:{ok:!1,error:d?.message||"failed"}}}}h.post("/sessions/:agentId/capability-tools",P,async(i,t)=>{const e=await x({agentId:String(i.params.agentId??""),capability:String(i.body?.capability??""),action:i.body?.action});t.status(e.status).json(e.body)}),h.post("/sessions/:agentId/capability-tools/call",P,async(i,t)=>{const e=await L({agentId:String(i.params.agentId??""),capability:String(i.body?.capability??""),tool:String(i.body?.tool??""),args:i.body?.arguments});t.status(e.status).json(e.body)});function $(i,t,e){const n=String(i||"").trim();if(n){const s=String(t||"").trim(),o=String(e||"").trim().toLowerCase();return n.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&o==="idle"?s:n}return String(t||"").trim()||"running"}h.get("/sessions",I,async(i,t)=>{try{const n=Array.from(m.entries()).map(([a,d])=>{const l=y.get(d.providerId||"claude-code"),p=$(l.getSessionStatus(a),d.currentRuntimeStatus,d.currentRuntimeActionType);return{sessionId:a,agentId:d.agentId,workspacePath:d.workspacePath,status:p,runtimeStatus:p,runtimeActionType:d.currentRuntimeActionType,runtimeActionLabel:d.currentRuntimeActionLabel,runtimeActionDetail:d.currentRuntimeActionDetail,mode:"sdk",startedAt:null}}),r=await F(),s=new Set(n.map(a=>a.sessionId)),o=r.filter(a=>!s.has(a.sessionId)),c={ok:!0,active:n,persisted:o};t.json(c)}catch(e){const n=e;t.status(500).json({error:n.message})}}),h.post("/sessions/recover",I,async(i,t)=>{const{agentId:e,workspacePath:n,command:r}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const s=Array.from(m.entries()).find(([,g])=>g.agentId===e);if(s){const g=y.get(s[1].providerId||"claude-code"),k=$(g.getSessionStatus(s[0]),s[1].currentRuntimeStatus,s[1].currentRuntimeActionType);t.json({ok:!0,sessionId:s[0],agentId:e,workspacePath:s[1].workspacePath,command:s[1].config.command,status:k,runtimeStatus:k,runtimeActionType:s[1].currentRuntimeActionType,runtimeActionLabel:s[1].currentRuntimeActionLabel,runtimeActionDetail:s[1].currentRuntimeActionDetail,mode:"sdk",recovered:!1,message:"SDK session already active"});return}const o=await S(e);let c=!1,a;if(o?.pid&&b(o.pid))c=!0,a=o.pid,u.info(`[Recover] Detected orphan process for agentId=${e}, pid=${o.pid}`);else if(o?.mode==="sdk"||!o?.pid){const g=await A(e);g&&(c=!0,a=g.pid,u.info(`[Recover] Found orphan process by agentId search: agentId=${e}, pid=${g.pid}`))}const d=n||o?.workspacePath,l=r||o?.command||"acode",p=o?.mode||"sdk";if(!d){t.status(400).json({error:"workspacePath is required (not found in persisted session)"});return}if(c&&a){u.info(`[Recover] Returning orphan process info for agentId=${e}`),t.json({ok:!0,sessionId:o?.sessionId||"",agentId:e,workspacePath:d,command:l,status:"orphan_detected",runtimeStatus:o?.runtimeStatus,runtimeActionType:o?.runtimeActionType,runtimeActionLabel:o?.runtimeActionLabel,runtimeActionDetail:o?.runtimeActionDetail,recovered:!1,orphan:{pid:a,message:"Found orphan process still running. Manual intervention may be required."},mode:p});return}await w(o?.sessionId||"");const f={ok:!1,sessionId:o?.sessionId||"",agentId:e,workspacePath:d,command:l,status:"stopped",recovered:!1,message:"No active SDK session found; start a new SDK runtime session instead."};t.json(f)}catch(s){const o=s;u.error("Error:",o),t.status(500).json({error:o.message})}}),h.post("/search-orphan",I,async(i,t)=>{const{agentId:e,workspacePath:n}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const r=Array.from(m.entries()).find(([,p])=>p.agentId===e);let s=!1,o,c;if(r){const[p,f]=r,g=y.get(f.providerId||"claude-code");o=g.getSessionPid?.(p),c=f.config?.command;const k=o?b(o):!1,v=g.getSessionStatus(p),D=v==="completed"||v==="terminated"||v==="error";if(k)s=!0;else if(o&&!k)u.info(`[search-orphan] Cleaning up stale SDK session (process dead): agentId=${e}, sessionId=${p}, pid=${o}`),m.delete(p),await w(p);else if(D){u.info(`[search-orphan] Cleaning up stale in-process SDK session (status=${v}): agentId=${e}, sessionId=${p}`);try{await g.terminateSession(p)}catch(j){u.warn(`[search-orphan] Failed to terminate stale in-process session: ${j}`)}m.delete(p),await w(p)}else{u.info(`[search-orphan] Terminating unreachable in-process SDK session: agentId=${e}, sessionId=${p}, status=${v||"unknown"}`);try{await g.abortCurrentTurn(p).catch(()=>{}),await g.terminateSession(p)}catch(j){u.warn(`[search-orphan] Failed to terminate in-process session: ${j}`)}m.delete(p),await w(p)}}const a=await A(e);if(a){u.info(`[search-orphan] Found orphan process for agentId=${e}, pid=${a.pid}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:a.pid,command:a.command,cwd:a.cwd,startedAt:a.startedAt,message:"Found orphan process. Click terminate to stop it."}});return}if(s&&o){u.info(`[search-orphan] Active session process still running, reporting as terminable orphan: agentId=${e}, pid=${o}`),t.json({ok:!0,agentId:e,hasActiveSession:!0,found:!0,orphan:{pid:o,command:c||"(active SDK session)",message:"Found active SDK session process. Click terminate to stop it."}});return}const d=await S(e);if(d?.pid&&b(d.pid)){u.info(`[search-orphan] Found orphan by persisted PID: agentId=${e}, pid=${d.pid}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:d.pid,command:d.command||"(persisted session)",message:"Found orphan process by persisted PID. Click terminate to stop it."}});return}const l=n||d?.workspacePath;if(l){const p=await C(l);if(p){u.info(`[search-orphan] Found orphan by workspace: agentId=${e}, pid=${p.pid}, workspace=${l}`),t.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:p.pid,command:p.command,message:"Found orphan process by workspace path. Click terminate to stop it."}});return}}u.info(`[search-orphan] No orphan process found for agentId=${e}, hasActiveSession=${!!s}`),t.json({ok:!0,agentId:e,hasActiveSession:!!s,found:!1,orphan:null,message:s?"Agent has active session in runtime-bridge":"No orphan process and no active session found"})}catch(r){const s=r;u.error("[search-orphan] Error:",s),t.status(500).json({error:s.message})}}),h.post("/terminate-orphan",I,async(i,t)=>{const{agentId:e,pid:n}=i.body;if(!e||!n){t.status(400).json({error:"agentId and pid are required"});return}try{const r=Array.from(m.entries()).find(([,c])=>c.agentId===e);if(r){const[c,a]=r,d=y.get(a.providerId||"claude-code");try{await d.terminateSession(c)}catch(l){u.warn(`[terminate-orphan] Failed to terminate SDK session for agentId=${e}:`,l)}m.delete(c),await w(c),u.info(`[terminate-orphan] Cleaned up SDK session for agentId=${e}, sessionId=${c}`)}if(!b(n)){t.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Process already terminated"});return}const s=process.platform;let o=!1;if(s==="win32")try{T(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3}),o=!0}catch(c){u.warn(`[terminate-orphan] taskkill failed for pid=${n}:`,c)}else try{process.kill(n,"SIGTERM"),o=!0}catch(c){u.warn(`[terminate-orphan] kill failed for pid=${n}:`,c)}o?(u.info(`[terminate-orphan] Terminated orphan process for agentId=${e}, pid=${n}`),t.json({ok:!0,agentId:e,pid:n,terminated:!0,message:"Orphan process terminated successfully"})):t.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Failed to terminate process"})}catch(r){const s=r;u.error("[terminate-orphan] Error:",s),t.status(500).json({error:s.message})}}),h.get("/sessions/by-agent/:agentId",I,async(i,t)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){t.status(400).json({error:"agentId is required"});return}try{const r=Array.from(m.entries()).find(([,o])=>o.agentId===n);if(r){const o=y.get(r[1].providerId||"claude-code"),c=o.getSessionPid?.(r[0]),a=$(o.getSessionStatus(r[0]),r[1].currentRuntimeStatus,r[1].currentRuntimeActionType);t.json({ok:!0,sessionId:r[0],agentId:n,workspacePath:r[1].workspacePath,status:a,runtimeStatus:a,isActive:!0,mode:"sdk",pid:c,isManaged:!0,providerId:r[1].providerId});return}const s=await S(n);if(s){const{isProcessRunning:o}=await import("../services/process-detector.js"),c=s.pid?o(s.pid):!1;t.json({ok:!0,sessionId:s.sessionId,agentId:n,workspacePath:s.workspacePath,command:s.command,status:c?"orphan":"stopped",runtimeStatus:s.runtimeStatus,runtimeActionType:s.runtimeActionType,runtimeActionLabel:s.runtimeActionLabel,runtimeActionDetail:s.runtimeActionDetail,startedAt:s.startedAt,isActive:!1,mode:s.mode,pid:s.pid,isManaged:!1,isProcessAlive:c,isOrphan:c});return}t.json({ok:!0,agentId:n,status:"none",isActive:!1,isManaged:!1})}catch(r){const s=r;u.error("[sessions/by-agent] Error:",s),t.status(500).json({error:s.message})}}),h.post("/takeover-session",I,async(i,t)=>{const{agentId:e}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{const n=Array.from(m.entries()).find(([,o])=>o.agentId===e);if(n){t.json({ok:!0,agentId:e,sessionId:n[0],mode:"sdk",status:"running",isActive:!0,recovered:!1,message:"SDK session already active"});return}const r=await S(e);if(!r){t.status(404).json({error:"No persisted session found for this agentId",agentId:e});return}let s=!1;if(r.mode==="sdk"&&(s=!!await A(e),!s&&r.pid&&(s=b(r.pid))),!s){u.info(`[takeover-session] Process not alive for agentId=${e}, mode=${r.mode}`),t.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"Agent process is no longer running"});return}if(u.info(`[takeover-session] Taking over session for agentId=${e}, mode=${r.mode}, pid=${r.pid}`),r.mode==="sdk"){const o=await A(e);o?(u.info(`[takeover-session] Found SDK process for agentId=${e}, pid=${o.pid}`),t.json({ok:!0,agentId:e,sessionId:r.sessionId,mode:"sdk",status:"running",isActive:!0,recovered:!0,pid:o.pid||r.pid,message:"SDK session process found, can be taken over by aws-mcp-server"})):t.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"SDK process not found"})}else t.status(410).json({error:"Session takeover is no longer supported; start a new SDK runtime session.",agentId:e,mode:"sdk"})}catch(n){const r=n;u.error("[takeover-session] Error:",r),t.status(500).json({error:r.message})}}),h.post("/terminate-tree",I,async(i,t)=>{const{agentId:e,sessionId:n}=i.body;if(!e){t.status(400).json({error:"agentId is required"});return}try{let r=n;if(!r){const f=await S(e);if(!f){t.status(404).json({error:"Session not found for this agentId"});return}r=f.sessionId}const s=m.get(r);let o,c;if(s)o=y.get(s.providerId||"claude-code").getSessionPid?.(r),c="sdk";else{const f=await S(e);if(!f?.pid){t.status(404).json({error:"Session PID not found"});return}o=f.pid,c=f.mode||"sdk"}const{terminateProcessTree:a,waitForProcessExit:d}=await import("../services/process-detector.js");if(!o){t.status(404).json({error:"PID not found"});return}const l=await a(o),p=await d(o,5e3);E(e),await import("../services/terminal-persistence.js").then(f=>f.removePersistedSession(r)),u.info(`[terminate-tree] Terminated process tree for agentId=${e}, pid=${o}, mode=${c}, terminated=${l.terminated}, failed=${l.failed}, exited=${p}`),t.json({ok:!0,agentId:e,pid:o,mode:c,terminated:l.terminated,failed:l.failed,exited:p,message:p?`Successfully terminated ${l.terminated} processes`:`Terminated ${l.terminated} processes, but process ${o} still running`})}catch(r){const s=r;u.error("[terminate-tree] Error:",s),t.status(500).json({error:s.message})}}),h.get("/health/:agentId",I,async(i,t)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){t.status(400).json({error:"agentId is required"});return}try{const r=await S(n);if(!r){t.status(404).json({error:"Session not found"});return}const s=m.get(r.sessionId),o=!!s,{checkProcessHealth:c}=await import("../services/process-detector.js"),a={sessionId:r.sessionId,mode:r.mode,workspacePath:r.workspacePath,isManaged:o,isActive:!!s};if(r.pid){const d=await c(r.pid,n);Object.assign(a,d)}else Object.assign(a,{pid:0,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date});t.json({agentId:n,...a})}catch(r){const s=r;u.error("[health] Error:",s),t.status(500).json({error:s.message})}});export{L as handleCapabilityToolCallRequest,x as handleCapabilityToolsRequest,$ as resolveActiveSdkSessionSnapshotStatus,h as sessionsRouter};
1
+ import{execSync as R}from"node:child_process";import{Router as C}from"express";import{adapterRegistry as y}from"../adapter/index.js";import{validateToken as I,validateTokenOrLoopback as P}from"../middleware/auth.js";import{isProcessRunning as A,findOrphanProcessByAgentId as w,findOrphanProcessByWorkspace as F}from"../services/process-detector.js";import{findPersistedSessionByAgentId as S,loadPersistedSessions as E,removePersistedSession as b}from"../services/terminal-persistence.js";import{createLogger as K}from"../utils/logger.js";import{sdkSessions as m,cleanupSdkSessionByAgentId as L}from"./terminal.js";const d=K("sessions"),h=C();h.post("/sessions/:agentId/notify-force-message",P,(i,r)=>{const e=String(i.params.agentId??"").trim();if(!e){r.status(400).json({ok:!1,error:"agentId is required"});return}const n=Array.from(m.entries()).find(([,a])=>a.agentId===e);if(!n){r.json({ok:!0,notified:!1,message:"No active SDK session for this agentId"});return}const[o,s]=n,t=y.get(s.providerId||"claude-code");if(typeof t.notifyForceMessage=="function"){const a=t.notifyForceMessage(o);r.json({ok:!0,notified:a})}else r.json({ok:!0,notified:!1,message:"Adapter does not support force message notification"})}),h.post("/sessions/:agentId/capability-tools",P,async(i,r)=>{const e=String(i.params.agentId??"").trim(),n=()=>{const s=Array.from(m.entries()).find(([,t])=>t.agentId===e);return s?{agentId:e,providerId:s[1].providerId||""}:void 0},o=await x({agentId:e,capability:String(i.body?.capability??""),action:i.body?.action,resolveSession:n,resolveAdapter:s=>y.get(s||"claude-code")});r.status(o.status).json(o.body)}),h.post("/sessions/:agentId/capability-tools/call",P,async(i,r)=>{const e=String(i.params.agentId??"").trim(),n=()=>{const s=Array.from(m.entries()).find(([,t])=>t.agentId===e);return s?{agentId:e,providerId:s[1].providerId||""}:void 0},o=await B({agentId:e,capability:String(i.body?.capability??""),tool:String(i.body?.tool??""),args:i.body?.args??{},resolveSession:n,resolveAdapter:s=>y.get(s||"claude-code")});r.status(o.status).json(o.body)});const D=new Set(["browser","desktop"]);async function x(i){const r=String(i.agentId??"").trim();if(!r)return{status:400,body:{ok:!1,error:"agentId is required"}};const e=String(i.capability??"").trim();if(!D.has(e))return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};const n=i.action;if(n!=="expand"&&n!=="collapse")return{status:400,body:{ok:!1,error:`action must be "expand" or "collapse", got: ${String(n)}`}};const o=i.resolveSession();if(!o)return{status:200,body:{ok:!0,changed:{sessions:0,tools:0}}};const s=i.resolveAdapter?.(o.providerId);if(!s||typeof s.setBuiltInCapabilityTools!="function")return{status:200,body:{ok:!0,changed:{sessions:0,tools:0},message:`Adapter for provider "${o.providerId}" does not support setBuiltInCapabilityTools`}};try{const t=await s.setBuiltInCapabilityTools(r,e,n),a={ok:!0,changed:{sessions:t.sessions,tools:t.tools}};return n==="expand"&&Array.isArray(t.manifests)&&(a.manifests=t.manifests),{status:200,body:a}}catch(t){const a=t instanceof Error?t.message:String(t);return d.error(`capability-tools ${n} failed for agent ${r}: ${a}`),{status:500,body:{ok:!1,error:a}}}}async function B(i){const r=String(i.agentId??"").trim();if(!r)return{status:400,body:{ok:!1,error:"agentId is required"}};const e=String(i.capability??"").trim();if(!D.has(e))return{status:400,body:{ok:!1,error:'capability must be "browser" or "desktop"'}};const n=String(i.tool??"").trim();if(!n)return{status:400,body:{ok:!1,error:"tool is required"}};const o=i.resolveSession();if(!o)return{status:200,body:{ok:!1,error:`No active SDK session for agentId "${r}"`}};const s=i.resolveAdapter?.(o.providerId);if(!s||typeof s.callBuiltInCapabilityTool!="function")return{status:200,body:{ok:!1,error:`Adapter for provider "${o.providerId}" does not support callBuiltInCapabilityTool`}};try{return{status:200,body:await s.callBuiltInCapabilityTool(r,e,n,i.args??{})}}catch(t){const a=t instanceof Error?t.message:String(t);return d.error(`capability-tools/call ${n} failed for agent ${r}: ${a}`),{status:500,body:{ok:!1,error:a}}}}function j(i,r,e){const n=String(i||"").trim();if(n){const s=String(r||"").trim(),t=String(e||"").trim().toLowerCase();return n.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&t==="idle"?s:n}return String(r||"").trim()||"running"}h.get("/sessions",I,async(i,r)=>{try{const n=Array.from(m.entries()).map(([p,u])=>{const l=y.get(u.providerId||"claude-code"),c=j(l.getSessionStatus(p),u.currentRuntimeStatus,u.currentRuntimeActionType);return{sessionId:p,agentId:u.agentId,workspacePath:u.workspacePath,status:c,runtimeStatus:c,runtimeActionType:u.currentRuntimeActionType,runtimeActionLabel:u.currentRuntimeActionLabel,runtimeActionDetail:u.currentRuntimeActionDetail,mode:"sdk",startedAt:null}}),o=await E(),s=new Set(n.map(p=>p.sessionId)),t=o.filter(p=>!s.has(p.sessionId)),a={ok:!0,active:n,persisted:t};r.json(a)}catch(e){const n=e;r.status(500).json({error:n.message})}}),h.post("/sessions/recover",I,async(i,r)=>{const{agentId:e,workspacePath:n,command:o}=i.body;if(!e){r.status(400).json({error:"agentId is required"});return}try{const s=Array.from(m.entries()).find(([,g])=>g.agentId===e);if(s){const g=y.get(s[1].providerId||"claude-code"),k=j(g.getSessionStatus(s[0]),s[1].currentRuntimeStatus,s[1].currentRuntimeActionType);r.json({ok:!0,sessionId:s[0],agentId:e,workspacePath:s[1].workspacePath,command:s[1].config.command,status:k,runtimeStatus:k,runtimeActionType:s[1].currentRuntimeActionType,runtimeActionLabel:s[1].currentRuntimeActionLabel,runtimeActionDetail:s[1].currentRuntimeActionDetail,mode:"sdk",recovered:!1,message:"SDK session already active"});return}const t=await S(e);let a=!1,p;if(t?.pid&&A(t.pid))a=!0,p=t.pid,d.info(`[Recover] Detected orphan process for agentId=${e}, pid=${t.pid}`);else if(t?.mode==="sdk"||!t?.pid){const g=await w(e);g&&(a=!0,p=g.pid,d.info(`[Recover] Found orphan process by agentId search: agentId=${e}, pid=${g.pid}`))}const u=n||t?.workspacePath,l=o||t?.command||"acode",c=t?.mode||"sdk";if(!u){r.status(400).json({error:"workspacePath is required (not found in persisted session)"});return}if(a&&p){d.info(`[Recover] Returning orphan process info for agentId=${e}`),r.json({ok:!0,sessionId:t?.sessionId||"",agentId:e,workspacePath:u,command:l,status:"orphan_detected",runtimeStatus:t?.runtimeStatus,runtimeActionType:t?.runtimeActionType,runtimeActionLabel:t?.runtimeActionLabel,runtimeActionDetail:t?.runtimeActionDetail,recovered:!1,orphan:{pid:p,message:"Found orphan process still running. Manual intervention may be required."},mode:c});return}await b(t?.sessionId||"");const f={ok:!1,sessionId:t?.sessionId||"",agentId:e,workspacePath:u,command:l,status:"stopped",recovered:!1,message:"No active SDK session found; start a new SDK runtime session instead."};r.json(f)}catch(s){const t=s;d.error("Error:",t),r.status(500).json({error:t.message})}}),h.post("/search-orphan",I,async(i,r)=>{const{agentId:e,workspacePath:n}=i.body;if(!e){r.status(400).json({error:"agentId is required"});return}try{const o=Array.from(m.entries()).find(([,c])=>c.agentId===e);let s=!1,t,a;if(o){const[c,f]=o,g=y.get(f.providerId||"claude-code");t=g.getSessionPid?.(c),a=f.config?.command;const k=t?A(t):!1,v=g.getSessionStatus(c),T=v==="completed"||v==="terminated"||v==="error";if(k)s=!0;else if(t&&!k)d.info(`[search-orphan] Cleaning up stale SDK session (process dead): agentId=${e}, sessionId=${c}, pid=${t}`),m.delete(c),await b(c);else if(T){d.info(`[search-orphan] Cleaning up stale in-process SDK session (status=${v}): agentId=${e}, sessionId=${c}`);try{await g.terminateSession(c)}catch($){d.warn(`[search-orphan] Failed to terminate stale in-process session: ${$}`)}m.delete(c),await b(c)}else{d.info(`[search-orphan] Terminating unreachable in-process SDK session: agentId=${e}, sessionId=${c}, status=${v||"unknown"}`);try{await g.abortCurrentTurn(c).catch(()=>{}),await g.terminateSession(c)}catch($){d.warn(`[search-orphan] Failed to terminate in-process session: ${$}`)}m.delete(c),await b(c)}}const p=await w(e);if(p){d.info(`[search-orphan] Found orphan process for agentId=${e}, pid=${p.pid}`),r.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:p.pid,command:p.command,cwd:p.cwd,startedAt:p.startedAt,message:"Found orphan process. Click terminate to stop it."}});return}if(s&&t){d.info(`[search-orphan] Active session process still running, reporting as terminable orphan: agentId=${e}, pid=${t}`),r.json({ok:!0,agentId:e,hasActiveSession:!0,found:!0,orphan:{pid:t,command:a||"(active SDK session)",message:"Found active SDK session process. Click terminate to stop it."}});return}const u=await S(e);if(u?.pid&&A(u.pid)){d.info(`[search-orphan] Found orphan by persisted PID: agentId=${e}, pid=${u.pid}`),r.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:u.pid,command:u.command||"(persisted session)",message:"Found orphan process by persisted PID. Click terminate to stop it."}});return}const l=n||u?.workspacePath;if(l){const c=await F(l);if(c){d.info(`[search-orphan] Found orphan by workspace: agentId=${e}, pid=${c.pid}, workspace=${l}`),r.json({ok:!0,agentId:e,hasActiveSession:s,found:!0,orphan:{pid:c.pid,command:c.command,message:"Found orphan process by workspace path. Click terminate to stop it."}});return}}d.info(`[search-orphan] No orphan process found for agentId=${e}, hasActiveSession=${!!s}`),r.json({ok:!0,agentId:e,hasActiveSession:!!s,found:!1,orphan:null,message:s?"Agent has active session in runtime-bridge":"No orphan process and no active session found"})}catch(o){const s=o;d.error("[search-orphan] Error:",s),r.status(500).json({error:s.message})}}),h.post("/terminate-orphan",I,async(i,r)=>{const{agentId:e,pid:n}=i.body;if(!e||!n){r.status(400).json({error:"agentId and pid are required"});return}try{const o=Array.from(m.entries()).find(([,a])=>a.agentId===e);if(o){const[a,p]=o,u=y.get(p.providerId||"claude-code");try{await u.terminateSession(a)}catch(l){d.warn(`[terminate-orphan] Failed to terminate SDK session for agentId=${e}:`,l)}m.delete(a),await b(a),d.info(`[terminate-orphan] Cleaned up SDK session for agentId=${e}, sessionId=${a}`)}if(!A(n)){r.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Process already terminated"});return}const s=process.platform;let t=!1;if(s==="win32")try{R(`taskkill /PID ${n} /T /F`,{encoding:"utf8",timeout:5e3}),t=!0}catch(a){d.warn(`[terminate-orphan] taskkill failed for pid=${n}:`,a)}else try{process.kill(n,"SIGTERM"),t=!0}catch(a){d.warn(`[terminate-orphan] kill failed for pid=${n}:`,a)}t?(d.info(`[terminate-orphan] Terminated orphan process for agentId=${e}, pid=${n}`),r.json({ok:!0,agentId:e,pid:n,terminated:!0,message:"Orphan process terminated successfully"})):r.json({ok:!0,agentId:e,pid:n,terminated:!1,message:"Failed to terminate process"})}catch(o){const s=o;d.error("[terminate-orphan] Error:",s),r.status(500).json({error:s.message})}}),h.get("/sessions/by-agent/:agentId",I,async(i,r)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){r.status(400).json({error:"agentId is required"});return}try{const o=Array.from(m.entries()).find(([,t])=>t.agentId===n);if(o){const t=y.get(o[1].providerId||"claude-code"),a=t.getSessionPid?.(o[0]),p=j(t.getSessionStatus(o[0]),o[1].currentRuntimeStatus,o[1].currentRuntimeActionType);r.json({ok:!0,sessionId:o[0],agentId:n,workspacePath:o[1].workspacePath,status:p,runtimeStatus:p,isActive:!0,mode:"sdk",pid:a,isManaged:!0,providerId:o[1].providerId});return}const s=await S(n);if(s){const{isProcessRunning:t}=await import("../services/process-detector.js"),a=s.pid?t(s.pid):!1;r.json({ok:!0,sessionId:s.sessionId,agentId:n,workspacePath:s.workspacePath,command:s.command,status:a?"orphan":"stopped",runtimeStatus:s.runtimeStatus,runtimeActionType:s.runtimeActionType,runtimeActionLabel:s.runtimeActionLabel,runtimeActionDetail:s.runtimeActionDetail,startedAt:s.startedAt,isActive:!1,mode:s.mode,pid:s.pid,isManaged:!1,isProcessAlive:a,isOrphan:a});return}r.json({ok:!0,agentId:n,status:"none",isActive:!1,isManaged:!1})}catch(o){const s=o;d.error("[sessions/by-agent] Error:",s),r.status(500).json({error:s.message})}}),h.post("/takeover-session",I,async(i,r)=>{const{agentId:e}=i.body;if(!e){r.status(400).json({error:"agentId is required"});return}try{const n=Array.from(m.entries()).find(([,t])=>t.agentId===e);if(n){r.json({ok:!0,agentId:e,sessionId:n[0],mode:"sdk",status:"running",isActive:!0,recovered:!1,message:"SDK session already active"});return}const o=await S(e);if(!o){r.status(404).json({error:"No persisted session found for this agentId",agentId:e});return}let s=!1;if(o.mode==="sdk"&&(s=!!await w(e),!s&&o.pid&&(s=A(o.pid))),!s){d.info(`[takeover-session] Process not alive for agentId=${e}, mode=${o.mode}`),r.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"Agent process is no longer running"});return}if(d.info(`[takeover-session] Taking over session for agentId=${e}, mode=${o.mode}, pid=${o.pid}`),o.mode==="sdk"){const t=await w(e);t?(d.info(`[takeover-session] Found SDK process for agentId=${e}, pid=${t.pid}`),r.json({ok:!0,agentId:e,sessionId:o.sessionId,mode:"sdk",status:"running",isActive:!0,recovered:!0,pid:t.pid||o.pid,message:"SDK session process found, can be taken over by aws-mcp-server"})):r.json({ok:!1,agentId:e,status:"process_not_alive",isActive:!1,message:"SDK process not found"})}else r.status(410).json({error:"Session takeover is no longer supported; start a new SDK runtime session.",agentId:e,mode:"sdk"})}catch(n){const o=n;d.error("[takeover-session] Error:",o),r.status(500).json({error:o.message})}}),h.post("/terminate-tree",I,async(i,r)=>{const{agentId:e,sessionId:n}=i.body;if(!e){r.status(400).json({error:"agentId is required"});return}try{let o=n;if(!o){const f=await S(e);if(!f){r.status(404).json({error:"Session not found for this agentId"});return}o=f.sessionId}const s=m.get(o);let t,a;if(s)t=y.get(s.providerId||"claude-code").getSessionPid?.(o),a="sdk";else{const f=await S(e);if(!f?.pid){r.status(404).json({error:"Session PID not found"});return}t=f.pid,a=f.mode||"sdk"}const{terminateProcessTree:p,waitForProcessExit:u}=await import("../services/process-detector.js");if(!t){r.status(404).json({error:"PID not found"});return}const l=await p(t),c=await u(t,5e3);L(e),await import("../services/terminal-persistence.js").then(f=>f.removePersistedSession(o)),d.info(`[terminate-tree] Terminated process tree for agentId=${e}, pid=${t}, mode=${a}, terminated=${l.terminated}, failed=${l.failed}, exited=${c}`),r.json({ok:!0,agentId:e,pid:t,mode:a,terminated:l.terminated,failed:l.failed,exited:c,message:c?`Successfully terminated ${l.terminated} processes`:`Terminated ${l.terminated} processes, but process ${t} still running`})}catch(o){const s=o;d.error("[terminate-tree] Error:",s),r.status(500).json({error:s.message})}}),h.get("/health/:agentId",I,async(i,r)=>{const e=i.params.agentId,n=Array.isArray(e)?e[0]:e;if(!n){r.status(400).json({error:"agentId is required"});return}try{const o=await S(n);if(!o){r.status(404).json({error:"Session not found"});return}const s=m.get(o.sessionId),t=!!s,{checkProcessHealth:a}=await import("../services/process-detector.js"),p={sessionId:o.sessionId,mode:o.mode,workspacePath:o.workspacePath,isManaged:t,isActive:!!s};if(o.pid){const u=await a(o.pid,n);Object.assign(p,u)}else Object.assign(p,{pid:0,alive:!1,cpu:0,memoryMB:0,status:"dead",lastUpdate:new Date});r.json({agentId:n,...p})}catch(o){const s=o;d.error("[health] Error:",s),r.status(500).json({error:s.message})}});export{B as handleCapabilityToolCallRequest,x as handleCapabilityToolsRequest,j as resolveActiveSdkSessionSnapshotStatus,h as sessionsRouter};
2
2
 
@@ -52,6 +52,14 @@ export declare function resolveStatusChangeRuntimeState(status: string, actionIn
52
52
  status: string;
53
53
  actionInfo?: RuntimeStatusActionInfo;
54
54
  };
55
+
56
+ export declare function isIdleStatusChangeRetryable(params: {
57
+ status: string;
58
+ actionInfo?: RuntimeStatusActionInfo;
59
+ restoredActionInfo?: RuntimeStatusActionInfo;
60
+ currentRuntimeActionType?: string;
61
+ shouldPreservePrevAction: boolean;
62
+ }): boolean;
55
63
  export declare function buildAcodeCommandOutputPath(agentId: string, now?: Date): string;
56
64
  export declare function countTerminalOutputLines(output: string): number;
57
65
  export declare function formatCommandOutputSpilloverNotice(outputPath: string, lineLimit?: number): string;