aws-runtime-bridge 1.9.139 → 1.9.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/AcodeSdkAdapter.d.ts +2 -1
- package/dist/adapter/AcodeSdkAdapter.js +2 -2
- package/dist/config.d.ts +22 -6
- package/dist/config.js +2 -2
- package/dist/index.js +1 -1
- package/dist/remote-desktop/computer-control.d.ts +1 -1
- package/dist/remote-desktop/index.js +2 -2
- package/dist/remote-desktop/screen-capture.js +1 -1
- package/dist/remote-desktop/session-manager.js +1 -1
- package/dist/remote-desktop/types.d.ts +1 -1
- package/dist/remote-desktop/ui-automation.d.ts +2 -2
- package/dist/remote-desktop/ui-automation.js +5 -5
- package/dist/routes/ai-sources.js +1 -1
- package/dist/routes/background-tasks.js +5 -5
- package/dist/routes/dashboard.js +1 -1
- package/dist/routes/git.js +20 -20
- package/dist/routes/terminal.js +27 -27
- package/dist/services/agent-capability-sync.js +1 -1
- package/dist/services/ai-config-service.js +2 -2
- package/dist/services/auto-register.js +1 -1
- package/dist/services/aws-client-agent-mcp.d.ts +5 -0
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/browser-session-manager.js +3 -3
- package/dist/services/capability-config.js +2 -2
- package/dist/services/event-delta-pusher.d.ts +1 -1
- package/dist/services/fileSnapshotStore.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/instance-init-service.js +1 -1
- package/dist/services/instance-state.d.ts +1 -1
- package/dist/services/instance-state.js +1 -1
- package/dist/services/legacy-path-migration.d.ts +0 -2
- package/dist/services/legacy-path-migration.js +1 -1
- package/dist/services/mcp-deploy.js +2 -2
- package/dist/services/plugin-manager.d.ts +1 -1
- package/dist/services/plugin-manager.js +9 -9
- package/dist/services/skill-manager.js +2 -2
- package/package/acode/dist/cli.js +2 -2
- package/package/acode/dist/runtime.d.ts +2 -0
- package/package/acode/dist/runtime.js +12 -12
- package/package/acode/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/dist/routes/terminal.js
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import{spawn as Xe}from"node:child_process";import{promises as
|
|
1
|
+
import{spawn as Xe}from"node:child_process";import{promises as q}from"node:fs";import Qe from"node:os";import B from"node:path";import{TextDecoder as ee}from"node:util";import be from"axios";import{Router as Ve}from"express";import{v4 as Ge}from"uuid";import{adapterRegistry as b,getToolActionInfo as ye,isTransientClipboardPasteFilePath as we,redactTransientClipboardPastePaths as v,registerSdkProviders as Je,resolveSdkProviderIdByCommand as Ye}from"../adapter/index.js";import{getActiveBridgeHttpPort as Ze,getAcodeDataHome as Ce}from"../config.js";import{validateToken as I}from"../middleware/auth.js";import{getAgentProcessManager as he}from"../services/agent-process-manager.js";import{createAiConfigService as et}from"../services/ai-config-service.js";import{resolveSchedulerBaseUrlFromToken as _e}from"../services/auto-register.js";import{setChangeCacheRetentionDays as tt}from"../services/change-cache-retention.js";import{getAllPushStats as nt,startHeartbeatScheduler as rt}from"../services/event-delta-pusher.js";import{prepareAcodeInstanceConfig as ot,redactForLog as te}from"../services/instance-ai-config-service.js";import{setAgentFeatures as st,setAgentCapabilities as it,getAgentFeatures as at,isFeatureEnabled as $e,LAUNCH_ITEM_FEATURE_KEY as ct,HIRE_FEATURE_KEY as ut}from"../services/instance-features.js";import{enqueueMcpLaunchBinding as dt}from"../services/mcp-launch-binding-queue.js";import{setPanelEnvVars as lt}from"../services/panel-env.js";import{findClaudeCodeProcesses as mt,isProcessRunning as ft}from"../services/process-detector.js";import{forgetSession as F,onSdkToolUseEnd as pt,onSdkToolUseStart as gt}from"../services/sdk-tool-file-change-recorder.js";import{bridgeEventBuffer as De,sendOutput as Q,sendQuestionRequest as yt,sendToolAuthRequest as ht,sendStatus as _}from"../services/session-output.js";import{findPersistedSessionByAgentId as It,removePersistedSession as K,savePersistedSessions as St,updatePersistedSessionAutoCommands as At,updatePersistedSessionRuntimeState as Tt,upsertPersistedSession as kt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as bt}from"../utils/instance-ai-config-debug-logger.js";import{logger as m}from"../utils/logger.js";const S=Ve();function Re(e){const n=e.header("X-Runtime-Token");return n&&n.trim()?n.trim():(e.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||void 0}const p=new Map,wt=45e3,ne=new Map;function Ct(e){if(ne.has(e))return;const n=setInterval(()=>{const t=p.get(e);if(!t){x(e);return}const r=t.currentRuntimeStatus;if(r!=="thinking"&&r!=="tool_using"&&r!=="compacting"){x(e);return}_(t.agentId,e,r,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},wt);ne.set(e,n)}function x(e){const n=ne.get(e);n&&(clearInterval(n),ne.delete(e))}const Pe=4e3,_t=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u4F53:
|
|
4
|
-
`;function
|
|
4
|
+
`;function Ee(e){if(e==null||typeof e!="object"||Array.isArray(e))return;const n=e,t={};return typeof n.model=="string"&&n.model.trim()&&(t.model=n.model.trim()),typeof n.baseURL=="string"&&n.baseURL.trim()&&(t.baseURL=n.baseURL.trim()),typeof n.apiKey=="string"&&n.apiKey.trim()&&(t.apiKey=n.apiKey.trim()),typeof n.effort=="string"&&n.effort.trim()&&(t.effort=n.effort.trim()),t}const $t=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u5934:
|
|
7
|
-
`,
|
|
7
|
+
`,z=new Set;async function Dt(e,n){const t=[],r=[],o=B.join(e,".agentswork","memory");try{const c=(await q.readdir(o)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await q.readFile(B.join(o,u),"utf-8");return JSON.parse(l)}catch{return m.warn("[loadAgentStartupMemories] Failed to parse memory file: %s",B.join(o,u)),null}}));for(const u of d)if(u?.by_uri)for(const l of Object.values(u.by_uri)){const f=l.memory_type||"memory",g=(l.content||"").trim();g&&(f==="recently_memory"?t.push({title:l.title,content:g,uri:l.uri||""}):f==="agent_memory"&&r.push({title:l.title,content:g,uri:l.uri||""}))}}catch{m.debug("[loadAgentStartupMemories] \u65E0\u6CD5\u8BFB\u53D6\u8BB0\u5FC6\u76EE\u5F55: %s",o)}if(t.length===0&&r.length===0&&n?.schedulerBaseUrl&&n?.runtimeAccessToken&&n?.agentId){const a=`${n.schedulerBaseUrl.replace(/\/+$/,"")}/mcp/call`,c={"Content-Type":"application/json","X-Runtime-Token":n.runtimeAccessToken,Authorization:`Bearer ${n.runtimeAccessToken}`},d=["recently_memory","agent_memory"],u=await Promise.allSettled(d.map(l=>fetch(a,{method:"POST",headers:c,body:JSON.stringify({tool:"list_memories",arguments:{agentId:n.agentId,memory_type:l}})}).then(f=>{if(!f.ok)throw new Error(`Server returned ${f.status}`);return f.json()})));for(let l=0;l<u.length;l++){const f=u[l];if(f.status!=="fulfilled")continue;const g=f.value;if(!Array.isArray(g))continue;const T=d[l]==="recently_memory"?t:r;for(const h of g){const y=(h.content||"").trim();y&&T.push({title:h.title,content:y,uri:h.uri||""})}}(t.length>0||r.length>0)&&m.info(`[loadAgentStartupMemories] Loaded ${t.length} task(s) and ${r.length} memory(s) from server for ${n.agentId}`)}const s=10;t.sort((a,c)=>c.uri.localeCompare(a.uri)),r.sort((a,c)=>c.uri.localeCompare(a.uri));const i=[];if(t.length>0){const c=t.slice(0,s).map((d,u)=>`${d.title?`\u3010${d.title}\u3011`:`\u6761\u76EE ${u+1}`}
|
|
8
8
|
${d.content}`);i.push(`\u3010\u77ED\u671F\u8BB0\u5FC6\u3011
|
|
9
9
|
${c.join(`
|
|
10
10
|
|
|
11
|
-
`)}`),t.length>s&&i.push(`... \u53CA\u53E6\u5916 ${t.length-s} \u6761\u77ED\u671F\u8BB0\u5FC6`)}if(
|
|
11
|
+
`)}`),t.length>s&&i.push(`... \u53CA\u53E6\u5916 ${t.length-s} \u6761\u77ED\u671F\u8BB0\u5FC6`)}if(r.length>0){const c=r.slice(0,s).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>s&&i.push(`... \u53CA\u53E6\u5916 ${r.length-s} \u6761 agent \u8BA4\u77E5`)}if(i.length!==0)return i.join(`
|
|
16
16
|
|
|
17
|
-
`)}function Rt(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 Pt(e){return e!=="acode"}function Et(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
|
|
17
|
+
`)}function Rt(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 Pt(e){return e!=="acode"}function Et(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function re(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,r=Number.isFinite(n.outputTokens)?n.outputTokens:0;if(t<=0&&r<=0&&!n.contextLimit&&!n.maxOutput&&!n.inputLimit&&!n.compactionThreshold)return;const o={inputTokens:t,outputTokens:r,...n.contextLimit?{contextLimit:n.contextLimit}:{},...n.maxOutput?{maxOutput:n.maxOutput}:{},...n.inputLimit?{inputLimit:n.inputLimit}:{},...n.compactionThreshold?{compactionThreshold:n.compactionThreshold}:{},...n.cacheHitTokens?{cacheHitTokens:n.cacheHitTokens}:{},...n.cacheMissTokens?{cacheMissTokens:n.cacheMissTokens}:{}};return process.env.ACODE_TOKEN_DEBUG==="1"&&(o.inputTokens>0||o.outputTokens>0||o.cacheHitTokens!==void 0||o.cacheMissTokens!==void 0)&&m.info(`[TokenDebug][Terminal] resolveStatusChangeUsage: input=${o.inputTokens} output=${o.outputTokens} cacheHit=${o.cacheHitTokens??"(none)"} cacheMiss=${o.cacheMissTokens??"(none)"} actionType=${e?.actionType??"(none)"}`),o}function Mt(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 V=new Map,xt="utf-8",Me="utf-8",xe=300,Le=6e4;function G(e){return String(e).padStart(2,"0")}function Lt(e,n=new Date){const t=n.getFullYear(),r=G(n.getMonth()+1),o=G(n.getDate()),s=G(n.getHours()),i=G(n.getMinutes()),a=`${t}${r}${o}-${s}${i}${G(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return B.join(Ce(),"cmd-dist",e,`${t}-${r}-${o}`,s,i,`${a}-cmd.out`)}function Ut(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
|
|
18
18
|
`).replace(/\r/g,`
|
|
19
19
|
`),t=n.endsWith(`
|
|
20
20
|
`)?n.slice(0,-1):n;return t?t.split(`
|
|
21
|
-
`).length:1}function jt(e,n=
|
|
21
|
+
`).length:1}function jt(e,n=xe){return`\r
|
|
22
22
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u8D85\u8FC7 ${n} \u884C\uFF0C\u5B8C\u6574\u8F93\u51FA\u5DF2\u5199\u5165: ${e}\r
|
|
23
23
|
[ACode] Agent \u53EF\u81EA\u884C\u8BFB\u53D6\u8BE5\u6587\u4EF6\uFF0C\u6216\u5728\u8BE5\u6587\u4EF6\u4E2D\u641C\u7D22\u9700\u8981\u7684\u5185\u5BB9\u3002\r
|
|
24
|
-
`}function Bt(e=
|
|
24
|
+
`}function Bt(e=Le){return`\r
|
|
25
25
|
[ACode] \u547D\u4EE4\u8D85\u8FC7 ${Math.round(e/1e3)} \u79D2\u6CA1\u6709\u65B0\u7684\u8F93\u51FA\uFF0C\u5DF2\u505C\u6B62\u6267\u884C\u5E76\u4FDD\u7559\u6B64\u524D\u8F93\u51FA\u3002\r
|
|
26
|
-
`}async function Ue(e){const n=e.outputPath||
|
|
27
|
-
`).trim()}function Nt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?
|
|
28
|
-
`),!0;const
|
|
29
|
-
`),!0):(w(e,`cd: not a directory: ${
|
|
26
|
+
`}async function Ue(e){const n=e.outputPath||Lt(e.agentId,e.startedAt);return e.outputPath=n,await q.mkdir(B.dirname(n),{recursive:!0}),await q.writeFile(n,e.chunks.join(""),"utf-8"),n}function Ot(e){return String(e??"").replace(/\r/g,`
|
|
27
|
+
`).trim()}function Nt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?xt:Me)}function je(e=Nt()){if(e!=="utf-8")try{return new ee(e,{fatal:!1})}catch{return new ee(Me,{fatal:!1})}return qt()}function qt(){let e=null,n=null,t=null;const r=[];function o(s){try{return new ee(s,{fatal:!1})}catch{return new ee("utf-8",{fatal:!1})}}return{decode(s,i){if(s!=null&&r.push(s instanceof ArrayBuffer?Buffer.from(s):Buffer.isBuffer(s)?s:Buffer.from(s.buffer,s.byteOffset,s.byteLength)),t==="gb18030")return n||(n=o("gb18030")),n.decode(s,i);e||(e=o("utf-8"));const a=e.decode(s,i);if(t===null&&a.includes("\uFFFD")){t="gb18030",n=o("gb18030");const c=Buffer.concat(r);return n.decode(c)}return t===null&&!i?.stream&&(t="utf-8"),a}}}function oe(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function vt(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 Ft(e){const n=V.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return V.set(e.sessionId,t),t}function Be(e){for(const n of p.values())if(n.agentId===e)return n}async function Kt(e){const n=b.get(e.providerId||"claude-code"),t=se(n.getSessionStatus(e.sessionId),e.currentRuntimeStatus,e.currentRuntimeActionType);return{sessionId:e.sessionId,status:t,runtimeStatus:t,runtimeActionType:e.currentRuntimeActionType,runtimeActionLabel:e.currentRuntimeActionLabel,runtimeActionDetail:e.currentRuntimeActionDetail,agentId:e.agentId,workspacePath:e.workspacePath,command:e.config.command,mode:"sdk",providerSessionId:n.getProviderSessionId(e.sessionId),reused:!0}}function se(e,n,t){const r=String(e||"").trim();if(r){const s=String(n||"").trim(),i=String(t||"").trim().toLowerCase();return r.toLowerCase()==="tool_using"&&s.toLowerCase()==="waiting_input"&&i==="idle"?s:r}return String(n||"").trim()||"running"}function zt(e,n=ft){return e.pid?n(e.pid)?Ke(e.command)==="acode"?{reusable:!1,reason:"in-process-provider"}:{reusable:!0,reason:"active-pid"}:{reusable:!1,reason:"dead-pid"}:{reusable:!1,reason:"missing-pid"}}function er(e){const n=Be(e);if(!n)m.info(`[cleanupSdkSessionByAgentId] No active SDK session found for agentId=${e}, cleaning residual state anyway`);else{const t=n.sessionId;return m.info(`[cleanupSdkSessionByAgentId] Cleaning up SDK session for agentId=${e}, sessionId=${t}`),x(t),p.delete(t),F(t),ie(t),K(t).catch(r=>{m.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${r}`)}),t}z.has(e)&&(z.delete(e),m.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ie(e){const n=V.get(e);if(!n?.runningProcess){V.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,V.delete(e)}}function w(e,n){n&&(e.seq+=1,Q(e.agentId,n,e.sessionId,e.seq,void 0,{runtimeAccessToken:e.runtimeAccessToken,schedulerBaseUrl:e.schedulerBaseUrl}).catch(()=>{}))}function Ie(e){return`\x1B[36m${e}>\x1B[0m `}function Ht(e,n){return n==="~"?Qe.homedir():B.resolve(e,n)}async function Wt(e,n,t){const r=vt(t);if(r===void 0)return!1;if(r===null)return w(e,`${n.currentDirectory}\r
|
|
28
|
+
`),!0;const o=Ht(n.currentDirectory,r);try{return(await q.stat(o)).isDirectory()?(n.currentDirectory=o,w(e,`${n.currentDirectory}\r
|
|
29
|
+
`),!0):(w(e,`cd: not a directory: ${o}\r
|
|
30
30
|
`),!0)}catch(s){const i=s instanceof Error?s.message:String(s);return w(e,`cd: ${i}\r
|
|
31
|
-
`),!0}}async function Xt(e,n){const t=
|
|
32
|
-
`),
|
|
33
|
-
`),w(t,
|
|
31
|
+
`),!0}}async function Xt(e,n){const t=p.get(e);if(!t)throw new Error("SDK session not found");const r=Ot(n),o=Ft(t);if(!r)return{started:!1,cwd:o.currentDirectory};if(o.runningProcess)throw new Error("A terminal command is already running for this session");const s=v(r);if(w(t,`${Ie(o.currentDirectory)}${s}\r
|
|
32
|
+
`),we(r))return w(t,`[Terminal Warning] \u68C0\u6D4B\u5230\u526A\u8D34\u677F\u4E34\u65F6 paste \u6587\u4EF6\u8DEF\u5F84\uFF0C\u5DF2\u8DF3\u8FC7\u6267\u884C\u3002\u8BF7\u7C98\u8D34\u6587\u4EF6\u5185\u5BB9\u6216\u4F7F\u7528\u663E\u5F0F\u8BFB\u53D6\u547D\u4EE4\u3002\r
|
|
33
|
+
`),w(t,Ie(o.currentDirectory)),{started:!1,cwd:o.currentDirectory};if(await Wt(t,o,r))return{started:!1,cwd:o.currentDirectory};await _(t.agentId,e,"tool_using",{actionType:"bash",actionLabel:"\u7EC8\u7AEF\u547D\u4EE4",actionDetail:s},void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl});const a=Xe(r,{cwd:o.currentDirectory,shell:!0,env:Oe(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});o.runningProcess=a;const c=je(),d=je(),u=t.providerId==="acode",l={agentId:t.agentId,startedAt:new Date,chunks:[],spilled:!1};let f;const g=()=>{f&&(clearTimeout(f),f=void 0)},T=()=>{g(),f=setTimeout(()=>{o.runningProcess===a&&(w(t,Bt()),a.kill())},Le)},h=(y,C=!0)=>{if(y&&(u&&l.chunks.push(y),u&&C&&T(),!(u&&l.spilled))){if(u&&Ut(l.chunks.join(""))>xe){l.spilled=!0,Ue(l).then($=>{w(t,jt($))}).catch($=>{const M=$ instanceof Error?$.message:String($);w(t,`\r
|
|
34
34
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${M}\r
|
|
35
|
-
`)});return}w(t,
|
|
36
|
-
[Terminal Error] ${
|
|
37
|
-
`)}),a.on("close",(
|
|
35
|
+
`)});return}w(t,y)}};return u&&T(),a.stdout.on("data",y=>{h(oe(c,y))}),a.stderr.on("data",y=>{h(oe(d,y))}),a.on("error",y=>{w(t,`\r
|
|
36
|
+
[Terminal Error] ${y.message}\r
|
|
37
|
+
`)}),a.on("close",(y,C)=>{g(),o.runningProcess=null,h(oe(c,void 0,!0),!1),h(oe(d,void 0,!0),!1),l.spilled&&Ue(l).catch($=>{const M=$ instanceof Error?$.message:String($);w(t,`\r
|
|
38
38
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u6700\u7EC8\u843D\u76D8\u5931\u8D25: ${M}\r
|
|
39
|
-
`)}),
|
|
40
|
-
[exit ${
|
|
39
|
+
`)}),y&&y!==0?w(t,`\r
|
|
40
|
+
[exit ${y}]\r
|
|
41
41
|
`):C&&w(t,`\r
|
|
42
42
|
[signal ${C}]\r
|
|
43
|
-
`),w(t,
|
|
44
|
-
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function Yt(e){try{const n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return["directMessages","groupMessages","messages"].some(t=>Array.isArray(n[t])&&n[t].length>0)}catch{}return e.trim().length>0}function Zt(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 en(e){if(e.type!=="tool_use_end")return;const n=Jt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),
|
|
43
|
+
`),w(t,Ie(o.currentDirectory)),_(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:o.currentDirectory}}function Oe(e,n,t,r){const o={};for(const[s,i]of Object.entries(t))i!==void 0&&(o[s]=i);if(n&&(o.AWS_WORKSPACE_PATH=String(n)),r)for(const[s,i]of Object.entries(r)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(o[a]=c)}return o.AWS_AGENT_ID=String(e),o.AWS_MCP_CLAIM_LAUNCH_BINDING="true",o.AWS_RUNTIME_BRIDGE_BASE_URL=`http://127.0.0.1:${Ze()}`,String(o.ACODE_HOME||"").trim()||(o.ACODE_HOME=Ce()),$e(e,ct)&&(o.AWS_LAUNCH_CONFIG_TOOLS="1"),$e(e,ut)&&(o.AWS_HIRE_TOOLS="1"),o}function Qt(e){const n=e.trim(),t=n[0],r=n[n.length-1];return(t==='"'||t==="'")&&t===r?n.slice(1,-1):n}async function Vt(e){const n=String(e);if(!we(n))return n;const t=Qt(n);return B.isAbsolute(t)?q.readFile(t,"utf-8"):n}function Ne(e,n){const t={};for(const o of[e?.env,n])if(o)for(const[s,i]of Object.entries(o)){const a=s.trim();if(!a||i===void 0||i===null)continue;const c=String(i).trim();c&&(t[a]=c)}const r=t.ANTHROPIC_MODEL?.trim()||t.CODEX_MODEL?.trim()||void 0;return{envOverrides:t,model:r}}async function Gt(){try{return await et().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function Jt(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 Yt(e){try{const n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return["directMessages","groupMessages","messages"].some(t=>Array.isArray(n[t])&&n[t].length>0)}catch{}return e.trim().length>0}function Zt(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 en(e){if(e.type!=="tool_use_end")return;const n=Jt(e.data.toolResult??e.data.actionResult);if(!n)return;const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionType||t.actionType;if(r==="idle"){const o=String(e.data.rawToolName||e.data.toolName||"").toLowerCase();if((o.includes("poll_message")||o.includes("get_message"))&&!Yt(n))return}return r==="mcp"&&Zt(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 tn(e){if(e.type==="ai_request"){const n=e.data.model?` ${e.data.model}`:"",t=e.data.lastUserMessagePreview?`\uFF1A${e.data.lastUserMessagePreview}`:"";return`\r
|
|
45
45
|
[ACode] \u6B63\u5728\u8BF7\u6C42\u6A21\u578B${n}${t}\r
|
|
46
46
|
`}if(e.type==="text_delta"||e.type==="thinking"||e.type==="command_output")return e.data.text||void 0;if(e.type==="error")return e.data.text?`\r
|
|
47
47
|
[SDK Error] ${e.data.text}\r
|
|
48
|
-
`:void 0}function nn(e){const n=sn(e);return{sourceEventType:e.type,logCategory:"acode",...
|
|
49
|
-
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function fn(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=pn(e.requestHeaders),
|
|
50
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",
|
|
51
|
-
`)}`:"",s=e.requestBody?`${_t}${e.requestBody}`:"";return`${o}${r}${s}`}function pn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function gn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function yn(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],o=Number(t);if(Number.isFinite(o)&&o>0)return o}}function hn(e,n){if(!gn(e,n)){if(e.type==="ai_request"){const t=yn(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:fn(e.data),...t!==void 0?{usage:{inputTokens:t,outputTokens:0}}:{}}}}if(e.type==="background_command_completed")return{status:"tool_result",actionInfo:{actionType:"background_command",actionLabel:"\u540E\u53F0\u547D\u4EE4",actionDetail:"background_command_completed"}};if(e.type==="thinking"||e.type==="text_delta")return{status:"thinking"};if(e.type==="tool_use_start"){const t=ye(e.data.toolName,e.data.toolInput),o=ve(e,t),r=mn(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:o||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:r,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const x=new Map,ae=new Map,ce=new Map,G=new Map,In=20,Sn=500,An=3e4;async function ue(e,n=An,t=2){for(let o=0;o<=t;o++){const r=new AbortController;let s;try{const i=e(r.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{r.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(o<t){const c=1e3*(o+1);h.warn(`sendOutput attempt ${o+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}h.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let o,r;if(t)o=G.get(t),r=t;else{const p=[];for(const[T,y]of G)T.startsWith(e+":")&&y.buffer&&p.push(y.sourceEventType);for(const T of p)de(e,T);return}if(!o||!o.buffer)return;o.timer=null;const s=o.buffer,i=o.seq,a=o.entry,c=o.sourceEventType;o.buffer="",r&&G.delete(r);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},m=(x.get(e)??Promise.resolve()).then(()=>ue(p=>X(a.agentId,s,e,i,d,u,p)),()=>ue(p=>X(a.agentId,s,e,i,d,u,p)));x.set(e,m),m.finally(()=>{x.get(e)===m&&x.delete(e)})}function Tn(e,n){const t=tn(e);if(!t)return;n.seq+=1;const o=n.seq,r=nn(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<In){const c=`${e.sessionId}:${e.type}`;let d=G.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=o,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),Sn)}G.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)),()=>ue(c=>X(n.agentId,t,e.sessionId,o,r,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function Ke(e){return Ye(e)}let ze=!1;function kn(){ze||(Je(b,bn),ot(),ze=!0)}function bn(e,n){e.on("event",t=>{const o=f.get(t.sessionId);if(o){if(t.type==="tool_use_start"?gt(o.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,o.workspacePath):t.type==="tool_use_end"&&pt(t,{sessionId:o.sessionId,agentId:o.agentId,workspacePath:o.workspacePath,providerId:o.providerId}),console.log(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(o.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=hn(t,o.currentRuntimeStatus);i&&_(o.agentId,t.sessionId,i.status,i.actionInfo,oe(i.actionInfo),{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}Tn(t,o);const s=en(t);if(s){const i={runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(p=>setTimeout(p,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await _(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(p=>setTimeout(p,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):_(o.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,o,r)=>{const s=f.get(t);if(s){de(t),o==="thinking"||o==="tool_using"||o==="compacting"?Ct(t):L(t);const i=Mt(o,r);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),console.log(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),Tt(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const p=(ae.get(t)??Promise.resolve()).then(async()=>{for(let y=0;y<=2;y++){if(await _(s.agentId,t,i.status,l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;y<2&&(h.warn(`[${n.displayName}] compaction sendStatus attempt ${y+1} failed (HTTP), retrying in ${1e3*(y+1)}ms...`),await new Promise(C=>setTimeout(C,1e3*(y+1))))}h.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{h.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,p),p.finally(()=>{ae.get(t)===p&&ae.delete(t)})}else{const m=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const y=(ce.get(t)??Promise.resolve()).then(async()=>{for(let C=0;C<=2;C++){if(await _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;C<2&&await new Promise(M=>setTimeout(M,1e3*(C+1)))}h.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(g=>{h.warn(`[${n.displayName}] idle status chain error:`,g)});ce.set(t,y),y.finally(()=>{ce.get(t)===y&&ce.delete(t)})}else _(s.agentId,t,i.status,m?void 0:l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const m=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,console.log(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),_(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:m},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const o=f.get(t.sessionId);o&&(console.log(`[${n.displayName} Adapter] AskUserQuestion for agent ${o.agentId}`),yt(o.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl},t.toolCallId))}),e.on("tool-permission-request",t=>{const o=f.get(t.sessionId);o&&t.requestId&&(console.log(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${o.agentId}`),ht(o.agentId,t.sessionId,{requestId:t.requestId,capability:t.capability,...t.detail||{}},{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}))}),e.on("permission-request",t=>{const o=f.get(t.sessionId);if(o){console.log(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${o.agentId}`);const r=t.toolInput?q(JSON.stringify(t.toolInput).slice(0,400)):void 0;_(o.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:r||t.toolName},void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl})}})}S.post("/start",I,async(e,n)=>{const{agentId:t,workspacePath:o,mode:r="sdk"}=e.body||{};if(!t||!o){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||$e(Pe(e))||void 0;dt({agentId:String(t),workspacePath:String(o),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!=null&&(st(String(t),e.body.runtimeFeatures),console.log(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(at(String(t)))}`)),e.body?.capabilities!==void 0&&it(String(t),e.body.capabilities),e.body?.envVars!=null&&typeof e.body.envVars=="object"&&(lt(e.body.envVars),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(tt(e.body.changeCacheRetentionDays),console.log(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),r&&r!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${r}" requested for agent ${t}; starting SDK session instead.`),await wn(e,n)});async function wn(e,n){const{agentId:t,workspacePath:o,command:r,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:m,envOverrides:p,idleInputAutoCommand:T,nonInputAutoCommand:y,model:g,instanceAiConfig:C,subAgentModel:$,subAgentEffort:M,scopeKey:Te,browserAllowPrivate:ke}=e.body||{},z=bt();z.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:C?te(C):null,perAgentModel:g??null}});let D=null;const A=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,B=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||$e(Pe(e))||void 0;B?h.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${B} (agentId=${A})`):h.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(kn(),!A){n.status(400).json({error:"agentId is required"});return}const O=Be(A);if(O){n.json(await Kt(O));return}const k=await It(A);if(k){const R=zt(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${k.sessionId}, reason=${R.reason}`),await F(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(K.has(A)){n.status(409).json({error:"SDK session is already starting for this agent"});return}K.add(A);const Dn=(r||"acode").toLowerCase(),E=Ke(r),He=b.get(E);D=Ge();const We=E==="claude-code"?await Gt():null,J=Ne(E==="claude-code"?We:null,p),H=E==="acode"?g?String(g).trim():void 0:(()=>{const R=g?String(g).trim():void 0,P=J.model?String(J.model).trim():void 0;return R||P})();z.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:D??void 0,details:{perAgentModel:g??null,globalModel:J.model??null,resolvedModel:H??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...J.envOverrides};H&&(me.ANTHROPIC_MODEL=H,me.CODEX_MODEL=H);let W,fe=l;if(E==="acode"){const R=C||{},P=await rt({apiOverrides:Ie(R)??void 0,agentId:A,sessionId:D??void 0,runtimeBridgeBaseUrl:B});W=P.instanceConfig.config,fe=P.perInstanceConfigPath,z.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:D??void 0,details:{sanitizedApiOverrides:Ie(R)?te(Ie(R)):null,resolvedInstanceAiConfig:W?te(W):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let be=a||void 0,pe,ge,Y;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Y=u.trim();else{const R=await Dt(o,{schedulerBaseUrl:B,runtimeAccessToken:le,agentId:A});R&&(Y=R,h.info(`[startSdkSession] Auto-loaded memories for ACode agent ${A}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(Z=>typeof Z=="string"&&Z.trim().length>0).map(Z=>Z.trim());be=P.length>0?P.join(`
|
|
48
|
+
`:void 0}function nn(e){const n=sn(e);return{sourceEventType:e.type,logCategory:"acode",...on(e),...n?{logLevel:rn(e),logMessage:n}:{}}}function rn(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function on(e){return e.type!=="command_output"?{}:{...typeof e.data.stream=="string"?{stream:e.data.stream}:{},...typeof e.data.sequence=="number"?{sequence:e.data.sequence}:{},...typeof e.data.cwd=="string"?{cwd:e.data.cwd}:{},...typeof e.data.commandFilePath=="string"?{commandFilePath:e.data.commandFilePath}:{},...typeof e.data.commandLineCount=="number"?{commandLineCount:e.data.commandLineCount}:{}}}function sn(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 qe(e,"\u5F00\u59CB");if(e.type==="tool_use_end")return qe(e,"\u5B8C\u6210");if(e.type==="command_output")return un(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 an=/\x1b\[[0-9;?]*[a-zA-Z]/g;function cn(e){return e.replace(an,"")}function un(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",r=cn(String(e.data.text||"")).replace(/\s+/g," ").trim(),o=r.length>240?`${r.slice(0,240)}...`:r;return`\u547D\u4EE4\u8F93\u51FA(${n}${t}): ${o||"(empty)"}`}function qe(e,n){const t=ye(e.data.toolName,e.data.toolInput),r=e.data.actionLabel||t.actionLabel||"\u8C03\u7528\u5DE5\u5177",o=ve(e,t);return o?`${n}${r}: ${o}`:`${n}${r}: ${e.data.actionDetail||e.data.toolName||"tool"}`}function ve(e,n){const t=e.data.toolInput;return n.actionType==="bash"?dn(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?ln(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function dn(e){const n=Se(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(r=>String(r??"").trim()).filter(Boolean).join(" ");return t?v(t):void 0}return Se(e?.args)}function ln(e){const n=Fe(e?.paths);return n.length>0?n.length===1?n[0]:`${n.length}\u4E2A\u6587\u4EF6: ${n.join(", ")}`:Se(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)}function Se(...e){for(const n of e){if(typeof n=="string"&&n.trim())return v(n.trim());if(Array.isArray(n)){const t=Fe(n)[0];if(t)return t}}}function Fe(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>v(n)):[]}function mn(e){if(!(!e||Object.keys(e).length===0))try{const n=v(JSON.stringify(e,null,2));return n.length>8e3?`${n.slice(0,8e3)}
|
|
49
|
+
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function fn(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=pn(e.requestHeaders),r=n.join(`
|
|
50
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",o=t.length>0?`${$t}${t.join(`
|
|
51
|
+
`)}`:"",s=e.requestBody?`${_t}${e.requestBody}`:"";return`${r}${o}${s}`}function pn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function gn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function yn(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 hn(e,n){if(!gn(e,n)){if(e.type==="ai_request"){const t=yn(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:fn(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=ve(e,t),o=mn(e.data.toolInput);return e.data.actionType==="idle"||t.actionType==="idle"?{status:"waiting_input",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}:{status:"tool_using",actionInfo:{actionType:e.data.actionType||t.actionType,actionLabel:e.data.actionLabel||t.actionLabel,actionDetail:r||e.data.actionDetail||t.actionDetail||e.data.toolName,actionInput:o,actionId:e.data.actionId||e.data.toolUseId}}}if(e.type==="turn_complete")return{status:"waiting_input",actionInfo:e.data.usage?{usage:e.data.usage}:void 0};if(e.type==="error")return{status:"error"};if(e.type==="context_compaction")return{status:"compacting",actionInfo:{actionType:"context_compaction",actionLabel:e.data.actionLabel,actionDetail:e.data.actionDetail,...e.data.actionId?{actionId:e.data.actionId}:{},...e.data.parentId?{parentId:e.data.parentId}:{}}};if(e.type==="runtime_capabilities")return{status:n||"waiting_input",actionInfo:{actionType:"runtime_capabilities",actionLabel:e.data.actionLabel||"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:e.data.actionDetail}}}}const L=new Map,ae=new Map,ce=new Map,J=new Map,In=20,Sn=500,An=3e4;async function ue(e,n=An,t=2){for(let r=0;r<=t;r++){const o=new AbortController;let s;try{const i=e(o.signal);i.catch(()=>{}),await Promise.race([i,new Promise((a,c)=>{s=setTimeout(()=>{o.abort(),c(new Error(`sendOutput timeout after ${n}ms`))},n)})]),s&&clearTimeout(s);return}catch(i){s&&clearTimeout(s);const a=i instanceof Error?i.message:String(i);if(r<t){const c=1e3*(r+1);m.warn(`sendOutput attempt ${r+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}m.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function de(e,n){const t=n?`${e}:${n}`:void 0;let r,o;if(t)r=J.get(t),o=t;else{const g=[];for(const[T,h]of J)T.startsWith(e+":")&&h.buffer&&g.push(h.sourceEventType);for(const T of g)de(e,T);return}if(!r||!r.buffer)return;r.timer=null;const s=r.buffer,i=r.seq,a=r.entry,c=r.sourceEventType;r.buffer="",o&&J.delete(o);const d={sourceEventType:c,logCategory:"acode"},u={runtimeAccessToken:a.runtimeAccessToken,schedulerBaseUrl:a.schedulerBaseUrl},f=(L.get(e)??Promise.resolve()).then(()=>ue(g=>Q(a.agentId,s,e,i,d,u,g)),()=>ue(g=>Q(a.agentId,s,e,i,d,u,g)));L.set(e,f),f.finally(()=>{L.get(e)===f&&L.delete(e)})}function Tn(e,n){const t=tn(e);if(!t)return;n.seq+=1;const r=n.seq,o=nn(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<In){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),Sn)}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,o,s,c)),()=>ue(c=>Q(n.agentId,t,e.sessionId,r,o,s,c)));L.set(e.sessionId,a),a.finally(()=>{L.get(e.sessionId)===a&&L.delete(e.sessionId)})}function Ke(e){return Ye(e)}let ze=!1;function kn(){ze||(Je(b,bn),rt(),ze=!0)}function bn(e,n){e.on("event",t=>{const r=p.get(t.sessionId);if(r){if(t.type==="tool_use_start"?gt(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&pt(t,{sessionId:r.sessionId,agentId:r.agentId,workspacePath:r.workspacePath,providerId:r.providerId}),m.info(`[${n.displayName} Adapter] Event: ${t.type} for session ${t.sessionId}`),!(t.type==="thinking"||t.type==="text_delta"||t.type==="tool_use_start"||t.type==="context_compaction"||t.type==="ai_request")){t.type==="runtime_capabilities"&&t.data.actionDetail&&(r.cachedCapabilitiesActionDetail=t.data.actionDetail);const i=hn(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)}Tn(t,r);const s=en(t);if(s){const i={runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},a=t.timestamp?new Date(t.timestamp).getTime():void 0,c=String(t.data?.toolName||"").toLowerCase()==="browser_launch",d=t.type==="tool_use_end"&&String(t.data?.rawToolName||t.data?.toolName||"").toLowerCase().replace(/[_-]/g,"").includes("todowrite");c?(async()=>{for(let l=0;l<3;l++){if(await _(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,3e3*(l+1)))}})().catch(u=>console.warn("[Runtime] browser_launch sendStatus retry exhausted:",u)):d?(async()=>{for(let l=0;l<3;l++){if(await _(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)!==void 0)return;l<2&&await new Promise(g=>setTimeout(g,1e3*(l+1)))}})().catch(u=>console.warn("[Runtime] todo_write sendStatus retry exhausted:",u)):_(r.agentId,t.sessionId,"tool_result",s,void 0,i,a,t.type)}}}),e.on("status-change",(t,r,o)=>{const s=p.get(t);if(s){de(t),r==="thinking"||r==="tool_using"||r==="compacting"?Ct(t):x(t);const i=Mt(r,o);s.currentRuntimeStatus=i.status;const a=s.currentRuntimeActionDetail??"",c=a.includes("poll_message")||a.includes("get_message"),u=!(i.actionInfo?.actionType==="ai_request")&&(i.status==="thinking"||i.status==="waiting_input")&&(s.currentRuntimeActionType==="idle"||s.currentRuntimeActionType==="mcp")&&c;(i.actionInfo?.actionType||!u)&&(s.currentRuntimeActionType=i.actionInfo?.actionType,s.currentRuntimeActionLabel=i.actionInfo?.actionLabel,s.currentRuntimeActionDetail=i.actionInfo?.actionDetail,s.currentRuntimeActionInput=i.actionInfo?.actionInput),m.info(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),Tt(t,{runtimeStatus:i.status,runtimeActionType:s.currentRuntimeActionType,runtimeActionLabel:s.currentRuntimeActionLabel,runtimeActionDetail:s.currentRuntimeActionDetail});const l=i.actionInfo?.actionType?i.actionInfo:s.currentRuntimeActionType?{actionType:s.currentRuntimeActionType,actionLabel:s.currentRuntimeActionLabel??"",actionDetail:s.currentRuntimeActionDetail,actionInput:s.currentRuntimeActionInput}:void 0;if(i.status==="compacting"){const g=(ae.get(t)??Promise.resolve()).then(async()=>{for(let h=0;h<=2;h++){if(await _(s.agentId,t,i.status,l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;h<2&&(m.warn(`[${n.displayName}] compaction sendStatus attempt ${h+1} failed (HTTP), retrying in ${1e3*(h+1)}ms...`),await new Promise(C=>setTimeout(C,1e3*(h+1))))}m.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{m.warn(`[${n.displayName}] compaction status chain error:`,T)});ae.set(t,g),g.finally(()=>{ae.get(t)===g&&ae.delete(t)})}else{const f=u&&!i.actionInfo?.actionType;if(l?.actionType==="idle"||s.currentRuntimeActionType==="idle"&&u){const h=(ce.get(t)??Promise.resolve()).then(async()=>{for(let C=0;C<=2;C++){if(await _(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;C<2&&await new Promise(M=>setTimeout(M,1e3*(C+1)))}m.warn(`[${n.displayName}] idle tool sendStatus failed after 3 attempts, status may be stale (frontend will fall back to timeline tool_use event)`)}).catch(y=>{m.warn(`[${n.displayName}] idle status chain error:`,y)});ce.set(t,h),h.finally(()=>{ce.get(t)===h&&ce.delete(t)})}else _(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}if(i.status==="waiting_input"&&s.cachedCapabilitiesActionDetail){const f=s.cachedCapabilitiesActionDetail;s.cachedCapabilitiesActionDetail=void 0,m.info(`[${n.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${s.agentId} (session stabilized to waiting_input)`),_(s.agentId,t,"waiting_input",{actionType:"runtime_capabilities",actionLabel:"\u8FD0\u884C\u65F6\u80FD\u529B",actionDetail:f},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const r=p.get(t.sessionId);r&&(m.info(`[${n.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),yt(r.agentId,t.sessionId,Array.isArray(t.questions)?t.questions:[],{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.toolCallId))}),e.on("tool-permission-request",t=>{const r=p.get(t.sessionId);r&&t.requestId&&(m.info(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${r.agentId}`),ht(r.agentId,t.sessionId,{requestId:t.requestId,capability:t.capability,...t.detail||{}},{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}))}),e.on("permission-request",t=>{const r=p.get(t.sessionId);if(r){m.info(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${r.agentId}`);const o=t.toolInput?v(JSON.stringify(t.toolInput).slice(0,400)):void 0;_(r.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail:o||t.toolName},void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl})}})}S.post("/start",I,async(e,n)=>{const{agentId:t,workspacePath:r,mode:o="sdk"}=e.body||{};if(!t||!r){n.status(400).json({error:"agentId and workspacePath are required"});return}const s=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||_e(Re(e))||void 0;dt({agentId:String(t),workspacePath:String(r),serverUrl:e.body?.serverUrl||s,runtimeAccessToken:e.body?.runtimeAccessToken,userId:e.body?.userId,schedulerBaseUrl:s}),e.body?.runtimeFeatures!==null&&e.body?.runtimeFeatures!==void 0&&(st(String(t),e.body.runtimeFeatures),m.info(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(at(String(t)))}`)),e.body?.capabilities!==void 0&&it(String(t),e.body.capabilities),e.body?.envVars!==null&&e.body?.envVars!==void 0&&typeof e.body.envVars=="object"&&(lt(e.body.envVars),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u9762\u677F\u73AF\u5883\u53D8\u91CF: ${Object.keys(e.body.envVars).length} \u9879 \u2192 \u684C\u9762\u5DE5\u5177\u5B50\u8FDB\u7A0B`)),e.body?.changeCacheRetentionDays!==void 0&&(tt(e.body.changeCacheRetentionDays),m.info(`[Runtime] agent ${t} \u4E0B\u53D1\u53D8\u66F4\u7F13\u5B58\u4FDD\u7559\u5929\u6570: ${e.body.changeCacheRetentionDays??"\u4E0D\u6E05\u7406"}`)),o&&o!=="sdk"&&console.warn(`[Runtime] Unsupported runtime mode "${o}" requested for agent ${t}; starting SDK session instead.`),await wn(e,n)});async function wn(e,n){const{agentId:t,workspacePath:r,command:o,autoAccept:s=!0,initialPrompt:i,systemPrompt:a,globalPrompt:c,rolePrompt:d,memory:u,mcpConfigPath:l,extraMcpServers:f,envOverrides:g,idleInputAutoCommand:T,nonInputAutoCommand:h,model:y,instanceAiConfig:C,subAgentModel:$,subAgentEffort:M,scopeKey:Ae,browserAllowPrivate:Te}=e.body||{},H=bt();H.log({level:"info",category:"launch",message:"startSdkSession: \u6536\u5230\u542F\u52A8\u8BF7\u6C42",source:"bridge",agentId:String(t||"").trim()||void 0,details:{reqBodyKeys:Object.keys(e.body||{}),perInstanceAiConfig:C?te(C):null,perAgentModel:y??null}});let D=null;const A=String(t||"").trim(),le=String(e.body?.runtimeAccessToken||"").trim()||void 0,O=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||_e(Re(e))||void 0;O?m.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${O} (agentId=${A})`):m.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(kn(),!A){n.status(400).json({error:"agentId is required"});return}const N=Be(A);if(N){n.json(await Kt(N));return}const k=await It(A);if(k){const R=zt(k);if(!R.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${k.sessionId}, reason=${R.reason}`),await K(k.sessionId);else{const P=se(k.runtimeStatus,k.runtimeStatus,k.runtimeActionType);n.json({sessionId:k.sessionId,status:P,runtimeStatus:P,runtimeActionType:k.runtimeActionType,runtimeActionLabel:k.runtimeActionLabel,runtimeActionDetail:k.runtimeActionDetail,agentId:k.agentId,workspacePath:k.workspacePath,command:k.command,mode:k.mode||"sdk",pid:k.pid,reused:!0,persistedOnly:!0});return}}if(z.has(A)){n.status(409).json({error:"SDK session is already starting for this agent"});return}z.add(A);const E=Ke(o),He=b.get(E);D=Ge();const We=E==="claude-code"?await Gt():null,Y=Ne(E==="claude-code"?We:null,g),W=E==="acode"?y?String(y).trim():void 0:(()=>{const R=y?String(y).trim():void 0,P=Y.model?String(Y.model).trim():void 0;return R||P})();H.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:D??void 0,details:{perAgentModel:y??null,globalModel:Y.model??null,resolvedModel:W??null,providerId:E,note:E==="acode"?"adapter handles full priority":"request > global"}});const me={...Y.envOverrides};W&&(me.ANTHROPIC_MODEL=W,me.CODEX_MODEL=W);let X,fe=l;if(E==="acode"){const R=C||{},P=await ot({apiOverrides:Ee(R)??void 0,agentId:A,sessionId:D??void 0,runtimeBridgeBaseUrl:O});X=P.instanceConfig.config,fe=P.perInstanceConfigPath,H.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:D??void 0,details:{sanitizedApiOverrides:(()=>{const j=Ee(R);return j?te(j):null})(),resolvedInstanceAiConfig:X?te(X):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let ke=a||void 0,pe,ge,Z;if(E==="acode")if(pe=typeof c=="string"&&c.trim()||void 0,ge=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())Z=u.trim();else{const R=await Dt(r,{schedulerBaseUrl:O,runtimeAccessToken:le,agentId:A});R&&(Z=R,m.info(`[startSdkSession] Auto-loaded memories for ACode agent ${A}`))}else if(typeof c=="string"&&c.trim()||typeof d=="string"&&d.trim()||typeof u=="string"&&u.trim()){const P=[c,d,u,a].filter(j=>typeof j=="string"&&j.trim().length>0).map(j=>j.trim());ke=P.length>0?P.join(`
|
|
52
52
|
|
|
53
|
-
`):void 0}const U={command:r||"acode",workingDirectory:o,agentId:A,...Te?{scopeKey:Te}:{},...typeof ke=="boolean"?{browserAllowPrivate:ke}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:be,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Y!==void 0?{memory:Y}:{},model:H,mcpConfigPath:fe,...W?{instanceAiConfig:W}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:m||{},envOverrides:Oe(String(t),String(o),process.env,me)};z.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await z.flush(),f.set(D,{agentId:A,workspacePath:o,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:B}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:o,command:U.command,mode:"sdk"}),Cn({sessionId:D,agentId:A,config:U,adapter:He,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:y,runtimeAccessToken:le,requestedSchedulerBaseUrl:B})}catch(O){if(D&&(L(D),f.delete(D),v(D)),A&&K.delete(A),!n.headersSent){const k=O instanceof Error?O.message:String(O);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function Cn(e){const{sessionId:n,agentId:t,config:o,adapter:r,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await r.startSession(n,o),(i||a)&&r.setIdleCommands?.(n,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(Pt(s))try{if(await new Promise(m=>setTimeout(m,500)),u=r.getSessionPid?.(n),!u){const p=(await mt()).find(T=>T.agentId===t||T.cwd===o.workingDirectory||T.command.includes(o.workingDirectory));p&&(u=p.pid,console.log(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(m){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,m)}const l=se(r.getSessionStatus(n),f.get(n)?.currentRuntimeStatus,f.get(n)?.currentRuntimeActionType);await kt({sessionId:n,agentId:t,workspacePath:o.workingDirectory,command:o.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:r.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:o.workingDirectory,command:o.command}),await _n({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(n),f.delete(n),v(n),await F(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await $n({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{K.delete(t)}}async function _n(e){const{agentId:n,sessionId:t,sdkPid:o,status:r,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){h.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(a,{agentId:n,sessionId:t,status:r,pid:o},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${r}`)}catch(c){const d=c instanceof Error?c.message:String(c);h.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function $n(e){const{agentId:n,sessionId:t,schedulerBaseUrl:o,runtimeAccessToken:r}=e;if(!o||!r)return;const s=`${o.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await we.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":r,"Content-Type":"application/json"},timeout:5e3}),h.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);h.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}S.post("/sdk/message",I,async(e,n)=>{const{sessionId:t,message:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and message are required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await b.get(s).sendMessage(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/answer",I,async(e,n)=>{const{sessionId:t,answers:o}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and answers are required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code",i=b.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/tool-auth/answer",I,async(e,n)=>{const{sessionId:t,requestId:o,allowed:r}=e.body||{};if(!t||!o){n.status(400).json({error:"sessionId and requestId are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(!a.submitToolPermissionDecision){n.status(400).json({error:"adapter does not support tool authorization"});return}const c=a.submitToolPermissionDecision(t,String(o),!!r);n.json({ok:!0,existed:c})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.get("/tool-auth/pending/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=b.get(r).getPendingToolAuthRequests?.(t)??[];n.json({ok:!0,sessionId:t,agentId:o.agentId,pendingRequests:i,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/sdk/confirm",I,async(e,n)=>{const{sessionId:t,accept:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const s=r.providerId||"claude-code";await b.get(s).sendConfirmation(t,!!o),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/abort",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code";await b.get(r).abortCurrentTurn(t),n.json({ok:!0})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/sdk/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.json({ok:!0,status:"stopped"});return}try{const r=o.providerId||"claude-code",s=b.get(r);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),L(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(o.agentId),await _(o.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}),n.json({ok:!0,status:"stopped"})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/status/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",s=b.get(r),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:o.agentId,workspacePath:o.workspacePath,messageCount:a.length})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/capabilities/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=b.get(r).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,capabilities:i,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.get("/sdk/pending-questions/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const o=f.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const r=o.providerId||"claude-code",i=b.get(r).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:o.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/command",I,async(e,n)=>{const{sessionId:t,command:o}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and command are required"});return}try{const r=await Xt(String(t),o);n.json({ok:!0,mode:"terminal",...r})}catch(r){const s=r instanceof Error?r.message:String(r);n.status(500).json({error:s})}}),S.post("/input",I,async(e,n)=>{const{sessionId:t,input:o,mode:r}=e.body||{};if(!t||o===void 0||o===null){n.status(400).json({error:"sessionId and input are required"});return}const s=f.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(r==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(o)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Vt(o)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.post("/update-auto-commands",I,async(e,n)=>{const{agentId:t,idleInputAutoCommand:o="",nonInputAutoCommand:r=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...f.values()].find(c=>c.agentId===s),a={idleInputCommand:String(o||""),nonInputCommand:String(r||"")};try{let c=!1;i&&(b.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await At(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),S.post("/resize",I,(e,n)=>{const{sessionId:t,cols:o,rows:r}=e.body||{};if(!t||!o||!r){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!f.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(o),rows:Number(r)})}),S.post("/reset-context",I,async(e,n)=>{const{sessionId:t,reason:o}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}const s=r.providerId||"claude-code",i=b.get(s),a=i.resetContext?.bind(i),c=Rt(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),r.currentRuntimeStatus,r.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:r.agentId,mode:"sdk",providerId:s,reason:typeof o=="string"&&o.trim()?o.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),S.post("/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{},o=Et(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const r=f.get(t);if(!r){await F(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:o.reason});return}const s=r.agentId;try{console.log(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!o.statusNotified}, reason=${o.reason||"unspecified"}`);const i=r.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),L(t),f.delete(t),v(t),ie(t),await F(t),await he().removeProcess(s),o.statusNotified?await _(s,null,"stopped",void 0,void 0,{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl}):console.log(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${o.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:o.statusNotified,reason:o.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),S.post("/stop-all",I,async(e,n)=>{const t=[],o=[];for(const[r,s]of f.entries())try{const i=s.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(r).catch(()=>{}),await a.terminateSession(r),L(r),f.delete(r),v(r),ie(r),t.push(r),await _(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);o.push(`SDK ${r}: ${a}`)}try{await St([]),console.log("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(r){const s=r instanceof Error?r.message:String(r);o.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:o.length>0?o:void 0})}),S.get("/events/last/:n",I,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const o=Re.getLastN(t);n.json({ok:!0,count:o.length,entries:o})}),S.get("/events/since/:index",I,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const o=Re.getSinceIndex(t);n.json({ok:!0,entries:o.entries,nextIndex:o.nextIndex,oldestIndex:o.oldestIndex,dataLoss:o.oldestIndex>t+1})}),S.get("/events/push-stats",I,(e,n)=>{const t=nt();n.json({ok:!0,count:t.length,agents:t})});export{xt as buildAcodeCommandOutputPath,Ne as buildClaudeCodeLaunchConfig,Oe as buildRuntimeEnv,nn as buildSdkOutputMetadata,en as buildToolResultTimelineActionInfo,to as cleanupSdkSessionByAgentId,Ut as countTerminalOutputLines,je as createTerminalOutputDecoder,re as decodeTerminalOutputChunk,zt as evaluatePersistedSessionReuse,Bt as formatCommandInactivityTimeoutNotice,jt as formatCommandOutputSpilloverNotice,tn as formatSdkOutputEvent,Se as formatTerminalPrompt,Ot as normalizeTerminalCommandInput,Et as parseRuntimeStopOptions,vt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Rt as resolveRuntimeContextResetSupport,hn as resolveRuntimeStatusFromProviderEvent,Vt as resolveSdkInputMessage,Ke as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,Mt as resolveStatusChangeRuntimeState,oe as resolveStatusChangeUsage,Nt as resolveTerminalOutputEncoding,f as sdkSessions,Pt as shouldProbeSdkProcessPid,S as terminalRouter};
|
|
53
|
+
`):void 0}const U={command:o||"acode",workingDirectory:r,agentId:A,...Ae?{scopeKey:Ae}:{},...typeof Te=="boolean"?{browserAllowPrivate:Te}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:ke,...pe!==void 0?{globalPrompt:pe}:{},...ge!==void 0?{rolePrompt:ge}:{},...Z!==void 0?{memory:Z}:{},model:W,mcpConfigPath:fe,...X?{instanceAiConfig:X}:{},...typeof $=="string"&&$.trim()?{subAgentModel:$.trim()}:{},...typeof M=="string"&&M.trim()?{subAgentEffort:M.trim()}:{},extraMcpServers:f||{},envOverrides:Oe(String(t),String(r),process.env,me)};H.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:D,details:{adapterModel:U.model??null,adapterInstanceAiConfig:U.instanceAiConfig?te(U.instanceAiConfig):null,adapterMcpConfigPath:U.mcpConfigPath??null}}),await H.flush(),p.set(D,{agentId:A,workspacePath:r,sessionId:D,config:U,providerId:E,seq:0,runtimeAccessToken:le,schedulerBaseUrl:O}),n.json({sessionId:D,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:r,command:U.command,mode:"sdk"}),Cn({sessionId:D,agentId:A,config:U,adapter:He,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:h,runtimeAccessToken:le,requestedSchedulerBaseUrl:O})}catch(N){if(D&&(x(D),p.delete(D),F(D)),A&&z.delete(A),!n.headersSent){const k=N instanceof Error?N.message:String(N);n.status(500).json({error:`Failed to start SDK session: ${k}`})}}}async function Cn(e){const{sessionId:n,agentId:t,config:r,adapter:o,providerId:s,idleInputAutoCommand:i,nonInputAutoCommand:a,runtimeAccessToken:c,requestedSchedulerBaseUrl:d}=e;try{await o.startSession(n,r),(i||a)&&o.setIdleCommands?.(n,{idleInputCommand:i||"",nonInputCommand:a||""});let u;if(Pt(s))try{if(await new Promise(f=>setTimeout(f,500)),u=o.getSessionPid?.(n),!u){const g=(await mt()).find(T=>T.agentId===t||T.cwd===r.workingDirectory||T.command.includes(r.workingDirectory));g&&(u=g.pid,m.info(`[Runtime] Found SDK process PID: ${u} for agentId=${t}`))}}catch(f){console.warn(`[Runtime] Failed to get SDK PID for agentId=${t}:`,f)}const l=se(o.getSessionStatus(n),p.get(n)?.currentRuntimeStatus,p.get(n)?.currentRuntimeActionType);await kt({sessionId:n,agentId:t,workspacePath:r.workingDirectory,command:r.command,startedAt:new Date().toISOString(),status:"running",runtimeStatus:l,mode:"sdk",pid:u,providerSessionId:o.getProviderSessionId(n)}),u&&await he().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await _n({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){x(n),p.delete(n),F(n),await K(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await $n({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{z.delete(t)}}async function _n(e){const{agentId:n,sessionId:t,sdkPid:r,status:o,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){m.debug(`[Runtime] notifyServerSessionReady skipped: missing schedulerBaseUrl or runtimeAccessToken for agentId=${n}`);return}const a=`${s.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(a,{agentId:n,sessionId:t,status:o,pid:r},{headers:{"X-Runtime-Token":i,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${o}`)}catch(c){const d=c instanceof Error?c.message:String(c);m.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function $n(e){const{agentId:n,sessionId:t,schedulerBaseUrl:r,runtimeAccessToken:o}=e;if(!r||!o)return;const s=`${r.replace(/\/+$/,"")}/api/runtime/callback/status`;try{await be.post(s,{agentId:n,sessionId:t,status:"stopped"},{headers:{"X-Runtime-Token":o,"Content-Type":"application/json"},timeout:5e3}),m.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);m.warn(`[Runtime] Failed to notify server session failed: agentId=${n}, error=${a}`)}}S.post("/sdk/message",I,async(e,n)=>{const{sessionId:t,message:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and message are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendMessage(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/answer",I,async(e,n)=>{const{sessionId:t,answers:r}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and answers are required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code",i=b.get(s);i.sendQuestionAnswer&&await i.sendQuestionAnswer(t,r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/tool-auth/answer",I,async(e,n)=>{const{sessionId:t,requestId:r,allowed:o}=e.body||{};if(!t||!r){n.status(400).json({error:"sessionId and requestId are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(!a.submitToolPermissionDecision){n.status(400).json({error:"adapter does not support tool authorization"});return}const c=a.submitToolPermissionDecision(t,String(r),!!o);n.json({ok:!0,existed:c})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.get("/tool-auth/pending/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingToolAuthRequests?.(t)??[];n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingRequests:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/confirm",I,async(e,n)=>{const{sessionId:t,accept:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}try{const s=o.providerId||"claude-code";await b.get(s).sendConfirmation(t,!!r),n.json({ok:!0})}catch(s){const i=s instanceof Error?s.message:String(s);n.status(500).json({error:i})}}),S.post("/sdk/abort",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code";await b.get(o).abortCurrentTurn(t),n.json({ok:!0})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/sdk/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.json({ok:!0,status:"stopped"});return}try{const o=r.providerId||"claude-code",s=b.get(o);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),x(t),p.delete(t),F(t),ie(t),await K(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(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/status/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",s=b.get(o),i=s.getSessionStatus(t),a=s.getConversation(t);n.json({sessionId:t,status:i,agentId:r.agentId,workspacePath:r.workspacePath,messageCount:a.length})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/capabilities/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getCapabilities?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,capabilities:i,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.get("/sdk/pending-questions/:sessionId",I,(e,n)=>{const t=e.params.sessionId;if(!t){n.status(400).json({error:"sessionId is required"});return}const r=p.get(t);if(!r){n.status(404).json({error:"SDK session not found"});return}try{const o=r.providerId||"claude-code",i=b.get(o).getPendingQuestion?.(t)??null;n.json({ok:!0,sessionId:t,agentId:r.agentId,pendingQuestion:i?{toolCallId:i.toolCallId,questions:i.questions}:null,fetchedAt:Date.now()})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/command",I,async(e,n)=>{const{sessionId:t,command:r}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and command are required"});return}try{const o=await Xt(String(t),r);n.json({ok:!0,mode:"terminal",...o})}catch(o){const s=o instanceof Error?o.message:String(o);n.status(500).json({error:s})}}),S.post("/input",I,async(e,n)=>{const{sessionId:t,input:r,mode:o}=e.body||{};if(!t||r===void 0||r===null){n.status(400).json({error:"sessionId and input are required"});return}const s=p.get(t);if(!s){n.status(404).json({error:"SDK session not found"});return}try{const i=s.providerId||"claude-code",a=b.get(i);if(o==="shortcut"){if(!a.sendShortcutInput){n.status(400).json({error:"shortcut input is not supported by this SDK provider"});return}await a.sendShortcutInput(t,String(r)),n.json({ok:!0,mode:"shortcut"});return}await a.sendMessage(t,await Vt(r)),n.json({ok:!0,mode:"sdk"})}catch(i){const a=i instanceof Error?i.message:String(i);n.status(500).json({error:a})}}),S.post("/update-auto-commands",I,async(e,n)=>{const{agentId:t,idleInputAutoCommand:r="",nonInputAutoCommand:o=""}=e.body||{},s=String(t||"").trim();if(!s){n.status(400).json({error:"agentId is required"});return}const i=[...p.values()].find(c=>c.agentId===s),a={idleInputCommand:String(r||""),nonInputCommand:String(o||"")};try{let c=!1;i&&(b.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await At(s,{idleInputAutoCommand:a.idleInputCommand,nonInputAutoCommand:a.nonInputCommand});n.json({ok:!0,mode:"sdk",sessionUpdated:c,persistedUpdated:d})}catch(c){const d=c instanceof Error?c.message:String(c);n.status(500).json({ok:!1,mode:"sdk",error:d})}}),S.post("/resize",I,(e,n)=>{const{sessionId:t,cols:r,rows:o}=e.body||{};if(!t||!r||!o){n.status(400).json({error:"sessionId, cols, rows are required"});return}if(!p.has(t)){n.status(404).json({error:"SDK session not found"});return}n.json({ok:!0,mode:"sdk",noop:!0,cols:Number(r),rows:Number(o)})}),S.post("/reset-context",I,async(e,n)=>{const{sessionId:t,reason:r}=e.body||{};if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){n.status(404).json({error:"SDK session not found"});return}const s=o.providerId||"claude-code",i=b.get(s),a=i.resetContext?.bind(i),c=Rt(s,!!a);if(!c.supported){n.status(c.statusCode).json({error:c.error});return}if(!a){n.status(500).json({error:"ACode adapter does not expose resetContext"});return}try{await a(String(t));const d=se(i.getSessionStatus(String(t)),o.currentRuntimeStatus,o.currentRuntimeActionType);n.json({ok:!0,contextReset:!0,sessionId:t,status:d,runtimeStatus:d,agentId:o.agentId,mode:"sdk",providerId:s,reason:typeof r=="string"&&r.trim()?r.trim():void 0})}catch(d){const u=d instanceof Error?d.message:String(d);n.status(500).json({ok:!1,contextReset:!1,mode:"sdk",error:u})}}),S.post("/stop",I,async(e,n)=>{const{sessionId:t}=e.body||{},r=Et(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){await K(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const s=o.agentId;try{m.info(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=o.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),x(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(s),r.statusNotified?await _(s,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}):m.info(`[Runtime] Stopped status notification suppressed for SDK session ${t}; reason=${r.reason||"unspecified"}`),n.json({ok:!0,status:"stopped",mode:"sdk",statusNotified:r.statusNotified,reason:r.reason})}catch(i){const a=i instanceof Error?i.message:String(i);console.error(`[Runtime] Failed to terminate SDK session ${t}:`,a),n.status(500).json({ok:!1,status:"stop_failed",mode:"sdk",error:a})}}),S.post("/stop-all",I,async(e,n)=>{const t=[],r=[];for(const[o,s]of p.entries())try{const i=s.providerId||"claude-code",a=b.get(i);a.abortCurrentTurn(o).catch(()=>{}),await a.terminateSession(o),x(o),p.delete(o),F(o),ie(o),t.push(o),await _(s.agentId,null,"stopped",void 0,void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}catch(i){const a=i instanceof Error?i.message:String(i);r.push(`SDK ${o}: ${a}`)}try{await St([]),m.info("[Runtime] \u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD")}catch(o){const s=o instanceof Error?o.message:String(o);r.push(`Persistence: ${s}`)}n.json({ok:!0,stopped:{sdk:t.length},errors:r.length>0?r:void 0})}),S.get("/events/last/:n",I,(e,n)=>{const t=parseInt(e.params.n,10);if(!Number.isFinite(t)||t<1){n.status(400).json({error:":n must be a positive integer"});return}const r=De.getLastN(t);n.json({ok:!0,count:r.length,entries:r})}),S.get("/events/since/:index",I,(e,n)=>{const t=parseInt(e.params.index,10);if(!Number.isFinite(t)||t<0){n.status(400).json({error:":index must be a non-negative integer"});return}const r=De.getSinceIndex(t);n.json({ok:!0,entries:r.entries,nextIndex:r.nextIndex,oldestIndex:r.oldestIndex,dataLoss:r.oldestIndex>t+1})}),S.get("/events/push-stats",I,(e,n)=>{const t=nt();n.json({ok:!0,count:t.length,agents:t})});export{Lt as buildAcodeCommandOutputPath,Ne as buildClaudeCodeLaunchConfig,Oe as buildRuntimeEnv,nn as buildSdkOutputMetadata,en as buildToolResultTimelineActionInfo,er as cleanupSdkSessionByAgentId,Ut as countTerminalOutputLines,je as createTerminalOutputDecoder,oe as decodeTerminalOutputChunk,zt as evaluatePersistedSessionReuse,Bt as formatCommandInactivityTimeoutNotice,jt as formatCommandOutputSpilloverNotice,tn as formatSdkOutputEvent,Ie as formatTerminalPrompt,Ot as normalizeTerminalCommandInput,Et as parseRuntimeStopOptions,vt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Rt as resolveRuntimeContextResetSupport,hn as resolveRuntimeStatusFromProviderEvent,Vt as resolveSdkInputMessage,Ke as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,Mt as resolveStatusChangeRuntimeState,re as resolveStatusChangeUsage,Nt as resolveTerminalOutputEncoding,p as sdkSessions,Pt as shouldProbeSdkProcessPid,S as terminalRouter};
|
|
54
54
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{cpSync as v,existsSync as y,lstatSync as S,mkdirSync as
|
|
1
|
+
import{cpSync as v,existsSync as y,lstatSync as S,mkdirSync as D,readdirSync as g,realpathSync as d,rmSync as l,symlinkSync as p}from"node:fs";import o from"node:path";import{getBridgeDataHome as E,getBridgeInstanceSkillsDir as h,getBridgeTemplateSkillsDir as b}from"../config.js";import{createLogger as L}from"../utils/logger.js";import{isCapabilityEnabled as w}from"./instance-features.js";const f=L("agent-capability-sync"),j=process.platform==="win32"?"junction":"dir";function z(){return o.join(E(),"instance-runtime")}function x(t){return h(t)}function T(){return o.join(b(),"deployed")}function B(){return b()}function F(){const t=new Map,r=[B(),T()].filter(e=>e&&e.length>0);for(const e of r){if(!y(e))continue;let s=[];try{s=g(e)}catch{continue}for(const n of s){if(n.startsWith("."))continue;const i=o.join(e,n);try{if(!y(o.join(i,"SKILL.md")))continue;t.set(n,i)}catch{continue}}}return{sources:t}}function k(t,r){try{p(t,r,j)}catch(e){if(e.code==="EEXIST")try{if(S(r).isSymbolicLink()){l(r,{recursive:!0,force:!0}),p(t,r,j);return}f.warn("[farm] \u6280\u80FD\u540D %s \u4E0E\u519C\u573A\u4E2D\u771F\u5B9E\u76EE\u5F55\u51B2\u7A81\uFF0C\u8DF3\u8FC7\uFF08\u4FDD\u7559\u7528\u6237\u76EE\u5F55\uFF09: %s",o.basename(r),r);return}catch{}f.warn("[farm] junction \u5931\u8D25\uFF0C\u56DE\u9000\u590D\u5236 %s \u2192 %s: %s",t,r,e instanceof Error?e.message:String(e));try{let n=!1;try{n=S(r).isSymbolicLink()}catch{n=!1}const i=y(r);if(i&&!n){f.warn("[farm] \u56DE\u9000\u590D\u5236\u76EE\u6807\u4E3A\u771F\u5B9E\u76EE\u5F55\uFF0C\u8DF3\u8FC7\uFF08\u4FDD\u7559\u7528\u6237\u76EE\u5F55\uFF09: %s",r);return}i&&n&&l(r,{recursive:!0,force:!0}),v(t,r,{recursive:!0})}catch(n){f.error("[farm] \u590D\u5236\u56DE\u9000\u4E5F\u5931\u8D25 %s: %s",r,n instanceof Error?n.message:String(n))}}}function A(t,r){try{return o.resolve(d(t))===o.resolve(d(r))}catch{return!1}}function G(t){if(!t)return null;const r=x(t);try{const{sources:e}=F();D(r,{recursive:!0});const s=new Set;let n=[];try{n=g(r)}catch{n=[]}for(const c of n){const a=o.join(r,c);try{S(a).isSymbolicLink()&&s.add(c)}catch{continue}}let i=0,m=0;for(const[c,a]of e){const u=o.join(r,c);if(w(t,"skills",c))s.has(c)?A(u,a)||(l(u,{recursive:!0,force:!0}),k(a,u),i++):(k(a,u),i++);else if(s.has(c))try{l(u,{recursive:!0,force:!0}),m++}catch{}}for(const c of s)if(!e.has(c))try{l(o.join(r,c),{recursive:!0,force:!0}),m++}catch{}return(i>0||m>0)&&f.info("[farm] agent=%s \u6280\u80FD\u519C\u573A\u5DF2\u540C\u6B65: +%d \u94FE\u63A5, -%d \u53D6\u6D88\u94FE\u63A5 (\u5171 %d \u9879)",t,i,m,e.size),r}catch(e){return f.warn("[farm] agent=%s \u6280\u80FD\u519C\u573A\u540C\u6B65\u5931\u8D25\uFF08\u56DE\u9000\u5168\u5C40\u6280\u80FD\u76EE\u5F55\uFF09: %s",t,e instanceof Error?e.message:String(e)),null}}export{x as getAgentSkillsFarmDir,z as getSkillFarmRoot,G as syncAgentSkillFarm};
|
|
2
2
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{promises as u}from"node:fs";import d from"node:path";import{
|
|
1
|
+
import{promises as u}from"node:fs";import d from"node:path";import{getBridgeTemplateConfigFile as y,getClaudeConfigFile as v,getCodexConfigFile as w,getOpencodeConfigFile as A,getUserHomeDir as b}from"../config.js";function z(){const o=d.resolve(b());return new T({acodeConfigFile:d.resolve(y()),claudecodeConfigFile:d.resolve(v(o)),codexConfigFile:d.resolve(w(o)),opencodeConfigFile:d.resolve(A(o))})}function x(o){const e=new Set,i=n=>{const r=String(n||"").trim();r&&e.add(r)};return Array.isArray(o.models)&&o.models.forEach(i),i(o.model),[...e]}async function m(o,e){try{const i=await u.readFile(o,"utf-8"),n=JSON.parse(i);return n&&typeof n=="object"&&!Array.isArray(n)?n:{...e}}catch{return{...e}}}async function C(o,e){const i=d.dirname(o);await u.mkdir(i,{recursive:!0}),await u.writeFile(o,JSON.stringify(e,null,2),"utf-8")}function p(o,e){if(!e||typeof e!="object"||Array.isArray(e))return o;const i={...o};for(const[n,r]of Object.entries(e))r!==void 0&&(r!==null&&typeof r=="object"&&!Array.isArray(r)&&i[n]!==null&&typeof i[n]=="object"&&!Array.isArray(i[n])?i[n]=p(i[n],r):i[n]=r);return i}function F(o){return h(o)}function a(o){return String(o||"").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function _(o){const e=String(o||"").trim();return e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"):e}function O(o){const e=String(o||"").trim().toLowerCase();if(e==="true")return!0;if(e==="false")return!1}function S(o){const e={model_providers:{}};let i=null;for(const n of o.split(/\r?\n/)){const r=n.trim();if(!r||r.startsWith("#"))continue;const s=r.match(/^\[model_providers\.([^\]]+)\]$/);if(s){i=s[1],e.model_providers=e.model_providers||{},e.model_providers[i]=e.model_providers[i]||{};continue}if(r.startsWith("[")){i=null;continue}const c=r.match(/^([A-Za-z0-9_-]+)\s*=\s*(.+)$/);if(!c)continue;const[,t,l]=c;if(i){const f=e.model_providers?.[i]||{};if(t==="requires_openai_auth"){const g=O(l);g!==void 0&&(f.requires_openai_auth=g)}else["name","base_url","wire_api","env_key","env_key_instructions"].includes(t)&&(f[t]=_(l));e.model_providers={...e.model_providers||{},[i]:f};continue}["model","model_provider","openai_base_url"].includes(t)&&(e[t]=_(l))}return e}function $(o){const e=[];o.model&&e.push(`model = "${a(o.model)}"`),o.model_provider&&e.push(`model_provider = "${a(o.model_provider)}"`),o.openai_base_url&&e.push(`openai_base_url = "${a(o.openai_base_url)}"`);const i=o.model_providers||{};for(const[n,r]of Object.entries(i))e.push(""),e.push(`[model_providers.${n}]`),r.name&&e.push(`name = "${a(r.name)}"`),r.base_url&&e.push(`base_url = "${a(r.base_url)}"`),r.wire_api&&e.push(`wire_api = "${a(r.wire_api)}"`),r.env_key&&e.push(`env_key = "${a(r.env_key)}"`),r.env_key_instructions&&e.push(`env_key_instructions = "${a(r.env_key_instructions)}"`),r.requires_openai_auth!==void 0&&e.push(`requires_openai_auth = ${r.requires_openai_auth?"true":"false"}`);return`${e.join(`
|
|
2
2
|
`)}
|
|
3
|
-
`}function k(o){let e=String(o.baseUrl||"").trim();const i=String(o.apiKey||"").trim(),n=x(o),r=String(o.model||"").trim()||n[0];if(!e||!i||!r)return null;e&&!e.startsWith("http://")&&!e.startsWith("https://")&&(e=`https://${e}`),e=e.replace(/\/+$/,"");const s=h(e),c=F(e),t=Object.fromEntries(n.map(l=>[l,{name:l,modalities:{input:["text","image"],output:["text"]}}]));return{acode:{provider:{default:{npm:"@ai-sdk/openai-compatible",model:r,options:{baseURL:s,apiKey:i},models:t}}},claudecode:{env:{ANTHROPIC_BASE_URL:e,ANTHROPIC_AUTH_TOKEN:i,ANTHROPIC_MODEL:r}},codex:{model:r,model_provider:"default",model_providers:{default:{name:"Default",base_url:c,wire_api:"responses",env_key:"OPENAI_API_KEY",env_key_instructions:"Set OPENAI_API_KEY in your environment"}}},opencode:{provider:{default:{npm:"@ai-sdk/openai-compatible",model:r,options:{baseURL:s,apiKey:i},models:t}}}}}function h(o){const e=String(o||"").trim().replace(/\/+$/,"");return e&&(e.endsWith("/v1")?e:`${e}/v1`)}class T{constructor(e){this.paths=e}async readClaudeCodeConfig(){return
|
|
3
|
+
`}function k(o){let e=String(o.baseUrl||"").trim();const i=String(o.apiKey||"").trim(),n=x(o),r=String(o.model||"").trim()||n[0];if(!e||!i||!r)return null;e&&!e.startsWith("http://")&&!e.startsWith("https://")&&(e=`https://${e}`),e=e.replace(/\/+$/,"");const s=h(e),c=F(e),t=Object.fromEntries(n.map(l=>[l,{name:l,modalities:{input:["text","image"],output:["text"]}}]));return{acode:{provider:{default:{npm:"@ai-sdk/openai-compatible",model:r,options:{baseURL:s,apiKey:i},models:t}}},claudecode:{env:{ANTHROPIC_BASE_URL:e,ANTHROPIC_AUTH_TOKEN:i,ANTHROPIC_MODEL:r}},codex:{model:r,model_provider:"default",model_providers:{default:{name:"Default",base_url:c,wire_api:"responses",env_key:"OPENAI_API_KEY",env_key_instructions:"Set OPENAI_API_KEY in your environment"}}},opencode:{provider:{default:{npm:"@ai-sdk/openai-compatible",model:r,options:{baseURL:s,apiKey:i},models:t}}}}}function h(o){const e=String(o||"").trim().replace(/\/+$/,"");return e&&(e.endsWith("/v1")?e:`${e}/v1`)}class T{constructor(e){this.paths=e}async readClaudeCodeConfig(){return m(this.paths.claudecodeConfigFile,{})}async readAcodeConfig(){return m(this.paths.acodeConfigFile,{})}async readOpenCodeConfig(){return m(this.paths.opencodeConfigFile,{})}async readCodexConfig(){try{const e=await u.readFile(this.paths.codexConfigFile,"utf-8");return S(e)}catch{return{}}}async writeClaudeCodeConfig(e){await C(this.paths.claudecodeConfigFile,e)}async writeAcodeConfig(e){await C(this.paths.acodeConfigFile,e)}async writeOpenCodeConfig(e){await C(this.paths.opencodeConfigFile,e)}async writeCodexConfig(e){const i=d.dirname(this.paths.codexConfigFile);await u.mkdir(i,{recursive:!0}),await u.writeFile(this.paths.codexConfigFile,$(e),"utf-8")}async applyClaudeCodeConfig(e){const i=await this.readClaudeCodeConfig(),n=p(i,e);return await this.writeClaudeCodeConfig(n),n}async applyOpenCodeConfig(e){const i=await this.readOpenCodeConfig(),n=p(i,e);return await this.writeOpenCodeConfig(n),n}async applyAcodeConfig(e){const i=await this.readAcodeConfig(),n=p(i,e);return await this.writeAcodeConfig(n),n}async applyCodexConfig(e){const i=await this.readCodexConfig(),n=p(i,e);return await this.writeCodexConfig(n),n}async applyAiConfigTemplate(e){const i=k(e);if(!i)return null;const n=await this.applyAcodeConfig(i.acode),r=await this.applyClaudeCodeConfig(i.claudecode),s=await this.applyCodexConfig(i.codex),c=await this.applyOpenCodeConfig(i.opencode);return{acode:n,claudecode:r,codex:s,opencode:c}}}export{T as AiConfigService,k as buildToolSpecificAiConfig,z as createAiConfigService};
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import g from"node:fs";import A from"node:os";import I from"axios";import{v4 as G}from"uuid";import{getActiveBridgeHttpPort as M,getAutoRegisterConfigFilePath as m,schedulerBaseUrl as d}from"../config.js";import{runExclusiveConfigWrite as z}from"../utils/config-write-queue.js";import{logger as i}from"../utils/logger.js";import{clearRuntimeBinding as J,clearScopedRuntimeAccessToken as Y,getRuntimeAccessToken as h,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as q,loadRuntimeBinding as y,normalizeSchedulerBaseUrl as p,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as C}from"./runtime-binding.js";const b={enabled:!1,serverUrl:d,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},u={registered:!1,registrations:{}};let P=[];function Ae(){return[...P]}const H=3e4;function W(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const R=new Map;function L(e){const r=e.serverUrl||d,t=p(r)||r;if(R.has(t))return;const n=setTimeout(()=>{R.delete(t),V(e,t)},W());n.unref?.(),R.set(t,n)}async function V(e,r){try{const t=S().find(n=>(p(n.serverUrl||d)||n.serverUrl||d)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),L(e)}}function Ie(){for(const e of R.values())clearTimeout(e);R.clear()}function f(e){return e==null?void 0:String(e).trim()||void 0}function O(e){return p(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 x(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function k(e){const r=f(e.serverUrl)||f(e.schedulerBaseUrl),t=f(e.connectionKey)||f(e.password);return{enabled:T(e.enabled),serverUrl:r,tenantId:f(e.tenantId),userKey:f(e.userKey),connectionKey:t,instanceName:f(e.instanceName),instanceId:f(e.instanceId),projectId:f(e.projectId),roleName:f(e.roleName),workspacePath:f(e.workspacePath),registerAddr:f(e.registerAddr),registerIp:f(e.registerIp),virtualIp:f(e.virtualIp),tunnel:T(e.tunnel),preferSameLanIp:T(e.preferSameLanIp),maxRetries:x(e.maxRetries),retryInterval:x(e.retryInterval)}}function j(){const e=m();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}`),k(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=m();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=k(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=k(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 F(){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 U(){const e=j(),r=F(),t={...b,...e||{},...r},n=t.instanceName||A.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||d,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=F(),n=(e.length>0?e:[j()||{}]).map(o=>{const s={...b,...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||d,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||A.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 P=n.map(o=>o.connectionKey).filter(o=>!!(o&&o.trim())),n}function Q(){const e=A.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 N(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=N(e),o=N(r),s=N(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=d){return te(e)}function D(e){const r=e||U();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function _(e){const r=M();if(D(e)){const s=e.serverUrl||d;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||d),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 v(){return S()[0]||U()}function Re(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=y();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=q(o);if(s&&s===r)return p(o)}}function se(e){return e?Object.entries(u.registrations).find(([,t])=>t===e)?.[0]:void 0}function E(e,r){const t=se(r);if(t)return t;const n=f(e.serverUrl);if(n&&(n!==d||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=y(),s=f(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||d}async function oe(e){const r=e.instanceName||A.hostname(),t=e.serverUrl||d,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:A.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:_(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 I.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function ie(e,r){const t=m();return z(t,()=>{if(!g.existsSync(t))return;const n=g.readFileSync(t,"utf-8"),o=JSON.parse(n),s=p(e);if(!s)return;let a=!1;const l=c=>{p(String(c.serverUrl||c.schedulerBaseUrl||""))===s&&r&&c.instanceId!==r&&(c.instanceId=r,a=!0)};if(Array.isArray(o.autoRegisterTargets))for(const c of o.autoRegisterTargets)c&&typeof c=="object"&&!Array.isArray(c)&&l(c);else l(o);a&&(g.writeFileSync(t,JSON.stringify(o,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))})}async function ae(e){const r=E(v(),e),t=y(),n=h(r);if(!n)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await I.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":n},timeout:1e4})).data}async function Se(e){const r=e?[{...U(),...e}]:S(),n=(r.length>1?await Promise.all(r.map(s=>$(s))):[await $(r[0]||U())]).every(Boolean),o=r.every(s=>!s.enabled||!s.userKey);if(!e&&(n||o)){const{stopTunnelClientsExcept:s}=await import("./tunnel-client.js");s(r.map(a=>a.serverUrl).filter(a=>!!a))}return n}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 ${m()} \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-${G().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{u.lastAttempt=new Date;const a=await oe(e);if(a.success){if(u.registered=!0,u.instanceId=a.instanceId,a.instanceId&&(u.registrations[e.serverUrl||d]=a.instanceId),u.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{const l=e.serverUrl||d;K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:l});const c=p(a.serverUrl);c&&c!==p(l)&&(C({serverBaseUrl:c,accessToken:a.runtimeAccessToken}),i.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${c})\u4E0E\u8FDE\u63A5\u5730\u5740(${l})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||d,a.instanceId).catch(B=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${B.message}`)})}catch(l){const c=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${c.message}`),u.error=c.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"),c=e.serverUrl||d;l(c,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${c}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),u.error=a.message}catch(a){const l=a,c=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${c}`),u.error=c}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||d}): ${u.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||d}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${u.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${m()} \u6216\u73AF\u5883\u53D8\u91CF`),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(W()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),L(e),!1}async function ve(){const e=v();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=E(e),n=_(e);try{const o=await I.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 ye(e){const r=O(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>O(s.serverUrl)===r)||v();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=_(t);try{const s=await I.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 C({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 Te(){if(!u.registered||!u.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(u.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${u.instanceId}`);const r=E(v(),u.instanceId);y().schedulerBaseUrl&&Y(r),J();try{const{stopTunnelClientForServer:n}=await import("./tunnel-client.js");n(r)}catch(n){i.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${n.message}`)}return u.registered=!1,u.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 Ue(){return{...u}}function _e(){return u.registered}function Ee(){return u.instanceId}async function he(){const e=v(),r=u.instanceId,t=E(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=_(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 I.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{Se as autoRegister,he as bridgeRestartCleanup,Ie as cancelBackgroundRegisterRetries,m as getAutoRegisterConfigFilePath,Ae as getConfiguredConnectionKeys,Ee as getInstanceId,Ue as getRegistrationState,_e as isRegistered,D as isTunnelConfig,U as loadConfig,S as loadConfigs,v as loadPrimaryLifecycleConfig,ve as requestRuntimeAccessTokenRefresh,ye as requestRuntimeAccessTokenRefreshForServer,Re as resolveSchedulerBaseUrlFromToken,Te as unregister};
|
|
1
|
+
import g from"node:fs";import A from"node:os";import I from"axios";import{v4 as G}from"uuid";import{getActiveBridgeHttpPort as M,getAutoRegisterConfigFilePath as m,schedulerBaseUrl as d}from"../config.js";import{runExclusiveConfigWrite as z}from"../utils/config-write-queue.js";import{logger as i}from"../utils/logger.js";import{clearRuntimeBinding as J,clearScopedRuntimeAccessToken as Y,getRuntimeAccessToken as E,getRuntimeBindingPublicState as w,getScopedRuntimeAccessToken as q,loadRuntimeBinding as h,normalizeSchedulerBaseUrl as p,saveRuntimeBinding as K,saveScopedRuntimeAccessToken as C}from"./runtime-binding.js";const P={enabled:!1,serverUrl:d,preferSameLanIp:!0,maxRetries:3,retryInterval:2e3},u={registered:!1,registrations:{}};let b=[];function Ae(){return[...b]}const H=3e4;function W(){const e=Number(process.env.AWS_REGISTER_BACKGROUND_RETRY_INTERVAL);return Number.isFinite(e)&&e>0?e:H}const R=new Map;function L(e){const r=e.serverUrl||d,t=p(r)||r;if(R.has(t))return;const n=setTimeout(()=>{R.delete(t),V(e,t)},W());n.unref?.(),R.set(t,n)}async function V(e,r){try{const t=S().find(n=>(p(n.serverUrl||d)||n.serverUrl||d)===r)||e;await $(t,{backgroundRetry:!0})}catch(t){i.warn(`[AutoRegister] \u540E\u53F0\u91CD\u8BD5\u6CE8\u518C\u5F02\u5E38: ${t.message}`),L(e)}}function Ie(){for(const e of R.values())clearTimeout(e);R.clear()}function f(e){return e==null?void 0:String(e).trim()||void 0}function O(e){return p(e)}function v(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 x(e){if(e==null||e==="")return;const r=Number(e);return Number.isFinite(r)?r:void 0}function k(e){const r=f(e.serverUrl)||f(e.schedulerBaseUrl),t=f(e.connectionKey)||f(e.password);return{enabled:v(e.enabled),serverUrl:r,tenantId:f(e.tenantId),userKey:f(e.userKey),connectionKey:t,instanceName:f(e.instanceName),instanceId:f(e.instanceId),projectId:f(e.projectId),roleName:f(e.roleName),workspacePath:f(e.workspacePath),registerAddr:f(e.registerAddr),registerIp:f(e.registerIp),virtualIp:f(e.virtualIp),tunnel:v(e.tunnel),preferSameLanIp:v(e.preferSameLanIp),maxRetries:x(e.maxRetries),retryInterval:x(e.retryInterval)}}function j(){const e=m();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}`),k(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=m();try{if(!g.existsSync(e))return[];const r=g.readFileSync(e,"utf-8"),t=JSON.parse(r),n=k(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=k(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 F(){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=v(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 T(){const e=j(),r=F(),t={...P,...e||{},...r},n=t.instanceName||A.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||d,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=F(),n=(e.length>0?e:[j()||{}]).map(o=>{const s={...P,...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||d,tenantId:s.tenantId||"",userKey:s.userKey||"",connectionKey:s.connectionKey,instanceName:s.instanceName||A.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=A.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 N(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=N(e),o=N(r),s=N(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=d){return te(e)}function D(e){const r=e||T();return!r.enabled||!r.userKey?!1:r.tunnel===!0?!0:r.tunnel===!1?!1:!r.registerAddr&&!r.registerIp&&!r.virtualIp}function U(e){const r=M();if(D(e)){const s=e.serverUrl||d;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||d),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]||T()}function Re(e){const r=String(e||"").trim();if(!r)return;const t=[];for(const o of S())o?.serverUrl&&t.push(o.serverUrl);const n=h();n.schedulerBaseUrl&&t.push(n.schedulerBaseUrl);for(const o of t){const s=q(o);if(s&&s===r)return p(o)}}function se(e){return e?Object.entries(u.registrations).find(([,t])=>t===e)?.[0]:void 0}function _(e,r){const t=se(r);if(t)return t;const n=f(e.serverUrl);if(n&&(n!==d||process.env.AWS_RUNTIME_SCHEDULER_BASE_URL))return n;const o=h(),s=f(o.schedulerBaseUrl);return o.status==="paired"&&s?s:n||d}async function oe(e){const r=e.instanceName||A.hostname(),t=e.serverUrl||d,n={tenantId:e.tenantId,userKey:e.userKey,instanceId:e.instanceId,instanceName:r,hostname:A.hostname(),virtualIp:e.registerAddr||e.registerIp||e.virtualIp,runtimeBridgeBaseUrl:U(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 I.post(`${t}/api/instances/register`,n,{headers:{"Content-Type":"application/json"},timeout:1e4})).data}function ie(e,r){const t=m();return z(t,()=>{if(!g.existsSync(t))return;const n=g.readFileSync(t,"utf-8"),o=JSON.parse(n),s=p(e);if(!s)return;let a=!1;const l=c=>{p(String(c.serverUrl||c.schedulerBaseUrl||""))===s&&r&&c.instanceId!==r&&(c.instanceId=r,a=!0)};if(Array.isArray(o.autoRegisterTargets))for(const c of o.autoRegisterTargets)c&&typeof c=="object"&&!Array.isArray(c)&&l(c);else l(o);a&&(g.writeFileSync(t,JSON.stringify(o,null,2),"utf-8"),i.info(`[AutoRegister] \u5DF2\u56DE\u5199 instanceId \u5230 config.json (serverUrl=${e})`))})}async function ae(e){const r=_(y(),e),t=E(r);if(!t)throw new Error("runtimeAccessToken is required to unregister bridge instance");return(await I.post(`${r}/api/instances/unregister`,{instanceId:e},{headers:{"Content-Type":"application/json","X-Runtime-Token":t},timeout:1e4})).data}async function Se(e){const r=e?[{...T(),...e}]:S(),n=(r.length>1?await Promise.all(r.map(s=>$(s))):[await $(r[0]||T())]).every(Boolean),o=r.every(s=>!s.enabled||!s.userKey);if(!e&&(n||o)){const{stopTunnelClientsExcept:s}=await import("./tunnel-client.js");s(r.map(a=>a.serverUrl).filter(a=>!!a))}return n}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 ${m()} \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-${G().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{u.lastAttempt=new Date;const a=await oe(e);if(a.success){if(u.registered=!0,u.instanceId=a.instanceId,a.instanceId&&(u.registrations[e.serverUrl||d]=a.instanceId),u.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{const l=e.serverUrl||d;K({accessToken:a.runtimeAccessToken,instanceId:a.instanceId,userId:a.userId,schedulerBaseUrl:l});const c=p(a.serverUrl);c&&c!==p(l)&&(C({serverBaseUrl:c,accessToken:a.runtimeAccessToken}),i.info(`[AutoRegister] \u68C0\u6D4B\u5230 server \u4E0B\u53D1\u5730\u5740(${c})\u4E0E\u8FDE\u63A5\u5730\u5740(${l})\u4E0D\u540C\uFF0C\u5DF2\u6309\u4E24\u4E2A\u5730\u5740\u5206\u522B\u4FDD\u5B58 scoped token`)),i.info("[AutoRegister] \u5DF2\u4FDD\u5B58\u8C03\u5EA6\u4E2D\u5FC3\u4E0B\u53D1\u7684 runtime access token"),a.instanceId&&ie(e.serverUrl||d,a.instanceId).catch(B=>{i.warn(`[AutoRegister] \u56DE\u5199 instanceId \u5230 config.json \u5931\u8D25: ${B.message}`)})}catch(l){const c=l;return i.error(`[AutoRegister] \u4FDD\u5B58 runtime access token \u5931\u8D25: ${c.message}`),u.error=c.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"),c=e.serverUrl||d;l(c,a.instanceId),i.info(`[AutoRegister] \u96A7\u9053\u5BA2\u6237\u7AEF\u5DF2\u542F\u52A8: server=${c}, instanceId=${a.instanceId}`)}return!0}else i.warn(`[AutoRegister] \u6CE8\u518C\u5931\u8D25: ${a.message}`),u.error=a.message}catch(a){const l=a,c=l.response?.data?JSON.stringify(l.response.data):l.message;i.error(`[AutoRegister] \u6CE8\u518C\u8BF7\u6C42\u5931\u8D25 (\u5C1D\u8BD5 ${s}/${n}): ${c}`),u.error=c}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||d}): ${u.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||d}`),i.error(`[AutoRegister] - \u6700\u540E\u9519\u8BEF: ${u.error||"\u672A\u77E5"}`),i.error("[AutoRegister] ========================================"),i.error(`[AutoRegister] \u914D\u7F6E\u6765\u6E90\uFF1A${m()} \u6216\u73AF\u5883\u53D8\u91CF`),i.warn(`[AutoRegister] \u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u6CE8\u518C\uFF08\u6BCF ${Math.round(W()/1e3)} \u79D2\uFF09\uFF0C\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5`)),L(e),!1}async function ye(){const e=y();if(!e.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const r=w(),t=_(e),n=U(e);try{const o=await I.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=E()!==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 ve(e){const r=O(e);if(!r)return{success:!1,error:"serverUrl is required for runtime token refresh"};const t=S().find(s=>O(s.serverUrl)===r)||y();if(!t.userKey)return{success:!1,error:"userKey is required for runtime token refresh"};const n=w(),o=U(t);try{const s=await I.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=E(r)!==s.data.runtimeAccessToken;return C({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 Te(){if(!u.registered||!u.instanceId)return i.info("[AutoRegister] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u65E0\u9700\u6CE8\u9500"),!0;try{const e=await ae(u.instanceId);if(e.success){i.info(`[AutoRegister] \u2713 \u6CE8\u9500\u6210\u529F: ${u.instanceId}`);const r=_(y(),u.instanceId);h().schedulerBaseUrl&&Y(r),J();try{const{stopTunnelClientForServer:n}=await import("./tunnel-client.js");n(r)}catch(n){i.warn(`[AutoRegister] \u6CE8\u9500\u540E\u505C\u6B62\u96A7\u9053\u5931\u8D25: ${n.message}`)}return u.registered=!1,u.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 Ue(){return{...u}}function _e(){return u.registered}function Ee(){return u.instanceId}async function he(){const e=y(),r=u.instanceId,t=_(e,r),n={};if(r&&(n.instanceId=r),e.enabled&&(n.runtimeBridgeBaseUrl=U(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 I.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{Se as autoRegister,he as bridgeRestartCleanup,Ie as cancelBackgroundRegisterRetries,m as getAutoRegisterConfigFilePath,Ae as getConfiguredConnectionKeys,Ee as getInstanceId,Ue as getRegistrationState,_e as isRegistered,D as isTunnelConfig,T as loadConfig,S as loadConfigs,y as loadPrimaryLifecycleConfig,ye as requestRuntimeAccessTokenRefresh,ve as requestRuntimeAccessTokenRefreshForServer,Re as resolveSchedulerBaseUrlFromToken,Te as unregister};
|
|
2
2
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { McpDeploySpec } from "./mcp-deploy.js";
|
|
1
2
|
|
|
2
3
|
export declare const AWS_MCP_SERVER_NAME: string;
|
|
3
4
|
export interface AwsMcpServerConfigInput {
|
|
@@ -29,3 +30,7 @@ export declare function resolveAwsClientAgentMcpCommand(options?: ResolveAwsClie
|
|
|
29
30
|
export declare function getAwsClientAgentMcpPreparedInfo(options?: ResolveAwsClientAgentMcpCommandOptions): AwsMcpPreparedInfo;
|
|
30
31
|
export declare function buildAwsMcpServerConfig(input: AwsMcpServerConfigInput): AwsMcpServerConfig;
|
|
31
32
|
export declare function ensureAwsClientAgentMcpReleased(): void;
|
|
33
|
+
|
|
34
|
+
export declare const BUILTIN_AWS_MCP_SERVER_NAME = "agents-work-studio";
|
|
35
|
+
|
|
36
|
+
export declare function buildBuiltinAwsMcpDeploySpec(): McpDeploySpec;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{createHash as
|
|
2
|
-
`,"utf-8"),i.info(`[runtime-bridge] ${a} MCP \u5DF2\u66F4\u65B0\u5230: ${u}`)):(
|
|
1
|
+
import{createHash as j}from"node:crypto";import{cpSync as l,existsSync as c,lstatSync as L,mkdirSync as U,readdirSync as b,readFileSync as p,realpathSync as S,rmSync as E,statSync as M,symlinkSync as W,writeFileSync as v}from"node:fs";import t from"node:path";import{fileURLToPath as I}from"node:url";import{getActiveBridgeHttpPort as B,getRuntimeHomeDir as D,isDevMode as H,schedulerBaseUrl as O}from"../config.js";import{logger as i}from"../utils/logger.js";import{loadRuntimeBinding as $}from"./runtime-binding.js";const a=H()?"aws-mcp-dev":"aws-mcp",k=["AWS_PROJECT_NAME","AWS_PROMPT","AWS_ROLE_NAME","AWS_SERVER_URL","AWS_MCP_HTTP_URL","AWS_RUNTIME_BRIDGE_BASE_URL","AWS_HEARTBEAT_INTERVAL","AWS_HEARTBEAT_TIMEOUT","PATH","HOME","USERPROFILE","TMP","TEMP","SystemRoot","COMSPEC","PATHEXT","WINDIR"];function R(){const r=I(import.meta.url);return t.resolve(t.dirname(r),"..","..")}function V(r=R()){return t.join(f(r),"dist","index.js")}function f(r){return t.join(r,"package","aws-client-agent-mcp")}function g(){return t.join(D(),".aws-bridge","mcp")}function le(){return t.join(g(),"dist")}function C(r=g()){return t.join(r,".release.json")}function y(r){try{return JSON.parse(p(r,"utf-8")).version||"unknown"}catch{return"unknown"}}function x(r){return y(t.join(r,"package.json"))}function G(r){return y(t.join(f(r),"package.json"))}function m(r,e){c(r)&&F(r,e)}function F(r,e){if(M(r).isDirectory()){l(r,e,{errorOnExist:!1,force:!0,recursive:!0});return}l(r,e,{errorOnExist:!1,force:!0})}function w(r,e){const n=f(r);m(t.join(n,"package.json"),t.join(e,"package.json")),m(t.join(n,"README.md"),t.join(e,"README.md")),m(t.join(n,"package-lock.json"),t.join(e,"package-lock.json"))}function J(r){if(!c(r))return!0;const e=L(r);return e.isSymbolicLink()||e.isDirectory()}function z(r,e){if(!c(r))return!1;try{return S(r)===S(e)}catch{return!1}}function N(r,e){const n=t.join(r,"node_modules"),o=t.join(e,"node_modules");if(!c(n)){i.warn(`[runtime-bridge] ${a} MCP \u672A\u627E\u5230\u4F9D\u8D56\u76EE\u5F55\uFF0Crelease \u4EA7\u7269\u53EF\u80FD\u65E0\u6CD5\u89E3\u6790\u8FD0\u884C\u65F6\u4F9D\u8D56: ${n}`);return}if(!z(o,n)){if(!J(o)){i.warn(`[runtime-bridge] ${a} MCP \u4F9D\u8D56\u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55\u6216\u94FE\u63A5\uFF0C\u5DF2\u4FDD\u7559: ${o}`);return}E(o,{recursive:!0,force:!0}),W(n,o,process.platform==="win32"?"junction":"dir")}}function P(r,e=r){return b(r,{withFileTypes:!0}).flatMap(n=>{const o=t.join(r,n.name);return n.isDirectory()?P(o,e):n.isFile()?[t.relative(e,o).split(t.sep).join("/")]:[]})}function K(r){const e=j("sha256");for(const n of P(r).sort()){const o=t.join(r,...n.split("/")),s=M(o);e.update(n),e.update("\0"),e.update(String(s.size)),e.update("\0"),e.update(p(o)),e.update("\0")}return`sha256:${e.digest("hex")}`}function X(r){try{const e=JSON.parse(p(C(r),"utf-8"));if(typeof e.bridgeVersion=="string"&&typeof e.mcpVersion=="string"&&typeof e.distHash=="string")return{bridgeVersion:e.bridgeVersion,mcpVersion:e.mcpVersion,distHash:e.distHash,releasedAt:typeof e.releasedAt=="string"?e.releasedAt:""}}catch{return null}return null}function Y(r,e,n){return!c(r)||!e||e.bridgeVersion!==n.bridgeVersion||e.mcpVersion!==n.mcpVersion||e.distHash!==n.distHash}function q(r={}){const e=r.packageRoot||R(),n=t.dirname(V(e)),o=t.join(n,"index.js");if(!c(o))return null;if(c(t.join(e,"src")))return i.info(`[runtime-bridge] ${a} MCP \u672C\u5730\u5F00\u53D1\u6A21\u5F0F\uFF0C\u76F4\u63A5\u4F7F\u7528\u9879\u76EE dist: ${o}`),o;const s=r.releasedRoot||g(),u=t.join(s,"dist"),A=t.join(u,"index.js"),_={bridgeVersion:x(e),mcpVersion:G(e),distHash:K(n)},h=X(s);return Y(A,h,_)?(E(u,{recursive:!0,force:!0}),U(s,{recursive:!0}),w(e,s),N(e,s),l(n,u,{errorOnExist:!1,force:!0,recursive:!0}),v(C(s),`${JSON.stringify({..._,releasedAt:r.now?r.now():new Date().toISOString()},null,2)}
|
|
2
|
+
`,"utf-8"),i.info(`[runtime-bridge] ${a} MCP \u5DF2\u66F4\u65B0\u5230: ${u}`)):(w(e,s),N(e,s),i.info(`[runtime-bridge] ${a} MCP \u5DF2\u662F\u6700\u65B0: ${u}`)),A}function Q(){return Object.fromEntries(Object.entries(process.env).filter(r=>typeof r[1]=="string"))}function Z(r){return Object.fromEntries(k.flatMap(e=>{const n=r[e];return typeof n=="string"&&n.length>0?[[e,n]]:[]}))}function ee(r){try{const e=JSON.parse(r);if(Array.isArray(e)&&e.every(n=>typeof n=="string"))return e}catch(e){i.warn(`[runtime-bridge] AWS_CLIENT_AGENT_MCP_ARGS \u4E0D\u662F\u5408\u6CD5 JSON\uFF0C\u5DF2\u5FFD\u7565: ${e instanceof Error?e.message:String(e)}`)}return i.warn("[runtime-bridge] AWS_CLIENT_AGENT_MCP_ARGS \u5FC5\u987B\u662F string[] JSON\uFF0C\u5DF2\u5FFD\u7565"),[]}function T(r){const e=r.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1");try{const n=new URL(e);return n.protocol==="ws:"?n.protocol="http:":n.protocol==="wss:"?n.protocol="https:":n.protocol=n.protocol.toLowerCase(),n.origin}catch{return e.replace(/\/+$/,"")}}function re(r){const e=new URL("/ws/agent",T(r));return e.protocol==="https:"?e.protocol="wss:":e.protocol="ws:",e.toString()}function ne(r){const e=T(r);return new URL("/mcp/call",e).toString()}function te(){const r=String(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL||"").trim();if(r)return r;const e=$(),n=String(e.schedulerBaseUrl||"").trim();return e.status==="paired"&&n?n:O}function pe(r={}){return d(r)}function d(r={}){const e=String(process.env.AWS_CLIENT_AGENT_MCP_COMMAND||"").trim();if(e)return{source:"override",command:e,args:process.env.AWS_CLIENT_AGENT_MCP_ARGS?ee(process.env.AWS_CLIENT_AGENT_MCP_ARGS):[]};const n=r.exists||c,s=(r.release||q)();return s&&n(s)?{source:"bundled",command:process.execPath,args:[s]}:{source:"global",command:"aws-client-agent-mcp",args:[]}}function fe(r){const e=Q(),n=d(),o=te();return{command:n.command,args:n.args,env:{...Z(e),AWS_AGENT_ID:r.agentId,AWS_WORKSPACE_PATH:r.workspacePath,AWS_SERVER_URL:e.AWS_SERVER_URL||re(o),AWS_MCP_HTTP_URL:e.AWS_MCP_HTTP_URL||ne(o),AWS_RUNTIME_BRIDGE_BASE_URL:e.AWS_RUNTIME_BRIDGE_BASE_URL||`http://127.0.0.1:${B()}`,AWS_MCP_CLAIM_LAUNCH_BINDING:e.AWS_MCP_CLAIM_LAUNCH_BINDING||"true"}}}function ge(){const r=d(),e=r.args[0]?`${r.command} ${r.args.join(" ")}`:r.command;if(r.source==="global"){i.warn(`[runtime-bridge] ${a} MCP \u672A\u627E\u5230 bundled \u4EA7\u7269\uFF0C\u542F\u52A8\u65F6\u5C06\u56DE\u9000\u5230 PATH \u547D\u4EE4: ${e}`);return}i.info(`[runtime-bridge] ${a} MCP \u5DF2\u51C6\u5907(${r.source}): ${e}`)}const me="agents-work-studio";function Ae(){const r=d(),e={type:"stdio"};if(r.command&&(e.command=r.command),r.args.length>0&&(e.args=[...r.args]),!e.command)throw new Error("\u5185\u7F6E\u901A\u8BAF MCP \u547D\u4EE4\u89E3\u6790\u5931\u8D25\uFF1A\u672A\u80FD\u5B9A\u4F4D\u53EF\u6267\u884C\u5165\u53E3\uFF08bundled/\u8986\u76D6\u53D8\u91CF/PATH \u5747\u4E0D\u53EF\u7528\uFF09");return e}export{a as AWS_MCP_SERVER_NAME,me as BUILTIN_AWS_MCP_SERVER_NAME,fe as buildAwsMcpServerConfig,Ae as buildBuiltinAwsMcpDeploySpec,ge as ensureAwsClientAgentMcpReleased,d as getAwsClientAgentMcpPreparedInfo,le as getReleasedMcpDistPath,q as releaseBundledAwsClientAgentMcp,pe as resolveAwsClientAgentMcpCommand};
|
|
3
3
|
|