aws-runtime-bridge 1.9.131 → 1.9.134
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.d.ts +15 -0
- package/dist/adapter/AcodeSdkAdapter.js +5 -5
- package/dist/adapter/types.d.ts +9 -0
- package/dist/browser/built-in-browser-tools.js +1 -1
- package/dist/routes/system-metrics.js +1 -1
- package/dist/routes/terminal.js +19 -19
- package/dist/services/instance-features.d.ts +5 -0
- package/dist/services/instance-features.js +1 -1
- package/dist/services/process-detail.d.ts +77 -0
- package/dist/services/process-detail.js +32 -0
- package/dist/services/process-top.d.ts +53 -0
- package/dist/services/process-top.js +50 -0
- package/dist/services/session-output.d.ts +10 -0
- package/dist/services/session-output.js +3 -3
- package/package/acode/dist/built-in-file-tools.d.ts +25 -1
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/image-utils.d.ts +52 -0
- package/package/acode/dist/image-utils.js +2 -0
- package/package/acode/dist/index.d.ts +1 -0
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/runtime.d.ts +15 -1
- package/package/acode/dist/runtime.js +26 -26
- package/package/acode/dist/types.d.ts +3 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +8 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +28 -25
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +6 -6
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +6 -0
- package/package/aws-client-agent-mcp/dist/memory-tools.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +4 -0
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package.json +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +0 -1066
- package/package/aws-client-agent-mcp/dist/config.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +0 -259
- package/package/aws-client-agent-mcp/dist/context-manager.test.d.ts +0 -2
- package/package/aws-client-agent-mcp/dist/context-manager.test.js +0 -312
- package/package/aws-client-agent-mcp/dist/http-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/http-client.test.js +0 -808
- package/package/aws-client-agent-mcp/dist/launch-config-tools.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/launch-config-tools.test.js +0 -110
- package/package/aws-client-agent-mcp/dist/logger.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/logger.test.js +0 -27
- package/package/aws-client-agent-mcp/dist/mcp-server.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +0 -2798
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +0 -152
- package/package/aws-client-agent-mcp/dist/memory-store.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js +0 -664
- package/package/aws-client-agent-mcp/dist/message-buffer.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.test.js +0 -142
- package/package/aws-client-agent-mcp/dist/parent-lifecycle.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/parent-lifecycle.test.js +0 -81
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +0 -201
- package/package/aws-client-agent-mcp/dist/status-reporter.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js +0 -157
- package/package/aws-client-agent-mcp/dist/watchdog.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/watchdog.test.js +0 -124
- package/package/aws-client-agent-mcp/dist/websocket-client.test.d.ts +0 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.test.js +0 -725
package/dist/routes/terminal.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{spawn as Xe}from"node:child_process";import{promises as N}from"node:fs";import Qe from"node:os";import j from"node:path";import{TextDecoder as ee}from"node:util";import{Router as Ve}from"express";import{v4 as Ge}from"uuid";import be from"axios";import{adapterRegistry as w,getToolActionInfo as ye,isTransientClipboardPasteFilePath as Ce,redactTransientClipboardPastePaths as
|
|
1
|
+
import{spawn as Xe}from"node:child_process";import{promises as N}from"node:fs";import Qe from"node:os";import j from"node:path";import{TextDecoder as ee}from"node:util";import{Router as Ve}from"express";import{v4 as Ge}from"uuid";import be from"axios";import{adapterRegistry as w,getToolActionInfo as ye,isTransientClipboardPasteFilePath as Ce,redactTransientClipboardPastePaths as q,registerSdkProviders as Je,resolveSdkProviderIdByCommand as Ye}from"../adapter/index.js";import{validateToken as I}from"../middleware/auth.js";import{getActiveBridgeHttpPort as Ze,getAcodeDataHome as _e}from"../config.js";import{getAgentProcessManager as he}from"../services/agent-process-manager.js";import{setAgentFeatures as et,getAgentFeatures as tt,isFeatureEnabled as $e,LAUNCH_ITEM_FEATURE_KEY as nt,HIRE_FEATURE_KEY as ot}from"../services/instance-features.js";import{setPanelEnvVars as rt}from"../services/panel-env.js";import{setChangeCacheRetentionDays as st}from"../services/change-cache-retention.js";import{getAiConfigService as it}from"../services/cc-switch-sdk.js";import{prepareAcodeInstanceConfig as at,redactForLog as te}from"../services/instance-ai-config-service.js";import{enqueueMcpLaunchBinding as ct}from"../services/mcp-launch-binding-queue.js";import{resolveSchedulerBaseUrlFromToken as De}from"../services/auto-register.js";import{findClaudeCodeProcesses as ut,isProcessRunning as dt}from"../services/process-detector.js";import{bridgeEventBuffer as Re,sendOutput as X,sendQuestionRequest as lt,sendToolAuthRequest as mt,sendStatus as _}from"../services/session-output.js";import{getAllPushStats as ft,startHeartbeatScheduler as pt}from"../services/event-delta-pusher.js";import{forgetSession as v,onSdkToolUseEnd as gt,onSdkToolUseStart as yt}from"../services/sdk-tool-file-change-recorder.js";import{findPersistedSessionByAgentId as ht,removePersistedSession as F,savePersistedSessions as It,updatePersistedSessionAutoCommands as St,updatePersistedSessionRuntimeState as At,upsertPersistedSession as Tt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as kt}from"../utils/instance-ai-config-debug-logger.js";import{logger as h}from"../utils/logger.js";const S=Ve();function Pe(e){const n=e.header("X-Runtime-Token");return n&&n.trim()?n.trim():(e.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||void 0}const f=new Map,wt=45e3,ne=new Map;function bt(e){if(ne.has(e))return;const n=setInterval(()=>{const t=f.get(e);if(!t){L(e);return}const o=t.currentRuntimeStatus;if(o!=="thinking"&&o!=="tool_using"&&o!=="compacting"){L(e);return}_(t.agentId,e,o,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},wt);ne.set(e,n)}function L(e){const n=ne.get(e);n&&(clearInterval(n),ne.delete(e))}const Ee=4e3,Ct=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u4F53:
|
|
4
|
-
`;function Ie(e){if(e==null||typeof e!="object"||Array.isArray(e))return;const n=e,t={};return typeof n.model=="string"&&n.model.trim()&&(t.model=n.model.trim()),typeof n.baseURL=="string"&&n.baseURL.trim()&&(t.baseURL=n.baseURL.trim()),typeof n.apiKey=="string"&&n.apiKey.trim()&&(t.apiKey=n.apiKey.trim()),typeof n.effort=="string"&&n.effort.trim()&&(t.effort=n.effort.trim()),t}const
|
|
4
|
+
`;function Ie(e){if(e==null||typeof e!="object"||Array.isArray(e))return;const n=e,t={};return typeof n.model=="string"&&n.model.trim()&&(t.model=n.model.trim()),typeof n.baseURL=="string"&&n.baseURL.trim()&&(t.baseURL=n.baseURL.trim()),typeof n.apiKey=="string"&&n.apiKey.trim()&&(t.apiKey=n.apiKey.trim()),typeof n.effort=="string"&&n.effort.trim()&&(t.effort=n.effort.trim()),t}const _t=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u5934:
|
|
7
|
-
`,K=new Set;async function
|
|
7
|
+
`,K=new Set;async function $t(e,n){const t=[],o=[],r=j.join(e,".agentswork","memory");try{const c=(await N.readdir(r)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await N.readFile(j.join(r,u),"utf-8");return JSON.parse(l)}catch{return h.warn("[loadAgentStartupMemories] Failed to parse memory file: %s",j.join(r,u)),null}}));for(const u of d)if(u?.by_uri)for(const l of Object.values(u.by_uri)){const m=l.memory_type||"memory",p=(l.content||"").trim();p&&(m==="recently_memory"?t.push({title:l.title,content:p,uri:l.uri||""}):m==="agent_memory"&&o.push({title:l.title,content:p,uri:l.uri||""}))}}catch{h.debug("[loadAgentStartupMemories] \u65E0\u6CD5\u8BFB\u53D6\u8BB0\u5FC6\u76EE\u5F55: %s",r)}if(t.length===0&&o.length===0&&n?.schedulerBaseUrl&&n?.runtimeAccessToken&&n?.agentId){const a=`${n.schedulerBaseUrl.replace(/\/+$/,"")}/mcp/call`,c={"Content-Type":"application/json","X-Runtime-Token":n.runtimeAccessToken,Authorization:`Bearer ${n.runtimeAccessToken}`},d=["recently_memory","agent_memory"],u=await Promise.allSettled(d.map(l=>fetch(a,{method:"POST",headers:c,body:JSON.stringify({tool:"list_memories",arguments:{agentId:n.agentId,memory_type:l}})}).then(m=>{if(!m.ok)throw new Error(`Server returned ${m.status}`);return m.json()})));for(let l=0;l<u.length;l++){const m=u[l];if(m.status!=="fulfilled")continue;const p=m.value;if(!Array.isArray(p))continue;const T=d[l]==="recently_memory"?t:o;for(const y of p){const g=(y.content||"").trim();g&&T.push({title:y.title,content:g,uri:y.uri||""})}}(t.length>0||o.length>0)&&h.info(`[loadAgentStartupMemories] Loaded ${t.length} task(s) and ${o.length} memory(s) from server for ${n.agentId}`)}const s=10;t.sort((a,c)=>c.uri.localeCompare(a.uri)),o.sort((a,c)=>c.uri.localeCompare(a.uri));const i=[];if(t.length>0){const c=t.slice(0,s).map((d,u)=>`${d.title?`\u3010${d.title}\u3011`:`\u6761\u76EE ${u+1}`}
|
|
8
8
|
${d.content}`);i.push(`\u3010\u77ED\u671F\u8BB0\u5FC6\u3011
|
|
9
9
|
${c.join(`
|
|
10
10
|
|
|
@@ -14,41 +14,41 @@ ${c.join(`
|
|
|
14
14
|
|
|
15
15
|
`)}`),o.length>s&&i.push(`... \u53CA\u53E6\u5916 ${o.length-s} \u6761 agent \u8BA4\u77E5`)}if(i.length!==0)return i.join(`
|
|
16
16
|
|
|
17
|
-
`)}function
|
|
17
|
+
`)}function Dt(e,n){return e!=="acode"?{supported:!1,statusCode:400,error:"context reset without restart is only supported by ACode"}:n?{supported:!0}:{supported:!1,statusCode:500,error:"ACode adapter does not expose resetContext"}}function Rt(e){return e!=="acode"}function Pt(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function oe(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,o=Number.isFinite(n.outputTokens)?n.outputTokens:0;if(t<=0&&o<=0&&!n.contextLimit&&!n.maxOutput&&!n.inputLimit&&!n.compactionThreshold)return;const r={inputTokens:t,outputTokens:o,...n.contextLimit?{contextLimit:n.contextLimit}:{},...n.maxOutput?{maxOutput:n.maxOutput}:{},...n.inputLimit?{inputLimit:n.inputLimit}:{},...n.compactionThreshold?{compactionThreshold:n.compactionThreshold}:{},...n.cacheHitTokens?{cacheHitTokens:n.cacheHitTokens}:{},...n.cacheMissTokens?{cacheMissTokens:n.cacheMissTokens}:{}};return process.env.ACODE_TOKEN_DEBUG==="1"&&(r.inputTokens>0||r.outputTokens>0||r.cacheHitTokens!==void 0||r.cacheMissTokens!==void 0)&&console.log(`[TokenDebug][Terminal] resolveStatusChangeUsage: input=${r.inputTokens} output=${r.outputTokens} cacheHit=${r.cacheHitTokens??"(none)"} cacheMiss=${r.cacheMissTokens??"(none)"} actionType=${e?.actionType??"(none)"}`),r}function Et(e,n){const t=String(e||"").trim().toLowerCase(),o=String(n?.actionType||"").trim().toLowerCase();return t==="tool_using"&&o==="idle"?n?{status:"waiting_input",actionInfo:n}:{status:"waiting_input"}:n?{status:e,actionInfo:n}:{status:e}}const Q=new Map,Mt="utf-8",Me="utf-8",Le=300,xe=6e4;function V(e){return String(e).padStart(2,"0")}function Lt(e,n=new Date){const t=n.getFullYear(),o=V(n.getMonth()+1),r=V(n.getDate()),s=V(n.getHours()),i=V(n.getMinutes()),a=`${t}${o}${r}-${s}${i}${V(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return j.join(_e(),"cmd-dist",e,`${t}-${o}-${r}`,s,i,`${a}-cmd.out`)}function xt(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
|
|
18
18
|
`).replace(/\r/g,`
|
|
19
19
|
`),t=n.endsWith(`
|
|
20
20
|
`)?n.slice(0,-1):n;return t?t.split(`
|
|
21
|
-
`).length:1}function
|
|
21
|
+
`).length:1}function Ut(e,n=Le){return`\r
|
|
22
22
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u8D85\u8FC7 ${n} \u884C\uFF0C\u5B8C\u6574\u8F93\u51FA\u5DF2\u5199\u5165: ${e}\r
|
|
23
23
|
[ACode] Agent \u53EF\u81EA\u884C\u8BFB\u53D6\u8BE5\u6587\u4EF6\uFF0C\u6216\u5728\u8BE5\u6587\u4EF6\u4E2D\u641C\u7D22\u9700\u8981\u7684\u5185\u5BB9\u3002\r
|
|
24
|
-
`}function
|
|
24
|
+
`}function jt(e=xe){return`\r
|
|
25
25
|
[ACode] \u547D\u4EE4\u8D85\u8FC7 ${Math.round(e/1e3)} \u79D2\u6CA1\u6709\u65B0\u7684\u8F93\u51FA\uFF0C\u5DF2\u505C\u6B62\u6267\u884C\u5E76\u4FDD\u7559\u6B64\u524D\u8F93\u51FA\u3002\r
|
|
26
|
-
`}async function Ue(e){const n=e.outputPath||
|
|
27
|
-
`).trim()}function
|
|
28
|
-
`),!0;const r=
|
|
26
|
+
`}async function Ue(e){const n=e.outputPath||Lt(e.agentId,e.startedAt);return e.outputPath=n,await N.mkdir(j.dirname(n),{recursive:!0}),await N.writeFile(n,e.chunks.join(""),"utf-8"),n}function Bt(e){return String(e??"").replace(/\r/g,`
|
|
27
|
+
`).trim()}function Ot(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?Mt:Me)}function je(e=Ot()){if(e!=="utf-8")try{return new ee(e,{fatal:!1})}catch{return new ee(Me,{fatal:!1})}return Nt()}function Nt(){let e=null,n=null,t=null;const o=[];function r(s){try{return new ee(s,{fatal:!1})}catch{return new ee("utf-8",{fatal:!1})}}return{decode(s,i){if(s!=null&&o.push(s instanceof ArrayBuffer?Buffer.from(s):Buffer.isBuffer(s)?s:Buffer.from(s.buffer,s.byteOffset,s.byteLength)),t==="gb18030")return n||(n=r("gb18030")),n.decode(s,i);e||(e=r("utf-8"));const a=e.decode(s,i);if(t===null&&a.includes("\uFFFD")){t="gb18030",n=r("gb18030");const c=Buffer.concat(o);return n.decode(c)}return t===null&&!i?.stream&&(t="utf-8"),a}}}function re(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function qt(e){const n=e.trim().match(/^cd(?:\s+(.*))?$/i);if(!n)return;const t=n[1]?.trim();if(!t)return null;const o=t.replace(/^\/d\s+/i,"").trim();return o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'")?o.slice(1,-1):o}function vt(e){const n=Q.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return Q.set(e.sessionId,t),t}function Be(e){for(const n of f.values())if(n.agentId===e)return n}async function Ft(e){const n=w.get(e.providerId||"claude-code"),t=se(n.getSessionStatus(e.sessionId),e.currentRuntimeStatus,e.currentRuntimeActionType);return{sessionId:e.sessionId,status:t,runtimeStatus:t,runtimeActionType:e.currentRuntimeActionType,runtimeActionLabel:e.currentRuntimeActionLabel,runtimeActionDetail:e.currentRuntimeActionDetail,agentId:e.agentId,workspacePath:e.workspacePath,command:e.config.command,mode:"sdk",providerSessionId:n.getProviderSessionId(e.sessionId),reused:!0}}function se(e,n,t){const o=String(e||"").trim();if(o){const s=String(n||"").trim(),i=String(t||"").trim().toLowerCase();return o.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&i==="idle"?s:o}return String(n||"").trim()||"running"}function Kt(e,n=dt){return e.pid?n(e.pid)?Ke(e.command)==="acode"?{reusable:!1,reason:"in-process-provider"}:{reusable:!0,reason:"active-pid"}:{reusable:!1,reason:"dead-pid"}:{reusable:!1,reason:"missing-pid"}}function eo(e){const n=Be(e);if(!n)h.info(`[cleanupSdkSessionByAgentId] No active SDK session found for agentId=${e}, cleaning residual state anyway`);else{const t=n.sessionId;return h.info(`[cleanupSdkSessionByAgentId] Cleaning up SDK session for agentId=${e}, sessionId=${t}`),L(t),f.delete(t),v(t),ie(t),F(t).catch(o=>{h.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${o}`)}),t}K.has(e)&&(K.delete(e),h.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ie(e){const n=Q.get(e);if(!n?.runningProcess){Q.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,Q.delete(e)}}function b(e,n){n&&(e.seq+=1,X(e.agentId,n,e.sessionId,e.seq,void 0,{runtimeAccessToken:e.runtimeAccessToken,schedulerBaseUrl:e.schedulerBaseUrl}).catch(()=>{}))}function Se(e){return`\x1B[36m${e}>\x1B[0m `}function zt(e,n){return n==="~"?Qe.homedir():j.resolve(e,n)}async function Ht(e,n,t){const o=qt(t);if(o===void 0)return!1;if(o===null)return b(e,`${n.currentDirectory}\r
|
|
28
|
+
`),!0;const r=zt(n.currentDirectory,o);try{return(await N.stat(r)).isDirectory()?(n.currentDirectory=r,b(e,`${n.currentDirectory}\r
|
|
29
29
|
`),!0):(b(e,`cd: not a directory: ${r}\r
|
|
30
30
|
`),!0)}catch(s){const i=s instanceof Error?s.message:String(s);return b(e,`cd: ${i}\r
|
|
31
|
-
`),!0}}async function
|
|
31
|
+
`),!0}}async function Wt(e,n){const t=f.get(e);if(!t)throw new Error("SDK session not found");const o=Bt(n),r=vt(t);if(!o)return{started:!1,cwd:r.currentDirectory};if(r.runningProcess)throw new Error("A terminal command is already running for this session");const s=q(o);if(b(t,`${Se(r.currentDirectory)}${s}\r
|
|
32
32
|
`),Ce(o))return b(t,`[Terminal Warning] \u68C0\u6D4B\u5230\u526A\u8D34\u677F\u4E34\u65F6 paste \u6587\u4EF6\u8DEF\u5F84\uFF0C\u5DF2\u8DF3\u8FC7\u6267\u884C\u3002\u8BF7\u7C98\u8D34\u6587\u4EF6\u5185\u5BB9\u6216\u4F7F\u7528\u663E\u5F0F\u8BFB\u53D6\u547D\u4EE4\u3002\r
|
|
33
|
-
`),b(t,Se(r.currentDirectory)),{started:!1,cwd:r.currentDirectory};if(await
|
|
33
|
+
`),b(t,Se(r.currentDirectory)),{started:!1,cwd:r.currentDirectory};if(await Ht(t,r,o))return{started:!1,cwd:r.currentDirectory};await _(t.agentId,e,"tool_using",{actionType:"bash",actionLabel:"\u7EC8\u7AEF\u547D\u4EE4",actionDetail:s},void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl});const a=Xe(o,{cwd:r.currentDirectory,shell:!0,env:Oe(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});r.runningProcess=a;const c=je(),d=je(),u=t.providerId==="acode",l={agentId:t.agentId,startedAt:new Date,chunks:[],spilled:!1};let m;const p=()=>{m&&(clearTimeout(m),m=void 0)},T=()=>{p(),m=setTimeout(()=>{r.runningProcess===a&&(b(t,jt()),a.kill())},xe)},y=(g,C=!0)=>{if(g&&(u&&l.chunks.push(g),u&&C&&T(),!(u&&l.spilled))){if(u&&xt(l.chunks.join(""))>Le){l.spilled=!0,Ue(l).then($=>{b(t,Ut($))}).catch($=>{const M=$ instanceof Error?$.message:String($);b(t,`\r
|
|
34
34
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${M}\r
|
|
35
35
|
`)});return}b(t,g)}};return u&&T(),a.stdout.on("data",g=>{y(re(c,g))}),a.stderr.on("data",g=>{y(re(d,g))}),a.on("error",g=>{b(t,`\r
|
|
36
36
|
[Terminal Error] ${g.message}\r
|
|
37
|
-
`)}),a.on("close",(g,C)=>{
|
|
37
|
+
`)}),a.on("close",(g,C)=>{p(),r.runningProcess=null,y(re(c,void 0,!0),!1),y(re(d,void 0,!0),!1),l.spilled&&Ue(l).catch($=>{const M=$ instanceof Error?$.message:String($);b(t,`\r
|
|
38
38
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u6700\u7EC8\u843D\u76D8\u5931\u8D25: ${M}\r
|
|
39
39
|
`)}),g&&g!==0?b(t,`\r
|
|
40
40
|
[exit ${g}]\r
|
|
41
41
|
`):C&&b(t,`\r
|
|
42
42
|
[signal ${C}]\r
|
|
43
|
-
`),b(t,Se(r.currentDirectory)),_(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:r.currentDirectory}}function Oe(e,n,t,o){const r={};for(const[s,i]of Object.entries(t))i!==void 0&&(r[s]=i);if(n&&(r.AWS_WORKSPACE_PATH=String(n)),o)for(const[s,i]of Object.entries(o)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(r[a]=c)}return r.AWS_AGENT_ID=String(e),r.AWS_MCP_CLAIM_LAUNCH_BINDING="true",r.AWS_RUNTIME_BRIDGE_BASE_URL=`http://127.0.0.1:${Ze()}`,String(r.ACODE_HOME||"").trim()||(r.ACODE_HOME=_e()),$e(e,nt)&&(r.AWS_LAUNCH_CONFIG_TOOLS="1"),$e(e,ot)&&(r.AWS_HIRE_TOOLS="1"),r}function
|
|
44
|
-
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function
|
|
43
|
+
`),b(t,Se(r.currentDirectory)),_(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:r.currentDirectory}}function Oe(e,n,t,o){const r={};for(const[s,i]of Object.entries(t))i!==void 0&&(r[s]=i);if(n&&(r.AWS_WORKSPACE_PATH=String(n)),o)for(const[s,i]of Object.entries(o)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(r[a]=c)}return r.AWS_AGENT_ID=String(e),r.AWS_MCP_CLAIM_LAUNCH_BINDING="true",r.AWS_RUNTIME_BRIDGE_BASE_URL=`http://127.0.0.1:${Ze()}`,String(r.ACODE_HOME||"").trim()||(r.ACODE_HOME=_e()),$e(e,nt)&&(r.AWS_LAUNCH_CONFIG_TOOLS="1"),$e(e,ot)&&(r.AWS_HIRE_TOOLS="1"),r}function Xt(e){const n=e.trim(),t=n[0],o=n[n.length-1];return(t==='"'||t==="'")&&t===o?n.slice(1,-1):n}async function Qt(e){const n=String(e);if(!Ce(n))return n;const t=Xt(n);return j.isAbsolute(t)?N.readFile(t,"utf-8"):n}function Ne(e,n){const t={};for(const r of[e?.env,n])if(r)for(const[s,i]of Object.entries(r)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(t[a]=c)}const o=t.ANTHROPIC_MODEL?.trim()||t.CODEX_MODEL?.trim()||void 0;return{envOverrides:t,model:o}}async function Vt(){try{return await it().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function Gt(e){if(e==null)return;const t=(typeof e=="string"?e:JSON.stringify(e,null,2)).trim();if(t)return t.length<=Ee?t:`${t.slice(0,Ee)}
|
|
44
|
+
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function Jt(e){try{const n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return["directMessages","groupMessages","messages"].some(t=>Array.isArray(n[t])&&n[t].length>0)}catch{}return e.trim().length>0}function Yt(e){if(e.data.actionType==="mcp")return!0;const t=String(e.data.toolName||"").toLowerCase();return t.startsWith("mcp__")||t.includes("-mcp__")||t.includes("mcp_")}function Zt(e){if(e.type!=="tool_use_end")return;const n=Gt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),o=e.data.actionType||t.actionType;if(o==="idle"){const r=String(e.data.rawToolName||e.data.toolName||"").toLowerCase();if((r.includes("poll_message")||r.includes("get_message"))&&!Jt(n))return}return o==="mcp"&&Yt(e)?{actionType:"mcp",actionLabel:"MCP\u8FD4\u56DE",actionDetail:e.data.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}:{actionType:o,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:e.data.actionDetail||t.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}}function en(e){if(e.type==="ai_request"){const n=e.data.model?` ${e.data.model}`:"",t=e.data.lastUserMessagePreview?`\uFF1A${e.data.lastUserMessagePreview}`:"";return`\r
|
|
45
45
|
[ACode] \u6B63\u5728\u8BF7\u6C42\u6A21\u578B${n}${t}\r
|
|
46
46
|
`}if(e.type==="text_delta"||e.type==="thinking"||e.type==="command_output")return e.data.text||void 0;if(e.type==="error")return e.data.text?`\r
|
|
47
47
|
[SDK Error] ${e.data.text}\r
|
|
48
|
-
`:void 0}function
|
|
49
|
-
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function
|
|
50
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",r=t.length>0?`${
|
|
51
|
-
`)}`:"",s=e.requestBody?`${bt}${e.requestBody}`:"";return`${o}${r}${s}`}function mn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function fn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function pn(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],o=Number(t);if(Number.isFinite(o)&&o>0)return o}}function gn(e,n){if(!fn(e,n)){if(e.type==="ai_request"){const t=pn(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:ln(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),o=qe(e,t),r=dn(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const x=new Map,ae=new Map,ce=new Map,G=new Map,yn=20,hn=500,In=3e4;async function ue(e,n=In,t=2){for(let o=0;o<=t;o++){const r=new AbortController;let s;try{const i=e(r.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{r.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(o<t){const c=1e3*(o+1);h.warn(`sendOutput attempt ${o+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}h.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let o,r;if(t)o=G.get(t),r=t;else{const f=[];for(const[T,y]of G)T.startsWith(e+":")&&y.buffer&&f.push(y.sourceEventType);for(const T of f)de(e,T);return}if(!o||!o.buffer)return;o.timer=null;const s=o.buffer,i=o.seq,a=o.entry,c=o.sourceEventType;o.buffer="",r&&G.delete(r);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},m=(x.get(e)??Promise.resolve()).then(()=>ue(f=>X(a.agentId,s,e,i,d,u,f)),()=>ue(f=>X(a.agentId,s,e,i,d,u,f)));x.set(e,m),m.finally(()=>{x.get(e)===m&&x.delete(e)})}function Sn(e,n){const t=Zt(e);if(!t)return;n.seq+=1;const o=n.seq,r=en(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<yn){const c=`${e.sessionId}:${e.type}`;let d=G.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=o,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),hn)}G.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)),()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function Ke(e){return Ye(e)}let ze=!1;function An(){ze||(Je(w,Tn),ft(),ze=!0)}function Tn(e,n){e.on("event",t=>{const o=p.get(t.sessionId);if(o){if(t.type==="tool_use_start"?gt(o.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,o.workspacePath):t.type==="tool_use_end"&&pt(t,{sessionId:o.sessionId,agentId:o.agentId,workspacePath:o.workspacePath,providerId:o.providerId}),console.log(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(o.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=gn(t,o.currentRuntimeStatus);i&&_(o.agentId,t.sessionId,i.status,i.actionInfo,oe(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}Sn(t,o);const s=Yt(t);if(s){const i={runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(f=>setTimeout(f,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(f=>setTimeout(f,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):_(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,o,r)=>{const s=p.get(t);if(s){de(t),o==="thinking"||o==="tool_using"||o==="compacting"?wt(t):L(t);const i=Pt(o,r);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),console.log(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),St(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const f=(ae.get(t)??Promise.resolve()).then(async()=>{for(let y=0;y<=2;y++){if(await _(s.agentId,t,i.status,l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;y<2&&(h.warn(`[${n.displayName}] compaction sendStatus attempt ${y+1} failed (HTTP), retrying in ${1e3*(y+1)}ms...`),await new Promise(C=>setTimeout(C,1e3*(y+1))))}h.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{h.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,f),f.finally(()=>{ae.get(t)===f&&ae.delete(t)})}else{const m=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const y=(ce.get(t)??Promise.resolve()).then(async()=>{for(let C=0;C<=2;C++){if(await _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;C<2&&await new Promise(M=>setTimeout(M,1e3*(C+1)))}h.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(g=>{h.warn(`[${n.displayName}] idle status chain error:`,g)});ce.set(t,y),y.finally(()=>{ce.get(t)===y&&ce.delete(t)})}else _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const m=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,console.log(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),_(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:m},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const o=p.get(t.sessionId);o&&(console.log(`[${n.displayName} Adapter] AskUserQuestion for agent ${o.agentId}`),lt(o.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.toolCallId))}),e.on("permission-request",t=>{const o=p.get(t.sessionId);if(o){console.log(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${o.agentId}`);const r=t.toolInput?v(JSON.stringify(t.toolInput).slice(0,400)):void 0;_(o.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:r||t.toolName},void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}})}A.post("/start",S,async(e,n)=>{const{agentId:t,workspacePath:o,mode:r="sdk"}=e.body||{};if(!t||!o){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;ct({agentId:String(t),workspacePath:String(o),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!=null&&(et(String(t),e.body.runtimeFeatures),console.log(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(tt(String(t)))}`)),e.body?.envVars!=null&&typeof e.body.envVars=="object"&&(rt(e.body.envVars),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(st(e.body.changeCacheRetentionDays),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),r&&r!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${r}" requested for agent ${t}; starting SDK session instead.`),await kn(e,n)});async function kn(e,n){const{agentId:t,workspacePath:o,command:r,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:m,envOverrides:f,idleInputAutoCommand:T,nonInputAutoCommand:y,model:g,instanceAiConfig:C,subAgentModel:$,subAgentEffort:M,scopeKey:Te,browserAllowPrivate:ke}=e.body||{},z=Tt();z.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:C?te(C):null,perAgentModel:g??null}});let D=null;const I=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,B=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;B?h.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${B} (agentId=${I})`):h.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${I})`);try{if(An(),!I){n.status(400).json({error:"agentId is required"});return}const O=Be(I);if(O){n.json(await qt(O));return}const k=await yt(I);if(k){const R=Ft(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${I}, sessionId=${k.sessionId}, reason=${R.reason}`),await F(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(K.has(I)){n.status(409).json({error:"SDK session is already starting for this agent"});return}K.add(I);const _n=(r||"acode").toLowerCase(),E=Ke(r),He=w.get(E);D=Ge();const We=E==="claude-code"?await Qt():null,J=Ne(E==="claude-code"?We:null,f),H=E==="acode"?g?String(g).trim():void 0:(()=>{const R=g?String(g).trim():void 0,P=J.model?String(J.model).trim():void 0;return R||P})();z.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:I,sessionId:D??void 0,details:{perAgentModel:g??null,globalModel:J.model??null,resolvedModel:H??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...J.envOverrides};H&&(me.ANTHROPIC_MODEL=H,me.CODEX_MODEL=H);let W,fe=l;if(E==="acode"){const R=C||{},P=await at({apiOverrides:Ie(R)??void 0,agentId:I,sessionId:D??void 0,runtimeBridgeBaseUrl:B});W=P.instanceConfig.config,fe=P.perInstanceConfigPath,z.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:I,sessionId:D??void 0,details:{sanitizedApiOverrides:Ie(R)?te(Ie(R)):null,resolvedInstanceAiConfig:W?te(W):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let we=a||void 0,pe,ge,Y;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Y=u.trim();else{const R=await _t(o,{schedulerBaseUrl:B,runtimeAccessToken:le,agentId:I});R&&(Y=R,h.info(`[startSdkSession] Auto-loaded memories for ACode agent ${I}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(Z=>typeof Z=="string"&&Z.trim().length>0).map(Z=>Z.trim());we=P.length>0?P.join(`
|
|
48
|
+
`:void 0}function tn(e){const n=rn(e);return{sourceEventType:e.type,logCategory:"acode",...on(e),...n?{logLevel:nn(e),logMessage:n}:{}}}function nn(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function on(e){return e.type!=="command_output"?{}:{...typeof e.data.stream=="string"?{stream:e.data.stream}:{},...typeof e.data.sequence=="number"?{sequence:e.data.sequence}:{},...typeof e.data.cwd=="string"?{cwd:e.data.cwd}:{},...typeof e.data.commandFilePath=="string"?{commandFilePath:e.data.commandFilePath}:{},...typeof e.data.commandLineCount=="number"?{commandLineCount:e.data.commandLineCount}:{}}}function rn(e){if(e.type==="ai_request"){const n=e.data.model||"unknown-model",t=e.data.endpoint?` @ ${e.data.endpoint}`:"",o=typeof e.data.toolCount=="number"?`, tools=${e.data.toolCount}`:"";return`AI request started: ${n}${t}${o}`}if(e.type==="tool_use_start")return qe(e,"\u5F00\u59CB");if(e.type==="tool_use_end")return qe(e,"\u5B8C\u6210");if(e.type==="command_output")return cn(e);if(e.type==="turn_complete")return`Turn completed${e.data.finishReason?`, finish=${e.data.finishReason}`:""}`;if(e.type==="session_complete")return`Session completed: exitCode=${e.data.exitCode??0}`;if(e.type==="error")return e.data.text||"ACode runtime error"}const sn=/\x1b\[[0-9;?]*[a-zA-Z]/g;function an(e){return e.replace(sn,"")}function cn(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",o=an(String(e.data.text||"")).replace(/\s+/g," ").trim(),r=o.length>240?`${o.slice(0,240)}...`:o;return`\u547D\u4EE4\u8F93\u51FA(${n}${t}): ${r||"(empty)"}`}function qe(e,n){const t=ye(e.data.toolName,e.data.toolInput),o=e.data.actionLabel||t.actionLabel||"\u8C03\u7528\u5DE5\u5177",r=ve(e,t);return r?`${n}${o}: ${r}`:`${n}${o}: ${e.data.actionDetail||e.data.toolName||"tool"}`}function ve(e,n){const t=e.data.toolInput;return n.actionType==="bash"?un(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?dn(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function un(e){const n=Ae(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(o=>String(o??"").trim()).filter(Boolean).join(" ");return t?q(t):void 0}return Ae(e?.args)}function dn(e){const n=Fe(e?.paths);return n.length>0?n.length===1?n[0]:`${n.length}\u4E2A\u6587\u4EF6: ${n.join(", ")}`:Ae(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)}function Ae(...e){for(const n of e){if(typeof n=="string"&&n.trim())return q(n.trim());if(Array.isArray(n)){const t=Fe(n)[0];if(t)return t}}}function Fe(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>q(n)):[]}function ln(e){if(!(!e||Object.keys(e).length===0))try{const n=q(JSON.stringify(e,null,2));return n.length>8e3?`${n.slice(0,8e3)}
|
|
49
|
+
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function mn(e){const n=[e.model?`\u6A21\u578B: ${e.model}`:void 0,e.endpoint||e.requestUrl?`\u63A5\u53E3: ${e.endpoint||e.requestUrl}`:void 0,e.requestMethod?`\u65B9\u6CD5: ${e.requestMethod}`:void 0,typeof e.stream=="boolean"?`\u6D41\u5F0F: ${e.stream?"\u662F":"\u5426"}`:void 0,typeof e.messageCount=="number"?`\u4E0A\u4E0B\u6587\u6D88\u606F: ${e.messageCount}`:void 0,typeof e.toolCount=="number"?`\u53EF\u7528\u5DE5\u5177: ${e.toolCount}`:void 0,e.lastUserMessagePreview?`\u6700\u540E\u8BF7\u6C42: ${e.lastUserMessagePreview}`:void 0].filter(i=>!!i),t=fn(e.requestHeaders),o=n.join(`
|
|
50
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",r=t.length>0?`${_t}${t.join(`
|
|
51
|
+
`)}`:"",s=e.requestBody?`${Ct}${e.requestBody}`:"";return`${o}${r}${s}`}function fn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function pn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function gn(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],o=Number(t);if(Number.isFinite(o)&&o>0)return o}}function yn(e,n){if(!pn(e,n)){if(e.type==="ai_request"){const t=gn(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:mn(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),o=ve(e,t),r=ln(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const x=new Map,ae=new Map,ce=new Map,G=new Map,hn=20,In=500,Sn=3e4;async function ue(e,n=Sn,t=2){for(let o=0;o<=t;o++){const r=new AbortController;let s;try{const i=e(r.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{r.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(o<t){const c=1e3*(o+1);h.warn(`sendOutput attempt ${o+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}h.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let o,r;if(t)o=G.get(t),r=t;else{const p=[];for(const[T,y]of G)T.startsWith(e+":")&&y.buffer&&p.push(y.sourceEventType);for(const T of p)de(e,T);return}if(!o||!o.buffer)return;o.timer=null;const s=o.buffer,i=o.seq,a=o.entry,c=o.sourceEventType;o.buffer="",r&&G.delete(r);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},m=(x.get(e)??Promise.resolve()).then(()=>ue(p=>X(a.agentId,s,e,i,d,u,p)),()=>ue(p=>X(a.agentId,s,e,i,d,u,p)));x.set(e,m),m.finally(()=>{x.get(e)===m&&x.delete(e)})}function An(e,n){const t=en(e);if(!t)return;n.seq+=1;const o=n.seq,r=tn(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<hn){const c=`${e.sessionId}:${e.type}`;let d=G.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=o,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),In)}G.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)),()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function Ke(e){return Ye(e)}let ze=!1;function Tn(){ze||(Je(w,kn),pt(),ze=!0)}function kn(e,n){e.on("event",t=>{const o=f.get(t.sessionId);if(o){if(t.type==="tool_use_start"?yt(o.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,o.workspacePath):t.type==="tool_use_end"&>(t,{sessionId:o.sessionId,agentId:o.agentId,workspacePath:o.workspacePath,providerId:o.providerId}),console.log(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(o.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=yn(t,o.currentRuntimeStatus);i&&_(o.agentId,t.sessionId,i.status,i.actionInfo,oe(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}An(t,o);const s=Zt(t);if(s){const i={runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(p=>setTimeout(p,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(p=>setTimeout(p,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):_(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,o,r)=>{const s=f.get(t);if(s){de(t),o==="thinking"||o==="tool_using"||o==="compacting"?bt(t):L(t);const i=Et(o,r);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),console.log(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),At(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const p=(ae.get(t)??Promise.resolve()).then(async()=>{for(let y=0;y<=2;y++){if(await _(s.agentId,t,i.status,l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;y<2&&(h.warn(`[${n.displayName}] compaction sendStatus attempt ${y+1} failed (HTTP), retrying in ${1e3*(y+1)}ms...`),await new Promise(C=>setTimeout(C,1e3*(y+1))))}h.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{h.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,p),p.finally(()=>{ae.get(t)===p&&ae.delete(t)})}else{const m=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const y=(ce.get(t)??Promise.resolve()).then(async()=>{for(let C=0;C<=2;C++){if(await _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;C<2&&await new Promise(M=>setTimeout(M,1e3*(C+1)))}h.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(g=>{h.warn(`[${n.displayName}] idle status chain error:`,g)});ce.set(t,y),y.finally(()=>{ce.get(t)===y&&ce.delete(t)})}else _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const m=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,console.log(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),_(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:m},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const o=f.get(t.sessionId);o&&(console.log(`[${n.displayName} Adapter] AskUserQuestion for agent ${o.agentId}`),lt(o.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.toolCallId))}),e.on("tool-permission-request",t=>{const o=f.get(t.sessionId);o&&t.requestId&&(console.log(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${o.agentId}`),mt(o.agentId,t.sessionId,{requestId:t.requestId,capability:t.capability,...t.detail||{}},{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}))}),e.on("permission-request",t=>{const o=f.get(t.sessionId);if(o){console.log(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${o.agentId}`);const r=t.toolInput?q(JSON.stringify(t.toolInput).slice(0,400)):void 0;_(o.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:r||t.toolName},void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}})}S.post("/start",I,async(e,n)=>{const{agentId:t,workspacePath:o,mode:r="sdk"}=e.body||{};if(!t||!o){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;ct({agentId:String(t),workspacePath:String(o),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!=null&&(et(String(t),e.body.runtimeFeatures),console.log(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(tt(String(t)))}`)),e.body?.envVars!=null&&typeof e.body.envVars=="object"&&(rt(e.body.envVars),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(st(e.body.changeCacheRetentionDays),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),r&&r!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${r}" requested for agent ${t}; starting SDK session instead.`),await wn(e,n)});async function wn(e,n){const{agentId:t,workspacePath:o,command:r,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:m,envOverrides:p,idleInputAutoCommand:T,nonInputAutoCommand:y,model:g,instanceAiConfig:C,subAgentModel:$,subAgentEffort:M,scopeKey:Te,browserAllowPrivate:ke}=e.body||{},z=kt();z.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:C?te(C):null,perAgentModel:g??null}});let D=null;const A=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,B=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||De(Pe(e))||void 0;B?h.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${B} (agentId=${A})`):h.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(Tn(),!A){n.status(400).json({error:"agentId is required"});return}const O=Be(A);if(O){n.json(await Ft(O));return}const k=await ht(A);if(k){const R=Kt(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${k.sessionId}, reason=${R.reason}`),await F(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(K.has(A)){n.status(409).json({error:"SDK session is already starting for this agent"});return}K.add(A);const $n=(r||"acode").toLowerCase(),E=Ke(r),He=w.get(E);D=Ge();const We=E==="claude-code"?await Vt():null,J=Ne(E==="claude-code"?We:null,p),H=E==="acode"?g?String(g).trim():void 0:(()=>{const R=g?String(g).trim():void 0,P=J.model?String(J.model).trim():void 0;return R||P})();z.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:D??void 0,details:{perAgentModel:g??null,globalModel:J.model??null,resolvedModel:H??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...J.envOverrides};H&&(me.ANTHROPIC_MODEL=H,me.CODEX_MODEL=H);let W,fe=l;if(E==="acode"){const R=C||{},P=await at({apiOverrides:Ie(R)??void 0,agentId:A,sessionId:D??void 0,runtimeBridgeBaseUrl:B});W=P.instanceConfig.config,fe=P.perInstanceConfigPath,z.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:D??void 0,details:{sanitizedApiOverrides:Ie(R)?te(Ie(R)):null,resolvedInstanceAiConfig:W?te(W):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let we=a||void 0,pe,ge,Y;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Y=u.trim();else{const R=await $t(o,{schedulerBaseUrl:B,runtimeAccessToken:le,agentId:A});R&&(Y=R,h.info(`[startSdkSession] Auto-loaded memories for ACode agent ${A}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(Z=>typeof Z=="string"&&Z.trim().length>0).map(Z=>Z.trim());we=P.length>0?P.join(`
|
|
52
52
|
|
|
53
|
-
`):void 0}const U={command:r||"acode",workingDirectory:o,agentId:I,...Te?{scopeKey:Te}:{},...typeof ke=="boolean"?{browserAllowPrivate:ke}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:we,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Y!==void 0?{memory:Y}:{},model:H,mcpConfigPath:fe,...W?{instanceAiConfig:W}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:m||{},envOverrides:Oe(String(t),String(o),process.env,me)};z.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:I,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await z.flush(),p.set(D,{agentId:I,workspacePath:o,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:B}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:I,workspacePath:o,command:U.command,mode:"sdk"}),wn({sessionId:D,agentId:I,config:U,adapter:He,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:y,runtimeAccessToken:le,requestedSchedulerBaseUrl:B})}catch(O){if(D&&(L(D),p.delete(D),q(D)),I&&K.delete(I),!n.headersSent){const k=O instanceof Error?O.message:String(O);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function wn(e){const{sessionId:n,agentId:t,config:o,adapter:r,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await r.startSession(n,o),(i||a)&&r.setIdleCommands?.(n,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(Dt(s))try{if(await new Promise(m=>setTimeout(m,500)),u=r.getSessionPid?.(n),!u){const f=(await ut()).find(T=>T.agentId===t||T.cwd===o.workingDirectory||T.command.includes(o.workingDirectory));f&&(u=f.pid,console.log(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(m){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,m)}const l=se(r.getSessionStatus(n),p.get(n)?.currentRuntimeStatus,p.get(n)?.currentRuntimeActionType);await At({sessionId:n,agentId:t,workspacePath:o.workingDirectory,command:o.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:r.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:o.workingDirectory,command:o.command}),await bn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(n),p.delete(n),q(n),await F(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await Cn({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{K.delete(t)}}async function bn(e){const{agentId:n,sessionId:t,sdkPid:o,status:r,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){h.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(a,{agentId:n,sessionId:t,status:r,pid:o},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${r}`)}catch(c){const d=c instanceof Error?c.message:String(c);h.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function Cn(e){const{agentId:n,sessionId:t,schedulerBaseUrl:o,runtimeAccessToken:r}=e;if(!o||!r)return;const s=`${o.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":r,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);h.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}A.post("/sdk/message",S,async(e,n)=>{const{sessionId:t,message:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and message are required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await w.get(s).sendMessage(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),A.post("/sdk/answer",S,async(e,n)=>{const{sessionId:t,answers:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and answers are required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",i=w.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),A.post("/sdk/confirm",S,async(e,n)=>{const{sessionId:t,accept:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await w.get(s).sendConfirmation(t,!!o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),A.post("/sdk/abort",S,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code";await w.get(r).abortCurrentTurn(t),n.json({ok:!0})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.post("/sdk/stop",S,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.json({ok:!0,status:"stopped"});return}try{const r=o.providerId||"claude-code",s=w.get(r);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),L(t),p.delete(t),q(t),ie(t),await F(t),await he().removeProcess(o.agentId),await _(o.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.get("/sdk/status/:sessionId",S,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",s=w.get(r),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:o.agentId,workspacePath:o.workspacePath,messageCount:a.length})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.get("/sdk/capabilities/:sessionId",S,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=w.get(r).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,capabilities:i,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.get("/sdk/pending-questions/:sessionId",S,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=w.get(r).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.post("/command",S,async(e,n)=>{const{sessionId:t,command:o}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and command are required"});return}try{const r=await Ht(String(t),o);n.json({ok:!0,mode:"terminal",...r})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),A.post("/input",S,async(e,n)=>{const{sessionId:t,input:o,mode:r}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and input are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=w.get(i);if(r==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(o)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Xt(o)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),A.post("/update-auto-commands",S,async(e,n)=>{const{agentId:t,idleInputAutoCommand:o="",nonInputAutoCommand:r=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...p.values()].find(c=>c.agentId===s),a={idleInputCommand:String(o||""),nonInputCommand:String(r||"")};try{let c=!1;i&&(w.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await It(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),A.post("/resize",S,(e,n)=>{const{sessionId:t,cols:o,rows:r}=e.body||{};if(!t||!o||!r){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!p.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(o),rows:Number(r)})}),A.post("/reset-context",S,async(e,n)=>{const{sessionId:t,reason:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}const s=r.providerId||"claude-code",i=w.get(s),a=i.resetContext?.bind(i),c=$t(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),r.currentRuntimeStatus,r.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:r.agentId,mode:"sdk",providerId:s,reason:typeof o=="string"&&o.trim()?o.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),A.post("/stop",S,async(e,n)=>{const{sessionId:t}=e.body||{},o=Rt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){await F(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:o.reason});return}const s=r.agentId;try{console.log(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!o.statusNotified}, reason=${o.reason||"unspecified"}`);const i=r.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),L(t),p.delete(t),q(t),ie(t),await F(t),await he().removeProcess(s),o.statusNotified?await _(s,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}):console.log(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${o.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:o.statusNotified,reason:o.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),A.post("/stop-all",S,async(e,n)=>{const t=[],o=[];for(const[r,s]of p.entries())try{const i=s.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(r).catch(()=>{}),await a.terminateSession(r),L(r),p.delete(r),q(r),ie(r),t.push(r),await _(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);o.push(`SDK ${r}: ${a}`)}try{await ht([]),console.log("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(r){const s=r instanceof Error?r.message:String(r);o.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:o.length>0?o:void 0})}),A.get("/events/last/:n",S,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const o=Re.getLastN(t);n.json({ok:!0,count:o.length,entries:o})}),A.get("/events/since/:index",S,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const o=Re.getSinceIndex(t);n.json({ok:!0,entries:o.entries,nextIndex:o.nextIndex,oldestIndex:o.oldestIndex,dataLoss:o.oldestIndex>t+1})}),A.get("/events/push-stats",S,(e,n)=>{const t=mt();n.json({ok:!0,count:t.length,agents:t})});export{Mt as buildAcodeCommandOutputPath,Ne as buildClaudeCodeLaunchConfig,Oe as buildRuntimeEnv,en as buildSdkOutputMetadata,Yt as buildToolResultTimelineActionInfo,Zn as cleanupSdkSessionByAgentId,Lt as countTerminalOutputLines,je as createTerminalOutputDecoder,re as decodeTerminalOutputChunk,Ft as evaluatePersistedSessionReuse,Ut as formatCommandInactivityTimeoutNotice,xt as formatCommandOutputSpilloverNotice,Zt as formatSdkOutputEvent,Se as formatTerminalPrompt,jt as normalizeTerminalCommandInput,Rt as parseRuntimeStopOptions,Nt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,$t as resolveRuntimeContextResetSupport,gn as resolveRuntimeStatusFromProviderEvent,Xt as resolveSdkInputMessage,Ke as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,Pt as resolveStatusChangeRuntimeState,oe as resolveStatusChangeUsage,Bt as resolveTerminalOutputEncoding,p as sdkSessions,Dt as shouldProbeSdkProcessPid,A as terminalRouter};
|
|
53
|
+
`):void 0}const U={command:r||"acode",workingDirectory:o,agentId:A,...Te?{scopeKey:Te}:{},...typeof ke=="boolean"?{browserAllowPrivate:ke}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:we,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Y!==void 0?{memory:Y}:{},model:H,mcpConfigPath:fe,...W?{instanceAiConfig:W}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:m||{},envOverrides:Oe(String(t),String(o),process.env,me)};z.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await z.flush(),f.set(D,{agentId:A,workspacePath:o,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:B}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:o,command:U.command,mode:"sdk"}),bn({sessionId:D,agentId:A,config:U,adapter:He,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:y,runtimeAccessToken:le,requestedSchedulerBaseUrl:B})}catch(O){if(D&&(L(D),f.delete(D),v(D)),A&&K.delete(A),!n.headersSent){const k=O instanceof Error?O.message:String(O);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function bn(e){const{sessionId:n,agentId:t,config:o,adapter:r,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await r.startSession(n,o),(i||a)&&r.setIdleCommands?.(n,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(Rt(s))try{if(await new Promise(m=>setTimeout(m,500)),u=r.getSessionPid?.(n),!u){const p=(await ut()).find(T=>T.agentId===t||T.cwd===o.workingDirectory||T.command.includes(o.workingDirectory));p&&(u=p.pid,console.log(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(m){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,m)}const l=se(r.getSessionStatus(n),f.get(n)?.currentRuntimeStatus,f.get(n)?.currentRuntimeActionType);await Tt({sessionId:n,agentId:t,workspacePath:o.workingDirectory,command:o.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:r.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:o.workingDirectory,command:o.command}),await Cn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(n),f.delete(n),v(n),await F(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await _n({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{K.delete(t)}}async function Cn(e){const{agentId:n,sessionId:t,sdkPid:o,status:r,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){h.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(a,{agentId:n,sessionId:t,status:r,pid:o},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${r}`)}catch(c){const d=c instanceof Error?c.message:String(c);h.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function _n(e){const{agentId:n,sessionId:t,schedulerBaseUrl:o,runtimeAccessToken:r}=e;if(!o||!r)return;const s=`${o.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":r,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);h.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}S.post("/sdk/message",I,async(e,n)=>{const{sessionId:t,message:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and message are required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await w.get(s).sendMessage(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/answer",I,async(e,n)=>{const{sessionId:t,answers:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and answers are required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",i=w.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/tool-auth/answer",I,async(e,n)=>{const{sessionId:t,requestId:o,allowed:r}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and requestId are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=w.get(i);if(!a.submitToolPermissionDecision){n.status(400).json({error:"adapter does not support tool authorization"});return}const c=a.submitToolPermissionDecision(t,String(o),!!r);n.json({ok:!0,existed:c})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.get("/tool-auth/pending/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=w.get(r).getPendingToolAuthRequests?.(t)??[];n.json({ok:!0,sessionId:t,agentId:o.agentId,pendingRequests:i,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/sdk/confirm",I,async(e,n)=>{const{sessionId:t,accept:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await w.get(s).sendConfirmation(t,!!o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/abort",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code";await w.get(r).abortCurrentTurn(t),n.json({ok:!0})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/sdk/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.json({ok:!0,status:"stopped"});return}try{const r=o.providerId||"claude-code",s=w.get(r);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),L(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(o.agentId),await _(o.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/status/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",s=w.get(r),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:o.agentId,workspacePath:o.workspacePath,messageCount:a.length})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/capabilities/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=w.get(r).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,capabilities:i,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/pending-questions/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=w.get(r).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/command",I,async(e,n)=>{const{sessionId:t,command:o}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and command are required"});return}try{const r=await Wt(String(t),o);n.json({ok:!0,mode:"terminal",...r})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/input",I,async(e,n)=>{const{sessionId:t,input:o,mode:r}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and input are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=w.get(i);if(r==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(o)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Qt(o)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.post("/update-auto-commands",I,async(e,n)=>{const{agentId:t,idleInputAutoCommand:o="",nonInputAutoCommand:r=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...f.values()].find(c=>c.agentId===s),a={idleInputCommand:String(o||""),nonInputCommand:String(r||"")};try{let c=!1;i&&(w.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await St(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),S.post("/resize",I,(e,n)=>{const{sessionId:t,cols:o,rows:r}=e.body||{};if(!t||!o||!r){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!f.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(o),rows:Number(r)})}),S.post("/reset-context",I,async(e,n)=>{const{sessionId:t,reason:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}const s=r.providerId||"claude-code",i=w.get(s),a=i.resetContext?.bind(i),c=Dt(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),r.currentRuntimeStatus,r.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:r.agentId,mode:"sdk",providerId:s,reason:typeof o=="string"&&o.trim()?o.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),S.post("/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{},o=Pt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){await F(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:o.reason});return}const s=r.agentId;try{console.log(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!o.statusNotified}, reason=${o.reason||"unspecified"}`);const i=r.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),L(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(s),o.statusNotified?await _(s,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}):console.log(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${o.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:o.statusNotified,reason:o.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),S.post("/stop-all",I,async(e,n)=>{const t=[],o=[];for(const[r,s]of f.entries())try{const i=s.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(r).catch(()=>{}),await a.terminateSession(r),L(r),f.delete(r),v(r),ie(r),t.push(r),await _(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);o.push(`SDK ${r}: ${a}`)}try{await It([]),console.log("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(r){const s=r instanceof Error?r.message:String(r);o.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:o.length>0?o:void 0})}),S.get("/events/last/:n",I,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const o=Re.getLastN(t);n.json({ok:!0,count:o.length,entries:o})}),S.get("/events/since/:index",I,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const o=Re.getSinceIndex(t);n.json({ok:!0,entries:o.entries,nextIndex:o.nextIndex,oldestIndex:o.oldestIndex,dataLoss:o.oldestIndex>t+1})}),S.get("/events/push-stats",I,(e,n)=>{const t=ft();n.json({ok:!0,count:t.length,agents:t})});export{Lt as buildAcodeCommandOutputPath,Ne as buildClaudeCodeLaunchConfig,Oe as buildRuntimeEnv,tn as buildSdkOutputMetadata,Zt as buildToolResultTimelineActionInfo,eo as cleanupSdkSessionByAgentId,xt as countTerminalOutputLines,je as createTerminalOutputDecoder,re as decodeTerminalOutputChunk,Kt as evaluatePersistedSessionReuse,jt as formatCommandInactivityTimeoutNotice,Ut as formatCommandOutputSpilloverNotice,en as formatSdkOutputEvent,Se as formatTerminalPrompt,Bt as normalizeTerminalCommandInput,Pt as parseRuntimeStopOptions,qt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Dt as resolveRuntimeContextResetSupport,yn as resolveRuntimeStatusFromProviderEvent,Qt as resolveSdkInputMessage,Ke as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,Et as resolveStatusChangeRuntimeState,oe as resolveStatusChangeUsage,Ot as resolveTerminalOutputEncoding,f as sdkSessions,Rt as shouldProbeSdkProcessPid,S as terminalRouter};
|
|
54
54
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ToolPermissionPolicy } from "@agentswork/acode";
|
|
1
2
|
|
|
2
3
|
export declare const DESKTOP_FEATURE_KEY = "desktop";
|
|
3
4
|
|
|
@@ -15,4 +16,8 @@ export declare function isFeatureEnabled(agentId: string, key: string): boolean;
|
|
|
15
16
|
|
|
16
17
|
export declare function clearAgentFeatures(agentId: string): void;
|
|
17
18
|
|
|
19
|
+
export declare function getAgentToolPermissions(agentId: string): ToolPermissionPolicy | null;
|
|
20
|
+
|
|
21
|
+
export declare function resolveAgentToolPermissions(agentId: string): ToolPermissionPolicy;
|
|
22
|
+
|
|
18
23
|
export declare function instanceFeaturesCacheSize(): number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const
|
|
1
|
+
const c={},_="desktop",u="browser",d="agentSys.launchItem",T="agentSys.hire",f=new Set([u]),a=new Set,i=new Map,s=new Map,E=["fileReadOutside","commandExecution","fileModification"],A=new Set(["allow","ask","deny"]);function p(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of E){const l=t[r];typeof l=="string"&&A.has(l)?(n[r]=l,o=!0):n[r]="allow"}return o?n:null}function y(e){if(e==null)return{...c};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...c};const n={};for(const[o,r]of Object.entries(t))a.has(o)||typeof r=="boolean"&&(n[o]=r);return n}function F(e,t){if(!e)return;i.set(e,y(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=p(n.toolPermissions);o?s.set(e,o):s.delete(e)}else s.delete(e)}function S(e){return i.get(e)??{...c}}function R(e,t){const n=S(e)[t];return n!==void 0?n:f.has(t)}function m(e){i.delete(e),s.delete(e)}function x(e){return s.get(e)??null}function O(e){return s.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow"}}function g(){return i.size}export{u as BROWSER_FEATURE_KEY,_ as DESKTOP_FEATURE_KEY,T as HIRE_FEATURE_KEY,d as LAUNCH_ITEM_FEATURE_KEY,m as clearAgentFeatures,S as getAgentFeatures,x as getAgentToolPermissions,g as instanceFeaturesCacheSize,R as isFeatureEnabled,O as resolveAgentToolPermissions,F as setAgentFeatures};
|
|
2
2
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export interface ProcessConnectionInfo {
|
|
2
|
+
remote: string;
|
|
3
|
+
state?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ProcessDetailSnapshot {
|
|
6
|
+
ok: true;
|
|
7
|
+
pid: number;
|
|
8
|
+
name?: string;
|
|
9
|
+
|
|
10
|
+
command?: string;
|
|
11
|
+
exePath?: string;
|
|
12
|
+
user?: string;
|
|
13
|
+
ppid?: number;
|
|
14
|
+
|
|
15
|
+
status?: string;
|
|
16
|
+
threads?: number;
|
|
17
|
+
elapsedSeconds?: number;
|
|
18
|
+
cpuUserSeconds?: number;
|
|
19
|
+
cpuSystemSeconds?: number;
|
|
20
|
+
|
|
21
|
+
cpuTotalSeconds?: number;
|
|
22
|
+
virtualBytes?: number;
|
|
23
|
+
rssBytes?: number;
|
|
24
|
+
|
|
25
|
+
ioReadBytes?: number;
|
|
26
|
+
ioWriteBytes?: number;
|
|
27
|
+
connections?: ProcessConnectionInfo[];
|
|
28
|
+
|
|
29
|
+
unsupported?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export declare function parseProcStatus(content: string): {
|
|
33
|
+
name?: string;
|
|
34
|
+
status?: string;
|
|
35
|
+
ppid?: number;
|
|
36
|
+
threads?: number;
|
|
37
|
+
virtualBytes?: number;
|
|
38
|
+
rssBytes?: number;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export declare function parseProcUptime(content: string): number | null;
|
|
42
|
+
|
|
43
|
+
export declare function parseLinuxStatTimes(content: string): {
|
|
44
|
+
userTicks: number;
|
|
45
|
+
systemTicks: number;
|
|
46
|
+
startTicks: number;
|
|
47
|
+
} | null;
|
|
48
|
+
|
|
49
|
+
export declare function parsePsEtimeSeconds(value: string): number | null;
|
|
50
|
+
|
|
51
|
+
export declare function parsePsCpuTimeSeconds(value: string): number | null;
|
|
52
|
+
|
|
53
|
+
export declare function parseLsofConnectionLine(line: string): ProcessConnectionInfo | null;
|
|
54
|
+
|
|
55
|
+
export declare function parseSsConnectionsForPid(output: string, pid: number): ProcessConnectionInfo[];
|
|
56
|
+
|
|
57
|
+
export declare function parseLsofConnectionsForPid(output: string): ProcessConnectionInfo[];
|
|
58
|
+
|
|
59
|
+
export declare function parseJsonObject<T>(stdout: string): T | null;
|
|
60
|
+
export declare function parseLinuxCmdline(content: string): string;
|
|
61
|
+
export declare function parseLinuxIoBytes(content: string): {
|
|
62
|
+
readBytes: number;
|
|
63
|
+
writeBytes: number;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export declare function parseDarwinPsDetailLine(line: string): {
|
|
67
|
+
ppid?: number;
|
|
68
|
+
user?: string;
|
|
69
|
+
status?: string;
|
|
70
|
+
rssBytes?: number;
|
|
71
|
+
virtualBytes?: number;
|
|
72
|
+
elapsedSeconds?: number;
|
|
73
|
+
cpuTotalSeconds?: number;
|
|
74
|
+
command?: string;
|
|
75
|
+
} | null;
|
|
76
|
+
|
|
77
|
+
export declare function collectProcessDetail(pid: number): Promise<ProcessDetailSnapshot>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import{execFile as g}from"node:child_process";import{readFile as d,readlink as T}from"node:fs/promises";import{promisify as C}from"node:util";import F from"node:os";const l=C(g);import{createLogger as O}from"../utils/logger.js";const k=O("process-detail"),m=9e3,S=100,I=50,f="\u8FDB\u7A0B\u4E0D\u5B58\u5728\u3001\u5DF2\u9000\u51FA\u6216\u5F53\u524D\u7528\u6237\u65E0\u6743\u67E5\u770B";function v(n){const t=new Map;for(const c of n.split(/\r?\n/)){const a=c.indexOf(":");a<=0||t.set(c.slice(0,a).trim(),c.slice(a+1).trim())}const e=B(t.get("VmSize")),s=B(t.get("VmRSS")),r={},i=t.get("Name"),o=t.get("State"),u=Number(t.get("PPid")),p=Number(t.get("Threads"));return i&&(r.name=i),o&&(r.status=o.split(/\s+/)[0]),Number.isFinite(u)&&(r.ppid=u),Number.isFinite(p)&&(r.threads=p),e!==null&&(r.virtualBytes=e*1024),s!==null&&(r.rssBytes=s*1024),r}function B(n){if(!n)return null;const t=n.match(/^(\d+)\s*kB$/);if(!t)return null;const e=Number(t[1]);return Number.isFinite(e)?e:null}function L(n){const t=Number(n.trim().split(/\s+/)[0]);return Number.isFinite(t)?t:null}function D(n){const t=n.lastIndexOf(")");if(t<0)return null;const e=n.slice(t+1).trim().split(/\s+/),s=Number(e[11]),r=Number(e[12]),i=Number(e[19]);return!Number.isFinite(s)||!Number.isFinite(r)||!Number.isFinite(i)?null:{userTicks:s,systemTicks:r,startTicks:i}}function w(n){const t=n.trim();if(!t||!/^\d/.test(t))return null;const[e,s]=t.includes("-")?t.split("-",2):[void 0,t],r=s.split(":").map(Number);if(r.some(o=>!Number.isFinite(o)))return null;let i=0;for(const o of r)i=i*60+o;if(e!==void 0){if(!/^\d+$/.test(e))return null;i+=Number(e)*86400}return i}function E(n){const[t,e]=n.trim().split("."),s=w(t);return s===null?null:s+(e&&+`0.${e}`||0)}function M(n){const t=n.trim().split(/\s+/);if(t.length<8)return null;const e=t.slice(7).join(" ");if(e.includes("(LISTEN)"))return null;const s=e.match(/\(([A-Z ]+)\)$/),r=e.replace(/\s*\([A-Z ]+\)$/,""),i=r.includes("->")?r.split("->")[1]:r;return i?{remote:i,state:s?s[1]:void 0}:null}function R(n,t){const e=[];for(const s of n.split(/\r?\n/).slice(1)){if(!s.trim()||!s.includes(`pid=${t}`))continue;const r=s.trim().split(/\s+/);if(r[0]==="LISTEN")continue;const i=r[4]||"";i&&e.push({remote:i})}return e}function U(n){const t=[];for(const e of n.split(/\r?\n/).slice(1)){const s=M(e);s&&t.push(s)}return t}function _(n){const t=n.trim();return t?JSON.parse(t):null}async function W(n){let t;try{t=await d(`/proc/${n}/status`,"utf8")}catch{return{ok:!0,pid:n,unsupported:f}}const e=v(t),[s,r,i]=await Promise.all([d(`/proc/${n}/stat`,"utf8").catch(()=>""),d(`/proc/${n}/cmdline`,"utf8").catch(()=>""),d("/proc/uptime","utf8").catch(()=>"")]),o=s?D(s):null,u=i?L(i):null,[p,c,a,$]=await Promise.all([T(`/proc/${n}/exe`).catch(()=>""),d(`/proc/${n}/io`,"utf8").catch(()=>""),l("ps",["-o","user=","-p",String(n)],{encoding:"utf8",timeout:m}).then(N=>N.stdout.trim()).catch(()=>""),l("ss",["-tupn"],{encoding:"utf8",timeout:m}).then(N=>N.stdout).catch(()=>"")]),h=c?j(c):null,P=A(r)||e.name,x=o&&u!==null?Math.max(0,Math.round(u-o.startTicks/S)):void 0;return{ok:!0,pid:n,name:e.name,command:P||void 0,exePath:p||void 0,user:a||void 0,ppid:e.ppid,status:e.status,threads:e.threads,elapsedSeconds:x,cpuUserSeconds:o?y(o.userTicks/S):void 0,cpuSystemSeconds:o?y(o.systemTicks/S):void 0,virtualBytes:e.virtualBytes,rssBytes:e.rssBytes,ioReadBytes:h?.readBytes,ioWriteBytes:h?.writeBytes,connections:$?b(R($,n)):void 0}}function A(n){const t=n.replace(/\0+$/,"");return t?t.split("\0").filter(Boolean).join(" "):""}function j(n){let t,e;for(const s of n.split(/\r?\n/)){const[r,i]=s.split(":");if(!r||i===void 0)continue;const o=Number(i.trim());Number.isFinite(o)&&(r.trim()==="read_bytes"?t=o:r.trim()==="write_bytes"&&(e=o))}return{readBytes:t??0,writeBytes:e??0}}function G(n){const t=n.trim().match(/^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+([\s\S]+)$/);if(!t)return null;const e=Number(t[2]),s=Number(t[5])*1024,r=Number(t[6])*1024,i=w(t[7]),o=E(t[8]),u={user:t[3],status:t[4],command:t[9].trim()};return Number.isFinite(e)&&(u.ppid=e),Number.isFinite(s)&&(u.rssBytes=s),Number.isFinite(r)&&(u.virtualBytes=r),i!==null&&(u.elapsedSeconds=i),o!==null&&(u.cpuTotalSeconds=y(o)),u}async function K(n){const{stdout:t}=await l("ps",["-ww","-p",String(n),"-o","pid=,ppid=,user=,state=,rss=,vsz=,etime=,cputime=,command="],{encoding:"utf8",timeout:m}),e=t.split(/\r?\n/).find(i=>i.trim()),s=e?G(e):null;if(!s)return{ok:!0,pid:n,unsupported:f};const r=await l("lsof",["-n","-P","-i","TCP","-a","-p",String(n),"+c0"],{encoding:"utf8",timeout:m}).then(i=>i.stdout).catch(()=>"");return{ok:!0,pid:n,user:s.user,ppid:s.ppid,status:s.status,command:s.command||void 0,elapsedSeconds:s.elapsedSeconds,cpuTotalSeconds:s.cpuTotalSeconds,virtualBytes:s.virtualBytes,rssBytes:s.rssBytes,connections:r?b(U(r)):void 0}}function z(n){return`
|
|
2
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
3
|
+
$proc = Get-CimInstance Win32_Process -Filter 'ProcessId=${n}'
|
|
4
|
+
if (-not $proc) { Write-Output 'null'; exit }
|
|
5
|
+
$gp = Get-Process -Id ${n}
|
|
6
|
+
$owner = $proc | Invoke-CimMethod -MethodName GetOwner
|
|
7
|
+
$conns = @()
|
|
8
|
+
foreach ($c in (Get-NetTCPConnection -OwningProcess ${n})) {
|
|
9
|
+
$conns += [pscustomobject]@{ remote = ('{0}:{1}' -f $c.RemoteAddress, $c.RemotePort); state = [string]$c.State }
|
|
10
|
+
}
|
|
11
|
+
$elapsed = $null
|
|
12
|
+
if ($gp -and $gp.StartTime) { $elapsed = [int]((Get-Date) - $gp.StartTime).TotalSeconds }
|
|
13
|
+
$row = [pscustomobject]@{
|
|
14
|
+
pid = ${n}
|
|
15
|
+
name = $proc.Name
|
|
16
|
+
command = $proc.CommandLine
|
|
17
|
+
exePath = $proc.ExecutablePath
|
|
18
|
+
user = $(if ($owner -and $owner.User) { if ($owner.Domain) { '{0}\\{1}' -f $owner.Domain, $owner.User } else { $owner.User } } else { $null })
|
|
19
|
+
ppid = $proc.ParentProcessId
|
|
20
|
+
threads = $(if ($gp) { @($gp.Threads).Count } else { $null })
|
|
21
|
+
elapsedSeconds = $elapsed
|
|
22
|
+
cpuUserSeconds = [math]::Round($proc.UserModeTime / 10000000, 2)
|
|
23
|
+
cpuSystemSeconds = [math]::Round($proc.KernelModeTime / 10000000, 2)
|
|
24
|
+
virtualBytes = $gp.VirtualMemorySize64
|
|
25
|
+
rssBytes = $gp.WorkingSet64
|
|
26
|
+
ioReadBytes = $proc.ReadTransferCount
|
|
27
|
+
ioWriteBytes = $proc.WriteTransferCount
|
|
28
|
+
connections = $conns
|
|
29
|
+
}
|
|
30
|
+
ConvertTo-Json -InputObject $row -Compress -Depth 3
|
|
31
|
+
`.trim()}async function V(n){const{stdout:t}=await l("powershell",["-NoProfile","-NonInteractive","-Command",z(n)],{encoding:"utf8",timeout:m,windowsHide:!0}),e=_(t);return!e||!Number.isFinite(Number(e.pid))?{ok:!0,pid:n,unsupported:f}:{ok:!0,pid:n,name:e.name||void 0,command:e.command||void 0,exePath:e.exePath||void 0,user:e.user||void 0,ppid:Number.isFinite(Number(e.ppid))?Number(e.ppid):void 0,threads:Number.isFinite(Number(e.threads))?Number(e.threads):void 0,elapsedSeconds:Number.isFinite(Number(e.elapsedSeconds))?Number(e.elapsedSeconds):void 0,cpuUserSeconds:Number.isFinite(Number(e.cpuUserSeconds))?Number(e.cpuUserSeconds):void 0,cpuSystemSeconds:Number.isFinite(Number(e.cpuSystemSeconds))?Number(e.cpuSystemSeconds):void 0,virtualBytes:Number.isFinite(Number(e.virtualBytes))?Number(e.virtualBytes):void 0,rssBytes:Number.isFinite(Number(e.rssBytes))?Number(e.rssBytes):void 0,ioReadBytes:Number.isFinite(Number(e.ioReadBytes))?Number(e.ioReadBytes):void 0,ioWriteBytes:Number.isFinite(Number(e.ioWriteBytes))?Number(e.ioWriteBytes):void 0,connections:Array.isArray(e.connections)?b(e.connections.filter(s=>s&&s.remote).map(s=>({remote:String(s.remote),state:s.state?String(s.state):void 0}))):void 0}}function b(n){return n.slice(0,I)}function y(n){return Math.round(n*100)/100}async function Q(n){const t=F.platform();try{return t==="win32"?await V(n):t==="darwin"?await K(n):await W(n)}catch(e){return k.debug("Failed to collect process detail:",e),{ok:!0,pid:n,unsupported:f}}}export{Q as collectProcessDetail,G as parseDarwinPsDetailLine,_ as parseJsonObject,A as parseLinuxCmdline,j as parseLinuxIoBytes,D as parseLinuxStatTimes,M as parseLsofConnectionLine,U as parseLsofConnectionsForPid,v as parseProcStatus,L as parseProcUptime,E as parsePsCpuTimeSeconds,w as parsePsEtimeSeconds,R as parseSsConnectionsForPid};
|
|
32
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type ProcessTopResource = "cpu" | "memory" | "storage" | "network";
|
|
2
|
+
export declare const PROCESS_TOP_RESOURCES: readonly ProcessTopResource[];
|
|
3
|
+
export interface ProcessTopSample {
|
|
4
|
+
pid: number;
|
|
5
|
+
name: string;
|
|
6
|
+
|
|
7
|
+
value: number;
|
|
8
|
+
readBytesPerSecond?: number;
|
|
9
|
+
writeBytesPerSecond?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ProcessTopSnapshot {
|
|
12
|
+
ok: true;
|
|
13
|
+
resource: ProcessTopResource;
|
|
14
|
+
limit: number;
|
|
15
|
+
collectedAt: string;
|
|
16
|
+
samples: ProcessTopSample[];
|
|
17
|
+
|
|
18
|
+
unsupported?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function normalizeProcessTopResource(value: unknown): ProcessTopResource | null;
|
|
21
|
+
export declare function clampProcessTopLimit(value: unknown): number;
|
|
22
|
+
export declare function sortAndSliceSamples(samples: ProcessTopSample[], limit: number): ProcessTopSample[];
|
|
23
|
+
export declare function parseLinuxStatLine(content: string): {
|
|
24
|
+
name: string;
|
|
25
|
+
ticks: number;
|
|
26
|
+
} | null;
|
|
27
|
+
export declare function parseLinuxIoFile(content: string): {
|
|
28
|
+
readBytes: number;
|
|
29
|
+
writeBytes: number;
|
|
30
|
+
};
|
|
31
|
+
export interface PsMetricsRow {
|
|
32
|
+
pid: number;
|
|
33
|
+
cpuPercent: number;
|
|
34
|
+
rssBytes: number;
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export declare function parsePsMetricsLine(line: string): PsMetricsRow | null;
|
|
39
|
+
export declare function parsePsMetricsRows(output: string): PsMetricsRow[];
|
|
40
|
+
|
|
41
|
+
export declare function parseSsConnectionCounts(output: string): Map<number, {
|
|
42
|
+
name: string;
|
|
43
|
+
connectionCount: number;
|
|
44
|
+
}>;
|
|
45
|
+
|
|
46
|
+
export declare function parseLsofConnectionCounts(output: string): Map<number, {
|
|
47
|
+
name: string;
|
|
48
|
+
connectionCount: number;
|
|
49
|
+
}>;
|
|
50
|
+
|
|
51
|
+
export declare function parseJsonRows<T>(stdout: string): T[];
|
|
52
|
+
|
|
53
|
+
export declare function collectProcessTop(resource: ProcessTopResource, limit: number): Promise<ProcessTopSnapshot>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import{execFile as h}from"node:child_process";import{readdir as T,readFile as w}from"node:fs/promises";import{promisify as M}from"node:util";import I from"node:os";const l=M(h);import{createLogger as g}from"../utils/logger.js";const x=g("process-top"),E=["cpu","memory","storage","network"],a=400,O=100,P=10,_=50,m=9e3,B="\u5F53\u524D\u7CFB\u7EDF\u65E0\u6CD5\u6309\u8FDB\u7A0B\u7EDF\u8BA1\u7F51\u7EDC\u8FDE\u63A5",L="macOS \u6682\u4E0D\u652F\u6301\u6309\u8FDB\u7A0B\u7EDF\u8BA1\u78C1\u76D8 IO";function ce(t){const e=String(t??"").trim();return E.includes(e)?e:null}function ae(t){const e=Math.floor(Number(t??P));return Number.isFinite(e)?Math.min(_,Math.max(1,e)):P}function R(t,e){return[...t].sort((n,s)=>s.value-n.value).slice(0,e)}function A(t){const e=t.replace(/\\/g,"/"),n=e.split("/").filter(Boolean);return n[n.length-1]||e}function b(t){const e=t.indexOf("("),n=t.lastIndexOf(")");if(e<0||n<=e)return null;const s=t.slice(e+1,n),o=t.slice(n+1).trim().split(/\s+/),r=Number(o[11]),i=Number(o[12]);return!Number.isFinite(r)||!Number.isFinite(i)?null:{name:s,ticks:r+i}}function k(t){let e=0,n=0;for(const s of t.split(/\r?\n/)){const[o,r]=s.split(":");if(!o||r===void 0)continue;const i=Number(r.trim());Number.isFinite(i)&&(o.trim()==="read_bytes"?e=i:o.trim()==="write_bytes"&&(n=i))}return{readBytes:e,writeBytes:n}}function W(t){const e=t.trim().match(/^(\d+)\s+([\d.]+)\s+(\d+)\s+(.+)$/);if(!e)return null;const n=Number(e[1]),s=Number(e[2]),o=Number(e[3])*1024;return!Number.isFinite(n)||!Number.isFinite(s)||!Number.isFinite(o)?null:{pid:n,cpuPercent:s,rssBytes:o,name:A(e[4].trim())}}function F(t){const e=[];for(const n of t.split(/\r?\n/)){const s=W(n);s&&e.push(s)}return e}async function $(){const{stdout:t}=await l("ps",["-eo","pid=,pcpu=,rss=,comm="],{encoding:"utf8",timeout:m});return F(t)}function v(t){const e=new Map;for(const n of t.split(/\r?\n/).slice(1)){if(!n.trim()||n.startsWith("State ")||n.trim().split(/\s+/)[0]==="LISTEN")continue;const o=new Set;for(const r of n.matchAll(/\("([^"]+)",pid=(\d+)/g)){const i=Number(r[2]);if(!Number.isFinite(i)||o.has(i))continue;o.add(i);const c=e.get(i)||{name:r[1],connectionCount:0};c.connectionCount+=1,e.set(i,c)}}return e}async function N(){return(await T("/proc")).filter(e=>/^\d+$/.test(e)).map(e=>Number(e))}async function D(){const t=async()=>{const s=await N(),o=await Promise.all(s.map(async r=>{try{const i=await w(`/proc/${r}/stat`,"utf8"),c=b(i);return c?[r,c]:null}catch{return null}}));return new Map(o.filter(Boolean))},e=await t();await new Promise(s=>{setTimeout(s,a)});const n=await t();return{first:e,second:n}}async function G(){const{first:t,second:e}=await D(),n=[];for(const[s,o]of e){const r=t.get(s);if(!r)continue;const i=o.ticks-r.ticks;if(i<=0)continue;const c=a/1e3;n.push({pid:s,name:o.name,value:Math.round(i/O/c*1e3)/10})}return n}async function j(){return(await $()).map(e=>({pid:e.pid,name:e.name,value:e.rssBytes}))}async function U(){const t=async()=>{const r=await N(),i=await Promise.all(r.map(async c=>{try{const[u,p]=await Promise.all([w(`/proc/${c}/stat`,"utf8"),w(`/proc/${c}/io`,"utf8")]),S=b(u);if(!S)return null;const y=k(p);return[c,{name:S.name,readBytes:y.readBytes,writeBytes:y.writeBytes}]}catch{return null}}));return new Map(i.filter(Boolean))},e=await t();await new Promise(r=>{setTimeout(r,a)});const n=await t(),s=a/1e3,o=[];for(const[r,i]of n){const c=e.get(r);if(!c)continue;const u=Math.max(0,Math.round((i.readBytes-c.readBytes)/s)),p=Math.max(0,Math.round((i.writeBytes-c.writeBytes)/s));o.push({pid:r,name:i.name,value:u+p,readBytesPerSecond:u,writeBytesPerSecond:p})}return o}async function J(){const{stdout:t}=await l("ss",["-tupn"],{encoding:"utf8",timeout:m}),e=[];for(const[n,s]of v(t))e.push({pid:n,name:s.name,value:s.connectionCount});return e}async function K(){return(await $()).map(e=>({pid:e.pid,name:e.name,value:e.cpuPercent}))}async function V(){return(await $()).map(e=>({pid:e.pid,name:e.name,value:e.rssBytes}))}function X(t){const e=new Map;for(const n of t.split(/\r?\n/).slice(1)){const s=n.trim().split(/\s+/);if(s.length<8)continue;const o=s[0],r=Number(s[1]);if(!Number.isFinite(r)||r<=0||s.slice(7).join(" ").includes("(LISTEN)"))continue;const c=e.get(r)||{name:o,connectionCount:0};c.connectionCount+=1,e.set(r,c)}return e}async function z(){const{stdout:t}=await l("lsof",["-n","-P","-i","TCP","+c0"],{encoding:"utf8",timeout:m}),e=[];for(const[n,s]of X(t))e.push({pid:n,name:s.name,value:s.connectionCount});return e}const C=`
|
|
2
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
3
|
+
$cores = [Environment]::ProcessorCount
|
|
4
|
+
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
|
5
|
+
$first = @{}
|
|
6
|
+
foreach ($p in Get-Process) { try { $first[$p.Id] = $p.TotalProcessorTime.TotalMilliseconds } catch {} }
|
|
7
|
+
Start-Sleep -Milliseconds ${a}
|
|
8
|
+
$elapsed = [Math]::Max(1, $sw.ElapsedMilliseconds)
|
|
9
|
+
$rows = @()
|
|
10
|
+
foreach ($p in Get-Process) {
|
|
11
|
+
$before = $first[$p.Id]
|
|
12
|
+
$cpu = 0
|
|
13
|
+
if ($null -ne $before) {
|
|
14
|
+
try { $cpu = [Math]::Round((($p.TotalProcessorTime.TotalMilliseconds - $before) / $elapsed) / $cores * 100, 1) } catch {}
|
|
15
|
+
}
|
|
16
|
+
$rows += [pscustomobject]@{ pid = $p.Id; name = $p.ProcessName; cpuPercent = $cpu; rssBytes = $p.WorkingSet64 }
|
|
17
|
+
}
|
|
18
|
+
ConvertTo-Json -InputObject $rows -Compress -Depth 2
|
|
19
|
+
`.trim(),H=`
|
|
20
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
21
|
+
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
|
22
|
+
$first = @{}
|
|
23
|
+
foreach ($p in Get-CimInstance Win32_Process) { $first[$p.ProcessId] = @($p.ReadTransferCount, $p.WriteTransferCount) }
|
|
24
|
+
Start-Sleep -Milliseconds ${a}
|
|
25
|
+
$elapsedSeconds = [Math]::Max(1, $sw.ElapsedMilliseconds) / 1000
|
|
26
|
+
$rows = @()
|
|
27
|
+
foreach ($p in Get-CimInstance Win32_Process) {
|
|
28
|
+
$before = $first[$p.ProcessId]
|
|
29
|
+
$read = 0
|
|
30
|
+
$write = 0
|
|
31
|
+
if ($before) {
|
|
32
|
+
$read = [Math]::Max(0, [int](($p.ReadTransferCount - $before[0]) / $elapsedSeconds))
|
|
33
|
+
$write = [Math]::Max(0, [int](($p.WriteTransferCount - $before[1]) / $elapsedSeconds))
|
|
34
|
+
}
|
|
35
|
+
$rows += [pscustomobject]@{ pid = $p.ProcessId; name = ($p.Name -replace '\\.exe$', ''); readBytesPerSecond = $read; writeBytesPerSecond = $write }
|
|
36
|
+
}
|
|
37
|
+
ConvertTo-Json -InputObject $rows -Compress -Depth 2
|
|
38
|
+
`.trim(),Y=`
|
|
39
|
+
$ErrorActionPreference = 'SilentlyContinue'
|
|
40
|
+
$names = @{}
|
|
41
|
+
foreach ($p in Get-Process) { $names[[int]$p.Id] = $p.ProcessName }
|
|
42
|
+
$rows = @()
|
|
43
|
+
$groups = Get-NetTCPConnection | Where-Object { $_.State -ne 'Listen' } | Group-Object -AsHashTable -AsString OwningProcess
|
|
44
|
+
foreach ($key in $groups.Keys) {
|
|
45
|
+
$pidInt = [int]$key
|
|
46
|
+
$rows += [pscustomobject]@{ pid = $pidInt; name = $names[$pidInt]; connectionCount = @($groups[$key]).Count }
|
|
47
|
+
}
|
|
48
|
+
ConvertTo-Json -InputObject $rows -Compress -Depth 2
|
|
49
|
+
`.trim();function d(t){const e=t.trim();if(!e)return[];const n=JSON.parse(e);return Array.isArray(n)?n:[n]}function f(t){return l("powershell",["-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",timeout:m,windowsHide:!0}).then(e=>e.stdout)}async function q(){return d(await f(C)).filter(e=>Number.isFinite(Number(e.pid))&&Number(e.cpuPercent)>0).map(e=>({pid:Number(e.pid),name:String(e.name||"unknown"),value:Number(e.cpuPercent)}))}async function Q(){return d(await f(C)).filter(e=>Number.isFinite(Number(e.pid))).map(e=>({pid:Number(e.pid),name:String(e.name||"unknown"),value:Number(e.rssBytes||0)}))}async function Z(){return d(await f(H)).filter(e=>Number.isFinite(Number(e.pid))).map(e=>{const n=Number(e.readBytesPerSecond||0),s=Number(e.writeBytesPerSecond||0);return{pid:Number(e.pid),name:String(e.name||"unknown"),value:n+s,readBytesPerSecond:n,writeBytesPerSecond:s}})}async function ee(){return d(await f(Y)).filter(e=>Number.isFinite(Number(e.pid))).map(e=>({pid:Number(e.pid),name:String(e.name||"unknown"),value:Number(e.connectionCount||0)}))}function te(t){return!!(t&&typeof t=="object"&&t.code==="ENOENT")}async function ue(t,e){const n=I.platform(),s={ok:!0,resource:t,limit:e,collectedAt:new Date().toISOString()};if(n==="darwin"&&t==="storage")return{...s,samples:[],unsupported:L};try{let o;return n==="win32"?o=t==="cpu"?await q():t==="memory"?await Q():t==="storage"?await Z():await ee():n==="darwin"?o=t==="cpu"?await K():t==="memory"?await V():await z():o=t==="cpu"?await G():t==="memory"?await j():t==="storage"?await U():await J(),{...s,samples:R(o,e)}}catch(o){if(t==="network"&&(te(o)||n==="win32"))return x.debug("Failed to collect network process top:",o),{...s,samples:[],unsupported:B};throw o}}export{E as PROCESS_TOP_RESOURCES,ae as clampProcessTopLimit,ue as collectProcessTop,ce as normalizeProcessTopResource,d as parseJsonRows,k as parseLinuxIoFile,b as parseLinuxStatLine,X as parseLsofConnectionCounts,W as parsePsMetricsLine,F as parsePsMetricsRows,v as parseSsConnectionCounts,R as sortAndSliceSamples};
|
|
50
|
+
|
|
@@ -90,6 +90,16 @@ export interface RuntimeFileChangedPayload {
|
|
|
90
90
|
size?: number;
|
|
91
91
|
mtimeMs?: number;
|
|
92
92
|
}
|
|
93
|
+
export interface ToolAuthRequestPayload {
|
|
94
|
+
requestId: string;
|
|
95
|
+
capability: string;
|
|
96
|
+
path?: string;
|
|
97
|
+
command?: string;
|
|
98
|
+
cwd?: string;
|
|
99
|
+
operation?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export declare function sendToolAuthRequest(agentId: string, sessionId: string, request: ToolAuthRequestPayload, authOptions?: RuntimeCallbackAuthOptions): Promise<void>;
|
|
93
103
|
|
|
94
104
|
export declare function sendFileChanged(payload: RuntimeFileChangedPayload): Promise<void>;
|
|
95
105
|
|