aws-runtime-bridge 1.9.101 → 1.9.103
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/README.md +2 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/AcodeSdkAdapter.js +3 -3
- package/dist/index.js +1 -1
- package/dist/remote-desktop/computer-control.js +1 -1
- package/dist/remote-desktop/computer-use-backend.d.ts +111 -0
- package/dist/remote-desktop/computer-use-backend.js +1 -0
- package/dist/remote-desktop/frame-encode.d.ts +3 -0
- package/dist/remote-desktop/frame-encode.js +2 -0
- package/dist/remote-desktop/index.js +2 -2
- package/dist/remote-desktop/screen-capture.d.ts +80 -5
- package/dist/remote-desktop/screen-capture.js +1 -1
- package/dist/remote-desktop/session-manager.d.ts +3 -2
- package/dist/remote-desktop/session-manager.js +1 -1
- package/dist/remote-desktop/system-backend.js +1 -1
- package/dist/remote-desktop/types.d.ts +104 -0
- package/dist/routes/computer.d.ts +1 -0
- package/dist/routes/computer.js +2 -0
- package/dist/routes/file-change-diff.d.ts +27 -0
- package/dist/routes/file-change-diff.js +5 -0
- package/dist/routes/instance.js +2 -2
- package/dist/routes/pty.d.ts +2 -2
- package/dist/routes/pty.js +3 -3
- package/dist/routes/task-context.js +1 -1
- package/dist/routes/terminal.js +28 -28
- package/dist/services/auto-register.d.ts +1 -1
- package/dist/services/auto-register.js +1 -1
- package/dist/services/instance-features.d.ts +10 -0
- package/dist/services/instance-features.js +2 -0
- package/dist/services/sdk-tool-file-change-recorder.d.ts +12 -0
- package/dist/services/sdk-tool-file-change-recorder.js +2 -0
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/services/workspaceTaskChangeWatcher.d.ts +9 -1
- package/dist/services/workspaceTaskChangeWatcher.js +3 -1
- package/package/acode/dist/built-in-file-tools.d.ts +4 -0
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/runtime.d.ts +13 -0
- package/package/acode/dist/runtime.js +18 -18
- package/package/aws-client-agent-mcp/README.md +2 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +14 -4
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.test.js +36 -36
- package/package/aws-client-agent-mcp/dist/config.js +1 -1
- package/package/aws-client-agent-mcp/dist/config.test.js +2 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/mcp-server.js +21 -21
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +35 -36
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +6 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +25 -5
- package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +17 -1
- package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +14 -12
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package.json +3 -2
- package/scripts/ensure-playwright-browser.mjs +118 -0
package/dist/routes/terminal.js
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as We}from"node:child_process";import{promises as N}from"node:fs";import we from"node:os";import j from"node:path";import{TextDecoder as ee}from"node:util";import{Router as He}from"express";import{v4 as Qe}from"uuid";import Ce from"axios";import{adapterRegistry as w,getToolActionInfo as ye,isTransientClipboardPasteFilePath as be,redactTransientClipboardPastePaths as q,registerSdkProviders as Xe,resolveSdkProviderIdByCommand as Ge}from"../adapter/index.js";import{validateToken as S}from"../middleware/auth.js";import{getAgentProcessManager as he}from"../services/agent-process-manager.js";import{setAgentFeatures as Je,getAgentFeatures as Ve}from"../services/instance-features.js";import{getAiConfigService as Ye}from"../services/cc-switch-sdk.js";import{prepareAcodeInstanceConfig as Ze,redactForLog as te}from"../services/instance-ai-config-service.js";import{enqueueMcpLaunchBinding as et}from"../services/mcp-launch-binding-queue.js";import{resolveSchedulerBaseUrlFromToken as $e}from"../services/auto-register.js";import{findClaudeCodeProcesses as tt,isProcessRunning as nt}from"../services/process-detector.js";import{bridgeEventBuffer as _e,sendOutput as Q,sendQuestionRequest as rt,sendStatus as _}from"../services/session-output.js";import{getAllPushStats as ot,startHeartbeatScheduler as st}from"../services/event-delta-pusher.js";import{forgetSession as v,onSdkToolUseEnd as it,onSdkToolUseStart as at}from"../services/sdk-tool-file-change-recorder.js";import{findPersistedSessionByAgentId as ct,removePersistedSession as F,savePersistedSessions as ut,updatePersistedSessionAutoCommands as dt,updatePersistedSessionRuntimeState as lt,upsertPersistedSession as mt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as ft}from"../utils/instance-ai-config-debug-logger.js";import{logger as h}from"../utils/logger.js";const A=He();function De(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,pt=45e3,ne=new Map;function gt(e){if(ne.has(e))return;const n=setInterval(()=>{const t=f.get(e);if(!t){M(e);return}const r=t.currentRuntimeStatus;if(r!=="thinking"&&r!=="tool_using"&&r!=="compacting"){M(e);return}_(t.agentId,e,r,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},pt);ne.set(e,n)}function M(e){const n=ne.get(e);n&&(clearInterval(n),ne.delete(e))}const Pe=4e3,yt=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u4F53:
|
|
4
|
-
`;function
|
|
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 ht=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u5934:
|
|
7
|
-
`,K=new Set;async function
|
|
7
|
+
`,K=new Set;async function It(e,n){const t=[],r=[],s=j.join(e,".agentswork","memory");try{const c=(await N.readdir(s)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await N.readFile(j.join(s,u),"utf-8");return JSON.parse(l)}catch{return h.warn("[loadAgentStartupMemories] Failed to parse memory file: %s",j.join(s,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"&&r.push({title:l.title,content:p,uri:l.uri||""}))}}catch{h.debug("[loadAgentStartupMemories] \u65E0\u6CD5\u8BFB\u53D6\u8BB0\u5FC6\u76EE\u5F55: %s",s)}if(t.length===0&&r.length===0&&n?.schedulerBaseUrl&&n?.runtimeAccessToken&&n?.agentId){const a=`${n.schedulerBaseUrl.replace(/\/+$/,"")}/mcp/call`,c={"Content-Type":"application/json","X-Runtime-Token":n.runtimeAccessToken,Authorization:`Bearer ${n.runtimeAccessToken}`},d=["recently_memory","agent_memory"],u=await Promise.allSettled(d.map(l=>fetch(a,{method:"POST",headers:c,body:JSON.stringify({tool:"list_memories",arguments:{agentId:n.agentId,memory_type:l}})}).then(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:r;for(const y of p){const g=(y.content||"").trim();g&&T.push({title:y.title,content:g,uri:y.uri||""})}}(t.length>0||r.length>0)&&h.info(`[loadAgentStartupMemories] Loaded ${t.length} task(s) and ${r.length} memory(s) from server for ${n.agentId}`)}const o=10;t.sort((a,c)=>c.uri.localeCompare(a.uri)),r.sort((a,c)=>c.uri.localeCompare(a.uri));const i=[];if(t.length>0){const c=t.slice(0,o).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
|
|
|
11
|
-
`)}`),
|
|
11
|
+
`)}`),t.length>o&&i.push(`... \u53CA\u53E6\u5916 ${t.length-o} \u6761\u77ED\u671F\u8BB0\u5FC6`)}if(r.length>0){const c=r.slice(0,o).map(d=>{const u=d.title?`\u3010${d.title}\u3011`:"";return u?`${u}
|
|
12
12
|
${d.content}`:d.content});i.push(`\u3010agent\u8BA4\u77E5\u3011
|
|
13
13
|
${c.join(`
|
|
14
14
|
|
|
15
15
|
`)}`),r.length>o&&i.push(`... \u53CA\u53E6\u5916 ${r.length-o} \u6761 agent \u8BA4\u77E5`)}if(i.length!==0)return i.join(`
|
|
16
16
|
|
|
17
|
-
`)}function
|
|
17
|
+
`)}function St(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 At(e){return e!=="acode"}function Tt(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function re(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,r=Number.isFinite(n.outputTokens)?n.outputTokens:0;return t<=0&&r<=0&&!n.contextLimit&&!n.maxOutput&&!n.inputLimit&&!n.compactionThreshold?void 0:{inputTokens:t,outputTokens:r,...n.contextLimit?{contextLimit:n.contextLimit}:{},...n.maxOutput?{maxOutput:n.maxOutput}:{},...n.inputLimit?{inputLimit:n.inputLimit}:{},...n.compactionThreshold?{compactionThreshold:n.compactionThreshold}:{}}}function kt(e,n){const t=String(e||"").trim().toLowerCase(),r=String(n?.actionType||"").trim().toLowerCase();return t==="tool_using"&&r==="idle"?n?{status:"waiting_input",actionInfo:n}:{status:"waiting_input"}:n?{status:e,actionInfo:n}:{status:e}}const X=new Map,wt="utf-8",Re="utf-8",xe=300,Ee=6e4;function G(e){return String(e).padStart(2,"0")}function Ct(e,n=new Date){const t=n.getFullYear(),r=G(n.getMonth()+1),s=G(n.getDate()),o=G(n.getHours()),i=G(n.getMinutes()),a=`${t}${r}${s}-${o}${i}${G(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return j.join(we.homedir(),".acode","cmd-dist",e,`${t}-${r}-${s}`,o,i,`${a}-cmd.out`)}function bt(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
|
|
18
18
|
`).replace(/\r/g,`
|
|
19
|
-
`),n
|
|
20
|
-
`)?
|
|
21
|
-
`).length:1}function
|
|
22
|
-
[ACode] \u547D\u4EE4\u8F93\u51FA\u8D85\u8FC7 ${
|
|
19
|
+
`),t=n.endsWith(`
|
|
20
|
+
`)?n.slice(0,-1):n;return t?t.split(`
|
|
21
|
+
`).length:1}function $t(e,n=xe){return`\r
|
|
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 _t(e=Ee){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
|
|
27
|
-
`).trim()}function
|
|
28
|
-
`),!0;const s=
|
|
26
|
+
`}async function Me(e){const n=e.outputPath||Ct(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 Dt(e){return String(e??"").replace(/\r/g,`
|
|
27
|
+
`).trim()}function Pt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?wt:Re)}function Le(e=Pt()){if(e!=="utf-8")try{return new ee(e,{fatal:!1})}catch{return new ee(Re,{fatal:!1})}return Rt()}function Rt(){let e=null,n=null,t=null;const r=[];function s(o){try{return new ee(o,{fatal:!1})}catch{return new ee("utf-8",{fatal:!1})}}return{decode(o,i){if(o!=null&&r.push(o instanceof ArrayBuffer?Buffer.from(o):Buffer.isBuffer(o)?o:Buffer.from(o.buffer,o.byteOffset,o.byteLength)),t==="gb18030")return n||(n=s("gb18030")),n.decode(o,i);e||(e=s("utf-8"));const a=e.decode(o,i);if(t===null&&a.includes("\uFFFD")){t="gb18030",n=s("gb18030");const c=Buffer.concat(r);return n.decode(c)}return t===null&&!i?.stream&&(t="utf-8"),a}}}function oe(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function xt(e){const n=e.trim().match(/^cd(?:\s+(.*))?$/i);if(!n)return;const t=n[1]?.trim();if(!t)return null;const r=t.replace(/^\/d\s+/i,"").trim();return r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function Et(e){const n=X.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return X.set(e.sessionId,t),t}function Ue(e){for(const n of f.values())if(n.agentId===e)return n}async function Mt(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 r=String(e||"").trim();if(r){const o=String(n||"").trim(),i=String(t||"").trim().toLowerCase();return r.toLowerCase()==="tool_using"&&o.toLowerCase()==="waiting_input"&&i==="idle"?o:r}return String(n||"").trim()||"running"}function Lt(e,n=nt){return e.pid?n(e.pid)?ve(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 vn(e){const n=Ue(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}`),M(t),f.delete(t),v(t),ie(t),F(t).catch(r=>{h.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${r}`)}),t}K.has(e)&&(K.delete(e),h.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ie(e){const n=X.get(e);if(!n?.runningProcess){X.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,X.delete(e)}}function C(e,n){n&&(e.seq+=1,Q(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 Ut(e,n){return n==="~"?we.homedir():j.resolve(e,n)}async function jt(e,n,t){const r=xt(t);if(r===void 0)return!1;if(r===null)return C(e,`${n.currentDirectory}\r
|
|
28
|
+
`),!0;const s=Ut(n.currentDirectory,r);try{return(await N.stat(s)).isDirectory()?(n.currentDirectory=s,C(e,`${n.currentDirectory}\r
|
|
29
29
|
`),!0):(C(e,`cd: not a directory: ${s}\r
|
|
30
30
|
`),!0)}catch(o){const i=o instanceof Error?o.message:String(o);return C(e,`cd: ${i}\r
|
|
31
|
-
`),!0}}async function
|
|
32
|
-
`),
|
|
33
|
-
`),C(
|
|
31
|
+
`),!0}}async function Bt(e,n){const t=f.get(e);if(!t)throw new Error("SDK session not found");const r=Dt(n),s=Et(t);if(!r)return{started:!1,cwd:s.currentDirectory};if(s.runningProcess)throw new Error("A terminal command is already running for this session");const o=q(r);if(C(t,`${Se(s.currentDirectory)}${o}\r
|
|
32
|
+
`),be(r))return C(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
|
+
`),C(t,Se(s.currentDirectory)),{started:!1,cwd:s.currentDirectory};if(await jt(t,s,r))return{started:!1,cwd:s.currentDirectory};await _(t.agentId,e,"tool_using",{actionType:"bash",actionLabel:"\u7EC8\u7AEF\u547D\u4EE4",actionDetail:o},void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl});const a=We(r,{cwd:s.currentDirectory,shell:!0,env:je(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});s.runningProcess=a;const c=Le(),d=Le(),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(()=>{s.runningProcess===a&&(C(t,_t()),a.kill())},Ee)},y=(g,b=!0)=>{if(g&&(u&&l.chunks.push(g),u&&b&&T(),!(u&&l.spilled))){if(u&&bt(l.chunks.join(""))>xe){l.spilled=!0,Me(l).then($=>{C(t,$t($))}).catch($=>{const E=$ instanceof Error?$.message:String($);C(t,`\r
|
|
34
34
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${E}\r
|
|
35
|
-
`)});return}C(
|
|
35
|
+
`)});return}C(t,g)}};return u&&T(),a.stdout.on("data",g=>{y(oe(c,g))}),a.stderr.on("data",g=>{y(oe(d,g))}),a.on("error",g=>{C(t,`\r
|
|
36
36
|
[Terminal Error] ${g.message}\r
|
|
37
|
-
`)}),a.on("close",(g,b)=>{p(),s.runningProcess=null,y(
|
|
37
|
+
`)}),a.on("close",(g,b)=>{p(),s.runningProcess=null,y(oe(c,void 0,!0),!1),y(oe(d,void 0,!0),!1),l.spilled&&Me(l).catch($=>{const E=$ instanceof Error?$.message:String($);C(t,`\r
|
|
38
38
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u6700\u7EC8\u843D\u76D8\u5931\u8D25: ${E}\r
|
|
39
|
-
`)}),g&&g!==0?C(
|
|
39
|
+
`)}),g&&g!==0?C(t,`\r
|
|
40
40
|
[exit ${g}]\r
|
|
41
|
-
`):b&&C(
|
|
41
|
+
`):b&&C(t,`\r
|
|
42
42
|
[signal ${b}]\r
|
|
43
|
-
`),C(
|
|
44
|
-
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function
|
|
45
|
-
[ACode] \u6B63\u5728\u8BF7\u6C42\u6A21\u578B${
|
|
43
|
+
`),C(t,Se(s.currentDirectory)),_(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:s.currentDirectory}}function je(e,n,t,r){const s={};for(const[o,i]of Object.entries(t))i!==void 0&&(s[o]=i);if(n&&(s.AWS_WORKSPACE_PATH=String(n)),r)for(const[o,i]of Object.entries(r)){const a=o.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(s[a]=c)}return s.AWS_AGENT_ID=String(e),s.AWS_MCP_CLAIM_LAUNCH_BINDING="true",s}function Ot(e){const n=e.trim(),t=n[0],r=n[n.length-1];return(t==='"'||t==="'")&&t===r?n.slice(1,-1):n}async function Nt(e){const n=String(e);if(!be(n))return n;const t=Ot(n);return j.isAbsolute(t)?N.readFile(t,"utf-8"):n}function Be(e,n){const t={};for(const s of[e?.env,n])if(s)for(const[o,i]of Object.entries(s)){const a=o.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(t[a]=c)}const r=t.ANTHROPIC_MODEL?.trim()||t.CODEX_MODEL?.trim()||void 0;return{envOverrides:t,model:r}}async function qt(){try{return await Ye().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function vt(e){if(e==null)return;const t=(typeof e=="string"?e:JSON.stringify(e,null,2)).trim();if(t)return t.length<=Pe?t:`${t.slice(0,Pe)}
|
|
44
|
+
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function Ft(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 Kt(e){if(e.type!=="tool_use_end")return;const n=vt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionType||t.actionType;if(r!=="idle")return r==="mcp"&&Ft(e)?{actionType:"mcp",actionLabel:"MCP\u8FD4\u56DE",actionDetail:e.data.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}:{actionType:r,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:e.data.actionDetail||t.actionDetail||e.data.toolName,actionId:e.data.actionId||e.data.toolUseId,actionResult:n}}function zt(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
|
+
[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`:
|
|
50
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",s=
|
|
51
|
-
`)}`:"",o=e.requestBody?`${lt}${e.requestBody}`:"";return`${r}${s}${o}`}function Jt(e){return e?Object.entries(e).map(([t,n])=>`${t}: ${n}`).filter(t=>t.trim().length>0):[]}function Yt(e,t){return String(t||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function Zt(e){for(const t of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const n=e[t],r=Number(n);if(Number.isFinite(r)&&r>0)return r}}function en(e,t){if(!Yt(e,t)){if(e.type==="ai_request"){const n=Zt(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:Vt(e.data),...n!==void 0?{usage:{inputTokens:n,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 n=ge(e.data.toolName,e.data.toolInput),r=Oe(e,n),s=Gt(e.data.toolInput);return e.data.actionType==="idle"||n.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||n.actionType,actionLabel:e.data.actionLabel||n.actionLabel,actionDetail:r||e.data.actionDetail||n.actionDetail||e.data.toolName,actionInput:s,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||n.actionType,actionLabel:e.data.actionLabel||n.actionLabel,actionDetail:r||e.data.actionDetail||n.actionDetail||e.data.toolName,actionInput:s,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:t||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const L=new Map,ie=new Map,ae=new Map,G=new Map,tn=20,nn=500,rn=3e4;async function ce(e,t=rn,n=2){for(let r=0;r<=n;r++){const s=new AbortController;let o;try{const i=e(s.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{o=setTimeout(()=>{s.abort(),c(new Error(`sendOutput timeout after ${t}ms`))},t)})]),o&&clearTimeout(o);return}catch(i){o&&clearTimeout(o);const a=i instanceof Error?i.message:String(i);if(r<n){const c=1e3*(r+1);h.warn(`sendOutput attempt ${r+1}/${n+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}h.warn(`sendOutput failed after ${n+1} attempts (${a}), giving up to unblock serial queue`)}}}function ue(e,t){const n=t?`${e}:${t}`:void 0;let r,s;if(n)r=G.get(n),s=n;else{const p=[];for(const[T,y]of G)T.startsWith(e+":")&&y.buffer&&p.push(y.sourceEventType);for(const T of p)ue(e,T);return}if(!r||!r.buffer)return;r.timer=null;const o=r.buffer,i=r.seq,a=r.entry,c=r.sourceEventType;r.buffer="",s&&G.delete(s);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},m=(L.get(e)??Promise.resolve()).then(()=>ce(p=>H(a.agentId,o,e,i,d,u,p)),()=>ce(p=>H(a.agentId,o,e,i,d,u,p)));L.set(e,m),m.finally(()=>{L.get(e)===m&&L.delete(e)})}function on(e,t){const n=Nt(e);if(!n)return;t.seq+=1;const r=t.seq,s=qt(e),o={runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&n.length<tn){const c=`${e.sessionId}:${e.type}`;let d=G.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:t,sourceEventType:e.type}),d.buffer+=n,d.seq=r,d.entry=t,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>ue(u,l),nn)}G.set(c,d);return}ue(e.sessionId);const a=(L.get(e.sessionId)??Promise.resolve()).then(()=>ce(c=>H(t.agentId,n,e.sessionId,r,s,o,c)),()=>ce(c=>H(t.agentId,n,e.sessionId,r,s,o,c)));L.set(e.sessionId,a),a.finally(()=>{L.get(e.sessionId)===a&&L.delete(e.sessionId)})}function qe(e){return Xe(e)}let ve=!1;function sn(){ve||(Qe(w,an),nt(),ve=!0)}function an(e,t){e.on("event",n=>{const r=f.get(n.sessionId);if(r){if(console.log(`[${t.displayName} Adapter] Event: ${n.type} for session ${n.sessionId}`),!(n.type==="thinking"||n.type==="text_delta"||n.type==="tool_use_start"||n.type==="context_compaction"||n.type==="ai_request")){n.type==="runtime_capabilities"&&n.data.actionDetail&&(r.cachedCapabilitiesActionDetail=n.data.actionDetail);const i=en(n,r.currentRuntimeStatus);i&&_(r.agentId,n.sessionId,i.status,i.actionInfo,ne(i.actionInfo),{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},n.timestamp?new Date(n.timestamp).getTime():void 0,n.type)}on(n,r);const o=Ot(n);if(o){const i={runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},a=n.timestamp?new Date(n.timestamp).getTime():void 0;String(n.data?.toolName||"").toLowerCase()==="browser_launch"?(async()=>{for(let u=0;u<3;u++){if(await _(r.agentId,n.sessionId,"tool_result",o,void 0,i,a,n.type)!==void 0)return;u<2&&await new Promise(m=>setTimeout(m,3e3*(u+1)))}})().catch(d=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",d)):_(r.agentId,n.sessionId,"tool_result",o,void 0,i,a,n.type)}}}),e.on("status-change",(n,r,s)=>{const o=f.get(n);if(o){ue(n),r==="thinking"||r==="tool_using"||r==="compacting"?dt(n):M(n);const i=ht(r,s);o.currentRuntimeStatus=i.status;const a=o.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(o.currentRuntimeActionType==="idle"||o.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(o.currentRuntimeActionType=i.actionInfo?.actionType,o.currentRuntimeActionLabel=i.actionInfo?.actionLabel,o.currentRuntimeActionDetail=i.actionInfo?.actionDetail,o.currentRuntimeActionInput=i.actionInfo?.actionInput),console.log(`[${t.displayName} Adapter] Status changed: ${i.status} for agent ${o.agentId}`,i.actionInfo||""),it(n,{runtimeStatus:i.status,runtimeActionType:o.currentRuntimeActionType,runtimeActionLabel:o.currentRuntimeActionLabel,runtimeActionDetail:o.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:o.currentRuntimeActionType?{actionType:o.currentRuntimeActionType,actionLabel:o.currentRuntimeActionLabel??"",actionDetail:o.currentRuntimeActionDetail,actionInput:o.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const p=(ie.get(n)??Promise.resolve()).then(async()=>{for(let y=0;y<=2;y++){if(await _(o.agentId,n,i.status,l,ne(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})!==void 0)return;y<2&&(h.warn(`[${t.displayName}] compaction sendStatus attempt ${y+1} failed (HTTP), retrying in ${1e3*(y+1)}ms...`),await new Promise(b=>setTimeout(b,1e3*(y+1))))}h.warn(`[${t.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{h.warn(`[${t.displayName}] compaction status chain error:`,T)});ie.set(n,p),p.finally(()=>{ie.get(n)===p&&ie.delete(n)})}else{const m=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||o.currentRuntimeActionType==="idle"&&u){const y=(ae.get(n)??Promise.resolve()).then(async()=>{for(let b=0;b<=2;b++){if(await _(o.agentId,n,i.status,m?void 0:l,ne(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})!==void 0)return;b<2&&await new Promise(E=>setTimeout(E,1e3*(b+1)))}h.warn(`[${t.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(`[${t.displayName}] idle status chain error:`,g)});ae.set(n,y),y.finally(()=>{ae.get(n)===y&&ae.delete(n)})}else _(o.agentId,n,i.status,m?void 0:l,ne(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}if(i.status==="waiting_input"&&o.cachedCapabilitiesActionDetail){const m=o.cachedCapabilitiesActionDetail;o.cachedCapabilitiesActionDetail=void 0,console.log(`[${t.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${o.agentId} (session stabilized to waiting_input)`),_(o.agentId,n,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:m},void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}}}),e.on("ask-user-question",n=>{const r=f.get(n.sessionId);r&&(console.log(`[${t.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),et(r.agentId,n.sessionId,Array.isArray(n.questions)?n.questions:[],{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},n.toolCallId))}),e.on("permission-request",n=>{const r=f.get(n.sessionId);if(r){console.log(`[${t.displayName} Adapter] Permission request: ${n.toolName} for agent ${r.agentId}`);const s=n.toolInput?q(JSON.stringify(n.toolInput).slice(0,400)):void 0;_(r.agentId,n.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:s||n.toolName},void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl})}})}A.post("/start",S,async(e,t)=>{const{agentId:n,workspacePath:r,mode:s="sdk"}=e.body||{};if(!n||!r){t.status(400).json({error:"agentId and workspacePath are required"});return}const o=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||be(_e(e))||void 0;Je({agentId:String(n),workspacePath:String(r),serverUrl:e.body?.serverUrl||o,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:o}),s&&s!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${s}" requested for agent ${n}; starting SDK session instead.`),await cn(e,t)});async function cn(e,t){const{agentId:n,workspacePath:r,command:s,autoAccept:o=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:m,envOverrides:p,idleInputAutoCommand:T,nonInputAutoCommand:y,model:g,instanceAiConfig:b,subAgentModel:$,subAgentEffort:E,scopeKey:Ae}=e.body||{},F=ct();F.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(n||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:b?ee(b):null,perAgentModel:g??null}});let D=null;const I=String(n||"").trim(),de=String(e.body?.runtimeAccessToken||"").trim()||void 0,B=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||be(_e(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(sn(),!I){t.status(400).json({error:"agentId is required"});return}const O=Le(I);if(O){t.json(await Dt(O));return}const k=await rt(I);if(k){const P=Pt(k);if(!P.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${I}, sessionId=${k.sessionId}, reason=${P.reason}`),await v(k.sessionId);else{const R=oe(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);t.json({sessionId:k.sessionId,status:R,runtimeStatus:R,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)){t.status(409).json({error:"SDK session is already starting for this agent"});return}K.add(I);const mn=(s||"acode").toLowerCase(),x=qe(s),Ke=w.get(x);D=He();const Fe=x==="claude-code"?await jt():null,V=Ue(x==="claude-code"?Fe:null,p),z=x==="acode"?g?String(g).trim():void 0:(()=>{const P=g?String(g).trim():void 0,R=V.model?String(V.model).trim():void 0;return P||R})();F.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:V.model??null,resolvedModel:z??null,providerId:x,note:x==="acode"?"adapter handles full priority":"request > global"}});const le={...V.envOverrides};z&&(le.ANTHROPIC_MODEL=z,le.CODEX_MODEL=z);let W,me=l;if(x==="acode"){const P=b||{},R=await Ve({apiOverrides:he(P)??void 0,agentId:I,sessionId:D??void 0,runtimeBridgeBaseUrl:B});W=R.instanceConfig.config,me=R.perInstanceConfigPath,F.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:I,sessionId:D??void 0,details:{sanitizedApiOverrides:he(P)?ee(he(P)):null,resolvedInstanceAiConfig:W?ee(W):null,perInstanceConfigPath:me,instanceConfigSources:R.instanceConfig.source??null}})}let Te=a||void 0,fe,pe,J;if(x==="acode")if(fe=typeof c=="string"&&c.trim()||void 0,pe=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())J=u.trim();else{const P=await ft(r,{schedulerBaseUrl:B,runtimeAccessToken:de,agentId:I});P&&(J=P,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 R=[c,d,u,a].filter(Y=>typeof Y=="string"&&Y.trim().length>0).map(Y=>Y.trim());Te=R.length>0?R.join(`
|
|
48
|
+
`:void 0}function Wt(e){const n=Xt(e);return{sourceEventType:e.type,logCategory:"acode",...Qt(e),...n?{logLevel:Ht(e),logMessage:n}:{}}}function Ht(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function Qt(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 Xt(e){if(e.type==="ai_request"){const n=e.data.model||"unknown-model",t=e.data.endpoint?` @ ${e.data.endpoint}`:"",r=typeof e.data.toolCount=="number"?`, tools=${e.data.toolCount}`:"";return`AI request started: ${n}${t}${r}`}if(e.type==="tool_use_start")return Oe(e,"\u5F00\u59CB");if(e.type==="tool_use_end")return Oe(e,"\u5B8C\u6210");if(e.type==="command_output")return Vt(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 Gt=/\x1b\[[0-9;?]*[a-zA-Z]/g;function Jt(e){return e.replace(Gt,"")}function Vt(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",r=Jt(String(e.data.text||"")).replace(/\s+/g," ").trim(),s=r.length>240?`${r.slice(0,240)}...`:r;return`\u547D\u4EE4\u8F93\u51FA(${n}${t}): ${s||"(empty)"}`}function Oe(e,n){const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionLabel||t.actionLabel||"\u8C03\u7528\u5DE5\u5177",s=Ne(e,t);return s?`${n}${r}: ${s}`:`${n}${r}: ${e.data.actionDetail||e.data.toolName||"tool"}`}function Ne(e,n){const t=e.data.toolInput;return n.actionType==="bash"?Yt(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?Zt(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function Yt(e){const n=Ae(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(r=>String(r??"").trim()).filter(Boolean).join(" ");return t?q(t):void 0}return Ae(e?.args)}function Zt(e){const n=qe(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=qe(n)[0];if(t)return t}}}function qe(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>q(n)):[]}function en(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 tn(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=nn(e.requestHeaders),r=n.join(`
|
|
50
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",s=t.length>0?`${ht}${t.join(`
|
|
51
|
+
`)}`:"",o=e.requestBody?`${yt}${e.requestBody}`:"";return`${r}${s}${o}`}function nn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function rn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function on(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],r=Number(t);if(Number.isFinite(r)&&r>0)return r}}function sn(e,n){if(!rn(e,n)){if(e.type==="ai_request"){const t=on(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:tn(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),r=Ne(e,t),s=en(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:s,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:s,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 L=new Map,ae=new Map,ce=new Map,J=new Map,an=20,cn=500,un=3e4;async function ue(e,n=un,t=2){for(let r=0;r<=t;r++){const s=new AbortController;let o;try{const i=e(s.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{o=setTimeout(()=>{s.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),o&&clearTimeout(o);return}catch(i){o&&clearTimeout(o);const a=i instanceof Error?i.message:String(i);if(r<t){const c=1e3*(r+1);h.warn(`sendOutput attempt ${r+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 r,s;if(t)r=J.get(t),s=t;else{const p=[];for(const[T,y]of J)T.startsWith(e+":")&&y.buffer&&p.push(y.sourceEventType);for(const T of p)de(e,T);return}if(!r||!r.buffer)return;r.timer=null;const o=r.buffer,i=r.seq,a=r.entry,c=r.sourceEventType;r.buffer="",s&&J.delete(s);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},m=(L.get(e)??Promise.resolve()).then(()=>ue(p=>Q(a.agentId,o,e,i,d,u,p)),()=>ue(p=>Q(a.agentId,o,e,i,d,u,p)));L.set(e,m),m.finally(()=>{L.get(e)===m&&L.delete(e)})}function dn(e,n){const t=zt(e);if(!t)return;n.seq+=1;const r=n.seq,s=Wt(e),o={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<an){const c=`${e.sessionId}:${e.type}`;let d=J.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=r,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),cn)}J.set(c,d);return}de(e.sessionId);const a=(L.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>Q(n.agentId,t,e.sessionId,r,s,o,c)),()=>ue(c=>Q(n.agentId,t,e.sessionId,r,s,o,c)));L.set(e.sessionId,a),a.finally(()=>{L.get(e.sessionId)===a&&L.delete(e.sessionId)})}function ve(e){return Ge(e)}let Fe=!1;function ln(){Fe||(Xe(w,mn),st(),Fe=!0)}function mn(e,n){e.on("event",t=>{const r=f.get(t.sessionId);if(r){if(t.type==="tool_use_start"?at(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&it(t,{sessionId:r.sessionId,agentId:r.agentId,workspacePath:r.workspacePath,providerId:r.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&&(r.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=sn(t,r.currentRuntimeStatus);i&&_(r.agentId,t.sessionId,i.status,i.actionInfo,re(i.actionInfo),{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}dn(t,r);const o=Kt(t);if(o){const i={runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0;String(t.data?.toolName||"").toLowerCase()==="browser_launch"?(async()=>{for(let u=0;u<3;u++){if(await _(r.agentId,t.sessionId,"tool_result",o,void 0,i,a,t.type)!==void 0)return;u<2&&await new Promise(m=>setTimeout(m,3e3*(u+1)))}})().catch(d=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",d)):_(r.agentId,t.sessionId,"tool_result",o,void 0,i,a,t.type)}}}),e.on("status-change",(t,r,s)=>{const o=f.get(t);if(o){de(t),r==="thinking"||r==="tool_using"||r==="compacting"?gt(t):M(t);const i=kt(r,s);o.currentRuntimeStatus=i.status;const a=o.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(o.currentRuntimeActionType==="idle"||o.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(o.currentRuntimeActionType=i.actionInfo?.actionType,o.currentRuntimeActionLabel=i.actionInfo?.actionLabel,o.currentRuntimeActionDetail=i.actionInfo?.actionDetail,o.currentRuntimeActionInput=i.actionInfo?.actionInput),console.log(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${o.agentId}`,i.actionInfo||""),lt(t,{runtimeStatus:i.status,runtimeActionType:o.currentRuntimeActionType,runtimeActionLabel:o.currentRuntimeActionLabel,runtimeActionDetail:o.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:o.currentRuntimeActionType?{actionType:o.currentRuntimeActionType,actionLabel:o.currentRuntimeActionLabel??"",actionDetail:o.currentRuntimeActionDetail,actionInput:o.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 _(o.agentId,t,i.status,l,re(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.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(b=>setTimeout(b,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"||o.currentRuntimeActionType==="idle"&&u){const y=(ce.get(t)??Promise.resolve()).then(async()=>{for(let b=0;b<=2;b++){if(await _(o.agentId,t,i.status,m?void 0:l,re(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})!==void 0)return;b<2&&await new Promise(E=>setTimeout(E,1e3*(b+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 _(o.agentId,t,i.status,m?void 0:l,re(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}if(i.status==="waiting_input"&&o.cachedCapabilitiesActionDetail){const m=o.cachedCapabilitiesActionDetail;o.cachedCapabilitiesActionDetail=void 0,console.log(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${o.agentId} (session stabilized to waiting_input)`),_(o.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:m},void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const r=f.get(t.sessionId);r&&(console.log(`[${n.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),rt(r.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.toolCallId))}),e.on("permission-request",t=>{const r=f.get(t.sessionId);if(r){console.log(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${r.agentId}`);const s=t.toolInput?q(JSON.stringify(t.toolInput).slice(0,400)):void 0;_(r.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:s||t.toolName},void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl})}})}A.post("/start",S,async(e,n)=>{const{agentId:t,workspacePath:r,mode:s="sdk"}=e.body||{};if(!t||!r){n.status(400).json({error:"agentId and workspacePath are required"});return}const o=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||$e(De(e))||void 0;et({agentId:String(t),workspacePath:String(r),serverUrl:e.body?.serverUrl||o,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:o}),e.body?.runtimeFeatures!=null&&(Je(String(t),e.body.runtimeFeatures),console.log(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(Ve(String(t)))}`)),s&&s!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${s}" requested for agent ${t}; starting SDK session instead.`),await fn(e,n)});async function fn(e,n){const{agentId:t,workspacePath:r,command:s,autoAccept:o=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:m,envOverrides:p,idleInputAutoCommand:T,nonInputAutoCommand:y,model:g,instanceAiConfig:b,subAgentModel:$,subAgentEffort:E,scopeKey:Te}=e.body||{},z=ft();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:b?te(b):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()||$e(De(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(ln(),!I){n.status(400).json({error:"agentId is required"});return}const O=Ue(I);if(O){n.json(await Mt(O));return}const k=await ct(I);if(k){const P=Lt(k);if(!P.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${I}, sessionId=${k.sessionId}, reason=${P.reason}`),await F(k.sessionId);else{const R=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:R,runtimeStatus:R,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 hn=(s||"acode").toLowerCase(),x=ve(s),Ke=w.get(x);D=Qe();const ze=x==="claude-code"?await qt():null,V=Be(x==="claude-code"?ze:null,p),W=x==="acode"?g?String(g).trim():void 0:(()=>{const P=g?String(g).trim():void 0,R=V.model?String(V.model).trim():void 0;return P||R})();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:V.model??null,resolvedModel:W??null,providerId:x,note:x==="acode"?"adapter handles full priority":"request > global"}});const me={...V.envOverrides};W&&(me.ANTHROPIC_MODEL=W,me.CODEX_MODEL=W);let H,fe=l;if(x==="acode"){const P=b||{},R=await Ze({apiOverrides:Ie(P)??void 0,agentId:I,sessionId:D??void 0,runtimeBridgeBaseUrl:B});H=R.instanceConfig.config,fe=R.perInstanceConfigPath,z.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:I,sessionId:D??void 0,details:{sanitizedApiOverrides:Ie(P)?te(Ie(P)):null,resolvedInstanceAiConfig:H?te(H):null,perInstanceConfigPath:fe,instanceConfigSources:R.instanceConfig.source??null}})}let ke=a||void 0,pe,ge,Y;if(x==="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 P=await It(r,{schedulerBaseUrl:B,runtimeAccessToken:le,agentId:I});P&&(Y=P,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 R=[c,d,u,a].filter(Z=>typeof Z=="string"&&Z.trim().length>0).map(Z=>Z.trim());ke=R.length>0?R.join(`
|
|
52
52
|
|
|
53
|
-
`):void 0}const j={command:s||"acode",workingDirectory:r,agentId:I,...Ae?{scopeKey:Ae}:{},autoAccept:!!o,initialPrompt:i,systemPrompt:Te,...fe!==void 0?{globalPrompt:fe}:{},...pe!==void 0?{rolePrompt:pe}:{},...J!==void 0?{memory:J}:{},model:z,mcpConfigPath:me,...W?{instanceAiConfig:W}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof E=="string"&&E.trim()?{subAgentEffort:E.trim()}:{},extraMcpServers:m||{},envOverrides:je(String(n),String(r),process.env,le)};F.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:I,sessionId:D,details:{adapterModel:j.model??null,adapterInstanceAiConfig:j.instanceAiConfig?ee(j.instanceAiConfig):null,adapterMcpConfigPath:j.mcpConfigPath??null}}),await F.flush(),f.set(D,{agentId:I,workspacePath:r,sessionId:D,config:j,providerId:x,seq:0,runtimeAccessToken:de,schedulerBaseUrl:B}),t.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:I,workspacePath:r,command:j.command,mode:"sdk"}),un({sessionId:D,agentId:I,config:j,adapter:Ke,providerId:x,idleInputAutoCommand:T,nonInputAutoCommand:y,runtimeAccessToken:de,requestedSchedulerBaseUrl:B})}catch(O){if(D&&(M(D),f.delete(D)),I&&K.delete(I),!t.headersSent){const k=O instanceof Error?O.message:String(O);t.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function un(e){const{sessionId:t,agentId:n,config:r,adapter:s,providerId:o,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await s.startSession(t,r),(i||a)&&s.setIdleCommands?.(t,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(gt(o))try{if(await new Promise(m=>setTimeout(m,500)),u=s.getSessionPid?.(t),!u){const p=(await Ye()).find(T=>T.agentId===n||T.cwd===r.workingDirectory||T.command.includes(r.workingDirectory));p&&(u=p.pid,console.log(`[Runtime] Found SDK process PID: ${u} for agentId=${n}`))}}catch(m){console.warn(`[Runtime] Failed to get SDK PID for agentId=${n}:`,m)}const l=oe(s.getSessionStatus(t),f.get(t)?.currentRuntimeStatus,f.get(t)?.currentRuntimeActionType);await at({sessionId:t,agentId:n,workspacePath:r.workingDirectory,command:r.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:s.getProviderSessionId(t)}),u&&await ye().startProcess({agentId:n,sessionId:t,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await dn({agentId:n,sessionId:t,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){M(t),f.delete(t),await v(t);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${n}: ${l}`),await ln({agentId:n,sessionId:t,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{K.delete(n)}}async function dn(e){const{agentId:t,sessionId:n,sdkPid:r,status:s,schedulerBaseUrl:o,runtimeAccessToken:i}=e;if(!o||!i){h.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${t}`);return}const a=`${o.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(a,{agentId:t,sessionId:n,status:s,pid:r},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session ready: agentId=${t}, sessionId=${n}, status=${s}`)}catch(c){const d=c instanceof Error?c.message:String(c);h.warn(`[Runtime] Failed to notify server session ready: agentId=${t}, error=${d}`)}}async function ln(e){const{agentId:t,sessionId:n,schedulerBaseUrl:r,runtimeAccessToken:s}=e;if(!r||!s)return;const o=`${r.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(o,{agentId:t,sessionId:n,status:"stopped"},{headers:{"X-Runtime-Token":s,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session failed: agentId=${t}, sessionId=${n}`)}catch(i){const a=i instanceof Error?i.message:String(i);h.warn(`[Runtime] Failed to notify server session failed: agentId=${t}, error=${a}`)}}A.post("/sdk/message",S,async(e,t)=>{const{sessionId:n,message:r}=e.body||{};if(!n||!r){t.status(400).json({error:"sessionId and message are required"});return}const s=f.get(n);if(!s){t.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code";await w.get(o).sendMessage(n,r),t.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);t.status(500).json({error:i})}}),A.post("/sdk/answer",S,async(e,t)=>{const{sessionId:n,answers:r}=e.body||{};if(!n||!r){t.status(400).json({error:"sessionId and answers are required"});return}const s=f.get(n);if(!s){t.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code",i=w.get(o);i.sendQuestionAnswer&&await i.sendQuestionAnswer(n,r),t.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);t.status(500).json({error:i})}}),A.post("/sdk/confirm",S,async(e,t)=>{const{sessionId:n,accept:r}=e.body||{};if(!n){t.status(400).json({error:"sessionId is required"});return}const s=f.get(n);if(!s){t.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code";await w.get(o).sendConfirmation(n,!!r),t.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);t.status(500).json({error:i})}}),A.post("/sdk/abort",S,async(e,t)=>{const{sessionId:n}=e.body||{};if(!n){t.status(400).json({error:"sessionId is required"});return}const r=f.get(n);if(!r){t.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await w.get(s).abortCurrentTurn(n),t.json({ok:!0})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.post("/sdk/stop",S,async(e,t)=>{const{sessionId:n}=e.body||{};if(!n){t.status(400).json({error:"sessionId is required"});return}const r=f.get(n);if(!r){t.json({ok:!0,status:"stopped"});return}try{const s=r.providerId||"claude-code",o=w.get(s);o.abortCurrentTurn(n).catch(()=>{}),await o.terminateSession(n),M(n),f.delete(n),se(n),await v(n),await ye().removeProcess(r.agentId),await _(r.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}),t.json({ok:!0,status:"stopped"})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.get("/sdk/status/:sessionId",S,(e,t)=>{const n=e.params.sessionId;if(!n){t.status(400).json({error:"sessionId is required"});return}const r=f.get(n);if(!r){t.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",o=w.get(s),i=o.getSessionStatus(n),a=o.getConversation(n);t.json({sessionId:n,status:i,agentId:r.agentId,workspacePath:r.workspacePath,messageCount:a.length})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.get("/sdk/capabilities/:sessionId",S,(e,t)=>{const n=e.params.sessionId;if(!n){t.status(400).json({error:"sessionId is required"});return}const r=f.get(n);if(!r){t.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",i=w.get(s).getCapabilities?.(n)??null;t.json({ok:!0,sessionId:n,agentId:r.agentId,capabilities:i,fetchedAt:Date.now()})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.get("/sdk/pending-questions/:sessionId",S,(e,t)=>{const n=e.params.sessionId;if(!n){t.status(400).json({error:"sessionId is required"});return}const r=f.get(n);if(!r){t.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",i=w.get(s).getPendingQuestion?.(n)??null;t.json({ok:!0,sessionId:n,agentId:r.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.post("/command",S,async(e,t)=>{const{sessionId:n,command:r}=e.body||{};if(!n||r===void 0||r===null){t.status(400).json({error:"sessionId and command are required"});return}try{const s=await Et(String(n),r);t.json({ok:!0,mode:"terminal",...s})}catch(s){const o=s instanceof Error?s.message:String(s);t.status(500).json({error:o})}}),A.post("/input",S,async(e,t)=>{const{sessionId:n,input:r,mode:s}=e.body||{};if(!n||r===void 0||r===null){t.status(400).json({error:"sessionId and input are required"});return}const o=f.get(n);if(!o){t.status(404).json({error:"SDK session not found"});return}try{const i=o.providerId||"claude-code",a=w.get(i);if(s==="shortcut"){if(!a.sendShortcutInput){t.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(n,String(r)),t.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(n,await Lt(r)),t.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);t.status(500).json({error:a})}}),A.post("/update-auto-commands",S,async(e,t)=>{const{agentId:n,idleInputAutoCommand:r="",nonInputAutoCommand:s=""}=e.body||{},o=String(n||"").trim();if(!o){t.status(400).json({error:"agentId is required"});return}const i=[...f.values()].find(c=>c.agentId===o),a={idleInputCommand:String(r||""),nonInputCommand:String(s||"")};try{let c=!1;i&&(w.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await st(o,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});t.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);t.status(500).json({ok:!1,mode:"sdk",error:d})}}),A.post("/resize",S,(e,t)=>{const{sessionId:n,cols:r,rows:s}=e.body||{};if(!n||!r||!s){t.status(400).json({error:"sessionId, cols, rows are required"});return}if(!f.has(n)){t.status(404).json({error:"SDK session not found"});return}t.json({ok:!0,mode:"sdk",noop:!0,cols:Number(r),rows:Number(s)})}),A.post("/reset-context",S,async(e,t)=>{const{sessionId:n,reason:r}=e.body||{};if(!n){t.status(400).json({error:"sessionId is required"});return}const s=f.get(n);if(!s){t.status(404).json({error:"SDK session not found"});return}const o=s.providerId||"claude-code",i=w.get(o),a=i.resetContext?.bind(i),c=pt(o,!!a);if(!c.supported){t.status(c.statusCode).json({error:c.error});return}if(!a){t.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(n));const d=oe(i.getSessionStatus(String(n)),s.currentRuntimeStatus,s.currentRuntimeActionType);t.json({ok:!0,contextReset:!0,sessionId:n,status:d,runtimeStatus:d,agentId:s.agentId,mode:"sdk",providerId:o,reason:typeof r=="string"&&r.trim()?r.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);t.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),A.post("/stop",S,async(e,t)=>{const{sessionId:n}=e.body||{},r=yt(e.body);if(!n){t.status(400).json({error:"sessionId is required"});return}const s=f.get(n);if(!s){await v(n),t.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const o=s.agentId;try{console.log(`[Runtime] Stopping SDK session ${n}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=s.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(n).catch(()=>{}),await a.terminateSession(n),M(n),f.delete(n),se(n),await v(n),await ye().removeProcess(o),r.statusNotified?await _(o,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl}):console.log(`[Runtime] Stopped status notification suppressed for SDK session ${n}; reason=${r.reason||"unspecified"}`),t.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:r.statusNotified,reason:r.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${n}:`,a),t.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),A.post("/stop-all",S,async(e,t)=>{const n=[],r=[];for(const[s,o]of f.entries())try{const i=o.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(s).catch(()=>{}),await a.terminateSession(s),M(s),f.delete(s),se(s),n.push(s),await _(o.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);r.push(`SDK ${s}: ${a}`)}try{await ot([]),console.log("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(s){const o=s instanceof Error?s.message:String(s);r.push(`Persistence: ${o}`)}t.json({ok:!0,stopped:{sdk:n.length},errors:r.length>0?r:void 0})}),A.get("/events/last/:n",S,(e,t)=>{const n=parseInt(e.params.n,10);if(!Number.isFinite(n)||n<1){t.status(400).json({error:":n must be a positive integer"});return}const r=$e.getLastN(n);t.json({ok:!0,count:r.length,entries:r})}),A.get("/events/since/:index",S,(e,t)=>{const n=parseInt(e.params.index,10);if(!Number.isFinite(n)||n<0){t.status(400).json({error:":index must be a non-negative integer"});return}const r=$e.getSinceIndex(n);t.json({ok:!0,entries:r.entries,nextIndex:r.nextIndex,oldestIndex:r.oldestIndex,dataLoss:r.oldestIndex>n+1})}),A.get("/events/push-stats",S,(e,t)=>{const n=tt();t.json({ok:!0,count:n.length,agents:n})});export{St as buildAcodeCommandOutputPath,Ue as buildClaudeCodeLaunchConfig,je as buildRuntimeEnv,qt as buildSdkOutputMetadata,Ot as buildToolResultTimelineActionInfo,Ln as cleanupSdkSessionByAgentId,At as countTerminalOutputLines,Me as createTerminalOutputDecoder,re as decodeTerminalOutputChunk,Pt as evaluatePersistedSessionReuse,kt as formatCommandInactivityTimeoutNotice,Tt as formatCommandOutputSpilloverNotice,Nt as formatSdkOutputEvent,Ie as formatTerminalPrompt,wt as normalizeTerminalCommandInput,yt as parseRuntimeStopOptions,$t as parseTerminalDirectoryChangeTarget,ce as raceSendOutputWithRetry,pt as resolveRuntimeContextResetSupport,en as resolveRuntimeStatusFromProviderEvent,Lt as resolveSdkInputMessage,qe as resolveSdkProviderId,oe as resolveSdkSessionDisplayStatus,ht as resolveStatusChangeRuntimeState,ne as resolveStatusChangeUsage,Ct as resolveTerminalOutputEncoding,f as sdkSessions,gt as shouldProbeSdkProcessPid,A as terminalRouter};
|
|
53
|
+
`):void 0}const U={command:s||"acode",workingDirectory:r,agentId:I,...Te?{scopeKey:Te}:{},autoAccept:!!o,initialPrompt:i,systemPrompt:ke,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Y!==void 0?{memory:Y}:{},model:W,mcpConfigPath:fe,...H?{instanceAiConfig:H}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof E=="string"&&E.trim()?{subAgentEffort:E.trim()}:{},extraMcpServers:m||{},envOverrides:je(String(t),String(r),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(),f.set(D,{agentId:I,workspacePath:r,sessionId:D,config:U,providerId:x,seq:0,runtimeAccessToken:le,schedulerBaseUrl:B}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:I,workspacePath:r,command:U.command,mode:"sdk"}),pn({sessionId:D,agentId:I,config:U,adapter:Ke,providerId:x,idleInputAutoCommand:T,nonInputAutoCommand:y,runtimeAccessToken:le,requestedSchedulerBaseUrl:B})}catch(O){if(D&&(M(D),f.delete(D),v(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 pn(e){const{sessionId:n,agentId:t,config:r,adapter:s,providerId:o,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await s.startSession(n,r),(i||a)&&s.setIdleCommands?.(n,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(At(o))try{if(await new Promise(m=>setTimeout(m,500)),u=s.getSessionPid?.(n),!u){const p=(await tt()).find(T=>T.agentId===t||T.cwd===r.workingDirectory||T.command.includes(r.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(s.getSessionStatus(n),f.get(n)?.currentRuntimeStatus,f.get(n)?.currentRuntimeActionType);await mt({sessionId:n,agentId:t,workspacePath:r.workingDirectory,command:r.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:s.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await gn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){M(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 yn({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{K.delete(t)}}async function gn(e){const{agentId:n,sessionId:t,sdkPid:r,status:s,schedulerBaseUrl:o,runtimeAccessToken:i}=e;if(!o||!i){h.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${o.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await Ce.post(a,{agentId:n,sessionId:t,status:s,pid:r},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${s}`)}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 yn(e){const{agentId:n,sessionId:t,schedulerBaseUrl:r,runtimeAccessToken:s}=e;if(!r||!s)return;const o=`${r.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await Ce.post(o,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":s,"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:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and message are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code";await w.get(o).sendMessage(t,r),n.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);n.status(500).json({error:i})}}),A.post("/sdk/answer",S,async(e,n)=>{const{sessionId:t,answers:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and answers are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code",i=w.get(o);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,r),n.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);n.status(500).json({error:i})}}),A.post("/sdk/confirm",S,async(e,n)=>{const{sessionId:t,accept:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const o=s.providerId||"claude-code";await w.get(o).sendConfirmation(t,!!r),n.json({ok:!0})}catch(o){const i=o instanceof Error?o.message:String(o);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 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).abortCurrentTurn(t),n.json({ok:!0})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),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 r=f.get(t);if(!r){n.json({ok:!0,status:"stopped"});return}try{const s=r.providerId||"claude-code",o=w.get(s);o.abortCurrentTurn(t).catch(()=>{}),await o.terminateSession(t),M(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(r.agentId),await _(r.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),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 r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",o=w.get(s),i=o.getSessionStatus(t),a=o.getConversation(t);n.json({sessionId:t,status:i,agentId:r.agentId,workspacePath:r.workspacePath,messageCount:a.length})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),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 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).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,capabilities:i,fetchedAt:Date.now()})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),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 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).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),A.post("/command",S,async(e,n)=>{const{sessionId:t,command:r}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and command are required"});return}try{const s=await Bt(String(t),r);n.json({ok:!0,mode:"terminal",...s})}catch(s){const o=s instanceof Error?s.message:String(s);n.status(500).json({error:o})}}),A.post("/input",S,async(e,n)=>{const{sessionId:t,input:r,mode:s}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and input are required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const i=o.providerId||"claude-code",a=w.get(i);if(s==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(r)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Nt(r)),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:r="",nonInputAutoCommand:s=""}=e.body||{},o=String(t||"").trim();if(!o){n.status(400).json({error:"agentId is required"});return}const i=[...f.values()].find(c=>c.agentId===o),a={idleInputCommand:String(r||""),nonInputCommand:String(s||"")};try{let c=!1;i&&(w.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await dt(o,{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:r,rows:s}=e.body||{};if(!t||!r||!s){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(r),rows:Number(s)})}),A.post("/reset-context",S,async(e,n)=>{const{sessionId:t,reason:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}const o=s.providerId||"claude-code",i=w.get(o),a=i.resetContext?.bind(i),c=St(o,!!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)),s.currentRuntimeStatus,s.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:s.agentId,mode:"sdk",providerId:o,reason:typeof r=="string"&&r.trim()?r.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),A.post("/stop",S,async(e,n)=>{const{sessionId:t}=e.body||{},r=Tt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const s=f.get(t);if(!s){await F(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const o=s.agentId;try{console.log(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=s.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),M(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(o),r.statusNotified?await _(o,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl}):console.log(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${r.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:r.statusNotified,reason:r.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),A.post("/stop-all",S,async(e,n)=>{const t=[],r=[];for(const[s,o]of f.entries())try{const i=o.providerId||"claude-code",a=w.get(i);a.abortCurrentTurn(s).catch(()=>{}),await a.terminateSession(s),M(s),f.delete(s),v(s),ie(s),t.push(s),await _(o.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);r.push(`SDK ${s}: ${a}`)}try{await ut([]),console.log("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(s){const o=s instanceof Error?s.message:String(s);r.push(`Persistence: ${o}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:r.length>0?r: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 r=_e.getLastN(t);n.json({ok:!0,count:r.length,entries:r})}),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 r=_e.getSinceIndex(t);n.json({ok:!0,entries:r.entries,nextIndex:r.nextIndex,oldestIndex:r.oldestIndex,dataLoss:r.oldestIndex>t+1})}),A.get("/events/push-stats",S,(e,n)=>{const t=ot();n.json({ok:!0,count:t.length,agents:t})});export{Ct as buildAcodeCommandOutputPath,Be as buildClaudeCodeLaunchConfig,je as buildRuntimeEnv,Wt as buildSdkOutputMetadata,Kt as buildToolResultTimelineActionInfo,vn as cleanupSdkSessionByAgentId,bt as countTerminalOutputLines,Le as createTerminalOutputDecoder,oe as decodeTerminalOutputChunk,Lt as evaluatePersistedSessionReuse,_t as formatCommandInactivityTimeoutNotice,$t as formatCommandOutputSpilloverNotice,zt as formatSdkOutputEvent,Se as formatTerminalPrompt,Dt as normalizeTerminalCommandInput,Tt as parseRuntimeStopOptions,xt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,St as resolveRuntimeContextResetSupport,sn as resolveRuntimeStatusFromProviderEvent,Nt as resolveSdkInputMessage,ve as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,kt as resolveStatusChangeRuntimeState,re as resolveStatusChangeUsage,Pt as resolveTerminalOutputEncoding,f as sdkSessions,At as shouldProbeSdkProcessPid,A as terminalRouter};
|
|
54
54
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{v4 as M}from"uuid";import A from"axios";import m from"node:os";import F from"node:path";import g from"node:fs";import{logger as i}from"../utils/logger.js";import{schedulerBaseUrl as u}from"../config.js";import{clearRuntimeBinding as z,clearScopedRuntimeAccessToken as J,getRuntimeAccessToken as h,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as Y,loadRuntimeBinding as v,normalizeSchedulerBaseUrl as R,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as q}from"./runtime-binding.js";const C={enabled:!1,serverUrl:u,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3};let c={registered:!1,registrations:{}},b=[];function Ae(){return[...b]}const H=3e4;function P(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const I=new Map;function W(e){const r=e.serverUrl||u,t=R(r)||r;if(I.has(t))return;const n=setTimeout(()=>{I.delete(t),V(e,t)},P());n.unref?.(),I.set(t,n)}async function V(e,r){try{const t=S().find(n=>(R(n.serverUrl||u)||n.serverUrl||u)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),W(e)}}function Ie(){for(const e of I.values())clearTimeout(e);I.clear()}function d(e){return e==null?void 0:String(e).trim()||void 0}function L(e){return R(e)}function T(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function O(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function N(e){const r=d(e.serverUrl)||d(e.schedulerBaseUrl),t=d(e.connectionKey)||d(e.password);return{enabled:T(e.enabled),serverUrl:r,tenantId:d(e.tenantId),userKey:d(e.userKey),connectionKey:t,instanceName:d(e.instanceName),instanceId:d(e.instanceId),projectName:d(e.projectName),roleName:d(e.roleName),workspacePath:d(e.workspacePath),registerAddr:d(e.registerAddr),registerIp:d(e.registerIp),virtualIp:d(e.virtualIp),tunnel:T(e.tunnel),preferSameLanIp:T(e.preferSameLanIp),maxRetries:O(e.maxRetries),retryInterval:O(e.retryInterval)}}function k(){const e=String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||m.homedir();return F.join(e,".aws-bridge","config.json")}function x(){const e=k();try{if(!g.existsSync(e))return i.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r);return i.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),N(t)}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function X(){const e=k();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=N(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey?[n]:[]:o.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const a=N(s);return{...n,...a,connectionKey:a.connectionKey||n.connectionKey}})}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function j(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectName=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=T(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function _(){const e=x(),r=j(),t={...C,...e||{},...r},n=t.instanceName||m.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||u,tenantId:t.tenantId||"",userKey:t.userKey||"",connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,projectName:t.projectName,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function S(){const e=X(),r=j(),n=(e.length>0?e:[x()||{}]).map(o=>{const s={...C,...o,...r};let a=!1;return process.env.AWS_AUTO_REGISTER!==void 0?a=process.env.AWS_AUTO_REGISTER==="true":a=e.length>0||!!s.userKey,{enabled:a,serverUrl:s.serverUrl||u,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||m.hostname(),instanceId:s.instanceId,projectName:s.projectName,roleName:s.roleName,workspacePath:s.workspacePath,registerAddr:s.registerAddr,registerIp:s.registerIp,virtualIp:s.virtualIp,tunnel:typeof s.tunnel=="boolean"?s.tunnel:void 0,preferSameLanIp:s.preferSameLanIp!==!1,maxRetries:s.maxRetries,retryInterval:s.retryInterval}});return b=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function Q(){const e=m.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function B(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Z(e,r,t){const n=B(e),o=B(r),s=B(t);return(n&s)===(o&s)}function ee(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function re(e){return e==="127.0.0.1"}function te(e){const r=Q();if(r.length===0)return i.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=ee(e);if(t){if(re(t))return"127.0.0.1";for(const n of r)if(Z(n.address,t,n.netmask))return i.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;i.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else i.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function ne(e=u){return te(e)}function D(e){const r=e||_();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function E(e){const r=process.env.AWS_RUNTIME_BRIDGE_PORT||18081;if(D(e)){const s=e.serverUrl||u;try{const a=new URL(s);if(!e.instanceId)i.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${a.protocol}//${a.host}/tunnel/${e.instanceId}`}catch{i.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=e.preferSameLanIp===!1?"127.0.0.1":ne(e.serverUrl||u),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function y(){return S()[0]||_()}function Se(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=v();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=Y(o);if(s&&s===r)return R(o)}}function se(e){return e?Object.entries(c.registrations).find(([,t])=>t===e)?.[0]:void 0}function U(e,r){const t=se(r);if(t)return t;const n=d(e.serverUrl);if(n&&(n!==u||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=v(),s=d(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||u}async function oe(e){const r=e.instanceName||m.hostname(),t=e.serverUrl||u,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:m.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:E(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectName:e.projectName,roleName:e.roleName};return i.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),i.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),i.info(`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await A.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}let G=Promise.resolve();function ie(e,r){const t=G.then(()=>{const n=k();if(!g.existsSync(n))return;const o=g.readFileSync(n,"utf-8"),s=JSON.parse(o),a=R(e);if(!a)return;let l=!1;const f=p=>{R(String(p.serverUrl||p.schedulerBaseUrl||""))===a&&r&&p.instanceId!==r&&(p.instanceId=r,l=!0)};if(Array.isArray(s.autoRegisterTargets))for(const p of s.autoRegisterTargets)p&&typeof p=="object"&&!Array.isArray(p)&&f(p);else f(s);l&&(g.writeFileSync(n,JSON.stringify(s,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))});return G=t.catch(()=>{}),t}async function ae(e){const r=U(y(),e),t=v(),n=h(r);if(!n)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await A.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":n},timeout:1e4})).data}async function ye(e){const r=e?[{..._(),...e}]:S();return r.length>1?(await Promise.all(r.map(n=>$(n)))).every(Boolean):$(r[0]||_())}async function $(e,r){if(!e.enabled)return i.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),i.info("[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ~/.aws-bridge/config.json \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true"),!1;if(!e.userKey)return i.error("[AutoRegister] \u7F3A\u5C11\u7528\u6237 Key\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_USER_KEY\uFF09"),!1;const t=D(e);t&&!e.instanceId&&(e={...e,instanceId:`bridge-${M().replace(/-/g,"").slice(0,12)}`},i.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let s=1;s<=n;s++){try{c.lastAttempt=new Date;const a=await oe(e);if(a.success){if(c.registered=!0,c.instanceId=a.instanceId,a.instanceId&&(c.registrations[e.serverUrl||u]=a.instanceId),c.error=void 0,i.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),i.info(`[AutoRegister] \u5B9E\u4F8B ID: ${a.instanceId}`),i.info(`[AutoRegister] \u6D88\u606F: ${a.message}`),i.info(`[AutoRegister] \u66F4\u65B0: ${a.isUpdate?"\u662F":"\u5426"}`),a.runtimeAccessToken)try{K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:a.serverUrl||e.serverUrl||u}),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||u,a.instanceId).catch(l=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${l.message}`)})}catch(l){const f=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${f.message}`),c.error=f.message,!1}else i.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&a.instanceId&&a.runtimeAccessToken){const{startTunnelClient:l}=await import("./tunnel-client.js"),f=e.serverUrl||u;l(f,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${f}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),c.error=a.message}catch(a){const l=a,f=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${f}`),c.error=f}s<n&&(i.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(a=>setTimeout(a,o)))}return r?.backgroundRetry?i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||u}): ${c.error||"\u672A\u77E5"}`):(i.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),i.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),i.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),i.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),i.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||u}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${c.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A~/.aws-bridge/config.json \u6216\u73AF\u5883\u53D8\u91CF"),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(P()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),W(e),!1}async function ve(){const e=y();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=U(e),n=E(e);try{const o=await A.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.userKey,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const a=h()!==o.data.runtimeAccessToken;return K({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey,schedulerBaseUrl:t}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:a}}catch(o){const s=o;return{success:!1,error:s.response?.data?JSON.stringify(s.response.data):s.message}}}async function Te(e){const r=L(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>L(s.serverUrl)===r)||y();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=E(t);try{const s=await A.post(`${r}/api/instances/runtime-tokens/refresh`,{tenantId:t.tenantId,userKey:t.userKey,instanceId:n.instanceId,instanceName:t.instanceName,runtimeBridgeBaseUrl:o},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!s.data.success||!s.data.runtimeAccessToken)return{success:!1,error:s.data.message||"scheduler did not return runtimeAccessToken"};const l=h(r)!==s.data.runtimeAccessToken;return q({serverBaseUrl:r,accessToken:s.data.runtimeAccessToken}),{success:!0,runtimeAccessToken:s.data.runtimeAccessToken,updated:l}}catch(s){const a=s;return{success:!1,error:a.response?.data?JSON.stringify(a.response.data):a.message}}}async function _e(){if(!c.registered||!c.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(c.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${c.instanceId}`);const r=U(y(),c.instanceId);return v().schedulerBaseUrl&&J(r),z(),c.registered=!1,c.instanceId=void 0,!0}else return i.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${e.message}`),!1}catch(e){const r=e;return i.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${r.message}`),!1}}function Ee(){return{...c}}function Ue(){return c.registered}function he(){return c.instanceId}async function Ne(){const e=y(),r=c.instanceId,t=U(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=E(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),i.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),i.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await A.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(i.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),i.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const s=o,a=s.response?.data?JSON.stringify(s.response.data):s.message;return i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${a}`),{success:!1,error:a}}}export{ye as autoRegister,Ne as bridgeRestartCleanup,Ie as cancelBackgroundRegisterRetries,k as getAutoRegisterConfigFilePath,Ae as getConfiguredConnectionKeys,he as getInstanceId,Ee as getRegistrationState,Ue as isRegistered,D as isTunnelConfig,_ as loadConfig,S as loadConfigs,y as loadPrimaryLifecycleConfig,ve as requestRuntimeAccessTokenRefresh,Te as requestRuntimeAccessTokenRefreshForServer,Se as resolveSchedulerBaseUrlFromToken,_e as unregister};
|
|
1
|
+
import{v4 as M}from"uuid";import R from"axios";import m from"node:os";import F from"node:path";import g from"node:fs";import{logger as i}from"../utils/logger.js";import{schedulerBaseUrl as u}from"../config.js";import{clearRuntimeBinding as z,clearScopedRuntimeAccessToken as J,getRuntimeAccessToken as h,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as Y,loadRuntimeBinding as v,normalizeSchedulerBaseUrl as I,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as q}from"./runtime-binding.js";const C={enabled:!1,serverUrl:u,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3};let c={registered:!1,registrations:{}},b=[];function Re(){return[...b]}const H=3e4;function P(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const A=new Map;function W(e){const r=e.serverUrl||u,t=I(r)||r;if(A.has(t))return;const n=setTimeout(()=>{A.delete(t),V(e,t)},P());n.unref?.(),A.set(t,n)}async function V(e,r){try{const t=S().find(n=>(I(n.serverUrl||u)||n.serverUrl||u)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),W(e)}}function Ae(){for(const e of A.values())clearTimeout(e);A.clear()}function d(e){return e==null?void 0:String(e).trim()||void 0}function L(e){return I(e)}function T(e){if(typeof e=="boolean")return e;if(typeof e=="string"){const r=e.trim().toLowerCase();if(["true","1","yes","y"].includes(r))return!0;if(["false","0","no","n"].includes(r))return!1}}function O(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function N(e){const r=d(e.serverUrl)||d(e.schedulerBaseUrl),t=d(e.connectionKey)||d(e.password);return{enabled:T(e.enabled),serverUrl:r,tenantId:d(e.tenantId),userKey:d(e.userKey),connectionKey:t,instanceName:d(e.instanceName),instanceId:d(e.instanceId),projectId:d(e.projectId),roleName:d(e.roleName),workspacePath:d(e.workspacePath),registerAddr:d(e.registerAddr),registerIp:d(e.registerIp),virtualIp:d(e.virtualIp),tunnel:T(e.tunnel),preferSameLanIp:T(e.preferSameLanIp),maxRetries:O(e.maxRetries),retryInterval:O(e.retryInterval)}}function k(){const e=String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||m.homedir();return F.join(e,".aws-bridge","config.json")}function x(){const e=k();try{if(!g.existsSync(e))return i.debug(`[AutoRegister] \u914D\u7F6E\u6587\u4EF6\u4E0D\u5B58\u5728: ${e}`),null;const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r);return i.info(`[AutoRegister] \u4ECE\u914D\u7F6E\u6587\u4EF6\u52A0\u8F7D\u914D\u7F6E: ${e}`),N(t)}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${e}, error: ${t.message}`),null}}function X(){const e=k();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=N(t),o=Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[];return o.length===0?n.userKey?[n]:[]:o.filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(s=>{const a=N(s);return{...n,...a,connectionKey:a.connectionKey||n.connectionKey}})}catch(r){const t=r;return i.warn(`[AutoRegister] \u8BFB\u53D6\u81EA\u52A8\u6CE8\u518C\u76EE\u6807\u5931\u8D25: ${e}, error: ${t.message}`),[]}}function j(){const e={};return process.env.AWS_AUTO_REGISTER==="true"&&(e.enabled=!0),process.env.AWS_RUNTIME_SCHEDULER_BASE_URL&&(e.serverUrl=process.env.AWS_RUNTIME_SCHEDULER_BASE_URL),process.env.AWS_TENANT_ID&&(e.tenantId=process.env.AWS_TENANT_ID),process.env.AWS_USER_KEY&&(e.userKey=process.env.AWS_USER_KEY),process.env.AWS_BRIDGE_CONNECTION_KEY&&(e.connectionKey=process.env.AWS_BRIDGE_CONNECTION_KEY),process.env.AWS_INSTANCE_NAME&&(e.instanceName=process.env.AWS_INSTANCE_NAME),process.env.AWS_PROJECT_NAME&&(e.projectId=process.env.AWS_PROJECT_NAME),process.env.AWS_ROLE_NAME&&(e.roleName=process.env.AWS_ROLE_NAME),process.env.AWS_WORKSPACE_PATH&&(e.workspacePath=process.env.AWS_WORKSPACE_PATH),process.env.AWS_REGISTER_ADDR&&(e.registerAddr=process.env.AWS_REGISTER_ADDR),process.env.AWS_REGISTER_IP&&(e.registerIp=process.env.AWS_REGISTER_IP),process.env.AWS_VIRTUAL_IP&&(e.virtualIp=process.env.AWS_VIRTUAL_IP),process.env.AWS_PREFER_SAME_LAN_IP&&(e.preferSameLanIp=T(process.env.AWS_PREFER_SAME_LAN_IP)??!0),process.env.AWS_REGISTER_MAX_RETRIES&&(e.maxRetries=parseInt(process.env.AWS_REGISTER_MAX_RETRIES,10)),process.env.AWS_REGISTER_RETRY_INTERVAL&&(e.retryInterval=parseInt(process.env.AWS_REGISTER_RETRY_INTERVAL,10)),e}function _(){const e=x(),r=j(),t={...C,...e||{},...r},n=t.instanceName||m.hostname();let o=!1;return process.env.AWS_AUTO_REGISTER!==void 0?o=process.env.AWS_AUTO_REGISTER==="true":e&&(o=!0),{enabled:o,serverUrl:t.serverUrl||u,tenantId:t.tenantId||"",userKey:t.userKey||"",connectionKey:t.connectionKey,instanceName:n,instanceId:t.instanceId,projectId:t.projectId,roleName:t.roleName,workspacePath:t.workspacePath,registerAddr:t.registerAddr,registerIp:t.registerIp,virtualIp:t.virtualIp,tunnel:typeof t.tunnel=="boolean"?t.tunnel:void 0,preferSameLanIp:t.preferSameLanIp!==!1,maxRetries:t.maxRetries,retryInterval:t.retryInterval}}function S(){const e=X(),r=j(),n=(e.length>0?e:[x()||{}]).map(o=>{const s={...C,...o,...r};let a=!1;return process.env.AWS_AUTO_REGISTER!==void 0?a=process.env.AWS_AUTO_REGISTER==="true":a=e.length>0||!!s.userKey,{enabled:a,serverUrl:s.serverUrl||u,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||m.hostname(),instanceId:s.instanceId,projectId:s.projectId,roleName:s.roleName,workspacePath:s.workspacePath,registerAddr:s.registerAddr,registerIp:s.registerIp,virtualIp:s.virtualIp,tunnel:typeof s.tunnel=="boolean"?s.tunnel:void 0,preferSameLanIp:s.preferSameLanIp!==!1,maxRetries:s.maxRetries,retryInterval:s.retryInterval}});return b=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function Q(){const e=m.networkInterfaces(),r=[];for(const t of Object.keys(e)){const n=e[t];if(n)for(const o of n)o.family==="IPv4"&&!o.internal&&r.push({address:o.address,netmask:o.netmask,name:t})}return r}function B(e){const r=e.split(".").map(Number);return(r[0]<<24)+(r[1]<<16)+(r[2]<<8)+r[3]}function Z(e,r,t){const n=B(e),o=B(r),s=B(t);return(n&s)===(o&s)}function ee(e){try{const r=new URL(e);return r.hostname==="localhost"||r.hostname==="127.0.0.1"?"127.0.0.1":/^(\d{1,3}\.){3}\d{1,3}$/.test(r.hostname)?r.hostname:null}catch{return null}}function re(e){return e==="127.0.0.1"}function te(e){const r=Q();if(r.length===0)return i.warn("[AutoRegister] \u672A\u627E\u5230\u4EFB\u4F55\u975E\u5185\u90E8 IP \u5730\u5740\uFF0C\u4F7F\u7528 127.0.0.1"),"127.0.0.1";const t=ee(e);if(t){if(re(t))return"127.0.0.1";for(const n of r)if(Z(n.address,t,n.netmask))return i.info(`[AutoRegister] \u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u540C\u5B50\u7F51\u7684 IP: ${n.address} (\u7F51\u5361: ${n.name}, \u5B50\u7F51\u63A9\u7801: ${n.netmask})`),n.address;i.warn(`[AutoRegister] \u672A\u627E\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3 (${t}) \u540C\u5B50\u7F51\u7684\u672C\u673A IP\uFF0C\u4F7F\u7528 127.0.0.1`)}else i.warn("[AutoRegister] \u65E0\u6CD5\u89E3\u6790\u8C03\u5EA6\u4E2D\u5FC3 IP\uFF0C\u4F7F\u7528 127.0.0.1");return"127.0.0.1"}function ne(e=u){return te(e)}function D(e){const r=e||_();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function E(e){const r=process.env.AWS_RUNTIME_BRIDGE_PORT||18081;if(D(e)){const s=e.serverUrl||u;try{const a=new URL(s);if(!e.instanceId)i.warn("[AutoRegister] \u96A7\u9053\u6A21\u5F0F\u4F46\u7F3A\u5C11 instanceId\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F");else return`${a.protocol}//${a.host}/tunnel/${e.instanceId}`}catch{i.warn("[AutoRegister] serverUrl \u89E3\u6790\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u76F4\u8FDE\u6A21\u5F0F")}}const t=e.preferSameLanIp===!1?"127.0.0.1":ne(e.serverUrl||u),n=e.registerAddr||e.registerIp||e.virtualIp||t;return n?/^https?:\/\//i.test(n)?n:/:[0-9]+$/.test(n)?`http://${n}`:`http://${n}:${r}`:`http://127.0.0.1:${r}`}function y(){return S()[0]||_()}function Se(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=v();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=Y(o);if(s&&s===r)return I(o)}}function se(e){return e?Object.entries(c.registrations).find(([,t])=>t===e)?.[0]:void 0}function U(e,r){const t=se(r);if(t)return t;const n=d(e.serverUrl);if(n&&(n!==u||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=v(),s=d(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||u}async function oe(e){const r=e.instanceName||m.hostname(),t=e.serverUrl||u,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:m.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:E(e),connectionKey:e.connectionKey,workspacePath:e.workspacePath,projectId:e.projectId,roleName:e.roleName};return i.info(`[AutoRegister] \u6B63\u5728\u6CE8\u518C\u5B9E\u4F8B: ${r}`),i.info(`[AutoRegister] \u8C03\u5EA6\u4E2D\u5FC3: ${t}`),i.info(`[AutoRegister] \u7528\u6237 Key: ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.info(`[AutoRegister] \u79DF\u6237 ID: ${e.tenantId||"(\u81EA\u52A8\u63A8\u5BFC)"}`),(await R.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}let G=Promise.resolve();function ie(e,r){const t=G.then(()=>{const n=k();if(!g.existsSync(n))return;const o=g.readFileSync(n,"utf-8"),s=JSON.parse(o),a=I(e);if(!a)return;let l=!1;const f=p=>{I(String(p.serverUrl||p.schedulerBaseUrl||""))===a&&r&&p.instanceId!==r&&(p.instanceId=r,l=!0)};if(Array.isArray(s.autoRegisterTargets))for(const p of s.autoRegisterTargets)p&&typeof p=="object"&&!Array.isArray(p)&&f(p);else f(s);l&&(g.writeFileSync(n,JSON.stringify(s,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))});return G=t.catch(()=>{}),t}async function ae(e){const r=U(y(),e),t=v(),n=h(r);if(!n)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await R.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":n},timeout:1e4})).data}async function ye(e){const r=e?[{..._(),...e}]:S();return r.length>1?(await Promise.all(r.map(n=>$(n)))).every(Boolean):$(r[0]||_())}async function $(e,r){if(!e.enabled)return i.info("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u672A\u542F\u7528"),i.info("[AutoRegister] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ~/.aws-bridge/config.json \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_AUTO_REGISTER=true"),!1;if(!e.userKey)return i.error("[AutoRegister] \u7F3A\u5C11\u7528\u6237 Key\uFF08\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u8BBE\u7F6E userKey \u6216\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF AWS_USER_KEY\uFF09"),!1;const t=D(e);t&&!e.instanceId&&(e={...e,instanceId:`bridge-${M().replace(/-/g,"").slice(0,12)}`},i.info(`[AutoRegister] \u96A7\u9053\u6A21\u5F0F\uFF1A\u5DF2\u9884\u58F0\u660E instanceId=${e.instanceId}`));const n=r?.backgroundRetry?1:e.maxRetries??3,o=e.retryInterval??2e3;for(let s=1;s<=n;s++){try{c.lastAttempt=new Date;const a=await oe(e);if(a.success){if(c.registered=!0,c.instanceId=a.instanceId,a.instanceId&&(c.registrations[e.serverUrl||u]=a.instanceId),c.error=void 0,i.info("[AutoRegister] \u2713 \u6CE8\u518C\u6210\u529F\uFF01"),i.info(`[AutoRegister] \u5B9E\u4F8B ID: ${a.instanceId}`),i.info(`[AutoRegister] \u6D88\u606F: ${a.message}`),i.info(`[AutoRegister] \u66F4\u65B0: ${a.isUpdate?"\u662F":"\u5426"}`),a.runtimeAccessToken)try{K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:a.serverUrl||e.serverUrl||u}),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||u,a.instanceId).catch(l=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${l.message}`)})}catch(l){const f=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${f.message}`),c.error=f.message,!1}else i.warn("[AutoRegister] \u6CE8\u518C\u54CD\u5E94\u672A\u5305\u542B runtime access token\uFF0CMCP \u5C06\u65E0\u6CD5\u8BBF\u95EE\u8C03\u5EA6\u4E2D\u5FC3\uFF0C\u8BF7\u68C0\u67E5 server \u7684 bridge \u5B9E\u4F8B token \u9881\u53D1\u903B\u8F91");if(t&&a.instanceId&&a.runtimeAccessToken){const{startTunnelClient:l}=await import("./tunnel-client.js"),f=e.serverUrl||u;l(f,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${f}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),c.error=a.message}catch(a){const l=a,f=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${f}`),c.error=f}s<n&&(i.info(`[AutoRegister] ${o/1e3} \u79D2\u540E\u91CD\u8BD5...`),await new Promise(a=>setTimeout(a,o)))}return r?.backgroundRetry?i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u4ECD\u672A\u6210\u529F (server=${e.serverUrl||u}): ${c.error||"\u672A\u77E5"}`):(i.error("[AutoRegister] \u2717 \u6CE8\u518C\u5931\u8D25\uFF0C\u5DF2\u8FBE\u6700\u5927\u91CD\u8BD5\u6B21\u6570"),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u81EA\u52A8\u6CE8\u518C\u5DF2\u542F\u7528\u4F46\u6CE8\u518C\u5931\u8D25\uFF0C\u5B9E\u4F8B\u6682\u65F6\u65E0\u6CD5\u6B63\u5E38\u5DE5\u4F5C"),i.error("[AutoRegister] \u8BF7\u68C0\u67E5\u4EE5\u4E0B\u914D\u7F6E\uFF1A"),i.error(`[AutoRegister] - \u7528\u6237 Key (userKey): ${e.userKey?"****"+e.userKey.slice(-4):"(\u672A\u8BBE\u7F6E)"}`),i.error(`[AutoRegister] - \u79DF\u6237 ID (tenantId): ${e.tenantId||"(\u53EF\u9009\uFF0C\u5C06\u81EA\u52A8\u63A8\u5BFC)"}`),i.error(`[AutoRegister] - \u5B9E\u4F8B\u540D (instanceName): ${e.instanceName||"(\u4F7F\u7528\u4E3B\u673A\u540D)"}`),i.error(`[AutoRegister] - \u8C03\u5EA6\u4E2D\u5FC3\u5730\u5740: ${e.serverUrl||u}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${c.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error("[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A~/.aws-bridge/config.json \u6216\u73AF\u5883\u53D8\u91CF"),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(P()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),W(e),!1}async function ve(){const e=y();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=U(e),n=E(e);try{const o=await R.post(`${t}/api/instances/runtime-tokens/refresh`,{tenantId:e.tenantId,userKey:e.userKey,instanceId:r.instanceId,instanceName:e.instanceName,runtimeBridgeBaseUrl:n},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!o.data.success||!o.data.runtimeAccessToken)return{success:!1,error:o.data.message||"scheduler did not return runtimeAccessToken"};const a=h()!==o.data.runtimeAccessToken;return K({accessToken:o.data.runtimeAccessToken,instanceId:r.instanceId,userId:o.data.userId||e.userKey,schedulerBaseUrl:t}),{success:!0,runtimeAccessToken:o.data.runtimeAccessToken,updated:a}}catch(o){const s=o;return{success:!1,error:s.response?.data?JSON.stringify(s.response.data):s.message}}}async function Te(e){const r=L(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>L(s.serverUrl)===r)||y();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=E(t);try{const s=await R.post(`${r}/api/instances/runtime-tokens/refresh`,{tenantId:t.tenantId,userKey:t.userKey,instanceId:n.instanceId,instanceName:t.instanceName,runtimeBridgeBaseUrl:o},{headers:{"Content-Type":"application/json"},timeout:1e4});if(!s.data.success||!s.data.runtimeAccessToken)return{success:!1,error:s.data.message||"scheduler did not return runtimeAccessToken"};const l=h(r)!==s.data.runtimeAccessToken;return q({serverBaseUrl:r,accessToken:s.data.runtimeAccessToken}),{success:!0,runtimeAccessToken:s.data.runtimeAccessToken,updated:l}}catch(s){const a=s;return{success:!1,error:a.response?.data?JSON.stringify(a.response.data):a.message}}}async function _e(){if(!c.registered||!c.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(c.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${c.instanceId}`);const r=U(y(),c.instanceId);return v().schedulerBaseUrl&&J(r),z(),c.registered=!1,c.instanceId=void 0,!0}else return i.warn(`[AutoRegister] \u6CE8\u9500\u5931\u8D25: ${e.message}`),!1}catch(e){const r=e;return i.error(`[AutoRegister] \u6CE8\u9500\u8BF7\u6C42\u5931\u8D25: ${r.message}`),!1}}function Ee(){return{...c}}function Ue(){return c.registered}function he(){return c.instanceId}async function Ne(){const e=y(),r=c.instanceId,t=U(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=E(e)),!n.instanceId&&!n.runtimeBridgeBaseUrl)return i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6CA1\u6709 instanceId \u6216 runtimeBridgeBaseUrl\uFF0C\u8DF3\u8FC7\u6E05\u7406"),{success:!0,agentCount:0};try{i.info("[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\uFF1A\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3..."),i.info(`[AutoRegister] instanceId: ${n.instanceId||"(\u65E0)"}`),i.info(`[AutoRegister] runtimeBridgeBaseUrl: ${n.runtimeBridgeBaseUrl||"(\u65E0)"}`);const o=await R.post(`${t}/api/instances/bridge-restart-cleanup`,n,{headers:{"Content-Type":"application/json"},timeout:1e4});return o.data.success?(i.info(`[AutoRegister] \u2713 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF1A${o.data.message}`),i.info(`[AutoRegister] \u6E05\u7406\u4E86 ${o.data.agentCount||0} \u4E2A Agent`),{success:!0,agentCount:o.data.agentCount||0}):(i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25\uFF1A${o.data.message}`),{success:!1,error:o.data.message})}catch(o){const s=o,a=s.response?.data?JSON.stringify(s.response.data):s.message;return i.warn(`[AutoRegister] Bridge \u91CD\u542F\u6E05\u7406\u8BF7\u6C42\u5931\u8D25\uFF1A${a}`),{success:!1,error:a}}}export{ye as autoRegister,Ne as bridgeRestartCleanup,Ae as cancelBackgroundRegisterRetries,k as getAutoRegisterConfigFilePath,Re as getConfiguredConnectionKeys,he as getInstanceId,Ee as getRegistrationState,Ue as isRegistered,D as isTunnelConfig,_ as loadConfig,S as loadConfigs,y as loadPrimaryLifecycleConfig,ve as requestRuntimeAccessTokenRefresh,Te as requestRuntimeAccessTokenRefreshForServer,Se as resolveSchedulerBaseUrlFromToken,_e as unregister};
|
|
2
2
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
export declare function setAgentFeatures(agentId: string, features: unknown): void;
|
|
3
|
+
|
|
4
|
+
export declare function getAgentFeatures(agentId: string): Record<string, boolean>;
|
|
5
|
+
|
|
6
|
+
export declare function isFeatureEnabled(agentId: string, key: string): boolean;
|
|
7
|
+
|
|
8
|
+
export declare function clearAgentFeatures(agentId: string): void;
|
|
9
|
+
|
|
10
|
+
export declare function instanceFeaturesCacheSize(): number;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const r={},i=new Set(["desktop"]),n=new Map;function c(e){if(e==null)return{...r};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{...r};const u={};for(const[o,s]of Object.entries(t))i.has(o)||typeof s=="boolean"&&(u[o]=s);return u}function a(e,t){e&&n.set(e,c(t))}function f(e){return n.get(e)??{...r}}function l(e,t){return f(e)[t]===!0}function p(e){n.delete(e)}function A(){return n.size}export{p as clearAgentFeatures,f as getAgentFeatures,A as instanceFeaturesCacheSize,l as isFeatureEnabled,a as setAgentFeatures};
|
|
2
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ProviderEvent } from "../adapter/types.js";
|
|
2
|
+
|
|
3
|
+
export declare function onSdkToolUseStart(sessionId: string, toolUseId: string | undefined, toolInput: Record<string, unknown> | undefined, toolName?: string, workspacePath?: string): void;
|
|
4
|
+
|
|
5
|
+
export declare function forgetSession(sessionId: string): void;
|
|
6
|
+
|
|
7
|
+
export declare function onSdkToolUseEnd(event: ProviderEvent, entry: {
|
|
8
|
+
sessionId: string;
|
|
9
|
+
agentId: string;
|
|
10
|
+
workspacePath: string;
|
|
11
|
+
providerId: string;
|
|
12
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{promises as A}from"node:fs";import{existsSync as P,readFileSync as L}from"node:fs";import E from"node:path";import{getToolActionInfo as x}from"../adapter/types.js";import{recordAgentFileChange as F}from"./workspaceTaskChangeWatcher.js";import{logger as u}from"../utils/logger.js";const h=new Map,k=new Set(["write","writefile","fswrite","edit","editfile","strreplace","str_replace","editcode","multiedit","apply_patch","applypatch","file_change","write_file","edit_file","delete_file","notebookedit"]),b=new Set(["delete","deletefile","remove","rm","delete_file"]);function y(e){return String(e??"").toLowerCase().replace(/[_-]/g,"")}function w(e){if(!e||typeof e!="object")return;const r=[e.file_path,e.filePath,e.path,e.target_file,e.targetFile,e.file,e.files];for(const t of r){if(typeof t=="string"&&t.trim())return t.trim().replace(/\\/g,"/");if(Array.isArray(t)){const i=t.filter(n=>typeof n=="string"&&n.trim());i.length>1&&u.warn(`[SdkFileChange] \u591A\u6587\u4EF6\u5DE5\u5177\u4EC5\u8BB0\u5F55\u9996\u4E2A\u6587\u4EF6\u8DEF\u5F84\uFF08\u5171 ${i.length} \u4E2A\uFF09`);const o=i[0];if(o)return o.trim().replace(/\\/g,"/")}}}function T(e,r){const t=y(e);if(!t)return;if(b.has(t))return"DELETE";if(k.has(t))return"UPDATE";const i=x(e,r);if(i.actionType==="write_file"||i.actionType==="edit_file")return"UPDATE"}function C(e,r){const t=E.resolve(e).replace(/\\/g,"/"),i=E.resolve(e,r).replace(/\\/g,"/"),o=t+"/";if(!(process.platform==="win32"?i.toLowerCase().startsWith(o.toLowerCase())||i.toLowerCase()===t.toLowerCase():i.startsWith(o)||i===t))return;const s=i.slice(t.length).replace(/^\/+/,"");return s.length>0?s:void 0}function N(e,r,t,i,o){if(!r||!t||typeof t!="object")return;let n=h.get(e);n||(n=new Map,h.set(e,n)),n.set(r,{toolInput:t,startState:D(i,t,o)})}function D(e,r,t){if(!t||!T(e,r))return null;const i=w(r),o=i?C(t,i):void 0;if(!o)return null;const n=E.join(t,o);if(!P(n))return{beforeContent:null,existedAtStart:!1};try{return{beforeContent:L(n,"utf-8"),existedAtStart:!0}}catch{return{beforeContent:null,existedAtStart:!0}}}function O(e){h.delete(e)}async function j(e,r){if(e.type!=="tool_use_end"||r.providerId==="acode")return;const{toolName:t,isError:i}=e.data,o=e.data.toolUseId||e.data.actionId,n=h.get(r.sessionId),s=o&&n?.get(o)||void 0;o&&n&&(n.delete(o),n.size===0&&h.delete(r.sessionId));const S=s?.toolInput;if(i===!0)return;const m=T(t,S);if(!m)return;let l=w(S);if(!l){const c=String(e.data.toolResult??e.data.actionResult??"").match(/(?:path|file)[=:]\s*["']?([^"'\s,]+)["']?/i);c&&(l=c[1].replace(/\\/g,"/"))}if(!l){u.warn(`[SdkFileChange] \u8DF3\u8FC7\u65E0\u6CD5\u89E3\u6790\u8DEF\u5F84\u7684\u6587\u4EF6\u5DE5\u5177: session=${r.sessionId}, tool=${t}`);return}const f=C(r.workspacePath,l);if(!f){u.warn(`[SdkFileChange] \u6587\u4EF6\u8DEF\u5F84\u5728\u5DE5\u4F5C\u533A\u5916\u6216\u4E3A\u5DE5\u4F5C\u533A\u6839\u76EE\u5F55\uFF0C\u8DF3\u8FC7: ${l} (workspace=${r.workspacePath})`);return}try{const a=E.join(r.workspacePath,f);let c=null,p=!1;try{c=await A.readFile(a,"utf-8"),p=!0}catch{}const g=s?.startState??null,_=g?.beforeContent??null;let d;if(m==="DELETE")d="DELETE";else if(g!=null){if(!g.existedAtStart&&!p){u.warn(`[SdkFileChange] \u6587\u4EF6\u5728\u5DE5\u5177\u6267\u884C\u524D\u540E\u5747\u4E0D\u5B58\u5728\uFF0C\u8DF3\u8FC7\u8BB0\u5F55: ${f}`);return}d=g.existedAtStart?p?"UPDATE":"DELETE":"CREATE"}else d=p?"UPDATE":"CREATE";await F({filePath:f,operation:d,beforeContent:_,afterContent:d==="DELETE"?null:c,agentId:r.agentId,workspacePath:r.workspacePath})}catch(a){u.warn(`[SdkFileChange] \u8BB0\u5F55\u5931\u8D25: session=${r.sessionId}, tool=${t}, file=${f}, error=${a instanceof Error?a.message:String(a)}`)}}export{O as forgetSession,j as onSdkToolUseEnd,N as onSdkToolUseStart};
|
|
2
|
+
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import k,{AxiosError as U}from"axios";import m from"ws";import{getRuntimeAccessToken as
|
|
1
|
+
import k,{AxiosError as U}from"axios";import m from"ws";import{getRuntimeAccessToken as E,normalizeSchedulerBaseUrl as h}from"./runtime-binding.js";import{loadConfigs as _,loadPrimaryLifecycleConfig as B}from"./auto-register.js";import{logger as c}from"../utils/logger.js";import{port as T}from"../config.js";const A=15e3,I=5e3,N=200,O=1*1024*1024,M=4001,w=new Map;function L(e){const n=e.serverUrl,r=e.instanceId;if(!n||!r)return null;try{const t=new URL(n),o=t.protocol==="https:"?"wss:":"ws:",i=E(n),l=_().find(a=>h(a.serverUrl)===n)||B(),s=i||l.userKey;if(i?c.debug("[TunnelClient] \u4F7F\u7528 runtime access token \u8FDE\u63A5\u96A7\u9053"):l.userKey&&c.warn("[TunnelClient] getRuntimeAccessToken \u8FD4\u56DE\u7A7A\uFF0C\u56DE\u9000\u5230 userKey\uFF08\u975E runtime token\uFF0C\u9274\u6743\u53EF\u80FD\u5931\u8D25\uFF09: targetUrl=",n),!s)return c.warn("[TunnelClient] \u7F3A\u5C11 runtime token\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u96A7\u9053: targetUrl=",n),null;const u=new URLSearchParams({instanceId:r});return{url:`${o}//${t.host}/ws/bridge-tunnel?${u.toString()}`,token:s}}catch(t){return c.warn("[TunnelClient] \u65E0\u6CD5\u89E3\u6790 serverUrl:",String(t)),null}}function j(e,n){const r=h(e);if(!r){c.warn("[TunnelClient] serverUrl \u65E0\u6548\uFF0C\u65E0\u6CD5\u542F\u52A8\u96A7\u9053:",e);return}const t=w.get(r);t&&(t.shuttingDown=!0,S(t),w.delete(r));const o={serverUrl:r,instanceId:n,streams:new Map,shuttingDown:!1};w.set(r,o),y(o)}function z(){for(const e of w.values())e.shuttingDown=!0,S(e);w.clear()}function S(e){e.timer&&(clearInterval(e.timer),e.timer=void 0),e.reconnectTimer&&(clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0);for(const[n,r]of e.streams.entries()){try{r.ws.close(1e3,"tunnel client stopped")}catch{}e.streams.delete(n)}if(e.ws){e.ws.removeAllListeners();try{e.ws.close(1e3,"tunnel client stopped")}catch{}e.ws=void 0}}function y(e){if(e.shuttingDown)return;const n=e.instanceId;if(!n)return;const r=L(e);if(!r){g(e);return}c.info("[TunnelClient] \u8FDE\u63A5\u96A7\u9053\u670D\u52A1\u7AEF:",r.url);const t=new m(r.url,{handshakeTimeout:15e3,headers:{"X-Runtime-Token":r.token}});e.ws=t,t.on("open",()=>{c.info("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5DF2\u5EFA\u7ACB: server=",e.serverUrl,"instanceId=",n),e.reconnectTimer&&clearTimeout(e.reconnectTimer),e.reconnectTimer=void 0,e.timer=setInterval(()=>{t.readyState===m.OPEN&&t.send(JSON.stringify({t:"ping"}))},A)}),t.on("unexpected-response",(o,i)=>{c.error("[TunnelClient] \u670D\u52A1\u7AEF\u62D2\u7EDD\u8FDE\u63A5\uFF08\u975E 101 \u54CD\u5E94\uFF09: server=",e.serverUrl,"statusCode=",i.statusCode,"statusMessage=",i.statusMessage)}),t.on("upgrade",o=>{c.debug("[TunnelClient] \u6536\u5230\u5347\u7EA7\u54CD\u5E94: statusCode=",o.statusCode)}),t.on("message",o=>{let i;typeof o=="string"?i=o:Buffer.isBuffer(o)?i=o.toString("utf-8"):i=Buffer.from(o).toString("utf-8");try{const l=JSON.parse(i);R(e,l)}catch(l){c.warn("[TunnelClient] \u89E3\u6790\u96A7\u9053\u6D88\u606F\u5931\u8D25:",String(l))}}),t.on("close",(o,i)=>{if(c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u5173\u95ED: server=",e.serverUrl,"code=",o,"reason=",String(i)),C(e),o===M){c.warn("[TunnelClient] \u9274\u6743\u5931\u8D25\uFF084001\uFF09\uFF0C\u505C\u6B62\u81EA\u52A8\u91CD\u8FDE\uFF1B\u5F85\u91CD\u65B0\u6CE8\u518C\u540E\u518D\u542F\u52A8\u96A7\u9053: server=",e.serverUrl);return}g(e)}),t.on("error",o=>{c.warn("[TunnelClient] \u96A7\u9053\u8FDE\u63A5\u9519\u8BEF: server=",e.serverUrl,"err=",o.message,"code=",o.code),C(e),g(e)})}function C(e){e.timer&&(clearInterval(e.timer),e.timer=void 0);for(const[n,r]of e.streams.entries()){try{r.ws.close(1011,"tunnel disconnected")}catch{}e.streams.delete(n)}e.ws=void 0}function g(e){e.shuttingDown||e.reconnectTimer||(e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,y(e)},I))}function R(e,n){switch(n.t){case"req":D(e,n);break;case"wsopen":W(e,n);break;case"wsmsg":x(e,n);break;case"wsclose":P(e,n);break;case"ping":d(e,{t:"pong"});break;case"pong":break;default:c.debug("[TunnelClient] \u672A\u77E5\u6D88\u606F\u7C7B\u578B: t=",n.t)}}async function D(e,n){const r=n.id,t=n.method||"GET",o=n.path||"/",i=`http://127.0.0.1:${T}${o}`;try{const l=n.body?Buffer.from(n.body,"base64"):void 0,s={};if(n.headers)for(const[p,f]of Object.entries(n.headers))f&&f.length>0&&(s[p]=f[0]);s["x-bridge-tunnel-source"]=e.serverUrl;const u=await k.request({url:i,method:t,headers:s,data:l,timeout:12e4,responseType:"arraybuffer",validateStatus:()=>!0}),a={};for(const[p,f]of Object.entries(u.headers))f!==void 0&&(a[p]=Array.isArray(f)?f:[String(f)]);const v=Buffer.isBuffer(u.data)?u.data.toString("base64"):"";d(e,{t:"res",id:r,status:u.status,headers:a,body:v||null})}catch(l){const s=l instanceof U?l.message:String(l);c.warn("[TunnelClient] \u672C\u5730\u8F6C\u53D1\u5931\u8D25:",t,o,"->",s),d(e,{t:"res",id:r,status:502,headers:{"content-type":["text/plain; charset=utf-8"]},body:Buffer.from(s).toString("base64")})}}function W(e,n){const r=n.id,t=n.path||"/",o=`ws://127.0.0.1:${T}${t}`;let i;try{i=new m(o,{handshakeTimeout:1e4})}catch(s){c.warn("[TunnelClient] \u672C\u5730 WS \u8FDE\u63A5\u5931\u8D25:",String(s)),d(e,{t:"wsclose",id:r,code:1011,reason:"local ws connect failed"});return}const l={ws:i,pending:[]};e.streams.set(r,l),i.on("open",()=>{for(const s of l.pending)b(l,s.data,s.bin);l.pending=[],d(e,{t:"wsopened",id:r})}),i.on("message",(s,u)=>{const a=Buffer.isBuffer(s)?s:Buffer.from(s);u&&e.ws&&e.ws.bufferedAmount>O||d(e,{t:"wsmsg",id:r,bin:u,d:a.toString("base64")})}),i.on("close",(s,u)=>{e.streams.delete(r),d(e,{t:"wsclose",id:r,code:s,reason:String(u)})}),i.on("error",s=>{c.warn("[TunnelClient] \u672C\u5730 WS \u9519\u8BEF: id=",r,"err=",s.message),e.streams.delete(r);try{i.close(1011,s.message)}catch{}d(e,{t:"wsclose",id:r,code:1011,reason:s.message})})}function b(e,n,r){r?e.ws.send(n):e.ws.send(n.toString("utf-8"))}function x(e,n){const r=e.streams.get(n.id);if(!r)return;const t=n.d?Buffer.from(n.d,"base64"):Buffer.alloc(0);if(r.ws.readyState!==m.OPEN){r.pending.length>=N&&(r.pending.shift(),c.warn("[TunnelClient] \u672C\u5730 WS \u672A\u5C31\u7EEA\uFF0C\u6392\u961F\u6D88\u606F\u8D85\u4E0A\u9650\uFF0C\u4E22\u5F03\u6700\u65E7\u4E00\u6761: id=",n.id)),r.pending.push({data:t,bin:!!n.bin});return}b(r,t,!!n.bin)}function P(e,n){const r=e.streams.get(n.id);if(r){e.streams.delete(n.id);try{r.ws.close(n.code??1e3,n.reason||"")}catch{}}}function d(e,n){if(!(!e.ws||e.ws.readyState!==m.OPEN))try{e.ws.send(JSON.stringify(n))}catch(r){c.warn("[TunnelClient] sendJson \u5931\u8D25:",String(r))}}export{j as startTunnelClient,z as stopTunnelClient};
|
|
2
2
|
|