aws-runtime-bridge 1.9.125 → 1.9.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/AcodeSdkAdapter.js +4 -4
- package/dist/adapter/OpencodeSdkAdapter.js +2 -2
- package/dist/config.d.ts +8 -2
- package/dist/config.js +3 -1
- package/dist/index.js +1 -1
- package/dist/routes/acode-todos.js +1 -1
- package/dist/routes/background-tasks.js +1 -1
- package/dist/routes/pty.js +3 -3
- package/dist/routes/terminal.js +19 -19
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/cc-switch-sdk.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/package/acode/dist/background-command-store.js +1 -1
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/builtins/commandArtifacts.js +3 -3
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
- package/package/acode/dist/builtins/shellCommandPreparation.js +3 -3
- package/package/acode/dist/paths.d.ts +2 -0
- package/package/acode/dist/paths.js +2 -0
- package/package/acode/dist/runtime.d.ts +2 -0
- package/package/acode/dist/runtime.js +20 -20
- package/package/acode/dist/sub-agent-manager.d.ts +1 -0
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/sub-agent-store.js +3 -3
- package/package/acode/dist/sub-agent-tools.js +27 -31
- package/package/acode/dist/sub-agent-types.d.ts +1 -1
- package/package/acode/dist/todo-store.js +1 -1
- package/package/acode/dist/tool-allocation.d.ts +18 -4
- package/package/acode/dist/tool-allocation.js +1 -1
- package/package/acode/dist/types.d.ts +0 -3
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +72 -0
- package/package/aws-client-agent-mcp/dist/config.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/config.js +1 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +93 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +3 -3
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +24 -6
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts +14 -0
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +1 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +39 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{EventEmitter as Y}from"node:events";import I from"node:path";import X from"node:fs/promises";import{pathToFileURL as V}from"node:url";import{v4 as U}from"uuid";import{getAcodeConfigFile as $,getAcodeSkillsDir as Z,getUserHomeDir as R}from"../config.js";import{getReleasedAcodeEntryPath as tt}from"../services/acode-package.js";import{getInstanceAiConfigDebugLogger as x}from"../utils/instance-ai-config-debug-logger.js";import{redactForLog as v}from"../services/instance-ai-config-service.js";import{subAgentManager as et}from"../services/sub-agent-manager-instance.js";import{agentPtyManager as ot}from"../services/agent-pty-manager.js";import{resolveAcodeProviderConfig as st}from"./instance-ai-config-resolver.js";import{recordAgentFileChange as it}from"../services/workspaceTaskChangeWatcher.js";import{getBrowserTools as F,closeBrowserSession as at,registerListenerWakeHook as nt,unregisterListenerWakeHook as B}from"../services/browser-session-manager.js";import{getDesktopTools as O,getDesktopToolsIfReady as rt}from"../services/desktop-mcp-manager.js";import{BROWSER_FEATURE_KEY as W,DESKTOP_FEATURE_KEY as D,isFeatureEnabled as P}from"../services/instance-features.js";import{isMessagePollingIdleCommand as L,isPollMessageToolDescriptor as ut}from"./acode-tool-names.js";import{IdlePollLoop as lt}from"./idle-poll-loop.js";import{getCanonicalMcpDetail as q,getToolActionInfo as dt}from"./types.js";const ct=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...u){ct&&console.log(...u)}const mt=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){mt&&console.log("[TokenDebug][Adapter]",...u)}const N=["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(" "),pt=5e3;function E(u,t){const e=process.env[u];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const H=E("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),gt=5*6e4,ft=E("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),ht=250,Tt=2e3,K=E("ACODE_SUBMIT_TIMEOUT_MS",12e4),j=3e3,_t="\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";function At(){return I.resolve(tt())}function St(u){return V(I.resolve(u)).href}const Q=128e3,y={"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 kt(u){if(!u)return Q;const t=u.toLowerCase().trim();if(y[t])return y[t].contextLimit;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].contextLimit:Q}const G=4096;function bt(u){if(!u)return G;const t=u.toLowerCase().trim();if(y[t])return y[t].maxOutput;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].maxOutput:G}function Ct(u){if(!u||typeof u!="object")return;const t=u,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=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(s===0&&a===0){const n=h(t.cache_read_input_tokens),r=h(t.cache_creation_input_tokens);n>0||r>0?(s=n,a=r+h(t.input_tokens),i=!0):(s=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(s===0&&a===0){const n=h(t.prompt_tokens_details?.cached_tokens);n>0&&(s=n,a=e>n?e-n:0,i=!0)}return{inputTokens:e,outputTokens:o,...s>0||a>0?{cacheHitTokens:s,cacheMissTokens:a}:{},...i?{hasCache:!0}:{}}}function h(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function J(u){return h(u.estimatedContextTokens,u.contextTokens,u.context_tokens,u.contextUsedTokens,u.context_used_tokens)}function yt(u){return u==="stderr"||u==="mixed"?u:"stdout"}function wt(u){if(!u||typeof u!="object"||Array.isArray(u))return;const t={};for(const[e,o]of Object.entries(u))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function Pt(u){return u.failed===!0}function z(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?q(`${t}__${u.slice(o.length)}`):q(u.replace("/","__"))}function Lt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function $t(u){const t=xt(u);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof u=="string"&&u.trim().length>0}function xt(u){if(u&&typeof u=="object"&&!Array.isArray(u))return u;if(!(typeof u!="string"||!u.trim()))try{const t=JSON.parse(u);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class zt extends Y{constructor(){super(...arguments),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const o=R(),s=e.mcpConfigPath||$(o),{resolved:a,configContextLimit:i,supportsImage:n}=await this.resolveAcodeProvider(e,s),r=a.model,c=i??kt(r),p=bt(r),m={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:c,maxOutput:p,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:m,config:e,runtime:await this.createRuntime(t,r,e,o,a,n),autoPollActive:!1}),this.emit("status-change",t,"starting");const g=this.sessions.get(t);if(!g)throw new Error("ACode session was not initialized");const d=()=>{const f=this.sessions.get(t);f&&this.getIdlePollLoop(f).start()};this.listenerWakeHooks.set(t,d),nt(e.agentId,d);try{await g.runtime.start(),m.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:g.adapterSession.totalUsage}),e.initialPrompt?.trim()?this.startInitialPromptTurn(t,e.initialPrompt):this.armIdleLoopOrAutoPoll(t)}catch(f){m.status="error",this.emitRuntimeErrorEvent(t,f),this.emit("status-change",t,"error");const _=this.sessions.get(t);throw _?.capabilitiesFallbackTimer&&clearTimeout(_.capabilitiesFallbackTimer),this.sessions.delete(t),B(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),f}}async sendMessage(t,e){const o=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 s=this.requireSession(t),a=s.adapterSession.status;l(`[ACode] Previous status: ${a}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop();const i={id:U(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${a} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,s,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const n=Date.now();await s.runtime.submit(e);const r=Date.now()-n;this.cancelSubmitTimeoutDetection(s),l(`[ACode] \u2705 runtime.submit() completed in ${r}ms`),l(`[ACode] Current status after submit: ${s.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${s.adapterSession.status}`);const c=Date.now()-o;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(n){const r=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${r}ms:`,n instanceof Error?n.message:String(n)),this.cancelSubmitTimeoutDetection(s),l("[ACode] \u25B6\uFE0F Calling emitRuntimeError with recover=true..."),this.emitRuntimeError(t,n,{recover:!0}),l(`[ACode] Status after error recovery: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,o.runtime.submitQuestionAnswer&&o.runtime.submitQuestionAnswer(s,e),this.startSubmitTimeoutDetection(t,o,"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 o=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:o.contextLimit,maxOutput:o.maxOutput,inputLimit:o.inputLimit,compactionThreshold:o.compactionThreshold,cacheHitTokens:o.cacheHitTokens,cacheMissTokens:o.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(),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(B(o,this.listenerWakeHooks.get(t)),at(o)),this.listenerWakeHooks.delete(t),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(n=>n.config.agentId===t);if(!e)return;const o=R(),s=e.config.mcpConfigPath||$(o),{resolved:a,supportsImage:i}=await this.resolveAcodeProvider(e.config,s);return a?.model?{model:a.model,supportsImage:i===!0,...a.baseURL?{baseURL:a.baseURL}:{},...a.apiKey?{apiKey:a.apiKey}:{}}:void 0}catch{return}}async applyAgentFeatures(t){if(!t)return;const e=P(t,D),o=P(t,W);for(const[s,a]of this.sessions){if(a.config.agentId!==t)continue;const i=a.runtime;try{if(e){const n=await O(t,await this.resolveAgentAiInfo(t)),r=i.addBuiltInTools?.(n)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} desktop tools hot-added for agent ${t}`)}else{const n=i.removeBuiltInToolsByPrefix?.("desktop_")??0;n>0&&l(`[acode-adapter] session ${s}: ${n} desktop tools hot-removed for agent ${t}`)}}catch(n){l(`[acode-adapter] session ${s}: desktop feature hot-sync failed for agent ${t}:`,n.message)}if(o)try{const n=await F(t,a.config.scopeKey,typeof a.config.browserAllowPrivate=="boolean"?{allowPrivate:a.config.browserAllowPrivate}:void 0),r=i.addBuiltInTools?.(n)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} browser tools hot-added for agent ${t}`)}catch(n){l(`[acode-adapter] session ${s}: browser feature hot-sync failed for agent ${t}:`,n.message)}}this.syncMcpToolsForAgent(t)}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}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 o=this.sessions.get(t);if(o){if(o.idleCommands=e,this.cancelScheduledAutoPoll(o),e.idleInputCommand&&L(e.idleInputCommand)){this.getIdlePollLoop(o).start();return}o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(o).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await X.readFile(t,"utf-8"),o=JSON.parse(e),a=o.provider?.default,i=a?.options,n=h(o.contextLimit),r={},c={},p=a?.models;if(p&&typeof p=="object"){for(const[m,g]of Object.entries(p))if(g&&typeof g=="object"){const d=h(g.contextLimit);d>0&&(r[m.trim()]=d);const f=g.modalities?.input,_=Array.isArray(f)&&f.includes("image")||g.supportsImageInput===!0;c[m.trim()]=_===!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(r).length>0?{modelContextLimits:r}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return x().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${o}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const o=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,s=x();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?v(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}:{},...o?{model:o}:{}},i=await this.loadAcodeProviderSection(e);let n=i.contextLimit;if(!n&&i.modelContextLimits){const c=o||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(n=i.modelContextLimits[c])}const r=st(a,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:v(a),globalConfigModel:i?.model??null,resolvedModel:r.model,resolvedBaseURL:r.baseURL??null,resolvedApiKey:r.apiKey?"[set]":null,configContextLimit:n,resolvedSource:r.source}}),{resolved:r,configPath:e,perSessionModel:o,configContextLimit:n,supportsImage:i.modelImageSupport?.[r.model]===!0}}async createRuntime(t,e,o,s,a,i){const n=await this.loadRuntimeConstructor(),r=o.mcpConfigPath||$(s);let c=[];try{c=await F(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(d){l(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,d.message)}let p=[];if(P(o.agentId??"",W)&&(p=c),o.agentId&&P(o.agentId,D))try{const d=a?.model?{model:a.model,supportsImage:i===!0,...a.baseURL?{baseURL:a.baseURL}:{},...a.apiKey?{apiKey:a.apiKey}:{}}:void 0,f=await O(o.agentId,d);f.length>0&&(p=[...p,...f])}catch(d){l(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,d.message)}const m=new n({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:r,skillsDir:Z(s),model:e,systemPrompt:typeof o.systemPrompt=="string"?o.systemPrompt:void 0,globalPrompt:typeof o.globalPrompt=="string"?o.globalPrompt:void 0,rolePrompt:typeof o.rolePrompt=="string"?o.rolePrompt:void 0,memory:typeof o.memory=="string"?o.memory:void 0,env:o.envOverrides,subAgentManager:et,terminalManager:ot,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:d=>it({...d,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:p,subAgentSuiteTools:c,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return x().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:o.instanceAiConfig?.model||null,perInstanceBaseURL:o.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:o.instanceAiConfig?.apiKey?"[set]":null,configPath:r}}),m.on("event",d=>this.forwardAcodeEvent(d)),m}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!P(t,D))return[];if(e.length===0)return rt();if(!e.some(a=>{const i=a.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return O(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=At(),e=await import(St(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 o=this.sessions.get(t);o&&(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const a=this.sessions.get(t);a&&(this.cancelSubmitTimeoutDetection(a),this.emitRuntimeError(t,s,{recover:!0}))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:U(),sessionId:t.sessionId,role:"assistant",content:o,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:o});return}if(t.type==="thinking_delta"){const o=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:o});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:yt(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 o=J(t.data),s=t.data.lastUsage,a=h(s?.inputTokens),i=h(s?.outputTokens),n=h(s?.cacheHitTokens),r=h(s?.cacheMissTokens),c=!!(s&&(a>0||i>0));let p;if(c&&(a>0&&(e.adapterSession.totalUsage.inputTokens=a),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(s?.cacheHitTokens!==void 0||s?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=n,e.adapterSession.totalUsage.cacheMissTokens=r),p={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(s)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&o>0){const d=e.adapterSession.totalUsage.inputTokens;d>0?e.adapterSession.totalUsage.inputTokens=Math.min(o,Math.floor(d*1.5)):e.adapterSession.totalUsage.inputTokens=o,p={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const g={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};p&&(g.usage=p),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(p??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,g),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:wt(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 o=Ct(t.data.usage);if(o){const a=e.adapterSession.totalUsage.inputTokens,i=a>0&&o.inputTokens<Math.floor(a*.2)&&!o.hasCache;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${a} threshold20pct=${Math.floor(a*.2)} isFallbackUsage=${i}`),i?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens),(o.cacheHitTokens||o.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${o.cacheHitTokens||0}, miss=${o.cacheMissTokens||0})`)),w(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else w(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const s=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),Pt(t.data)){l(`[ACode] Recovering from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&e.autoPollActive){l(`[ACode] Recovering from aborted turn_complete (session: ${t.sessionId}), using R2 2s backoff instead of immediate rearm`),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}),w(`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 o=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",s=Array.isArray(t.data.questions)?t.data.questions:[];o&&(e.pendingQuestionToolCallId=o,e.pendingQuestions=s),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:o||void 0,questions:s});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=>ut(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 A=Array.isArray(t.data.servers)?t.data.servers:[],k=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),b={kind:"mcp",mcpServers:A,mcpTools:k};e.cachedMcpCapabilities=b,e.lastMcpCapabilities=b,e.lastCombinedCapabilities={kind:"combined",mcpServers:A,mcpTools:k,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${A.length} servers, ${k.length} tools`,{sessionId:t.sessionId,servers:A,toolNames:k.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 ${j}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},j);return}const o=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${o}, 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 s=typeof t.data.server=="string"?t.data.server:"mcp",a=typeof t.data.tool=="string"?t.data.tool:"",i=s&&a?`${s}__${a}`:a||s,n=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,r=dt(i,n);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,r.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=Lt(r.actionType)?r.actionDetail||z(void 0,s,a):z(r.actionDetail,s,a),p=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=n?JSON.stringify(n,null,2):void 0,g={toolName:c,rawToolName:i,actionType:r.actionType,actionLabel:r.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...n?{toolInput:n}:{},...p?{toolUseId:p,actionId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...g,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=r.actionType==="idle"&&!$t(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,r.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const _=r.actionType==="idle";this.emit("status-change",t.sessionId,f,_||f==="thinking"?void 0:g);return}const d=r.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=d,r.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),d==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...g}),this.emitProviderEvent(t,"tool_use_start",g),this.emit("status-change",t.sessionId,d,g);return}if(t.type==="skill_status"){const s=(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 g=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:g.map(d=>({name:String(d.name??""),description:typeof d.description=="string"?d.description:void 0,directory:typeof d.directory=="string"?d.directory:void 0})).filter(d=>d.name)}}).filter(m=>m.dir),r=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,p={kind:"combined",mcpServers:r?.mcpServers??[],mcpTools:r?.mcpTools??[],skills:s,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,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(r?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:r?.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 o=J(t.data),s=h(t.data.contextLimit)||void 0,a=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,n=h(t.data.compactionThreshold)||void 0;let r=!1;o>0&&(e.adapterSession.totalUsage.inputTokens=o,e.adapterSession.totalUsage.outputTokens=0,r=!0),s!==void 0&&(e.adapterSession.totalUsage.contextLimit=s,r=!0),a!==void 0&&(e.adapterSession.totalUsage.maxOutput=a,r=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,r=!0),n!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=n,r=!0),r&&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 o=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:o||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:o||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const o=t.data,s=o.action,a=s==="start",i=s==="end",n=s==="phase",r=o.parentId,c=o.compactionId;let p,m;if(a){const d=String(o.sizeKB??o.sizeBeforeKB??"?"),f=String(o.messageCount??o.messageCountBefore??"?"),_=o.estimatedTokens,A=o.actualInputTokens?`input=${o.actualInputTokens}`:"",k=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",b=o.trigger?`, \u89E6\u53D1: ${o.trigger}`:"";p="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",_!==void 0?m=`\u538B\u7F29\u524D: ~${_} tokens, \u6D88\u606F: ${f}\u6761`+(A?`, \u5B9E\u9645 tokens: ${A} ${k}`:"")+b:m=`\u538B\u7F29\u524D: ${d}KB, \u6D88\u606F: ${f}\u6761`+(A?`, \u5B9E\u9645 tokens: ${A} ${k}`:"")+b}else if(n)p=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(o.phaseDetail??"");else{const d=o.tokensBefore,f=o.tokensAfter,_=o.freedTokens,A=String(o.sizeBeforeKB??"?"),k=String(o.sizeAfterKB??"?"),b=String(o.freedKB??"?"),T=String(o.strategy??"?"),C=Number(o.prunedToolMessages??0),S=Number(o.summarizedMessages??0);p="\u538B\u7F29\u5B8C\u6210",d!==void 0&&f!==void 0?m=`\u91CA\u653E: ${_??d-f} tokens, ${d} tokens \u2192 ${f} tokens, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:""):m=`\u91CA\u653E: ${b}KB, ${A}KB \u2192 ${k}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:"")}a&&(e.adapterSession.status="compacting");const g={actionType:"context_compaction",actionLabel:p,actionDetail:m};if(a&&c)g.actionId=c;else if((n||i)&&c)if(g.parentId=c,n){const d=String(o.phase??"unknown");g.actionId=`${c}-phase-${d}`}else g.actionId=`${c}-end`;n&&r&&!g.parentId&&(g.parentId=r),i&&(e.adapterSession.totalUsage.inputTokens=h(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,g.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",g),this.emit("status-change",t.sessionId,"compacting",g);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,o){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:o})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(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 lt({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>L(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:_t,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.submitAutoPollPrompt(e,o)}),t.idlePollLoop}submitAutoPollPrompt(t,e,o){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status))return;const a=(s.autoPollToken??0)+1;s.autoPollToken=a,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeError(t,i)}).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=ht){const o=this.sessions.get(t);!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=setTimeout(()=>{const s=this.sessions.get(t);!s||s.autoPollActive||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=void 0,this.submitAutoPollPrompt(t,N,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeError(t,e,o){const s=this.sessions.get(t);s&&(s.adapterSession.status="error",this.emitRuntimeErrorEvent(t,e),this.emit("status-change",t,"error"),o?.recover&&this.recoverTurnFailure(t,s))}emitRuntimeErrorEvent(t,e){const o=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:o,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(o=>o.role==="assistant").map(o=>o.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.adapterSession.status==="tool_using"&&e.pendingToolEventData){const n=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${n.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:{...n,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const o=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(o>0){const n=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${n} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}const s=e.idleCommands?.idleInputCommand,i=!!(s&&L(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(e.autoPollTimer||e.failedTurnRecoveryScheduled){e.adapterSession.status!=="waiting_input"&&(e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}));return}this.cancelScheduledAutoPoll(e),e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}),e.failedTurnRecoveryScheduled=!0,e.autoPollTimer=setTimeout(()=>{const n=this.sessions.get(t);if(!n||n.autoPollActive||this.isTerminalStatus(n.adapterSession.status)){n&&(n.failedTurnRecoveryScheduled=!1);return}n.autoPollTimer=void 0,n.failedTurnRecoveryScheduled=!1,n.idleCommands?.idleInputCommand?this.getIdlePollLoop(n).start():this.submitAutoPollPrompt(t,N,{keepWaitingStatus:!0})},Tt)}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 o=e.idleCommands?.idleInputCommand,a=!!(o&&L(o))?{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,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const a=s.adapterSession.status,i=Date.now();if(a==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&s.idleToolActiveAt===void 0&&i-s.autoPollLastActivityAt>=ft){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-s.autoPollLastActivityAt)/1e3)}s (source: ${o}, 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,s,o,"stuck_autopoll",i-s.autoPollLastActivityAt);return}s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(a==="tool_using"){const c=i-(s.watchdogLastDataFlowTime||i);if(c>=gt){const p=String(s.pendingToolEventData?.rawToolName??"");if(p.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${p}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${o}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),s.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${p} to background (session: ${t}); waiting for the real tool_result to continue the turn`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,s,o,"tool_using_slow",c);return}s.watchdogSubmitStartTime=i;return}if(a!=="thinking")return;const n=i-(s.watchdogSubmitStartTime||i),r=i-(s.watchdogLastDataFlowTime||i);if(H>0&&r>=H){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(r/1e3)}s (source: ${o}, session: ${t}, status: ${a}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",r);return}if(K>0&&n>=K){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(n/1e3)}s (source: ${o}, session: ${t}, status: ${a}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",n);return}},pt)}executeWatchdogRecovery(t,e,o,s,a){l(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(a/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}) 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 z}from"node:events";import I from"node:path";import Y from"node:fs/promises";import{pathToFileURL as X}from"node:url";import{v4 as U}from"uuid";import{getAcodeConfigFile as $,getAcodeSkillsDir as V}from"../config.js";import{getReleasedAcodeEntryPath as Z}from"../services/acode-package.js";import{getInstanceAiConfigDebugLogger as x}from"../utils/instance-ai-config-debug-logger.js";import{redactForLog as R}from"../services/instance-ai-config-service.js";import{subAgentManager as tt}from"../services/sub-agent-manager-instance.js";import{agentPtyManager as et}from"../services/agent-pty-manager.js";import{resolveAcodeProviderConfig as ot}from"./instance-ai-config-resolver.js";import{recordAgentFileChange as st}from"../services/workspaceTaskChangeWatcher.js";import{getBrowserTools as v,closeBrowserSession as it,registerListenerWakeHook as at,unregisterListenerWakeHook as F}from"../services/browser-session-manager.js";import{getDesktopTools as O,getDesktopToolsIfReady as nt}from"../services/desktop-mcp-manager.js";import{BROWSER_FEATURE_KEY as B,DESKTOP_FEATURE_KEY as E,isFeatureEnabled as P}from"../services/instance-features.js";import{isMessagePollingIdleCommand as L,isPollMessageToolDescriptor as rt}from"./acode-tool-names.js";import{IdlePollLoop as ut}from"./idle-poll-loop.js";import{getCanonicalMcpDetail as W,getToolActionInfo as lt}from"./types.js";const dt=process.env.ACODE_COMPACTION_DEBUG==="1";function l(...u){dt&&console.log(...u)}const ct=process.env.ACODE_TOKEN_DEBUG==="1";function w(...u){ct&&console.log("[TokenDebug][Adapter]",...u)}const q=["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(" "),mt=5e3;function D(u,t){const e=process.env[u];if(e===void 0||e.trim()==="")return t;const o=Number(e.trim());return Number.isFinite(o)&&o>=0?Math.floor(o):t}const N=D("ACODE_DATA_FLOW_WATCHDOG_MS",12e4),pt=5*6e4,gt=D("ACODE_STUCK_AUTOPOLL_TIMEOUT_MS",5*6e4),ft=250,ht=2e3,H=D("ACODE_SUBMIT_TIMEOUT_MS",12e4),K=3e3,Tt="\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";function _t(){return I.resolve(Z())}function At(u){return X(I.resolve(u)).href}const j=128e3,y={"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 St(u){if(!u)return j;const t=u.toLowerCase().trim();if(y[t])return y[t].contextLimit;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].contextLimit:j}const Q=4096;function kt(u){if(!u)return Q;const t=u.toLowerCase().trim();if(y[t])return y[t].maxOutput;const e=Object.keys(y).filter(o=>t.startsWith(o)).sort((o,s)=>s.length-o.length);return e.length>0?y[e[0]].maxOutput:Q}function bt(u){if(!u||typeof u!="object")return;const t=u,e=h(t.inputTokens,t.input_tokens,t.promptTokens,t.prompt_tokens),o=h(t.outputTokens,t.output_tokens,t.completionTokens,t.completion_tokens);if(e===0&&o===0)return;let s=h(t.cacheHitTokens,t.promptCacheHitTokens,t.prompt_cache_hit_tokens),n=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(s===0&&n===0){const a=h(t.cache_read_input_tokens),r=h(t.cache_creation_input_tokens);a>0||r>0?(s=a,n=r+h(t.input_tokens),i=!0):(s=h(t.cache_hit_tokens),n=h(t.cache_miss_tokens),i=i||t.cache_hit_tokens!==void 0||t.cache_miss_tokens!==void 0)}if(s===0&&n===0){const a=h(t.prompt_tokens_details?.cached_tokens);a>0&&(s=a,n=e>a?e-a:0,i=!0)}return{inputTokens:e,outputTokens:o,...s>0||n>0?{cacheHitTokens:s,cacheMissTokens:n}:{},...i?{hasCache:!0}:{}}}function h(...u){for(const t of u){const e=Number(t);if(Number.isFinite(e)&&e>0)return e}return 0}function G(u){return h(u.estimatedContextTokens,u.contextTokens,u.context_tokens,u.contextUsedTokens,u.context_used_tokens)}function Ct(u){return u==="stderr"||u==="mixed"?u:"stdout"}function yt(u){if(!u||typeof u!="object"||Array.isArray(u))return;const t={};for(const[e,o]of Object.entries(u))typeof o=="string"&&(t[e]=o);return Object.keys(t).length>0?t:void 0}function wt(u){return u.failed===!0}function J(u,t,e){if(!u)return e?`${t}/${e}`:t;const o=`${t}__`;return u.startsWith(o)?W(`${t}__${u.slice(o.length)}`):W(u.replace("/","__"))}function Pt(u){return u==="read_file"||u==="edit_file"||u==="write_file"||u==="bash"}function Lt(u){const t=$t(u);return t?[t.directMessages,t.groupMessages,t.messages].some(e=>Array.isArray(e)&&e.length>0):typeof u=="string"&&u.trim().length>0}function $t(u){if(u&&typeof u=="object"&&!Array.isArray(u))return u;if(!(typeof u!="string"||!u.trim()))try{const t=JSON.parse(u);return t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}catch{return}}class Jt extends z{constructor(){super(...arguments),this.providerId="acode",this.displayName="ACode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const o=e.mcpConfigPath||$(),{resolved:s,configContextLimit:n,supportsImage:i}=await this.resolveAcodeProvider(e,o),a=s.model,r=n??St(a),c=kt(a),p={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0,contextLimit:r,maxOutput:c,cacheHitTokens:0,cacheMissTokens:0}};this.sessions.set(t,{adapterSession:p,config:e,runtime:await this.createRuntime(t,a,e,s,i),autoPollActive:!1}),this.emit("status-change",t,"starting");const m=this.sessions.get(t);if(!m)throw new Error("ACode session was not initialized");const d=()=>{const g=this.sessions.get(t);g&&this.getIdlePollLoop(g).start()};this.listenerWakeHooks.set(t,d),at(e.agentId,d);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),F(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),g}}async sendMessage(t,e){const o=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 s=this.requireSession(t),n=s.adapterSession.status;l(`[ACode] Previous status: ${n}`),this.cancelScheduledAutoPoll(s),s.failedTurnRecoveryScheduled=!1,s.idlePollLoop?.stop();const i={id:U(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};s.adapterSession.messages.push(i),this.emit("conversation-message",t,i),l(`[ACode] Changing status: ${n} \u2192 thinking`),s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,s,"sendMessage");try{l("[ACode] \u25B6\uFE0F Calling runtime.submit()...");const a=Date.now();await s.runtime.submit(e);const r=Date.now()-a;this.cancelSubmitTimeoutDetection(s),l(`[ACode] \u2705 runtime.submit() completed in ${r}ms`),l(`[ACode] Current status after submit: ${s.adapterSession.status}`),l("[ACode] \u25B6\uFE0F Calling recoverResolvedTurnWithoutTerminalEvent()..."),this.recoverResolvedTurnWithoutTerminalEvent(t),l(`[ACode] Status after recovery: ${s.adapterSession.status}`);const c=Date.now()-o;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(a){const r=Date.now()-o;console.error(`[ACode] \u274C sendMessage FAILED after ${r}ms:`,a instanceof Error?a.message:String(a)),this.cancelSubmitTimeoutDetection(s),l("[ACode] \u25B6\uFE0F Calling emitRuntimeError with recover=true..."),this.emitRuntimeError(t,a,{recover:!0}),l(`[ACode] Status after error recovery: ${s.adapterSession.status}`)}}async sendConfirmation(t,e){}async sendQuestionAnswer(t,e){const o=this.sessions.get(t);if(!o)return;const s=o.pendingQuestionToolCallId;if(!s){l(`[AcodeSdkAdapter] sendQuestionAnswer: no pending question for session ${t}`);return}o.pendingQuestionToolCallId=void 0,o.pendingQuestions=void 0,o.runtime.submitQuestionAnswer&&o.runtime.submitQuestionAnswer(s,e),this.startSubmitTimeoutDetection(t,o,"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 o=e.adapterSession.totalUsage;if(e.adapterSession.totalUsage={inputTokens:0,outputTokens:0,contextLimit:o.contextLimit,maxOutput:o.maxOutput,inputLimit:o.inputLimit,compactionThreshold:o.compactionThreshold,cacheHitTokens:o.cacheHitTokens,cacheMissTokens:o.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(),e.capabilitiesFallbackTimer&&(clearTimeout(e.capabilitiesFallbackTimer),e.capabilitiesFallbackTimer=void 0),await e.runtime.stop();const o=e.config.agentId;o&&(F(o,this.listenerWakeHooks.get(t)),it(o)),this.listenerWakeHooks.delete(t),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 o=e.config.mcpConfigPath||$(),{resolved:s,supportsImage:n}=await this.resolveAcodeProvider(e.config,o);return s?.model?{model:s.model,supportsImage:n===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0}catch{return}}async applyAgentFeatures(t){if(!t)return;const e=P(t,E),o=P(t,B);for(const[s,n]of this.sessions){if(n.config.agentId!==t)continue;const i=n.runtime;try{if(e){const a=await O(t,await this.resolveAgentAiInfo(t)),r=i.addBuiltInTools?.(a)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} desktop tools hot-added for agent ${t}`)}else{const a=i.removeBuiltInToolsByPrefix?.("desktop_")??0;a>0&&l(`[acode-adapter] session ${s}: ${a} desktop tools hot-removed for agent ${t}`)}}catch(a){l(`[acode-adapter] session ${s}: desktop feature hot-sync failed for agent ${t}:`,a.message)}if(o)try{const a=await v(t,n.config.scopeKey,typeof n.config.browserAllowPrivate=="boolean"?{allowPrivate:n.config.browserAllowPrivate}:void 0),r=i.addBuiltInTools?.(a)??0;r>0&&l(`[acode-adapter] session ${s}: ${r} browser tools hot-added for agent ${t}`)}catch(a){l(`[acode-adapter] session ${s}: browser feature hot-sync failed for agent ${t}:`,a.message)}}this.syncMcpToolsForAgent(t)}syncMcpToolsForAgent(t){if(t){for(const[e,o]of this.sessions)if(o.config.agentId===t)try{o.runtime.requestMcpToolsRefresh?.()}catch(s){l(`[acode-adapter] session ${e}: mcp tools refresh failed for agent ${t}:`,s.message)}}}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 o=this.sessions.get(t);if(o){if(o.idleCommands=e,this.cancelScheduledAutoPoll(o),e.idleInputCommand&&L(e.idleInputCommand)){this.getIdlePollLoop(o).start();return}o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.getIdlePollLoop(o).start()}}setRuntimeConstructorForTest(t){this.runtimeConstructor=t}async loadAcodeProviderSection(t){try{const e=await Y.readFile(t,"utf-8"),o=JSON.parse(e),n=o.provider?.default,i=n?.options,a=h(o.contextLimit),r={},c={},p=n?.models;if(p&&typeof p=="object"){for(const[m,d]of Object.entries(p))if(d&&typeof d=="object"){const g=h(d.contextLimit);g>0&&(r[m.trim()]=g);const f=d.modalities?.input,A=Array.isArray(f)&&f.includes("image")||d.supportsImageInput===!0;c[m.trim()]=A===!0}}return{...n?.model?{model:n.model}:{},...i?.baseURL||i?.baseUrl?{baseURL:i?.baseURL||i?.baseUrl}:{},...i?.apiKey?{apiKey:i.apiKey}:{},...a>0?{contextLimit:a}:{},...Object.keys(r).length>0?{modelContextLimits:r}:{},...Object.keys(c).length>0?{modelImageSupport:c}:{}}}catch(e){const o=e instanceof Error?e.message:String(e);return x().log({level:"warn",category:"load",message:`loadAcodeProviderSection failed: ${t}: ${o}`,source:"bridge"}),{}}}async resolveAcodeProvider(t,e){const o=typeof t.model=="string"&&t.model.trim()?t.model.trim():void 0,s=x();s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u8F93\u5165",source:"bridge",details:{configModel:t.model??null,configInstanceAiConfig:t.instanceAiConfig?R(t.instanceAiConfig):null,configPath:e}});const n={...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}:{},...o?{model:o}:{}},i=await this.loadAcodeProviderSection(e);let a=i.contextLimit;if(!a&&i.modelContextLimits){const c=o||t.instanceAiConfig?.model||i.model;c&&i.modelContextLimits[c]&&(a=i.modelContextLimits[c])}const r=ot(n,i,"acode-default");return s.log({level:"info",category:"resolve",message:"resolveAcodeProvider \u89E3\u6790\u7ED3\u679C",source:"bridge",details:{instanceConfig:R(n),globalConfigModel:i?.model??null,resolvedModel:r.model,resolvedBaseURL:r.baseURL??null,resolvedApiKey:r.apiKey?"[set]":null,configContextLimit:a,resolvedSource:r.source}}),{resolved:r,configPath:e,perSessionModel:o,configContextLimit:a,supportsImage:i.modelImageSupport?.[r.model]===!0}}async createRuntime(t,e,o,s,n){const i=await this.loadRuntimeConstructor(),a=o.mcpConfigPath||$();let r=[];try{r=await v(o.agentId,o.scopeKey,typeof o.browserAllowPrivate=="boolean"?{allowPrivate:o.browserAllowPrivate}:void 0)}catch(d){l(`[acode-adapter] browser tools injection skipped for agent ${o.agentId}:`,d.message)}let c=[];if(P(o.agentId??"",B)&&(c=r),o.agentId&&P(o.agentId,E))try{const d=s?.model?{model:s.model,supportsImage:n===!0,...s.baseURL?{baseURL:s.baseURL}:{},...s.apiKey?{apiKey:s.apiKey}:{}}:void 0,g=await O(o.agentId,d);g.length>0&&(c=[...c,...g])}catch(d){l(`[acode-adapter] desktop tools injection skipped for agent ${o.agentId}:`,d.message)}const p=new i({sessionId:t,agentId:o.agentId,workingDirectory:o.workingDirectory,configPath:a,skillsDir:V(),model:e,systemPrompt:typeof o.systemPrompt=="string"?o.systemPrompt:void 0,globalPrompt:typeof o.globalPrompt=="string"?o.globalPrompt:void 0,rolePrompt:typeof o.rolePrompt=="string"?o.rolePrompt:void 0,memory:typeof o.memory=="string"?o.memory:void 0,env:o.envOverrides,subAgentManager:tt,terminalManager:et,...o.subAgentModel?{subAgentModel:o.subAgentModel}:{},...o.subAgentEffort?{subAgentEffort:o.subAgentEffort}:{},...o.instanceAiConfig?.effort?{effort:o.instanceAiConfig.effort}:{},onFileChange:d=>st({...d,agentId:o.agentId,workspacePath:o.workingDirectory}),extraBuiltInTools:c,subAgentSuiteTools:r,subAgentSuiteToolProvider:this.buildSubAgentSuiteToolProvider(o.agentId)});return x().log({level:"info",category:"resolve",message:"ACode provider resolved",source:"bridge",sessionId:t,details:{resolvedModel:e,perInstanceModel:o.instanceAiConfig?.model||null,perInstanceBaseURL:o.instanceAiConfig?.baseURL?"[set]":null,perInstanceApiKey:o.instanceAiConfig?.apiKey?"[set]":null,configPath:a}}),p.on("event",d=>this.forwardAcodeEvent(d)),p}buildSubAgentSuiteToolProvider(t){return async e=>{if(!t)return[];if(!P(t,E))return[];if(e.length===0)return nt();if(!e.some(n=>{const i=n.trim().replace(/[.*]+$/,"");return i==="desktop"||i.startsWith("desktop.")}))return[];const s=await this.resolveAgentAiInfo(t);return O(t,s)}}async loadRuntimeConstructor(){if(this.runtimeConstructor)return this.runtimeConstructor;const t=_t(),e=await import(At(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 o=this.sessions.get(t);o&&(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.startSubmitTimeoutDetection(t,o,"startInitialPromptTurn"),o.runtime.submit(e).then(()=>{this.cancelSubmitTimeoutDetection(o),this.recoverResolvedTurnWithoutTerminalEvent(t)}).catch(s=>{const n=this.sessions.get(t);n&&(this.cancelSubmitTimeoutDetection(n),this.emitRuntimeError(t,s,{recover:!0}))}))}forwardAcodeEvent(t){const e=this.sessions.get(t.sessionId);if(e){if(e.autoPollActive&&(e.autoPollLastActivityAt=Date.now()),t.type==="assistant_delta"){const o=typeof t.data.text=="string"?t.data.text:"";e.autoPollActive&&(e.autoPollObservedAssistantText=!0),e.adapterSession.messages.push({id:U(),sessionId:t.sessionId,role:"assistant",content:o,timestamp:t.timestamp}),this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"text_delta",{text:o});return}if(t.type==="thinking_delta"){const o=typeof t.data.text=="string"?t.data.text:"";this.resetDataFlowWatchdog(t.sessionId,e),this.emitProviderEvent(t,"thinking",{text:o});return}if(t.type==="command_output"){this.emitProviderEvent(t,"command_output",{text:typeof t.data.text=="string"?t.data.text:"",stream:Ct(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 o=G(t.data),s=t.data.lastUsage,n=h(s?.inputTokens),i=h(s?.outputTokens),a=h(s?.cacheHitTokens),r=h(s?.cacheMissTokens),c=!!(s&&(n>0||i>0));let p;if(c&&(n>0&&(e.adapterSession.totalUsage.inputTokens=n),i>0&&(e.adapterSession.totalUsage.outputTokens=i),(s?.cacheHitTokens!==void 0||s?.cacheMissTokens!==void 0)&&(e.adapterSession.totalUsage.cacheHitTokens=a,e.adapterSession.totalUsage.cacheMissTokens=r),p={...e.adapterSession.totalUsage},w(`ai_request lastUsage applied: ${JSON.stringify(s)} -> totalUsage=${JSON.stringify(e.adapterSession.totalUsage)}`)),!c&&o>0){const g=e.adapterSession.totalUsage.inputTokens;g>0?e.adapterSession.totalUsage.inputTokens=Math.min(o,Math.floor(g*1.5)):e.adapterSession.totalUsage.inputTokens=o,p={...e.adapterSession.totalUsage}}e.adapterSession.status==="compacting"&&(e.adapterSession.status="thinking"),e.adapterSession.status==="waiting_input"&&(e.adapterSession.status="thinking");const d={actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:this.formatAiRequestActionDetail(t.data)};p&&(d.usage=p),w(`ai_request handled: estimatedContextTokens=${t.data.estimatedContextTokens??"n/a"} totalUsage=${JSON.stringify(e.adapterSession.totalUsage)} displayUsage=${JSON.stringify(p??null)}`),this.emit("status-change",t.sessionId,e.adapterSession.status,d),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:yt(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 o=bt(t.data.usage);if(o){const n=e.adapterSession.totalUsage.inputTokens,i=n>0&&o.inputTokens<Math.floor(n*.2)&&!o.hasCache;w(`turn_complete usage: raw=${JSON.stringify(t.data.usage)} parsed=${JSON.stringify(o)} currentInput=${n} threshold20pct=${Math.floor(n*.2)} isFallbackUsage=${i}`),i?o.outputTokens>0&&(e.adapterSession.totalUsage.outputTokens=o.outputTokens):(e.adapterSession.totalUsage.inputTokens=o.inputTokens,e.adapterSession.totalUsage.outputTokens=o.outputTokens),(o.cacheHitTokens||o.cacheMissTokens)&&(e.adapterSession.totalUsage.cacheHitTokens=o.cacheHitTokens,e.adapterSession.totalUsage.cacheMissTokens=o.cacheMissTokens,l(`[ACode] \u{1F4B0} Cache usage (overwrite from runtime cumulative): hit=${e.adapterSession.totalUsage.cacheHitTokens}, miss=${e.adapterSession.totalUsage.cacheMissTokens} (turn delta: hit=${o.cacheHitTokens||0}, miss=${o.cacheMissTokens||0})`)),w(`totalUsage after turn_complete: ${JSON.stringify(e.adapterSession.totalUsage)}`)}else w(`turn_complete has NO parseable usage: raw=${JSON.stringify(t.data.usage)} failed=${t.data.failed===!0} aborted=${t.data.aborted===!0}`);const s=e.adapterSession.status;if(l(`[ACode] turn_complete event received (session: ${t.sessionId}), previous status: ${s}, failed: ${t.data.failed===!0}, aborted: ${t.data.aborted===!0}`),wt(t.data)){l(`[ACode] Recovering from failed turn_complete (session: ${t.sessionId})`),this.cancelDataFlowWatchdog(e),this.recoverTurnFailure(t.sessionId,e);return}if(t.data.aborted===!0&&e.autoPollActive){l(`[ACode] Recovering from aborted turn_complete (session: ${t.sessionId}), using R2 2s backoff instead of immediate rearm`),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}),w(`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 o=typeof t.data.toolCallId=="string"?t.data.toolCallId:"",s=Array.isArray(t.data.questions)?t.data.questions:[];o&&(e.pendingQuestionToolCallId=o,e.pendingQuestions=s),this.emit("ask-user-question",{sessionId:t.sessionId,toolCallId:o||void 0,questions:s});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=>rt(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 _=Array.isArray(t.data.servers)?t.data.servers:[],k=f.map(T=>({name:String(T.name??""),source:String(T.source??""),description:String(T.description??"")})).filter(T=>T.name),b={kind:"mcp",mcpServers:_,mcpTools:k};e.cachedMcpCapabilities=b,e.lastMcpCapabilities=b,e.lastCombinedCapabilities={kind:"combined",mcpServers:_,mcpTools:k,skills:e.lastCombinedCapabilities?.skills??[],skillsDir:e.lastCombinedCapabilities?.skillsDir,skillGroups:e.lastCombinedCapabilities?.skillGroups??[]},l(`[cap-diag] MCP capabilities cached: ${_.length} servers, ${k.length} tools`,{sessionId:t.sessionId,servers:_,toolNames:k.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 ${K}ms)`,{sessionId:t.sessionId,mcpServers:T.mcpServers,mcpToolsCount:T.mcpTools?.length??0}),e.cachedMcpCapabilities=void 0,e.capabilitiesFallbackTimer=void 0},K);return}const o=String(t.data.action??"");l(`[ACode] \u{1F4E1} mcp_status event: action=${o}, 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 s=typeof t.data.server=="string"?t.data.server:"mcp",n=typeof t.data.tool=="string"?t.data.tool:"",i=s&&n?`${s}__${n}`:n||s,a=t.data.arguments&&typeof t.data.arguments=="object"&&!Array.isArray(t.data.arguments)?t.data.arguments:void 0,r=lt(i,a);e.autoPollActive&&(e.autoPollObservedAnyTool=!0,r.actionType==="idle"&&(e.autoPollObservedPollingTool=!0));const c=Pt(r.actionType)?r.actionDetail||J(void 0,s,n):J(r.actionDetail,s,n),p=typeof t.data.toolUseId=="string"?t.data.toolUseId:void 0,m=a?JSON.stringify(a,null,2):void 0,d={toolName:c,rawToolName:i,actionType:r.actionType,actionLabel:r.actionLabel,actionDetail:c,...m?{actionInput:m}:{},...a?{toolInput:a}:{},...p?{toolUseId:p,actionId:p}:{},metadata:{mcpServer:s}};if(t.data.action==="tool_result"){this.emitProviderEvent(t,"tool_use_end",{...d,toolResult:typeof t.data.result=="string"?t.data.result:JSON.stringify(t.data.result??"")});const f=r.actionType==="idle"&&!Lt(t.data.result)?"waiting_input":"thinking";e.adapterSession.status=f,r.actionType==="idle"&&(e.idleToolActiveAt=void 0),this.cancelDataFlowWatchdog(e),e.pendingToolEventData=void 0;const A=r.actionType==="idle";this.emit("status-change",t.sessionId,f,A||f==="thinking"?void 0:d);return}const g=r.actionType==="idle"?"waiting_input":"tool_using";e.adapterSession.status=g,r.actionType==="idle"&&(e.idleToolActiveAt=Date.now()),g==="tool_using"&&(this.resetDataFlowWatchdog(t.sessionId,e),e.pendingToolEventData={...d}),this.emitProviderEvent(t,"tool_use_start",d),this.emit("status-change",t.sessionId,g,d);return}if(t.type==="skill_status"){const s=(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),n=typeof t.data.skillsDir=="string"?t.data.skillsDir:void 0,a=(Array.isArray(t.data.skillGroups)?t.data.skillGroups:[]).map(m=>{const d=Array.isArray(m.skills)?m.skills:[];return{dir:typeof m.dir=="string"?m.dir:"",exists:m.exists===!0,skills:d.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),r=e.cachedMcpCapabilities??e.lastMcpCapabilities,c=e.cachedMcpCapabilities!==void 0,p={kind:"combined",mcpServers:r?.mcpServers??[],mcpTools:r?.mcpTools??[],skills:s,skillsDir:n,skillGroups:a};this.emitProviderEvent(t,"runtime_capabilities",{capabilities:p,actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:JSON.stringify(p)}),e.lastCombinedCapabilities=p,l(`[cap-diag] Combined capabilities emitted ${c?"(startup merge)":"(runtime refresh)"}: ${(r?.mcpTools??[]).length} MCP tools, ${s.length} skills`,{sessionId:t.sessionId,mcpServers:r?.mcpServers??[],skillsDir:n}),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 o=G(t.data),s=h(t.data.contextLimit)||void 0,n=h(t.data.maxOutput)||void 0,i=h(t.data.inputLimit)||void 0,a=h(t.data.compactionThreshold)||void 0;let r=!1;o>0&&(e.adapterSession.totalUsage.inputTokens=o,e.adapterSession.totalUsage.outputTokens=0,r=!0),s!==void 0&&(e.adapterSession.totalUsage.contextLimit=s,r=!0),n!==void 0&&(e.adapterSession.totalUsage.maxOutput=n,r=!0),i!==void 0&&(e.adapterSession.totalUsage.inputLimit=i,r=!0),a!==void 0&&(e.adapterSession.totalUsage.compactionThreshold=a,r=!0),r&&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 o=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:o||"\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"}),this.emit("status-change",t.sessionId,"waiting_input",{actionLabel:"\u5BA1\u6279\u8BA1\u5212",actionDetail:o||"\u7B49\u5F85\u7528\u6237\u5BA1\u6279\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F"});return}if(t.type==="context_compaction"){const o=t.data,s=o.action,n=s==="start",i=s==="end",a=s==="phase",r=o.parentId,c=o.compactionId;let p,m;if(n){const g=String(o.sizeKB??o.sizeBeforeKB??"?"),f=String(o.messageCount??o.messageCountBefore??"?"),A=o.estimatedTokens,_=o.actualInputTokens?`input=${o.actualInputTokens}`:"",k=o.actualOutputTokens?`output=${o.actualOutputTokens}`:"",b=o.trigger?`, \u89E6\u53D1: ${o.trigger}`:"";p="\u4E0A\u4E0B\u6587\u538B\u7F29\u5F00\u59CB",A!==void 0?m=`\u538B\u7F29\u524D: ~${A} tokens, \u6D88\u606F: ${f}\u6761`+(_?`, \u5B9E\u9645 tokens: ${_} ${k}`:"")+b:m=`\u538B\u7F29\u524D: ${g}KB, \u6D88\u606F: ${f}\u6761`+(_?`, \u5B9E\u9645 tokens: ${_} ${k}`:"")+b}else if(a)p=String(o.phaseLabel??"\u538B\u7F29\u9636\u6BB5"),m=String(o.phaseDetail??"");else{const g=o.tokensBefore,f=o.tokensAfter,A=o.freedTokens,_=String(o.sizeBeforeKB??"?"),k=String(o.sizeAfterKB??"?"),b=String(o.freedKB??"?"),T=String(o.strategy??"?"),C=Number(o.prunedToolMessages??0),S=Number(o.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: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:""):m=`\u91CA\u653E: ${b}KB, ${_}KB \u2192 ${k}KB, \u7B56\u7565: ${T}`+(C?`, \u88C1\u526A\u5DE5\u5177: ${C}\u6761`:"")+(S?`, \u6458\u8981\u5316: ${S}\u6761`:"")}n&&(e.adapterSession.status="compacting");const d={actionType:"context_compaction",actionLabel:p,actionDetail:m};if(n&&c)d.actionId=c;else if((a||i)&&c)if(d.parentId=c,a){const g=String(o.phase??"unknown");d.actionId=`${c}-phase-${g}`}else d.actionId=`${c}-end`;a&&r&&!d.parentId&&(d.parentId=r),i&&(e.adapterSession.totalUsage.inputTokens=h(o.tokensAfter),e.adapterSession.totalUsage.outputTokens=0,d.usage={...e.adapterSession.totalUsage}),this.emitProviderEvent(t,"context_compaction",d),this.emit("status-change",t.sessionId,"compacting",d);return}this.emitProviderEvent(t,"thinking",{text:JSON.stringify(t.data)})}}emitProviderEvent(t,e,o){this.emit("event",{type:e,sessionId:t.sessionId,timestamp:t.timestamp,data:o})}armIdleLoopOrAutoPoll(t){const e=this.sessions.get(t);if(!(!e||this.isTerminalStatus(e.adapterSession.status))){if(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 ut({getStatus:()=>this.sessions.get(e)?.adapterSession.status,getCommand:()=>this.sessions.get(e)?.idleCommands?.idleInputCommand,isPollingCommand:o=>L(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,s)=>this.submitAutoPollPrompt(e,s?o:Tt,{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.submitAutoPollPrompt(e,o)}),t.idlePollLoop}submitAutoPollPrompt(t,e,o){const s=this.sessions.get(t);if(!s||this.isTerminalStatus(s.adapterSession.status))return;const n=(s.autoPollToken??0)+1;s.autoPollToken=n,s.autoPollActive=!0,s.autoPollObservedPollingTool=!1,s.autoPollObservedAssistantText=!1,s.autoPollObservedAnyTool=!1,s.stopAutoPollAfterCurrentTurn=!1,s.autoPollQueuedAt=Date.now(),s.autoPollLastActivityAt=Date.now(),s.idleToolActiveAt=void 0,o?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking")),this.startSubmitTimeoutDetection(t,s,"submitAutoPollPrompt"),s.runtime.submit(e).catch(i=>{this.emitRuntimeError(t,i)}).finally(()=>{const i=this.sessions.get(t);if(i){if(i.autoPollToken!==n){l(`[ACode] submitAutoPollPrompt.finally: token mismatch (my=${n}, 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=ft){const o=this.sessions.get(t);!o||o.autoPollActive||o.autoPollTimer||this.isTerminalStatus(o.adapterSession.status)||(o.autoPollTimer=setTimeout(()=>{const s=this.sessions.get(t);!s||s.autoPollActive||this.isTerminalStatus(s.adapterSession.status)||(s.autoPollTimer=void 0,this.submitAutoPollPrompt(t,q,{keepWaitingStatus:!0}))},e))}cancelScheduledAutoPoll(t){t.autoPollTimer&&(clearTimeout(t.autoPollTimer),t.autoPollTimer=void 0)}isTerminalStatus(t){return t==="completed"||t==="terminated"}emitRuntimeError(t,e,o){const s=this.sessions.get(t);s&&(s.adapterSession.status="error",this.emitRuntimeErrorEvent(t,e),this.emit("status-change",t,"error"),o?.recover&&this.recoverTurnFailure(t,s))}emitRuntimeErrorEvent(t,e){const o=new Date().toISOString();this.emit("event",{type:"error",sessionId:t,timestamp:o,data:{text:e instanceof Error?e.message:String(e)}})}estimateOutputTokensFromMessages(t){const e=t.filter(o=>o.role==="assistant").map(o=>o.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.adapterSession.status==="tool_using"&&e.pendingToolEventData){const a=e.pendingToolEventData;l(`[ACode] recoverTurnFailure: \u8865\u53D1 tool_use_end (tool: ${a.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:{...a,toolResult:"[aborted] \u5DE5\u5177\u6267\u884C\u88AB\u6570\u636E\u6D41\u770B\u95E8\u72D7\u4E2D\u65AD"}}),e.pendingToolEventData=void 0}const o=this.estimateOutputTokensFromMessages(e.adapterSession.messages);if(o>0){const a=e.adapterSession.totalUsage.outputTokens;e.adapterSession.totalUsage.outputTokens=o,l(`[ACode] recoverTurnFailure: \u4F30\u7B97\u8986\u76D6 output tokens ${a} -> ${o} (totalUsage now: input=${e.adapterSession.totalUsage.inputTokens}, output=${e.adapterSession.totalUsage.outputTokens})`)}const s=e.idleCommands?.idleInputCommand,i=!!(s&&L(s))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;if(e.autoPollTimer||e.failedTurnRecoveryScheduled){e.adapterSession.status!=="waiting_input"&&(e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}));return}this.cancelScheduledAutoPoll(e),e.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage,...i}),e.failedTurnRecoveryScheduled=!0,e.autoPollTimer=setTimeout(()=>{const a=this.sessions.get(t);if(!a||a.autoPollActive||this.isTerminalStatus(a.adapterSession.status)){a&&(a.failedTurnRecoveryScheduled=!1);return}a.autoPollTimer=void 0,a.failedTurnRecoveryScheduled=!1,a.idleCommands?.idleInputCommand?this.getIdlePollLoop(a).start():this.submitAutoPollPrompt(t,q,{keepWaitingStatus:!0})},ht)}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 o=e.idleCommands?.idleInputCommand,n=!!(o&&L(o))?{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message"}:void 0;this.emit("status-change",t,"waiting_input",n),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,o){this.cancelSubmitTimeoutDetection(e),e.watchdogSubmitStartTime=Date.now(),e.watchdogLastDataFlowTime=Date.now(),e.watchdogTimer=setInterval(()=>{const s=this.sessions.get(t);if(!s){this.cancelSubmitTimeoutDetection(e);return}const n=s.adapterSession.status,i=Date.now();if(n==="waiting_input"){if(s.autoPollActive&&s.autoPollLastActivityAt&&s.idleToolActiveAt===void 0&&i-s.autoPollLastActivityAt>=gt){console.warn(`[ACode] CRITICAL: stuck auto-poll detected after ${Math.round((i-s.autoPollLastActivityAt)/1e3)}s (source: ${o}, 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,s,o,"stuck_autopoll",i-s.autoPollLastActivityAt);return}s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(n==="tool_using"){const c=i-(s.watchdogLastDataFlowTime||i);if(c>=pt){const p=String(s.pendingToolEventData?.rawToolName??"");if(p.endsWith("await_complete")){console.warn(`[ACode] tool_using elapsed ${Math.round(c/1e3)}s but await_complete is running (session: ${t}, tool: ${p}), skipping recovery (sub-agents have their own watchdogs, bg commands have timeout limits)`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}if(console.warn(`[ACode] CRITICAL: tool_using slow timeout triggered after ${Math.round(c/1e3)}s (source: ${o}, session: ${t}). Tool execution likely hung. Forcing recovery via recoverTurnFailure.`),s.runtime.detachCurrentToolExecution?.()){console.warn(`[ACode] tool_using slow (${Math.round(c/1e3)}s): detached tool ${p} to background (session: ${t}); waiting for the real tool_result to continue the turn`),s.watchdogSubmitStartTime=i,s.watchdogLastDataFlowTime=i;return}this.executeWatchdogRecovery(t,s,o,"tool_using_slow",c);return}s.watchdogSubmitStartTime=i;return}if(n!=="thinking")return;const a=i-(s.watchdogSubmitStartTime||i),r=i-(s.watchdogLastDataFlowTime||i);if(N>0&&r>=N){console.warn(`[ACode] CRITICAL: Data flow watchdog triggered after ${Math.round(r/1e3)}s (source: ${o}, session: ${t}, status: ${n}). No stream data received. Forcing recovery via recoverTurnFailure.`),this.executeWatchdogRecovery(t,s,o,"data_flow",r);return}if(H>0&&a>=H){console.warn(`[ACode] CRITICAL: submit timeout detected after ${Math.round(a/1e3)}s (source: ${o}, session: ${t}, status: ${n}). Forcing recovery to prevent permanent state stuck.`),this.executeWatchdogRecovery(t,s,o,"submit_timeout",a);return}},mt)}executeWatchdogRecovery(t,e,o,s,n){l(`[ACode] Watchdog (${s}): calling runtime.abort() after ${Math.round(n/1e3)}s...`);try{e.runtime.abort(),l(`[ACode] Watchdog (${s}): runtime.abort() called`)}catch(i){console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}): runtime.abort() threw: ${i instanceof Error?i.message:String(i)}`)}this.cancelSubmitTimeoutDetection(e),this.recoverTurnFailure(t,e),console.warn(`[ACode] \u26A0\uFE0F Watchdog (${s}) 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
|
`,o=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u4F53:
|
|
7
|
-
`,
|
|
8
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",k=
|
|
7
|
+
`,n=typeof t.model=="string"?t.model:"",i=typeof t.endpoint=="string"?t.endpoint:typeof t.requestUrl=="string"?t.requestUrl:"",a=typeof t.requestMethod=="string"?t.requestMethod:"",r=typeof t.stream=="boolean"?t.stream:void 0,c=typeof t.messageCount=="number"?t.messageCount:void 0,p=typeof t.toolCount=="number"?t.toolCount:void 0,m=typeof t.lastUserMessagePreview=="string"?t.lastUserMessagePreview:"",d=[n?`\u6A21\u578B: ${n}`:void 0,i?`\u63A5\u53E3: ${i}`:void 0,a?`\u65B9\u6CD5: ${a}`:void 0,r!==void 0?`\u6D41\u5F0F: ${r?"\u662F":"\u5426"}`:void 0,c!==void 0?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${c}`:void 0,p!==void 0?`\u53EF\u7528\u5DE5\u5177: ${p}`:void 0,m?`\u6700\u540E\u8BF7\u6C42: ${m}`:void 0].filter(S=>!!S),g=/^(authorization|x-api-key|api-key|cookie|set-cookie|x-auth-token|token)$/i,f=t.requestHeaders,A=f?Object.entries(f).filter(([S])=>!g.test(S)).map(([S,M])=>`${S}: ${M}`).filter(S=>S.trim().length>0):[],_=d.join(`
|
|
8
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",k=A.length>0?`${e}${A.join(`
|
|
9
9
|
`)}`:"",b=typeof t.requestBody=="string"?t.requestBody:"",T=b.length>6e4?`${b.slice(0,6e4)}
|
|
10
|
-
...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:b,C=T?`${o}${T}`:"";return`${
|
|
10
|
+
...(\u8BF7\u6C42\u4F53\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD)`:b,C=T?`${o}${T}`:"";return`${_}${k}${C}`}}export{Jt as AcodeSdkAdapter,wt as isFailedAcodeTurnComplete,At as toAcodeEsmImportSpecifier};
|
|
11
11
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as A}from"node:child_process";import{EventEmitter as E}from"node:events";import*as w from"node:fs";import*as x from"node:net";import*as T from"node:os";import*as h from"node:path";import{v4 as y}from"uuid";import{BRIDGE_PACKAGE_ROOT as _,importBridgeSdkPackage as $}from"../utils/sdk-package-loader.js";import{getAcodeDataHome as M}from"../config.js";import{logger as L}from"../utils/logger.js";import{IdlePollLoop as O}from"./idle-poll-loop.js";import{getToolActionInfo as D,redactTransientClipboardPastePaths as P,redactTransientClipboardPastePathsInValue as C}from"./types.js";import{registerListenerWakeHook as j,unregisterListenerWakeHook as I}from"../services/browser-session-manager.js";function N(d){if(d&&h.isAbsolute(d)&&w.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||T.homedir(),o=process.env.LOCALAPPDATA||"",r=[h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const s of r){const n=h.join(s,"opencode.exe");if(w.existsSync(n))return console.log(`[OpencodeSdkAdapter] Found opencode.exe: ${n}`),n}const i=[h.join(e,"AppData","Roaming","npm"),h.join(e,"AppData","Local","Volta","bin")];for(const s of i)for(const n of["opencode.cmd","opencode.exe","opencode"]){const a=h.join(s,n);if(w.existsSync(a))return console.log(`[OpencodeSdkAdapter] Found ${n}: ${a}`),a}}return t}async function R(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(o=>{const r=x.createServer();r.once("error",()=>o(!1)),r.once("listening",()=>{r.close(()=>o(!0))}),r.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function U(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function H(d,t){return U(d)&&d.code==="ERR_MODULE_NOT_FOUND"&&d.message.includes(t)}function v(d){if(!d||!d.trim())return;const t=d.trim(),e=t.indexOf("/");return e>0?{providerID:t.slice(0,e),modelID:t.slice(e+1)}:{modelID:t}}class Q extends E{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8 OpenCode SDK \u4F1A\u8BDD \u2605\u2605\u2605 sessionId="${t}", workingDirectory="${e.workingDirectory}"`);const o={adapterSession:{sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}},config:e,sseActive:!1,pendingPermissions:new Map,emittedToolStarts:new Set,workingDirectory:e.workingDirectory,userMessageIds:new Set,currentAssistantText:"",seenTextPartIds:new Set};if(this.sessions.set(t,o),e.agentId){const r=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,r),j(e.agentId,r)}this.emit("status-change",t,"starting");try{const r=await R();o.port=r,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u4F7F\u7528\u7AEF\u53E3 \u2605\u2605\u2605 port=${r}`);const i=N(e.command);console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8\u547D\u4EE4 \u2605\u2605\u2605 command="${i}"`);const s=i.endsWith(".cmd")||i.endsWith(".CMD")||process.platform==="win32"&&!h.isAbsolute(i);console.log(`[OpencodeSdkAdapter] shell=${s}`);const n={...process.env,...e.envOverrides},a={};v(e.model)?.modelID&&(a.model=e.model.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(n.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),L.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=A(i,["serve","--port",String(r)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:n,shell:s});o.serverProcess=l,o.startupOutput=[],l.stdout?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stdout: ${f.slice(0,200)}`)}),l.stderr?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stderr: ${f.slice(0,200)}`)}),l.on("error",c=>{console.error("[OpencodeSdkAdapter] Server process error:",c),o.adapterSession.status!=="terminated"&&(o.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${c.message}`}}))}),l.on("exit",c=>{console.log(`[OpencodeSdkAdapter] Server exited with code ${c}`),o.sseActive=!1});const p=new Promise(c=>{l.once("exit",(f,b)=>c({code:f,signal:b}))}),g=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${r}`});o.client=g,await Promise.race([this.waitForServer(g,e.workingDirectory,1e4,r),p.then(c=>{throw new Error(this.formatStartupExitMessage(c,o.startupOutput))})]),console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode server ready \u2605\u2605\u2605 port=${r}`);const k=(await g.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!k?.id)throw new Error("OpenCode session.create() did not return an ID");o.opencodeSessionId=k.id,o.adapterSession.providerSessionId=k.id,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode \u4F1A\u8BDD\u521B\u5EFA\u6210\u529F \u2605\u2605\u2605 sessionId="${k.id}"`),this.startSseLoop(t,o),o.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:o.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(r){e.agentId&&I(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const i=r instanceof Error?r.message:String(r);throw console.error("[OpencodeSdkAdapter] startSession failed:",r),o.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode start failed: ${i}`}}),r}}async sendMessage(t,e,o){const r=this.sessions.get(t);if(!r)throw new Error(`Session ${t} not found`);if(!r.client||!r.opencodeSessionId)throw new Error(`Session ${t} not ready`);const i={id:y(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};r.adapterSession.messages.push(i),this.emit("conversation-message",t,i),o?.keepWaitingStatus||(r.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const s=v(r.config.model),n={parts:[{type:"text",text:e}]};s?.providerID&&s?.modelID&&(n.model={providerID:s.providerID,modelID:s.modelID},console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 per-message model \u2605\u2605\u2605 provider=${s.providerID}, model=${s.modelID}`)),await r.client.session.prompt({path:{id:r.opencodeSessionId},body:n,query:{directory:r.workingDirectory}})}catch(s){const n=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:n}})}}async sendConfirmation(t,e){const o=this.sessions.get(t);if(!o?.client||!o.opencodeSessionId)return;const r=e?"once":"reject",i=o.opencodeSessionId;for(const[s]of o.pendingPermissions)try{await o.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:s},body:{response:r},query:{directory:o.workingDirectory}})}catch(n){console.warn("[OpencodeSdkAdapter] Permission response failed:",n)}o.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const o=this.sessions.get(t);o&&(o.idleCommands=e,o.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t))}async abortCurrentTurn(t){const e=this.sessions.get(t);if(!(!e?.client||!e.opencodeSessionId))try{await e.client.session.abort({path:{id:e.opencodeSessionId},query:{directory:e.workingDirectory}})}catch(o){console.warn("[OpencodeSdkAdapter] Abort failed:",o)}}async terminateSession(t){const e=this.sessions.get(t);if(e){if(this.stopIdleDetection(t),e.sseActive=!1,e.sseAbortController?.abort(),e.serverProcess)try{e.serverProcess.kill()}catch{}e.adapterSession.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent({type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}),e.config.agentId&&I(e.config.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.sessions.delete(t)}}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.opencodeSessionId}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getSessionPid(t){const e=this.sessions.get(t);if(e)return e.serverProcess?.pid}cleanup(){for(const[t]of this.sessions)try{this.terminateSession(t)}catch{}this.sessions.clear()}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await $("@opencode-ai/sdk")}catch(t){throw H(t,"@opencode-ai/sdk")?new Error(["OpenCode SDK provider is not installed.","","aws-runtime-bridge keeps Codex/OpenCode provider SDKs optional to reduce default install size.",'To use SDK mode with command "opencode", install the SDK into the aws-runtime-bridge package root:',"",` npm install --prefix "${_}" @opencode-ai/sdk@latest opencode-ai@latest`,"","If aws-runtime-bridge is installed locally, run the same command with that local package path.","",`Original error: ${t instanceof Error?t.message:String(t)}`].join(`
|
|
2
2
|
`)):t}return this.sdkModule}async waitForServer(t,e,o,r){const i=Date.now()+o;for(;Date.now()<i;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(s=>setTimeout(s,300))}throw new Error(`OpenCode server (port ${r}) did not start within ${o}ms`)}recordStartupOutput(t,e){const o=e.trim();o&&(t.startupOutput=[...t.startupOutput??[],o].slice(-8))}formatStartupExitMessage(t,e){const o=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,r=(e??[]).join(`
|
|
3
|
-
`).trim();return r?`OpenCode server exited during startup (${o}): ${r}`:`OpenCode server exited during startup (${o}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(o=>{const r=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const o=new AbortController;e.sseAbortController=o,this.runSseLoop(t,e,o).catch(r=>{o.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,o){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:o.signal});for await(const i of r.stream){if(!e.sseActive||o.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(o.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,o){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(o.type){case"message.updated":{const s=o.properties.info;if(s.sessionID!==i)break;if(s.role==="user")e.userMessageIds.add(s.id);else if(s.role==="assistant"){const n=s.tokens;n&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,n.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,n.output))}break}case"message.part.updated":{const{part:s,delta:n}=o.properties;if(s.sessionID!==i||e.userMessageIds.has(s.messageID))break;this.handlePartUpdate(t,e,s,n,r);break}case"session.idle":{if(o.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:y(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:r};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:r,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand;!!(s&&this.isMessagePollingIdleCommand(s))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.adapterSession.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),this.startIdleDetection(t);break}case"permission.updated":{const s=o.properties;if(s.sessionID!==i)break;const n=s.id;e.pendingPermissions.set(n,s),e.config.autoAccept&&e.client&&i?e.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:n},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(n)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:r,data:{permissionPrompt:s.title,toolName:s.type}});break}case"session.error":{const{sessionID:s,error:n}=o.properties;if(s&&s!==i)break;let a="OpenCode session error";if(n){const u=n.data;typeof u?.message=="string"?a=`${n.name}: ${u.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,o,r,i){switch(o.type){case"text":{let s;if(r!==void 0)s=r,e.seenTextPartIds.add(o.id);else if(!e.seenTextPartIds.has(o.id))s=o.text,s&&e.seenTextPartIds.add(o.id);else break;if(!s)break;e.currentAssistantText+=s,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:s}});break}case"reasoning":{const s=r??o.text;if(!s)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:s}});break}case"tool":{const s=o.callID,n=o.tool,a=o.state,u=a.input,l=o.metadata;l&&Object.keys(l).length>0&&console.log(`[OpencodeSdkAdapter] Tool "${n}" metadata:`,JSON.stringify(
|
|
3
|
+
`).trim();return r?`OpenCode server exited during startup (${o}): ${r}`:`OpenCode server exited during startup (${o}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(o=>{const r=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const o=new AbortController;e.sseAbortController=o,this.runSseLoop(t,e,o).catch(r=>{o.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,o){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:o.signal});for await(const i of r.stream){if(!e.sseActive||o.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(o.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,o){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(o.type){case"message.updated":{const s=o.properties.info;if(s.sessionID!==i)break;if(s.role==="user")e.userMessageIds.add(s.id);else if(s.role==="assistant"){const n=s.tokens;n&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,n.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,n.output))}break}case"message.part.updated":{const{part:s,delta:n}=o.properties;if(s.sessionID!==i||e.userMessageIds.has(s.messageID))break;this.handlePartUpdate(t,e,s,n,r);break}case"session.idle":{if(o.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:y(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:r};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:r,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand;!!(s&&this.isMessagePollingIdleCommand(s))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.adapterSession.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),this.startIdleDetection(t);break}case"permission.updated":{const s=o.properties;if(s.sessionID!==i)break;const n=s.id;e.pendingPermissions.set(n,s),e.config.autoAccept&&e.client&&i?e.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:n},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(n)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:r,data:{permissionPrompt:s.title,toolName:s.type}});break}case"session.error":{const{sessionID:s,error:n}=o.properties;if(s&&s!==i)break;let a="OpenCode session error";if(n){const u=n.data;typeof u?.message=="string"?a=`${n.name}: ${u.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,o,r,i){switch(o.type){case"text":{let s;if(r!==void 0)s=r,e.seenTextPartIds.add(o.id);else if(!e.seenTextPartIds.has(o.id))s=o.text,s&&e.seenTextPartIds.add(o.id);else break;if(!s)break;e.currentAssistantText+=s,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:s}});break}case"reasoning":{const s=r??o.text;if(!s)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:s}});break}case"tool":{const s=o.callID,n=o.tool,a=o.state,u=a.input,l=o.metadata;l&&Object.keys(l).length>0&&console.log(`[OpencodeSdkAdapter] Tool "${n}" metadata:`,JSON.stringify(C(l)));const p=C(u),S=p&&typeof p=="object"&&!Array.isArray(p)?p:{},g=()=>{if(e.emittedToolStarts.has(s))return;e.emittedToolStarts.add(s);const m={...D(n,u,l),actionId:s};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:i,data:{toolName:n,toolInput:S,toolUseId:s,...m}}),e.adapterSession.messages.push({id:y(),sessionId:t,role:"tool_use",content:`${n}: ${JSON.stringify(S).slice(0,100)}`,timestamp:i,toolName:n,toolInput:S,toolUseId:s})};if(a.status==="running"){g();const m={...D(n,u,l),actionId:s};this.emit("status-change",t,"tool_using",{...m,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(n==="todowrite"||n==="todo_write")&&this.syncTodosFromToolCall(e,u).catch(k=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",k)}),g();const m=P(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!1,toolUseId:s}}),e.emittedToolStarts.delete(s)}else if(a.status==="error"){g();const m=P(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!0,toolUseId:s}}),e.emittedToolStarts.delete(s)}break}}}getTodoStoreDir(){return h.join(M(),"todos")}async syncTodosFromToolCall(t,e){const o=t.config.agentId;if(!o)return;const r=e.todos;if(!Array.isArray(r)||r.length===0)return;const i=[];for(const p of r)if(p&&typeof p=="object"){const S=typeof p.content=="string"?p.content.trim():"",g=typeof p.status=="string"?p.status:"",m=typeof p.priority=="string"?p.priority:"";S&&g&&m&&i.push({content:S,status:g,priority:m})}if(i.length===0)return;const s=String(o).replace(/[^a-zA-Z0-9_-]/g,"_"),n=this.getTodoStoreDir(),a=h.join(n,`${s}.json`),u={agentId:o,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:i};await w.promises.mkdir(n,{recursive:!0});const l=`${a}.tmp`;await w.promises.writeFile(l,JSON.stringify(u,null,2),"utf-8"),await w.promises.rename(l,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),o=e?.idleCommands?.idleInputCommand;if(!e||!o)return;if(this.isMessagePollingIdleCommand(o)){e.idlePollLoop||(e.idlePollLoop=new O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500})),e.idlePollLoop.start();return}e.idlePollLoop||(e.idlePollLoop=new O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500}));const r=setInterval(()=>{this.checkIdleState(t)},500);e.idleTimer=r}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearInterval(e.idleTimer),e.idleTimer=void 0)}checkIdleState(t){const e=this.sessions.get(t);!e||e.adapterSession.status!=="waiting_input"||e.idleCommands?.idleInputCommand&&(this.sendMessage(t,this.toIdlePrompt(e.idleCommands.idleInputCommand)),this.stopIdleDetection(t))}toIdlePrompt(t){const e=t.trim();return this.isMessagePollingIdleCommand(e)?"\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":e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const o=e.toLowerCase();return o.includes("poll_message")||o.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Q as OpencodeSdkAdapter};
|
|
4
4
|
|
package/dist/config.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ export interface SchedulerBaseUrlResolution {
|
|
|
36
36
|
|
|
37
37
|
export declare function getAutoRegisterConfigFilePath(): string;
|
|
38
38
|
|
|
39
|
+
export declare function getBridgeRuntimePropertiesFilePath(): string;
|
|
40
|
+
|
|
41
|
+
export declare function writeBridgeRuntimePropertiesFile(): void;
|
|
42
|
+
|
|
39
43
|
export declare function resolveSchedulerBaseUrl(): SchedulerBaseUrlResolution;
|
|
40
44
|
|
|
41
45
|
export declare function resolveSchedulerBaseUrlFrom(requestSchedulerBaseUrl: unknown, instanceId?: unknown, instanceName?: unknown): SchedulerBaseUrlResolution;
|
|
@@ -58,7 +62,9 @@ export declare function getClaudeSkillsDir(runtimeHome: string): string;
|
|
|
58
62
|
|
|
59
63
|
export declare function getOpencodeConfigFile(runtimeHome: string): string;
|
|
60
64
|
|
|
61
|
-
export declare function
|
|
65
|
+
export declare function getAcodeDataHome(): string;
|
|
66
|
+
|
|
67
|
+
export declare function getAcodeConfigFile(): string;
|
|
62
68
|
|
|
63
69
|
export declare function getCodexConfigFile(runtimeHome: string): string;
|
|
64
70
|
|
|
@@ -66,7 +72,7 @@ export declare function getCodexSkillsDir(runtimeHome: string): string;
|
|
|
66
72
|
|
|
67
73
|
export declare function getOpencodeSkillsDir(runtimeHome: string): string;
|
|
68
74
|
|
|
69
|
-
export declare function getAcodeSkillsDir(
|
|
75
|
+
export declare function getAcodeSkillsDir(): string;
|
|
70
76
|
|
|
71
77
|
|
|
72
78
|
export declare const ORPHAN_SCAN_INTERVAL: number;
|
package/dist/config.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import u from"node:fs";import D from"node:net";import{homedir as L}from"node:os";import o from"node:path";import{fileURLToPath as f}from"node:url";import{logger as C}from"./utils/logger.js";function m(){return String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development"}let E;function P(){if(E!==void 0)return E;const e=o.dirname(f(import.meta.url)),t=o.resolve(e,".."),r=o.resolve(t,".."),n=u.existsSync(o.join(r,".git"))||u.existsSync(o.join(r,"package.json"));return E=o.join(n?r:t,".dev-home"),E}function T(){return String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||L()}function N(){return m()?String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||P():T()}const h=18081,H=28081,O=Number(process.env.AWS_RUNTIME_BRIDGE_PORT||(m()?H:h));let A;function M(){return A??O}function W(e){A=e}function z(){A=void 0}function I(e){return new Promise(t=>{const r=D.createServer();r.once("error",n=>{const s=n.code==="EADDRINUSE"||n.code==="EACCES"||n.code==="EPERM";t(!s)}),r.once("listening",()=>{r.close(()=>t(!0))}),r.listen(e)})}async function U(e){return await I({port:e})&&await I({port:e,host:"0.0.0.0"})?e:null}async function B(e,t=20){let r=Math.floor(e);for(let s=0;s<t;s+=1){if(r>=1&&r<=65535){const c=await U(r);if(c!==null)return c}r+=1}return await U(0)??e}async function J(e=O){const t=await B(e);return W(t),process.env.AWS_RUNTIME_BRIDGE_PORT=String(t),t!==e&&C.warn(`[runtime-bridge] \u9996\u9009\u7AEF\u53E3 ${e} \u5DF2\u88AB\u5360\u7528\uFF0C\u81EA\u52A8\u6539\u7528 ${t} \u542F\u52A8`),t}const S="http://localhost:8080";function R(e){return e==null?void 0:String(e).trim()||void 0}function _(e){const t=R(e);if(!t)return;const r=t.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1");try{const n=new URL(r);return n.protocol==="ws:"?n.protocol="http:":n.protocol==="wss:"?n.protocol="https:":n.protocol=n.protocol.toLowerCase(),n.hostname=n.hostname.toLowerCase(),n.origin}catch{return r.replace(/\/+$/,"")}}function w(){return o.join(N(),".aws-bridge","config.json")}function F(){return o.join(N(),".aws-bridge","bridge-runtime.properties")}function Y(){const e=F();u.mkdirSync(o.dirname(e),{recursive:!0});const t=[`port=${M()}`,`pid=${process.pid}`,`startedAt=${new Date().toISOString()}`];u.writeFileSync(e,`${t.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`,{encoding:"utf8",mode:384})}function v(){const e=w();try{if(!u.existsSync(e))return[];const t=JSON.parse(u.readFileSync(e,"utf-8")),r=i=>({serverUrl:_(i.serverUrl)||_(i.schedulerBaseUrl),instanceId:R(i.instanceId),instanceName:R(i.instanceName)}),s=(Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[]).filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))).map(r).filter(i=>!!i.serverUrl);if(s.length>0)return s;const c=r(t);return c.serverUrl?[c]:[]}catch{return[]}}function j(){const t=v().map(r=>r.serverUrl).filter(r=>!!r);return Array.from(new Set(t))}function q(){return k(void 0)}function k(e,t,r){const n=_(e);if(n)return{url:n,source:"request",ambiguousTargetUrls:[]};const s=typeof t=="string"?t.trim():"",c=typeof r=="string"?r.trim():"";if(s||c){const g=v();let a;if(s&&(a=g.find(p=>p.instanceId===s)),!a&&c&&(a=g.find(p=>p.instanceName===c)),!a&&s&&!c&&(a=g.find(p=>p.instanceName===s)),a?.serverUrl)return{url:a.serverUrl,source:"instance-id-match",ambiguousTargetUrls:[],instanceId:a.instanceId,instanceName:a.instanceName}}const i=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL);if(i)return{url:i,source:"env",ambiguousTargetUrls:[]};const l=j();return l.length===1?{url:l[0]||S,source:"single-auto-register-target",ambiguousTargetUrls:[]}:l.length>1?{url:S,source:"ambiguous-auto-register-targets",ambiguousTargetUrls:l}:{url:S,source:"default",ambiguousTargetUrls:[]}}const X=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL)||S,Q=process.env.NODE_ENV||"development",Z=process.env.AWS_ALLOW_HOST_FILE_BROWSER==="true",ee=String(process.env.AWS_RUNTIME_CORS_ORIGINS||"http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173").split(",").map(e=>e.trim()).filter(e=>e.length>0);function te(){}function re(e){return String(process.env.AWS_RUNTIME_CLAUDE_CONFIG_FILE||"").trim()||o.join(e,".claude","settings.json")}function ne(e){return String(process.env.AWS_RUNTIME_CLAUDE_MCP_CONFIG_FILE||"").trim()||o.join(e,".claude.json")}function oe(e){return String(process.env.AWS_RUNTIME_CLAUDE_SKILLS_DIR||"").trim()||o.join(e,".claude","skills")}function se(e){return String(process.env.AWS_RUNTIME_OPENCODE_CONFIG_FILE||"").trim()||o.join(e,".config","opencode","opencode.json")}function x(){return String(process.env.ACODE_HOME||"").trim()||o.join(T(),".acode")}function ie(){return String(process.env.AWS_RUNTIME_ACODE_CONFIG_FILE||"").trim()||o.join(x(),"config.json")}function ce(e){return String(process.env.AWS_RUNTIME_CODEX_CONFIG_FILE||"").trim()||o.join(e,".codex","config.toml")}function ae(e){return String(process.env.AWS_RUNTIME_CODEX_SKILLS_DIR||"").trim()||o.join(e,".codex","skills")}function ue(e){return String(process.env.AWS_RUNTIME_OPENCODE_SKILLS_DIR||"").trim()||o.join(e,".opencode","skills")}function le(){return String(process.env.AWS_RUNTIME_ACODE_SKILLS_DIR||"").trim()||o.join(x(),"skills")}const pe=Number(process.env.AWS_ORPHAN_SCAN_INTERVAL||3e4),_e=process.env.AWS_ORPHAN_AUTO_CLEAN_MODE||"alert",Ee=process.env.AWS_ORPHAN_SCAN_ENABLED!=="false",Se=Number(process.env.AWS_ORPHAN_UNRESPONSIVE_TIMEOUT||3e5),ge=Number(process.env.AWS_ORPHAN_CPU_THRESHOLD||100),Ae=Number(process.env.AWS_ORPHAN_MEMORY_THRESHOLD||2048),Re=process.env.AWS_AUTO_REGISTER==="true",de=process.env.AWS_TENANT_ID||"",fe=process.env.AWS_USER_KEY||"",me=process.env.AWS_INSTANCE_NAME||"",Te=process.env.AWS_PROJECT_NAME||"",Ne=process.env.AWS_ROLE_NAME||"",Oe=process.env.AWS_WORKSPACE_PATH||"",Ie=process.env.AWS_REGISTER_IP||process.env.AWS_VIRTUAL_IP||"";let d;function Ue(){if(d!==void 0)return d;let e="unknown";try{const t=o.dirname(f(import.meta.url)),r=o.resolve(t,"..","package.json");u.existsSync(r)&&(e=JSON.parse(u.readFileSync(r,"utf-8")).version||"unknown")}catch{}return d=e,e}export{Re as AUTO_REGISTER_ENABLED,me as AUTO_REGISTER_INSTANCE_NAME,Te as AUTO_REGISTER_PROJECT_NAME,Ne as AUTO_REGISTER_ROLE_NAME,de as AUTO_REGISTER_TENANT_ID,fe as AUTO_REGISTER_USER_KEY,Ie as AUTO_REGISTER_VIRTUAL_IP,Oe as AUTO_REGISTER_WORKSPACE_PATH,h as DEFAULT_BRIDGE_PORT,S as DEFAULT_SCHEDULER_BASE_URL,H as DEV_DEFAULT_BRIDGE_PORT,_e as ORPHAN_AUTO_CLEAN_MODE,ge as ORPHAN_CPU_THRESHOLD,Ae as ORPHAN_MEMORY_THRESHOLD,Ee as ORPHAN_SCAN_ENABLED,pe as ORPHAN_SCAN_INTERVAL,Se as ORPHAN_UNRESPONSIVE_TIMEOUT,Z as allowHostFileBrowser,ee as allowedCorsOrigins,B as findAvailableListenPort,ie as getAcodeConfigFile,x as getAcodeDataHome,le as getAcodeSkillsDir,M as getActiveBridgeHttpPort,w as getAutoRegisterConfigFilePath,F as getBridgeRuntimePropertiesFilePath,Ue as getBridgeVersion,re as getClaudeConfigFile,ne as getClaudeMcpConfigFile,oe as getClaudeSkillsDir,ce as getCodexConfigFile,ae as getCodexSkillsDir,se as getOpencodeConfigFile,ue as getOpencodeSkillsDir,N as getRuntimeHomeDir,T as getUserHomeDir,m as isDevMode,Q as nodeEnv,O as port,J as reserveBridgeListenPort,z as resetActiveBridgeHttpPort,q as resolveSchedulerBaseUrl,k as resolveSchedulerBaseUrlFrom,X as schedulerBaseUrl,W as setActiveBridgeHttpPort,te as validateProductionToken,Y as writeBridgeRuntimePropertiesFile};
|
|
2
4
|
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{existsSync as A,readFileSync as T}from"node:fs";import B from"node:os";import D from"node:path";import M from"cors";import R from"express";import{adapterRegistry as E}from"./adapter/index.js";import{attachBrowserWebSocketServer as x}from"./browser/browser-ws-bridge.js";import{getActiveBridgeHttpPort as G,getAutoRegisterConfigFilePath as O,reserveBridgeListenPort as F,validateProductionToken as _}from"./config.js";import{attachRemoteDesktopWebSocketServer as K}from"./remote-desktop/index.js";import{acodeTodosRouter as L}from"./routes/acode-todos.js";import{aiSourcesRouter as N}from"./routes/ai-sources.js";import{backgroundTasksRouter as j}from"./routes/background-tasks.js";import{browserListenersRouter as W}from"./routes/browser-listeners.js";import{browserSessionsRouter as U}from"./routes/browser-sessions.js";import{computerRouter as z}from"./routes/computer.js";import{dashboardRouter as H}from"./routes/dashboard.js";import{eventsRouter as J}from"./routes/events.js";import{fileBrowserRouter as Y}from"./routes/file-browser.js";import{fileChangeDiffRouter as q}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as Z}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as Q}from"./routes/file-snapshot.js";import{gitRouter as V}from"./routes/git.js";import{instanceRouter as X,setGracefulShutdownFn as ee}from"./routes/instance.js";import{jdksRouter as re}from"./routes/jdks.js";import{launchRouter as te}from"./routes/launch.js";import{mcpRouter as ie}from"./routes/mcp.js";import{processesRouter as oe}from"./routes/processes.js";import{propertiesRouter as ne}from"./routes/properties.js";import{attachPtyWebSocketServer as se,closeAllPtySessions as ae,ptyRouter as me,ptySessions as ce}from"./routes/pty.js";import{runtimeBindingRouter as ue,logRuntimeBindingStartupState as de}from"./routes/runtime-binding.js";import{sessionsRouter as ge}from"./routes/sessions.js";import{skillsRouter as pe}from"./routes/skills.js";import{subAgentsRouter as fe}from"./routes/sub-agents.js";import{systemMetricsRouter as le}from"./routes/system-metrics.js";import{taskContextRouter as be}from"./routes/task-context.js";import{terminalRouter as we,sdkSessions as h}from"./routes/terminal.js";import{ymlRouter as he}from"./routes/yml.js";import{ensureAcodePackageReleased as Se}from"./services/acode-package.js";import{accessControlMiddleware as Re}from"./services/access-control.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as Ie,unregister as Pe,bridgeRestartCleanup as ye,cancelBackgroundRegisterRetries as ke}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as $e}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as Ce}from"./services/browser-session-manager.js";import{handleCliCommand as ve}from"./services/cli-commands.js";import{disposeDesktopMcpManager as Ae}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Te}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Be}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as De}from"./services/lifecycle-state.js";import{startOrphanMonitor as Me,stopOrphanMonitor as Ee}from"./services/orphan-monitor.js";import{detectOrphanProcesses as xe}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Ge,shouldCleanupPersistedSessionsOnStartup as Oe}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Fe}from"./services/startup-config-wizard.js";import{subAgentStore as _e}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as P,savePersistedSessions as y}from"./services/terminal-persistence.js";import{stopTunnelClient as Ke}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const k=await ve();k.handled&&process.exit(k.exitCode),await Fe(),_(),$e(),Se(),Be(),de(),await F();async function Le(){try{if(await Ie())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),s=o();!!s.userKey&&s.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${O()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}Le().then(()=>Ne()).then(()=>De()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function Ne(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const s=await ye();s.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${s.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${s.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function je(){try{const r=await P();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await I().rebuildRegistry(r.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}je().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function We(){try{const r=await import("node:fs/promises"),o=await import("node:path"),s=await import("node:os"),f=o.join(s.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let c=!1;try{const t=await r.readFile(f,"utf-8");c=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${c}`)}catch{}const a=await P();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Oe(c)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await I().rebuildRegistry(a.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await xe(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:n}=await import("node:child_process");n(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(n){const u=n;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${u.message}`)}await new Promise(t=>setTimeout(t,1e3))}await y([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}We().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),Me().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=R();i.use(Re),i.use(M()),i.use(R.json({limit:"1mb"})),i.use("/runtime",ue),i.use("/runtime",ne),i.use("/runtime",he),i.use("/runtime",X),i.use("/runtime",pe),i.use("/runtime",ie),i.use("/runtime",we),i.use("/runtime",ge),i.use("/runtime",oe),i.use("/runtime",te),i.use("/runtime",re),i.use("/runtime",le),i.use("/runtime",J),i.use("/runtime",V),i.use("/runtime",Q),i.use("/runtime",L),i.use("/runtime",j),i.use("/runtime",fe),i.use("/runtime",U),i.use("/runtime",W),i.use("/runtime",N),i.use("/runtime",be),i.use("/runtime",Z),i.use("/runtime",q),i.use("/runtime/computer",z),i.use("/pty",me),i.use("/",H),i.use("/api/file-browser",Y);function Ue(){const r=G(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return se(o),K(o),x(o),o.on("error",s=>{if(s.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",s),process.exitCode=1}),o}let $=!1;async function b(r,o,s=!1){if($){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}$=!0,s||S()&&(s=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${s})`);const f=Date.now(),c=Ge(s);try{const a=h.size;if(c.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,n]of h.entries())try{const u=n.providerId||"claude-code",g=E.get(u);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),h.delete(t)}catch(u){const g=u;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),h.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=ce.size;c.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),ae("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:n}=await Te().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${n}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const u=(await import("file://"+require("path").join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;u&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await u.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(Ee(),c.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),c.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:n}=await import("./services/process-detector.js"),{loadPersistedSessions:u}=await import("./services/terminal-persistence.js"),g=await u();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const v=await n(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${v.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const n=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",n.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(c.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await Pe()}catch(t){const n=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(ke(),c.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Ke()),c.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await y([])}catch(t){const n=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await Ce(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Ae(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}_e.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const w=Ue(),C=D.join(B.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function S(){try{if(A(C)){const r=T(C,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ee(async(r,o)=>{await b(r,w,o)}),process.on("SIGTERM",()=>{const r=S();b("SIGTERM",w,r)}),process.on("SIGINT",()=>{const r=S();b("SIGINT",w,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=S();b("SIGBREAK",w,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",w)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
|
|
2
|
+
import{existsSync as E,readFileSync as T}from"node:fs";import B from"node:os";import R from"node:path";import M from"cors";import P from"express";import{adapterRegistry as O}from"./adapter/index.js";import{attachBrowserWebSocketServer as x}from"./browser/browser-ws-bridge.js";import{getActiveBridgeHttpPort as I,getAutoRegisterConfigFilePath as _,getBridgeRuntimePropertiesFilePath as F,getRuntimeHomeDir as G,reserveBridgeListenPort as K,validateProductionToken as L,writeBridgeRuntimePropertiesFile as j}from"./config.js";import{attachRemoteDesktopWebSocketServer as N}from"./remote-desktop/index.js";import{acodeTodosRouter as H}from"./routes/acode-todos.js";import{aiSourcesRouter as W}from"./routes/ai-sources.js";import{backgroundTasksRouter as U}from"./routes/background-tasks.js";import{browserListenersRouter as z}from"./routes/browser-listeners.js";import{browserSessionsRouter as J}from"./routes/browser-sessions.js";import{computerRouter as Y}from"./routes/computer.js";import{dashboardRouter as q}from"./routes/dashboard.js";import{eventsRouter as Z}from"./routes/events.js";import{fileBrowserRouter as Q}from"./routes/file-browser.js";import{fileChangeDiffRouter as V}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as X}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as ee}from"./routes/file-snapshot.js";import{gitRouter as re}from"./routes/git.js";import{instanceRouter as te,setGracefulShutdownFn as ie}from"./routes/instance.js";import{jdksRouter as oe}from"./routes/jdks.js";import{launchRouter as ne}from"./routes/launch.js";import{mcpRouter as se}from"./routes/mcp.js";import{processesRouter as ae}from"./routes/processes.js";import{propertiesRouter as me}from"./routes/properties.js";import{attachPtyWebSocketServer as ue,closeAllPtySessions as ce,ptyRouter as de,ptySessions as ge}from"./routes/pty.js";import{runtimeBindingRouter as pe,logRuntimeBindingStartupState as fe}from"./routes/runtime-binding.js";import{sessionsRouter as le}from"./routes/sessions.js";import{skillsRouter as be}from"./routes/skills.js";import{subAgentsRouter as we}from"./routes/sub-agents.js";import{systemMetricsRouter as he}from"./routes/system-metrics.js";import{taskContextRouter as Se}from"./routes/task-context.js";import{terminalRouter as Re,sdkSessions as h}from"./routes/terminal.js";import{ymlRouter as Pe}from"./routes/yml.js";import{ensureAcodePackageReleased as Ie}from"./services/acode-package.js";import{accessControlMiddleware as ye}from"./services/access-control.js";import{getAgentProcessManager as y}from"./services/agent-process-manager.js";import{autoRegister as $e,unregister as ke,bridgeRestartCleanup as Ce,cancelBackgroundRegisterRetries as ve}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Ae}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as De}from"./services/browser-session-manager.js";import{handleCliCommand as Ee}from"./services/cli-commands.js";import{disposeDesktopMcpManager as Te}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Be}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Me}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as Oe}from"./services/lifecycle-state.js";import{startOrphanMonitor as xe,stopOrphanMonitor as _e}from"./services/orphan-monitor.js";import{detectOrphanProcesses as Fe}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Ge,shouldCleanupPersistedSessionsOnStartup as Ke}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Le}from"./services/startup-config-wizard.js";import{subAgentStore as je}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as Ne}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const C=await Ee();C.handled&&process.exit(C.exitCode),await Le(),L(),Ae(),Ie(),Me(),fe(),await K(),j(),e.info(`[runtime-bridge] \u5DF2\u5199\u5165\u8FD0\u884C\u65F6\u914D\u7F6E ${F()}\uFF08port=${I()}\uFF09`),String(process.env.ACODE_HOME||"").trim()||(process.env.ACODE_HOME=R.join(G(),".acode")),e.info(`[runtime-bridge] ACode \u6570\u636E\u76EE\u5F55: ${process.env.ACODE_HOME}`);async function He(){try{if(await $e())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),s=o();!!s.userKey&&s.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${_()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}He().then(()=>We()).then(()=>Oe()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function We(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const s=await Ce();s.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${s.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${s.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function Ue(){try{const r=await $();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await y().rebuildRegistry(r.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}Ue().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function ze(){try{const r=await import("node:fs/promises"),o=await import("node:path"),s=await import("node:os"),f=o.join(s.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await $();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Ke(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await y().rebuildRegistry(a.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await Fe(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:n}=await import("node:child_process");n(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(n){const c=n;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await k([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}ze().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),xe().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(ye),i.use(M()),i.use(P.json({limit:"1mb"})),i.use("/runtime",pe),i.use("/runtime",me),i.use("/runtime",Pe),i.use("/runtime",te),i.use("/runtime",be),i.use("/runtime",se),i.use("/runtime",Re),i.use("/runtime",le),i.use("/runtime",ae),i.use("/runtime",ne),i.use("/runtime",oe),i.use("/runtime",he),i.use("/runtime",Z),i.use("/runtime",re),i.use("/runtime",ee),i.use("/runtime",H),i.use("/runtime",U),i.use("/runtime",we),i.use("/runtime",J),i.use("/runtime",z),i.use("/runtime",W),i.use("/runtime",Se),i.use("/runtime",X),i.use("/runtime",V),i.use("/runtime/computer",Y),i.use("/pty",de),i.use("/",q),i.use("/api/file-browser",Q);function Je(){const r=I(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return ue(o),N(o),x(o),o.on("error",s=>{if(s.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",s),process.exitCode=1}),o}let v=!1;async function b(r,o,s=!1){if(v){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}v=!0,s||S()&&(s=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${s})`);const f=Date.now(),u=Ge(s);try{const a=h.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,n]of h.entries())try{const c=n.providerId||"claude-code",g=O.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),h.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),h.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=ge.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),ce("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:n}=await Be().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${n}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+require("path").join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(_e(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:n}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const D=await n(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${D.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const n=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",n.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await ke()}catch(t){const n=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(ve(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Ne()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await k([])}catch(t){const n=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await De(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Te(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}je.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const w=Je(),A=R.join(B.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function S(){try{if(E(A)){const r=T(A,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ie(async(r,o)=>{await b(r,w,o)}),process.on("SIGTERM",()=>{const r=S();b("SIGTERM",w,r)}),process.on("SIGINT",()=>{const r=S();b("SIGINT",w,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=S();b("SIGBREAK",w,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",w)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
|
|
3
3
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{promises as
|
|
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};
|
|
2
2
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{promises as
|
|
1
|
+
import{promises as p}from"node:fs";import k from"node:path";import{Router as l}from"express";import{getAcodeDataHome as A}from"../config.js";import{validateToken as c}from"../middleware/auth.js";import{createLogger as I}from"../utils/logger.js";import{listPtySessions as y}from"./pty.js";const u=I("acode-bg-tasks"),g=l();function S(r){return String(r).replace(/[^a-zA-Z0-9_-]/g,"_")}function w(r){return k.join(A(),"bg-tasks",S(r),"state.json")}g.get("/acode-bg-tasks/:agentId",c,async(r,s)=>{const o=r.params.agentId,e=Array.isArray(o)?o[0]:o;if(!e||!String(e).trim()){s.status(400).json({ok:!1,error:"agentId is required"});return}const d=w(String(e));try{const a=await p.readFile(d,"utf-8"),n=JSON.parse(a),m=(Array.isArray(n.tasks)?n.tasks:[]).map(f=>{const t=f;return{taskId:t.taskId,status:t.status,command:t.commandPreview??t.command,commandPreview:t.commandPreview,cwd:t.cwd,startedAt:t.startedAt,finishedAt:t.finishedAt,exitCode:t.exitCode,signal:t.signal,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes}});s.json({ok:!0,agentId:String(e),updatedAt:typeof n.updatedAt=="number"?n.updatedAt:null,tasks:m})}catch(a){if((typeof a=="object"&&a!==null?Reflect.get(a,"code"):void 0)==="ENOENT"){s.json({ok:!0,agentId:String(e),updatedAt:null,tasks:[]});return}if(a instanceof SyntaxError){u.warn("[acode-bg-tasks] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",d),s.json({ok:!0,agentId:String(e),updatedAt:null,tasks:[]});return}const i=a;u.error("[acode-bg-tasks] \u8BFB\u53D6\u5931\u8D25: %s",i.message),s.status(500).json({ok:!1,error:i.message})}}),g.get("/acode-agent-pty-sessions/:agentId",c,(r,s)=>{const o=r.params.agentId,e=Array.isArray(o)?o[0]:o;if(!e||!String(e).trim()){s.status(400).json({ok:!1,error:"agentId is required"});return}const d=String(e),n=y().filter(i=>i.ownerUserId===d);s.json({ok:!0,agentId:d,sessions:n})});export{g as backgroundTasksRouter};
|
|
2
2
|
|