aws-runtime-bridge 1.9.151 → 1.9.162
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +560 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +51 -1
- package/dist/adapter/AcodeSdkAdapter.js +6 -5
- package/dist/adapter/prompts.d.ts +1 -1
- package/dist/adapter/prompts.js +1 -1
- package/dist/desktop/built-in-desktop-tools.js +1 -1
- package/dist/routes/acode-todos.js +1 -1
- package/dist/routes/ltr.js +1 -1
- package/dist/routes/sessions.d.ts +31 -0
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/terminal.d.ts +8 -0
- package/dist/routes/terminal.js +25 -25
- package/dist/services/instance-features.d.ts +25 -1
- package/dist/services/instance-features.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/services/workspace-watch.js +1 -1
- package/dist/utils/file-utils.d.ts +2 -0
- package/dist/utils/file-utils.js +2 -2
- package/package/acode/dist/ask-user-question-tool.js +1 -1
- package/package/acode/dist/await-complete-tool.js +1 -1
- package/package/acode/dist/background-command-manager.js +1 -1
- package/package/acode/dist/background-command-tools.js +1 -1
- package/package/acode/dist/built-in-file-tools.d.ts +18 -2
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/built-in-symbols-tool.js +1 -1
- package/package/acode/dist/context-overflow.d.ts +19 -0
- package/package/acode/dist/context-overflow.js +2 -0
- package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
- package/package/acode/dist/index.d.ts +3 -1
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
- package/package/acode/dist/parsers/ast-cache.js +1 -1
- package/package/acode/dist/parsers/language-queries.js +1 -1
- package/package/acode/dist/parsers/symbol-extractor.js +2 -2
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
- package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
- package/package/acode/dist/plugin-types.d.ts +5 -0
- package/package/acode/dist/plugin-types.js +1 -0
- package/package/acode/dist/read-file-state.d.ts +48 -0
- package/package/acode/dist/read-file-state.js +2 -0
- package/package/acode/dist/runtime.d.ts +63 -3
- package/package/acode/dist/runtime.js +30 -26
- package/package/acode/dist/skill-tool.js +3 -3
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/sub-agent-tools.js +5 -5
- package/package/acode/dist/todo-tool.js +3 -3
- package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
- package/package/acode/dist/tool-concurrency/index.js +2 -0
- package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
- package/package/acode/dist/tool-concurrency/observability.js +3 -0
- package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
- package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
- package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
- package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
- package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
- package/package/acode/dist/tool-concurrency/types.js +2 -0
- package/package/acode/dist/tool-group-manager.d.ts +116 -0
- package/package/acode/dist/tool-group-manager.js +14 -0
- package/package/acode/dist/types.d.ts +14 -1
- package/package/acode/package.json +2 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +4 -4
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +62 -17
- package/package/aws-client-agent-mcp/dist/mcp-server.js +29 -29
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +46 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +149 -7
- package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +25 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +57 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +3 -0
- package/package/aws-client-agent-mcp/dist/types.d.ts +27 -0
- package/package/aws-client-agent-mcp/package.json +2 -1
- package/package.json +1 -1
- package/package/acode/dist/plugin-tools.d.ts +0 -14
- package/package/acode/dist/plugin-tools.js +0 -9
package/dist/routes/terminal.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as rt}from"node:child_process";import{promises as F}from"node:fs";import ot from"node:os";import B from"node:path";import{TextDecoder as te}from"node:util";import be from"axios";import{Router as st}from"express";import{v4 as it}from"uuid";import{adapterRegistry as k,getToolActionInfo as he,isTransientClipboardPasteFilePath as we,redactTransientClipboardPastePaths as q,registerSdkProviders as at,resolveSdkProviderIdByCommand as ct}from"../adapter/index.js";import{MESSAGE_POLLING_IDLE_PROMPT as Ce}from"../adapter/prompts.js";import{getActiveBridgeHttpPort as ut,getAcodeDataHome as $e}from"../config.js";import{validateToken as I}from"../middleware/auth.js";import{getAgentProcessManager as Ie}from"../services/agent-process-manager.js";import{createAiConfigService as dt}from"../services/ai-config-service.js";import{resolveSchedulerBaseUrlFromToken as Re}from"../services/auto-register.js";import{setChangeCacheRetentionDays as lt}from"../services/change-cache-retention.js";import{getAllPushStats as ft,startHeartbeatScheduler as mt}from"../services/event-delta-pusher.js";import{prepareAcodeInstanceConfig as pt,redactForLog as ne}from"../services/instance-ai-config-service.js";import{setAgentFeatures as gt,setAgentCapabilities as yt,getAgentFeatures as ht,getFeatureState as b,LAUNCH_ITEM_FEATURE_KEY as Ee,HIRE_FEATURE_KEY as De,PENCIL_FEATURE_KEY as Pe,DRAW_FEATURE_KEY as Le,OFFICE_FEATURE_KEY as Oe,COLLABORATION_TASK_FEATURE_KEY as Me,COLLABORATION_MEETING_FEATURE_KEY as Ue,COLLABORATION_DEBUG_FEATURE_KEY as je,COLLABORATION_FILE_HISTORY_FEATURE_KEY as xe}from"../services/instance-features.js";import{enqueueMcpLaunchBinding as It}from"../services/mcp-launch-binding-queue.js";import{setPanelEnvVars as St}from"../services/panel-env.js";import{findClaudeCodeProcesses as At,isProcessRunning as Tt}from"../services/process-detector.js";import{forgetSession as K,onSdkToolUseEnd as _t,onSdkToolUseStart as kt}from"../services/sdk-tool-file-change-recorder.js";import{bridgeEventBuffer as Be,sendOutput as Y,sendQuestionRequest as bt,sendToolAuthRequest as wt,sendStatus as $}from"../services/session-output.js";import{findPersistedSessionByAgentId as Ct,removePersistedSession as H,savePersistedSessions as $t,updatePersistedSessionAutoCommands as Rt,updatePersistedSessionRuntimeState as Et,upsertPersistedSession as Dt}from"../services/terminal-persistence.js";import{getInstanceAiConfigDebugLogger as Pt}from"../utils/instance-ai-config-debug-logger.js";import{logger as f}from"../utils/logger.js";const S=st();function Ne(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,Lt=45e3,re=new Map;function Ot(e){if(re.has(e))return;const n=setInterval(()=>{const t=p.get(e);if(!t){M(e);return}const r=t.currentRuntimeStatus;if(r!=="thinking"&&r!=="tool_using"&&r!=="compacting"){M(e);return}$(t.agentId,e,r,void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl}).catch(()=>{})},Lt);re.set(e,n)}function M(e){const n=re.get(e);n&&(clearInterval(n),re.delete(e))}const ve=4e3,Mt=`
|
|
2
2
|
|
|
3
3
|
\u8BF7\u6C42\u4F53:
|
|
4
|
-
`;function
|
|
4
|
+
`;function Fe(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 Ut=`
|
|
5
5
|
|
|
6
6
|
\u8BF7\u6C42\u5934:
|
|
7
|
-
`,z=new Set;async function
|
|
7
|
+
`,z=new Set;async function jt(e,n){const t=[],r=[],o=B.join(e,".agentswork","memory");try{const c=(await F.readdir(o)).filter(u=>u.endsWith(".json")),d=await Promise.all(c.map(async u=>{try{const l=await F.readFile(B.join(o,u),"utf-8");return JSON.parse(l)}catch{return f.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 m=l.memory_type||"memory",g=(l.content||"").trim();g&&(m==="recently_memory"?t.push({title:l.title,content:g,uri:l.uri||""}):m==="agent_memory"&&r.push({title:l.title,content:g,uri:l.uri||""}))}}catch{f.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(m=>{if(!m.ok)throw new Error(`Server returned ${m.status}`);return m.json()})));for(let l=0;l<u.length;l++){const m=u[l];if(m.status!=="fulfilled")continue;const g=m.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)&&f.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
|
|
|
@@ -14,41 +14,41 @@ ${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
|
|
17
|
+
`)}function xt(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 Bt(e){return e!=="acode"}function Nt(e){const n=typeof e=="object"&&e!==null&&"suppressStatus"in e&&e.suppressStatus===!0,t=typeof e=="object"&&e!==null&&"reason"in e&&typeof e.reason=="string"&&e.reason.trim()?e.reason.trim():void 0;return{statusNotified:!n,reason:t}}function oe(e){const n=e?.usage;if(!n)return;const t=Number.isFinite(n.inputTokens)?n.inputTokens:0,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)&&f.info(`[TokenDebug][Terminal] resolveStatusChangeUsage: input=${o.inputTokens} output=${o.outputTokens} cacheHit=${o.cacheHitTokens??"(none)"} cacheMiss=${o.cacheMissTokens??"(none)"} actionType=${e?.actionType??"(none)"}`),o}function vt(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}}function Ft(e){return e.restoredActionInfo?.actionType==="idle"||e.currentRuntimeActionType==="idle"&&e.shouldPreservePrevAction||e.status==="waiting_input"&&!e.actionInfo?.actionType}const Q=new Map,qt="utf-8",qe="utf-8",Ke=300,He=6e4;function V(e){return String(e).padStart(2,"0")}function Kt(e,n=new Date){const t=n.getFullYear(),r=V(n.getMonth()+1),o=V(n.getDate()),s=V(n.getHours()),i=V(n.getMinutes()),a=`${t}${r}${o}-${s}${i}${V(n.getSeconds())}-${String(n.getMilliseconds()).padStart(3,"0")}`;return B.join($e(),"cmd-dist",e,`${t}-${r}-${o}`,s,i,`${a}-cmd.out`)}function Ht(e){if(!e)return 0;const n=e.replace(/\r\n/g,`
|
|
18
18
|
`).replace(/\r/g,`
|
|
19
19
|
`),t=n.endsWith(`
|
|
20
20
|
`)?n.slice(0,-1):n;return t?t.split(`
|
|
21
|
-
`).length:1}function
|
|
21
|
+
`).length:1}function zt(e,n=Ke){return`\r
|
|
22
22
|
[ACode] \u547D\u4EE4\u8F93\u51FA\u8D85\u8FC7 ${n} \u884C\uFF0C\u5B8C\u6574\u8F93\u51FA\u5DF2\u5199\u5165: ${e}\r
|
|
23
23
|
[ACode] Agent \u53EF\u81EA\u884C\u8BFB\u53D6\u8BE5\u6587\u4EF6\uFF0C\u6216\u5728\u8BE5\u6587\u4EF6\u4E2D\u641C\u7D22\u9700\u8981\u7684\u5185\u5BB9\u3002\r
|
|
24
|
-
`}function
|
|
24
|
+
`}function Wt(e=He){return`\r
|
|
25
25
|
[ACode] \u547D\u4EE4\u8D85\u8FC7 ${Math.round(e/1e3)} \u79D2\u6CA1\u6709\u65B0\u7684\u8F93\u51FA\uFF0C\u5DF2\u505C\u6B62\u6267\u884C\u5E76\u4FDD\u7559\u6B64\u524D\u8F93\u51FA\u3002\r
|
|
26
|
-
`}async function
|
|
27
|
-
`).trim()}function
|
|
28
|
-
`),!0;const o=
|
|
26
|
+
`}async function ze(e){const n=e.outputPath||Kt(e.agentId,e.startedAt);return e.outputPath=n,await F.mkdir(B.dirname(n),{recursive:!0}),await F.writeFile(n,e.chunks.join(""),"utf-8"),n}function Gt(e){return String(e??"").replace(/\r/g,`
|
|
27
|
+
`).trim()}function Xt(e=process.platform,n=process.env){const t=n.AWS_TERMINAL_OUTPUT_ENCODING?.trim();return t||(e==="win32"?qt:qe)}function We(e=Xt()){if(e!=="utf-8")try{return new te(e,{fatal:!1})}catch{return new te(qe,{fatal:!1})}return Yt()}function Yt(){let e=null,n=null,t=null;const r=[];function o(s){try{return new te(s,{fatal:!1})}catch{return new te("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 se(e,n,t=!1){return t?e.decode():!n||n.length===0?"":e.decode(n,{stream:!0})}function Qt(e){const n=e.trim().match(/^cd(?:\s+(.*))?$/i);if(!n)return;const t=n[1]?.trim();if(!t)return null;const r=t.replace(/^\/d\s+/i,"").trim();return r.startsWith('"')&&r.endsWith('"')||r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function Vt(e){const n=Q.get(e.sessionId);if(n)return n;const t={currentDirectory:e.workspacePath,runningProcess:null};return Q.set(e.sessionId,t),t}function Ge(e){for(const n of p.values())if(n.agentId===e)return n}async function Jt(e){const n=k.get(e.providerId||"claude-code"),t=ie(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 ie(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=Tt){return e.pid?n(e.pid)?Ze(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 ur(e){const n=Ge(e);if(!n)f.info(`[cleanupSdkSessionByAgentId] No active SDK session found for agentId=${e}, cleaning residual state anyway`);else{const t=n.sessionId;return f.info(`[cleanupSdkSessionByAgentId] Cleaning up SDK session for agentId=${e}, sessionId=${t}`),M(t),p.delete(t),K(t),ae(t),H(t).catch(r=>{f.warn(`[cleanupSdkSessionByAgentId] Failed to remove persisted session for agentId=${e}: ${r}`)}),t}z.has(e)&&(z.delete(e),f.info(`[cleanupSdkSessionByAgentId] Released startingAgents lock for agentId=${e}`))}function ae(e){const n=Q.get(e);if(!n?.runningProcess){Q.delete(e);return}try{n.runningProcess.kill()}catch{}finally{n.runningProcess=null,Q.delete(e)}}function w(e,n){n&&(e.seq+=1,Y(e.agentId,n,e.sessionId,e.seq,void 0,{runtimeAccessToken:e.runtimeAccessToken,schedulerBaseUrl:e.schedulerBaseUrl}).catch(()=>{}))}function Se(e){return`\x1B[36m${e}>\x1B[0m `}function en(e,n){return n==="~"?ot.homedir():B.resolve(e,n)}async function tn(e,n,t){const r=Qt(t);if(r===void 0)return!1;if(r===null)return w(e,`${n.currentDirectory}\r
|
|
28
|
+
`),!0;const o=en(n.currentDirectory,r);try{return(await F.stat(o)).isDirectory()?(n.currentDirectory=o,w(e,`${n.currentDirectory}\r
|
|
29
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
|
|
32
|
-
`),
|
|
33
|
-
`),w(t,Se(o.currentDirectory)),{started:!1,cwd:o.currentDirectory};if(await
|
|
34
|
-
[ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${
|
|
35
|
-
`)});return}w(t,y)}};return u&&T(),a.stdout.on("data",y=>{h(
|
|
31
|
+
`),!0}}async function nn(e,n){const t=p.get(e);if(!t)throw new Error("SDK session not found");const r=Gt(n),o=Vt(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=q(r);if(w(t,`${Se(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,Se(o.currentDirectory)),{started:!1,cwd:o.currentDirectory};if(await tn(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=rt(r,{cwd:o.currentDirectory,shell:!0,env:Xe(t.agentId,t.workspacePath,process.env,t.config.envOverrides)});o.runningProcess=a;const c=We(),d=We(),u=t.providerId==="acode",l={agentId:t.agentId,startedAt:new Date,chunks:[],spilled:!1};let m;const g=()=>{m&&(clearTimeout(m),m=void 0)},T=()=>{g(),m=setTimeout(()=>{o.runningProcess===a&&(w(t,Wt()),a.kill())},He)},h=(y,C=!0)=>{if(y&&(u&&l.chunks.push(y),u&&C&&T(),!(u&&l.spilled))){if(u&&Ht(l.chunks.join(""))>Ke){l.spilled=!0,ze(l).then(R=>{w(t,zt(R))}).catch(R=>{const O=R instanceof Error?R.message:String(R);w(t,`\r
|
|
34
|
+
[ACode] \u547D\u4EE4\u8F93\u51FA\u843D\u76D8\u5931\u8D25: ${O}\r
|
|
35
|
+
`)});return}w(t,y)}};return u&&T(),a.stdout.on("data",y=>{h(se(c,y))}),a.stderr.on("data",y=>{h(se(d,y))}),a.on("error",y=>{w(t,`\r
|
|
36
36
|
[Terminal Error] ${y.message}\r
|
|
37
|
-
`)}),a.on("close",(y,
|
|
38
|
-
[ACode] \u547D\u4EE4\u8F93\u51FA\u6700\u7EC8\u843D\u76D8\u5931\u8D25: ${
|
|
37
|
+
`)}),a.on("close",(y,C)=>{g(),o.runningProcess=null,h(se(c,void 0,!0),!1),h(se(d,void 0,!0),!1),l.spilled&&ze(l).catch(R=>{const O=R instanceof Error?R.message:String(R);w(t,`\r
|
|
38
|
+
[ACode] \u547D\u4EE4\u8F93\u51FA\u6700\u7EC8\u843D\u76D8\u5931\u8D25: ${O}\r
|
|
39
39
|
`)}),y&&y!==0?w(t,`\r
|
|
40
40
|
[exit ${y}]\r
|
|
41
|
-
`):
|
|
42
|
-
[signal ${
|
|
43
|
-
`),w(t,Se(o.currentDirectory))
|
|
44
|
-
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function
|
|
41
|
+
`):C&&w(t,`\r
|
|
42
|
+
[signal ${C}]\r
|
|
43
|
+
`),w(t,Se(o.currentDirectory)),$(t.agentId,e,"waiting_input",void 0,void 0,{runtimeAccessToken:t.runtimeAccessToken,schedulerBaseUrl:t.schedulerBaseUrl})}),{started:!0,cwd:o.currentDirectory}}function Xe(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:${ut()}`,String(o.ACODE_HOME||"").trim()||(o.ACODE_HOME=$e()),b(e,Ee)!=="disabled"&&(o.AWS_LAUNCH_CONFIG_TOOLS=b(e,Ee)),b(e,De)!=="disabled"&&(o.AWS_HIRE_TOOLS=b(e,De)),b(e,Pe)!=="disabled"&&(o.AWS_PENCIL_TOOLS=b(e,Pe)),b(e,Le)!=="disabled"&&(o.AWS_DRAW_TOOLS=b(e,Le)),b(e,Oe)!=="disabled"&&(o.AWS_OFFICE_TOOLS=b(e,Oe)),b(e,Me)!=="disabled"&&(o.AWS_COLLABORATION_TASK_TOOLS=b(e,Me)),b(e,Ue)!=="disabled"&&(o.AWS_COLLABORATION_MEETING_TOOLS=b(e,Ue)),b(e,je)!=="disabled"&&(o.AWS_COLLABORATION_DEBUG_TOOLS=b(e,je)),b(e,xe)!=="disabled"&&(o.AWS_COLLABORATION_FILE_HISTORY_TOOLS=b(e,xe)),o}function rn(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 on(e){const n=String(e);if(!we(n))return n;const t=rn(n);return B.isAbsolute(t)?F.readFile(t,"utf-8"):n}function Ye(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 sn(){try{return await dt().readClaudeCodeConfig()}catch(e){return console.warn(`[Runtime] Failed to read saved ClaudeCode AI config: ${e.message}`),{}}}function an(e){if(e==null)return;const t=(typeof e=="string"?e:JSON.stringify(e,null,2)).trim();if(t)return t.length<=ve?t:`${t.slice(0,ve)}
|
|
44
|
+
...\uFF08\u7ED3\u679C\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function cn(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 un(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 dn(e){if(e.type!=="tool_use_end")return;const n=an(e.data.toolResult??e.data.actionResult);if(!n)return;const t=he(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"))&&!cn(n))return}return r==="mcp"&&un(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 ln(e){if(e.type==="ai_request"){const n=e.data.model?` ${e.data.model}`:"",t=e.data.lastUserMessagePreview?`\uFF1A${e.data.lastUserMessagePreview}`:"";return`\r
|
|
45
45
|
[ACode] \u6B63\u5728\u8BF7\u6C42\u6A21\u578B${n}${t}\r
|
|
46
46
|
`}if(e.type==="text_delta"||e.type==="thinking"||e.type==="command_output")return e.data.text||void 0;if(e.type==="error")return e.data.text?`\r
|
|
47
47
|
[SDK Error] ${e.data.text}\r
|
|
48
|
-
`:void 0}function
|
|
49
|
-
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function
|
|
50
|
-
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",o=t.length>0?`${
|
|
51
|
-
`)}`:"",s=e.requestBody?`${Dt}${e.requestBody}`:"";return`${r}${o}${s}`}function yn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function hn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function In(e){for(const n of["estimatedContextTokens","contextTokens","context_tokens","contextUsedTokens","context_used_tokens"]){const t=e[n],r=Number(t);if(Number.isFinite(r)&&r>0)return r}}function Sn(e,n){if(!hn(e,n)){if(e.type==="ai_request"){const t=In(e.data);return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:gn(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=Fe(e,t),o=pn(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 x=new Map,ae=new Map,ce=new Map,J=new Map,An=20,Tn=500,kn=3e4;async function ue(e,n=kn,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=(x.get(e)??Promise.resolve()).then(()=>ue(g=>G(a.agentId,s,e,i,d,u,g)),()=>ue(g=>G(a.agentId,s,e,i,d,u,g)));x.set(e,f),f.finally(()=>{x.get(e)===f&&x.delete(e)})}function bn(e,n){const t=rn(e);if(!t)return;n.seq+=1;const r=n.seq,o=on(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<An){const c=`${e.sessionId}:${e.type}`;let d=J.get(c);if(d||(d={buffer:"",seq:0,timer:null,entry:n,sourceEventType:e.type}),d.buffer+=t,d.seq=r,d.entry=n,!d.timer){const u=e.sessionId,l=e.type;d.timer=setTimeout(()=>de(u,l),Tn)}J.set(c,d);return}de(e.sessionId);const a=(x.get(e.sessionId)??Promise.resolve()).then(()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)),()=>ue(c=>G(n.agentId,t,e.sessionId,r,o,s,c)));x.set(e.sessionId,a),a.finally(()=>{x.get(e.sessionId)===a&&x.delete(e.sessionId)})}function ze(e){return Ze(e)}let He=!1;function wn(){He||(Ye(b,_n),ot(),He=!0)}function _n(e,n){e.on("event",t=>{const r=p.get(t.sessionId);if(r){if(t.type==="tool_use_start"?ht(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&yt(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=Sn(t,r.currentRuntimeStatus);i&&C(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)}bn(t,r);const s=nn(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 C(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 C(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)):C(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"?$t(t):L(t);const i=xt(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||""),bt(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 C(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(_=>setTimeout(_,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 _=0;_<=2;_++){if(await C(s.agentId,t,i.status,f?void 0:l,re(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;_<2&&await new Promise(M=>setTimeout(M,1e3*(_+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 C(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)`),C(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}`),It(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}`),St(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;C(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()||De(Pe(e))||void 0;mt({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&&(it(String(t),e.body.runtimeFeatures),m.info(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(ct(String(t)))}`)),e.body?.capabilities!==void 0&&at(String(t),e.body.capabilities),e.body?.envVars!==null&&e.body?.envVars!==void 0&&typeof e.body.envVars=="object"&&(ft(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&&(nt(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 Cn(e,n)});async function Cn(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:_,subAgentModel:$,subAgentEffort:M,scopeKey:Te,browserAllowPrivate:ke}=e.body||{},H=_t();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:_?te(_):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()||De(Pe(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(wn(),!A){n.status(400).json({error:"agentId is required"});return}const N=Oe(A);if(N){n.json(await Ht(N));return}const k=await At(A);if(k){const R=Wt(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=ze(o),We=b.get(E);D=Je();const Xe=E==="claude-code"?await Yt():null,Y=qe(E==="claude-code"?Xe: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=_||{},P=await st({apiOverrides:Me(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=Me(R);return j?te(j):null})(),resolvedInstanceAiConfig:X?te(X):null,perInstanceConfigPath:fe,instanceConfigSources:P.instanceConfig.source??null}})}let be=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 Pt(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());be=P.length>0?P.join(`
|
|
48
|
+
`:void 0}function fn(e){const n=gn(e);return{sourceEventType:e.type,logCategory:"acode",...pn(e),...n?{logLevel:mn(e),logMessage:n}:{}}}function mn(e){return e.type==="error"?"error":e.type==="command_output"&&e.data.stream==="stderr"?"warn":"info"}function pn(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 gn(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 In(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 yn=/\x1b\[[0-9;?]*[a-zA-Z]/g;function hn(e){return e.replace(yn,"")}function In(e){const n=typeof e.data.stream=="string"?e.data.stream:"mixed",t=typeof e.data.sequence=="number"?` #${e.data.sequence}`:"",r=hn(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=he(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"?Sn(t)||e.data.actionDetail||n.actionDetail:n.actionType==="read_file"||n.actionType==="edit_file"||n.actionType==="write_file"?An(t)||e.data.actionDetail||n.actionDetail:e.data.actionDetail||n.actionDetail}function Sn(e){const n=Ae(e?.command,e?.cmd);if(n)return n;if(Array.isArray(e?.argv)){const t=e.argv.map(r=>String(r??"").trim()).filter(Boolean).join(" ");return t?q(t):void 0}return Ae(e?.args)}function An(e){const n=Je(e?.paths);return n.length>0?n.length===1?n[0]:`${n.length}\u4E2A\u6587\u4EF6: ${n.join(", ")}`:Ae(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)}function Ae(...e){for(const n of e){if(typeof n=="string"&&n.trim())return q(n.trim());if(Array.isArray(n)){const t=Je(n)[0];if(t)return t}}}function Je(e){return Array.isArray(e)?e.map(n=>typeof n=="string"?n.trim():"").filter(Boolean).map(n=>q(n)):[]}function Tn(e){if(!(!e||Object.keys(e).length===0))try{const n=q(JSON.stringify(e,null,2));return n.length>8e3?`${n.slice(0,8e3)}
|
|
49
|
+
...\uFF08\u8F93\u5165\u53C2\u6570\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`:n}catch{return}}function _n(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=kn(e.requestHeaders),r=n.join(`
|
|
50
|
+
`)||"ACode \u6B63\u5728\u53D1\u9001 AI \u8BF7\u6C42",o=t.length>0?`${Ut}${t.join(`
|
|
51
|
+
`)}`:"",s=e.requestBody?`${Mt}${e.requestBody}`:"";return`${r}${o}${s}`}function kn(e){return e?Object.entries(e).map(([n,t])=>`${n}: ${t}`).filter(n=>n.trim().length>0):[]}function bn(e,n){return String(n||"").trim().toLowerCase()!=="waiting_input"?!1:e.type==="thinking"||e.type==="text_delta"}function wn(e,n){if(!bn(e,n)){if(e.type==="ai_request")return{status:"thinking",actionInfo:{actionType:"ai_request",actionLabel:"AI\u8BF7\u6C42",actionDetail:_n(e.data)}};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=he(e.data.toolName,e.data.toolInput),r=Ve(e,t),o=Tn(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 U=new Map,ce=new Map,ue=new Map,J=new Map,Cn=20,$n=500,Rn=3e4;async function de(e,n=Rn,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);f.warn(`sendOutput attempt ${r+1}/${t+1} failed (${a}), retrying in ${c}ms...`),await new Promise(d=>setTimeout(d,c));continue}f.warn(`sendOutput failed after ${t+1} attempts (${a}), giving up to unblock serial queue`)}}}function le(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)le(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},m=(U.get(e)??Promise.resolve()).then(()=>de(g=>Y(a.agentId,s,e,i,d,u,g)),()=>de(g=>Y(a.agentId,s,e,i,d,u,g)));U.set(e,m),m.finally(()=>{U.get(e)===m&&U.delete(e)})}function En(e,n){const t=ln(e);if(!t)return;n.seq+=1;const r=n.seq,o=fn(e),s={runtimeAccessToken:n.runtimeAccessToken,schedulerBaseUrl:n.schedulerBaseUrl};if((e.type==="command_output"||e.type==="text_delta"||e.type==="thinking")&&t.length<Cn){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(()=>le(u,l),$n)}J.set(c,d);return}le(e.sessionId);const a=(U.get(e.sessionId)??Promise.resolve()).then(()=>de(c=>Y(n.agentId,t,e.sessionId,r,o,s,c)),()=>de(c=>Y(n.agentId,t,e.sessionId,r,o,s,c)));U.set(e.sessionId,a),a.finally(()=>{U.get(e.sessionId)===a&&U.delete(e.sessionId)})}function Ze(e){return ct(e)}let et=!1;function Dn(){et||(at(k,Pn),mt(),et=!0)}function Pn(e,n){e.on("event",t=>{const r=p.get(t.sessionId);if(r){if(t.type==="tool_use_start"?kt(r.sessionId,t.data.toolUseId||t.data.actionId,t.data.toolInput,t.data.toolName,r.workspacePath):t.type==="tool_use_end"&&_t(t,{sessionId:r.sessionId,agentId:r.agentId,workspacePath:r.workspacePath,providerId:r.providerId}),f.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=wn(t,r.currentRuntimeStatus);i&&$(r.agentId,t.sessionId,i.status,i.actionInfo,oe(i.actionInfo),{runtimeAccessToken:r.runtimeAccessToken,schedulerBaseUrl:r.schedulerBaseUrl},t.timestamp?new Date(t.timestamp).getTime():void 0,t.type)}En(t,r);const s=dn(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){le(t),r==="thinking"||r==="tool_using"||r==="compacting"?Ot(t):M(t);const i=vt(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),f.info(`[${n.displayName} Adapter] Status changed: ${i.status} for agent ${s.agentId}`,i.actionInfo||""),Et(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=(ce.get(t)??Promise.resolve()).then(async()=>{for(let h=0;h<=2;h++){if(await $(s.agentId,t,i.status,l,oe(i.actionInfo),{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})!==void 0)return;h<2&&(f.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))))}f.warn(`[${n.displayName}] compaction sendStatus failed after 3 attempts, event may be lost`)}).catch(T=>{f.warn(`[${n.displayName}] compaction status chain error:`,T)});ce.set(t,g),g.finally(()=>{ce.get(t)===g&&ce.delete(t)})}else{const m=u&&!i.actionInfo?.actionType;if(Ft({status:i.status,actionInfo:i.actionInfo,restoredActionInfo:l,currentRuntimeActionType:s.currentRuntimeActionType,shouldPreservePrevAction:u})){const h=(ue.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(O=>setTimeout(O,1e3*(C+1)))}f.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=>{f.warn(`[${n.displayName}] idle status chain error:`,y)});ue.set(t,h),h.finally(()=>{ue.get(t)===h&&ue.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,f.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:m},void 0,{runtimeAccessToken:s.runtimeAccessToken,schedulerBaseUrl:s.schedulerBaseUrl})}}}),e.on("ask-user-question",t=>{const r=p.get(t.sessionId);r&&(f.info(`[${n.displayName} Adapter] AskUserQuestion for agent ${r.agentId}`),bt(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&&(f.info(`[${n.displayName} Adapter] Tool permission request (${t.capability}) for agent ${r.agentId}`),wt(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){f.info(`[${n.displayName} Adapter] Permission request: ${t.toolName} for agent ${r.agentId}`);const o=t.toolInput?q(JSON.stringify(t.toolInput).slice(0,400)):void 0;$(r.agentId,t.sessionId,"waiting_input",{actionType:"other",actionLabel:"\u6743\u9650\u786E\u8BA4",actionDetail: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()||Re(Ne(e))||void 0;It({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&&(gt(String(t),e.body.runtimeFeatures),f.info(`[Runtime] agent ${t} \u542F\u52A8\u4E0B\u53D1\u80FD\u529B\u5F00\u5173: ${JSON.stringify(ht(String(t)))}`)),e.body?.capabilities!==void 0&&yt(String(t),e.body.capabilities),e.body?.envVars!==null&&e.body?.envVars!==void 0&&typeof e.body.envVars=="object"&&(St(e.body.envVars),f.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&&(lt(e.body.changeCacheRetentionDays),f.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 Ln(e,n)});async function Ln(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:m,envOverrides:g,idleInputAutoCommand:T,nonInputAutoCommand:h,model:y,instanceAiConfig:C,subAgentModel:R,subAgentEffort:O,scopeKey:Te,browserAllowPrivate:_e}=e.body||{},W=Pt();W.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?ne(C):null,perAgentModel:y??null}});let E=null;const A=String(t||"").trim(),fe=String(e.body?.runtimeAccessToken||"").trim()||void 0,N=String(e.body?.schedulerBaseUrl||"").trim()||String(e.header("x-bridge-tunnel-source")||"").trim()||Re(Ne(e))||void 0;N?f.info(`[startSdkSession] \u56DE\u8C03\u76EE\u6807 server: ${N} (agentId=${A})`):f.warn(`[startSdkSession] \u672A\u89E3\u6790\u5230 schedulerBaseUrl\uFF0C\u5C06\u56DE\u9000\u5230\u9ED8\u8BA4\u5730\u5740 (agentId=${A})`);try{if(Dn(),!A){n.status(400).json({error:"agentId is required"});return}const v=Ge(A);if(v){n.json(await Jt(v));return}const _=await Ct(A);if(_){const D=Zt(_);if(!D.reusable)console.warn(`[Runtime] Ignoring stale persisted SDK session for agentId=${A}, sessionId=${_.sessionId}, reason=${D.reason}`),await H(_.sessionId);else{const P=ie(_.runtimeStatus,_.runtimeStatus,_.runtimeActionType);n.json({sessionId:_.sessionId,status:P,runtimeStatus:P,runtimeActionType:_.runtimeActionType,runtimeActionLabel:_.runtimeActionLabel,runtimeActionDetail:_.runtimeActionDetail,agentId:_.agentId,workspacePath:_.workspacePath,command:_.command,mode:_.mode||"sdk",pid:_.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 L=Ze(o),tt=k.get(L);E=it();const nt=L==="claude-code"?await sn():null,Z=Ye(L==="claude-code"?nt:null,g),G=L==="acode"?y?String(y).trim():void 0:(()=>{const D=y?String(y).trim():void 0,P=Z.model?String(Z.model).trim():void 0;return D||P})();W.log({level:"info",category:"resolve",message:"\u6A21\u578B\u89E3\u6790\u7ED3\u679C",source:"bridge",agentId:A,sessionId:E??void 0,details:{perAgentModel:y??null,globalModel:Z.model??null,resolvedModel:G??null,providerId:L,note:L==="acode"?"adapter handles full priority":"request > global"}});const me={...Z.envOverrides};G&&(me.ANTHROPIC_MODEL=G,me.CODEX_MODEL=G);let X,pe=l;if(L==="acode"){const D=C||{},P=await pt({apiOverrides:Fe(D)??void 0,agentId:A,sessionId:E??void 0,runtimeBridgeBaseUrl:N});X=P.instanceConfig.config,pe=P.perInstanceConfigPath,W.log({level:"info",category:"apply",message:"prepareAcodeInstanceConfig \u5B8C\u6210",source:"bridge",agentId:A,sessionId:E??void 0,details:{sanitizedApiOverrides:(()=>{const x=Fe(D);return x?ne(x):null})(),resolvedInstanceAiConfig:X?ne(X):null,perInstanceConfigPath:pe,instanceConfigSources:P.instanceConfig.source??null}})}let ke=a||void 0,ge,ye,ee;if(L==="acode")if(ge=typeof c=="string"&&c.trim()||void 0,ye=typeof d=="string"&&d.trim()||void 0,typeof u=="string"&&u.trim())ee=u.trim();else{const D=await jt(r,{schedulerBaseUrl:N,runtimeAccessToken:fe,agentId:A});D&&(ee=D,f.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(x=>typeof x=="string"&&x.trim().length>0).map(x=>x.trim());ke=P.length>0?P.join(`
|
|
52
52
|
|
|
53
|
-
`):void 0}const U={command:o||"acode",workingDirectory:r,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}:{},...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:Ne(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"}),$n({sessionId:D,agentId:A,config:U,adapter:We,providerId:E,idleInputAutoCommand:T,nonInputAutoCommand:h,runtimeAccessToken:le,requestedSchedulerBaseUrl:O})}catch(N){if(D&&(L(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 $n(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),o.setIdleCommands?.(n,{idleInputCommand:i||Ce,nonInputCommand:a||""});let u;if(Mt(s))try{if(await new Promise(f=>setTimeout(f,500)),u=o.getSessionPid?.(n),!u){const g=(await pt()).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 wt({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 Dn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){L(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 Rn({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{z.delete(t)}}async function Dn(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 we.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 Rn(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 we.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),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(r.agentId),await C(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 Qt(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 Jt(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||"").trim()||Ce,nonInputCommand:String(o||"")};try{let c=!1;i&&(b.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await kt(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=Et(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=Lt(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),L(t),p.delete(t),F(t),ie(t),await K(t),await he().removeProcess(s),r.statusNotified?await C(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),L(o),p.delete(o),F(o),ie(o),t.push(o),await C(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 Tt([]),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=Re.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=Re.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=rt();n.json({ok:!0,count:t.length,agents:t})});export{jt as buildAcodeCommandOutputPath,qe as buildClaudeCodeLaunchConfig,Ne as buildRuntimeEnv,on as buildSdkOutputMetadata,nn as buildToolResultTimelineActionInfo,rr as cleanupSdkSessionByAgentId,Bt as countTerminalOutputLines,Be as createTerminalOutputDecoder,oe as decodeTerminalOutputChunk,Wt as evaluatePersistedSessionReuse,Nt as formatCommandInactivityTimeoutNotice,Ot as formatCommandOutputSpilloverNotice,rn as formatSdkOutputEvent,Se as formatTerminalPrompt,qt as normalizeTerminalCommandInput,Lt as parseRuntimeStopOptions,Kt as parseTerminalDirectoryChangeTarget,ue as raceSendOutputWithRetry,Et as resolveRuntimeContextResetSupport,Sn as resolveRuntimeStatusFromProviderEvent,Jt as resolveSdkInputMessage,ze as resolveSdkProviderId,se as resolveSdkSessionDisplayStatus,xt as resolveStatusChangeRuntimeState,re as resolveStatusChangeUsage,vt as resolveTerminalOutputEncoding,p as sdkSessions,Mt as shouldProbeSdkProcessPid,S as terminalRouter};
|
|
53
|
+
`):void 0}const j={command:o||"acode",workingDirectory:r,agentId:A,...Te?{scopeKey:Te}:{},...typeof _e=="boolean"?{browserAllowPrivate:_e}:{},autoAccept:!!s,initialPrompt:i,systemPrompt:ke,...ge!==void 0?{globalPrompt:ge}:{},...ye!==void 0?{rolePrompt:ye}:{},...ee!==void 0?{memory:ee}:{},model:G,mcpConfigPath:pe,...X?{instanceAiConfig:X}:{},...typeof R=="string"&&R.trim()?{subAgentModel:R.trim()}:{},...typeof O=="string"&&O.trim()?{subAgentEffort:O.trim()}:{},extraMcpServers:m||{},envOverrides:Xe(String(t),String(r),process.env,me)};W.log({level:"info",category:"launch",message:"\u4F20\u9012\u7ED9 Adapter \u7684\u5B8C\u6574 AdapterSessionConfig",source:"bridge",agentId:A,sessionId:E,details:{adapterModel:j.model??null,adapterInstanceAiConfig:j.instanceAiConfig?ne(j.instanceAiConfig):null,adapterMcpConfigPath:j.mcpConfigPath??null}}),await W.flush(),p.set(E,{agentId:A,workspacePath:r,sessionId:E,config:j,providerId:L,seq:0,runtimeAccessToken:fe,schedulerBaseUrl:N}),n.json({sessionId:E,status:"starting",runtimeStatus:"starting",agentId:A,workspacePath:r,command:j.command,mode:"sdk"}),On({sessionId:E,agentId:A,config:j,adapter:tt,providerId:L,idleInputAutoCommand:T,nonInputAutoCommand:h,runtimeAccessToken:fe,requestedSchedulerBaseUrl:N})}catch(v){if(E&&(M(E),p.delete(E),K(E)),A&&z.delete(A),!n.headersSent){const _=v instanceof Error?v.message:String(v);n.status(500).json({error:`Failed to start SDK session: ${_}`})}}}async function On(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),o.setIdleCommands?.(n,{idleInputCommand:i||Ce,nonInputCommand:a||""});let u;if(Bt(s))try{if(await new Promise(m=>setTimeout(m,500)),u=o.getSessionPid?.(n),!u){const g=(await At()).find(T=>T.agentId===t||T.cwd===r.workingDirectory||T.command.includes(r.workingDirectory));g&&(u=g.pid,f.info(`[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=ie(o.getSessionStatus(n),p.get(n)?.currentRuntimeStatus,p.get(n)?.currentRuntimeActionType);await Dt({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 Ie().startProcess({agentId:t,sessionId:n,pid:u,mode:"sdk",workspacePath:r.workingDirectory,command:r.command}),await Mn({agentId:t,sessionId:n,sdkPid:u,status:l,schedulerBaseUrl:d,runtimeAccessToken:c})}catch(u){M(n),p.delete(n),K(n),await H(n);const l=u instanceof Error?u.message:String(u);console.error(`[Runtime] Background SDK session startup failed for agentId=${t}: ${l}`),await Un({agentId:t,sessionId:n,schedulerBaseUrl:d,runtimeAccessToken:c,errorMessage:l})}finally{z.delete(t)}}async function Mn(e){const{agentId:n,sessionId:t,sdkPid:r,status:o,schedulerBaseUrl:s,runtimeAccessToken:i}=e;if(!s||!i){f.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}),f.debug(`[Runtime] Notified server session ready: agentId=${n}, sessionId=${t}, status=${o}`)}catch(c){const d=c instanceof Error?c.message:String(c);f.warn(`[Runtime] Failed to notify server session ready: agentId=${n}, error=${d}`)}}async function Un(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}),f.debug(`[Runtime] Notified server session failed: agentId=${n}, sessionId=${t}`)}catch(i){const a=i instanceof Error?i.message:String(i);f.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 k.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=k.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=k.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=k.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 k.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 k.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=k.get(o);s.abortCurrentTurn(t).catch(()=>{}),await s.terminateSession(t),M(t),p.delete(t),K(t),ae(t),await H(t),await Ie().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=k.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=k.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=k.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 nn(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=k.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 on(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||"").trim()||Ce,nonInputCommand:String(o||"")};try{let c=!1;i&&(k.get(i.providerId||"claude-code").setIdleCommands?.(i.sessionId,a),c=!0);const d=await Rt(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=k.get(s),a=i.resetContext?.bind(i),c=xt(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=ie(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=Nt(e.body);if(!t){n.status(400).json({error:"sessionId is required"});return}const o=p.get(t);if(!o){await H(t),n.json({ok:!0,status:"stopped",mode:"none",statusNotified:!1,reason:r.reason});return}const s=o.agentId;try{f.info(`[Runtime] Stopping SDK session ${t}; suppressStatus=${!r.statusNotified}, reason=${r.reason||"unspecified"}`);const i=o.providerId||"claude-code",a=k.get(i);a.abortCurrentTurn(t).catch(()=>{}),await a.terminateSession(t),M(t),p.delete(t),K(t),ae(t),await H(t),await Ie().removeProcess(s),r.statusNotified?await $(s,null,"stopped",void 0,void 0,{runtimeAccessToken:o.runtimeAccessToken,schedulerBaseUrl:o.schedulerBaseUrl}):f.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=k.get(i);a.abortCurrentTurn(o).catch(()=>{}),await a.terminateSession(o),M(o),p.delete(o),K(o),ae(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 $t([]),f.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=Be.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=Be.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=ft();n.json({ok:!0,count:t.length,agents:t})});export{Kt as buildAcodeCommandOutputPath,Ye as buildClaudeCodeLaunchConfig,Xe as buildRuntimeEnv,fn as buildSdkOutputMetadata,dn as buildToolResultTimelineActionInfo,ur as cleanupSdkSessionByAgentId,Ht as countTerminalOutputLines,We as createTerminalOutputDecoder,se as decodeTerminalOutputChunk,Zt as evaluatePersistedSessionReuse,Wt as formatCommandInactivityTimeoutNotice,zt as formatCommandOutputSpilloverNotice,ln as formatSdkOutputEvent,Se as formatTerminalPrompt,Ft as isIdleStatusChangeRetryable,Gt as normalizeTerminalCommandInput,Nt as parseRuntimeStopOptions,Qt as parseTerminalDirectoryChangeTarget,de as raceSendOutputWithRetry,xt as resolveRuntimeContextResetSupport,wn as resolveRuntimeStatusFromProviderEvent,on as resolveSdkInputMessage,Ze as resolveSdkProviderId,ie as resolveSdkSessionDisplayStatus,vt as resolveStatusChangeRuntimeState,oe as resolveStatusChangeUsage,Xt as resolveTerminalOutputEncoding,p as sdkSessions,Bt as shouldProbeSdkProcessPid,S as terminalRouter};
|
|
54
54
|
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { ToolPermissionPolicy } from "@agentswork/acode";
|
|
2
2
|
|
|
3
|
+
export type FeatureState = "disabled" | "collapsed" | "expanded";
|
|
4
|
+
|
|
5
|
+
export declare function normalizeFeatureState(raw: unknown): FeatureState | undefined;
|
|
6
|
+
|
|
3
7
|
export declare const DESKTOP_FEATURE_KEY = "desktop";
|
|
4
8
|
|
|
5
9
|
export declare const BROWSER_FEATURE_KEY = "browser";
|
|
@@ -10,9 +14,29 @@ export declare const HIRE_FEATURE_KEY = "agentSys.hire";
|
|
|
10
14
|
|
|
11
15
|
export declare const PENCIL_FEATURE_KEY = "pencil";
|
|
12
16
|
|
|
17
|
+
export declare const DRAW_FEATURE_KEY = "draw";
|
|
18
|
+
|
|
19
|
+
export declare const OFFICE_FEATURE_KEY = "office";
|
|
20
|
+
|
|
21
|
+
export declare const COLLABORATION_FEATURE_KEY = "collaboration";
|
|
22
|
+
|
|
23
|
+
export declare const COLLABORATION_TASK_FEATURE_KEY = "collaboration.task";
|
|
24
|
+
|
|
25
|
+
export declare const COLLABORATION_MEETING_FEATURE_KEY = "collaboration.meeting";
|
|
26
|
+
|
|
27
|
+
export declare const COLLABORATION_DEBUG_FEATURE_KEY = "collaboration.debug";
|
|
28
|
+
|
|
29
|
+
export declare const COLLABORATION_FILE_HISTORY_FEATURE_KEY = "collaboration.fileHistory";
|
|
30
|
+
|
|
31
|
+
export declare const GROUP_KEY_TO_FEATURE: ReadonlyMap<string, string>;
|
|
32
|
+
|
|
33
|
+
export declare function resolveGroupFeatureKey(key: string): string;
|
|
34
|
+
|
|
13
35
|
export declare function setAgentFeatures(agentId: string, features: unknown): void;
|
|
14
36
|
|
|
15
|
-
export declare function getAgentFeatures(agentId: string): Record<string,
|
|
37
|
+
export declare function getAgentFeatures(agentId: string): Record<string, FeatureState>;
|
|
38
|
+
|
|
39
|
+
export declare function getFeatureState(agentId: string, key: string): FeatureState;
|
|
16
40
|
|
|
17
41
|
export declare function isFeatureEnabled(agentId: string, key: string): boolean;
|
|
18
42
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getEffective as
|
|
1
|
+
import{getEffective as U,hasAnyDefault as h}from"./capability-config.js";const K=new Set(["disabled","collapsed","expanded"]);function P(e){if(e===!0)return"expanded";if(e===!1)return"disabled";if(typeof e=="string"&&K.has(e))return e}const d={},Z="desktop",C="browser",b="agentSys.launchItem",g="agentSys.hire",M="pencil",Y="draw",B="office",N="collaboration",S="collaboration.task",F="collaboration.meeting",R="collaboration.debug",x="collaboration.fileHistory",D=new Set,j=new Set([C,M,Y,B,b,g,S,F,R,x]),v=[["agentSys","agentSys."],[N,"collaboration."]],I=new Map([["task",S],["meeting",F],["debug",R],["fileHistory",x],["launch",b],["hire",g]]);function $(e){return I.get(e)??e}function z(e){for(const[t,n]of v)if(e.startsWith(n))return t}const G=new Set,E=new Map,c=new Map,H=["fileReadOutside","commandExecution","fileModification","fileModificationOutside"],k=new Set(["allow","ask","deny"]);function J(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,n={};let o=!1;for(const r of H){const i=t[r];typeof i=="string"&&k.has(i)?(n[r]=i,o=!0):n[r]="allow"}return o?n:null}function W(e){if(e==null)return{...d};let t=e;if(typeof e=="string")try{t=JSON.parse(e)}catch{t=null}if(typeof t!="object"||t===null||Array.isArray(t))return{...d};const n={};for(const[o,r]of Object.entries(t)){if(G.has(o))continue;const i=P(r);i!==void 0&&(n[o]=i)}return n}function ee(e,t){if(!e)return;E.set(e,W(t));let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n=="object"&&n!==null&&!Array.isArray(n)){const o=J(n.toolPermissions);o?c.set(e,o):c.delete(e)}else c.delete(e)}function w(e){return E.get(e)??{...d}}function V(e,t){const n=w(e),o=z(t);if(o&&n[o]==="disabled")return"disabled";const r=n[t];return r!==void 0?r:D.has(t)?"expanded":j.has(t)?"collapsed":"disabled"}function te(e,t){return V(e,t)!=="disabled"}function ne(e){E.delete(e),c.delete(e),u.delete(e),A.delete(e)}function oe(e){return c.get(e)??null}function re(e){return c.get(e)??{fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow",fileModificationOutside:"allow"}}const X=["skills","mcp","plugins"],u=new Map,A=new Map;function q(e){if(typeof e!="object"||e===null||Array.isArray(e))return;const t={};for(const[n,o]of Object.entries(e))n.trim()&&typeof o=="boolean"&&(t[n.trim()]=o);return t}function ie(e,t){if(!e)return;if(t==null){u.delete(e);return}let n=t;if(typeof t=="string")try{n=JSON.parse(t)}catch{n=null}if(typeof n!="object"||n===null||Array.isArray(n)){u.delete(e);return}const o=n,r={};let i=!1;for(const a of X){const s=q(o[a]);s&&(r[a]=s,i=!0)}i?u.set(e,r):u.delete(e);const f=o.plugins,y={};let _=!1;if(typeof f=="object"&&f!==null&&!Array.isArray(f))for(const[a,s]of Object.entries(f)){const p=a.trim();if(p){if(typeof s=="boolean"){const l=r.plugins??{};l[p]=s,r.plugins=l,i=!0;continue}if(s!==null&&typeof s=="object"&&!Array.isArray(s)){const l=s,m=l.enabled!==!1,T=typeof l.url=="string"?l.url:void 0,L=typeof l.sha256=="string"?l.sha256:void 0,O=r.plugins??{};O[p]=m,r.plugins=O,i=!0,T&&(y[p]={url:T,sha256:L},_=!0)}}}_?A.set(e,y):A.delete(e)}function se(e){return u.get(e)??null}function le(e){return A.get(e)??null}function ue(e,t,n){if(h(t))return U(e,t,n);const o=u.get(e);if(!o)return!0;const r=o[t];if(!r)return!0;const i=r[n];return i===void 0?!0:i}function ce(){return E.size}export{C as BROWSER_FEATURE_KEY,X as CAPABILITY_TYPES,R as COLLABORATION_DEBUG_FEATURE_KEY,N as COLLABORATION_FEATURE_KEY,x as COLLABORATION_FILE_HISTORY_FEATURE_KEY,F as COLLABORATION_MEETING_FEATURE_KEY,S as COLLABORATION_TASK_FEATURE_KEY,Z as DESKTOP_FEATURE_KEY,Y as DRAW_FEATURE_KEY,I as GROUP_KEY_TO_FEATURE,g as HIRE_FEATURE_KEY,b as LAUNCH_ITEM_FEATURE_KEY,B as OFFICE_FEATURE_KEY,M as PENCIL_FEATURE_KEY,ne as clearAgentFeatures,se as getAgentCapabilities,w as getAgentFeatures,le as getAgentPluginSources,oe as getAgentToolPermissions,V as getFeatureState,ce as instanceFeaturesCacheSize,ue as isCapabilityEnabled,te as isFeatureEnabled,P as normalizeFeatureState,re as resolveAgentToolPermissions,$ as resolveGroupFeatureKey,ie as setAgentCapabilities,ee as setAgentFeatures};
|
|
2
2
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createReadStream as q,createWriteStream as O,promises as s}from"node:fs";import lt from"node:os";import w from"node:path";import{Readable as ht}from"node:stream";import{pipeline as ut}from"node:stream/promises";import{TextDecoder as wt}from"node:util";import{createGunzip as dt}from"node:zlib";import*as ft from"tar";import pt from"unzipper";const{ZipArchive:_}=await import("archiver"),x={maxEntries:1e4,maxFileBytes:512*1024*1024,maxTotalBytes:2*1024*1024*1024,maxPathDepth:64,maxPathLength:4096},mt=new wt("gbk");function u(t){return String(t||"").replace(/\\/g,"/")}function Z(t){const e=w.resolve(String(t||"").trim());if(!e)throw new Error("workspacePath is required");return e}async function yt(t){const e=Z(t),r=await s.realpath(e);if(!(await s.stat(r)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);return r}async function v(t){return{requestedRoot:Z(t),workspaceRoot:await yt(t)}}function C(t,e){const r=w.resolve(e),i=w.relative(t,r);if(i.startsWith("..")||w.isAbsolute(i))throw new Error(`Target path is outside workspace: ${r}`);return r}async function D(t){return s.realpath(t)}async function F(t){await s.realpath(w.dirname(t));try{if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${t}`)}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)!=="ENOENT")throw e}}function L(t,e,r){const i=w.resolve(r),o=w.relative(t,i);return o.startsWith("..")||w.isAbsolute(o)?i:C(e,w.join(e,o))}async function b({workspacePath:t,targetPath:e=""}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim(),a=o?L(r,i,o):i,c=await D(a);return{workspaceRoot:i,resolvedTargetPath:c}}function $(t){const e=String(t||"").trim();if(!e)throw new Error("entryName is required");if(e==="."||e==="..")throw new Error("entryName is invalid");if(e.includes("/")||e.includes("\\")||w.basename(e)!==e)throw new Error(`entryName must be a plain file or directory name: ${e}`);return e}function G(t){const e=String(t||"");if(!/[\u00c0-\u00ff]/.test(e))return e;const r=Buffer.from(e,"latin1").toString("utf8");return!r||r.includes("\uFFFD")?e:r}function B(t){const e=G(t);return $(w.basename(e.replace(/\\/g,"/")))}function gt(t,e){if(!t)return B(e);const i=G(String(t||e||"")).replace(/\\/g,"/").split("/").filter(Boolean).map(o=>$(o));return i.length===0?B(e):w.join(...i)}function H(t){return(t&4095).toString(8).padStart(4,"0")}function Pt(t){const e=String(t||"").trim();if(!/^[0-7]{3,4}$/.test(e))throw new Error("mode must be a 3 or 4 digit octal string");return Number.parseInt(e,8)}function I(t,e,r,i,o,a,c){const n=t&e?"r":"-",h=t&r?"w":"-",l=(t&i)!==0,d=(t&o)!==0?l?a:c:l?"x":"-";return`${n}${h}${d}`}function kt(t){return[I(t,256,128,64,2048,"s","S"),I(t,32,16,8,1024,"s","S"),I(t,4,2,1,512,"t","T")].join("")}function xt(t){if(!(t.length<24||t.toString("hex",0,8)!=="89504e470d0a1a0a"))return{format:"png",width:t.readUInt32BE(16),height:t.readUInt32BE(20)}}function vt(t){if(!(t.length<10||t.toString("ascii",0,6)!=="GIF87a"&&t.toString("ascii",0,6)!=="GIF89a"))return{format:"gif",width:t.readUInt16LE(6),height:t.readUInt16LE(8)}}function Et(t){if(t.length<4||t[0]!==255||t[1]!==216)return;let e=2;for(;e+9<t.length;){if(t[e]!==255){e+=1;continue}const r=t[e+1],i=t.readUInt16BE(e+2);if(i<2)return;if(r>=192&&r<=207&&![196,200,204].includes(r)&&e+8<t.length)return{format:"jpeg",height:t.readUInt16BE(e+5),width:t.readUInt16BE(e+7)};e+=2+i}}function St(t){if(t.length<30||t.toString("ascii",0,4)!=="RIFF"||t.toString("ascii",8,12)!=="WEBP")return;const e=t.toString("ascii",12,16);if(e==="VP8X"&&t.length>=30)return{format:"webp",width:1+t.readUIntLE(24,3),height:1+t.readUIntLE(27,3)};if(e==="VP8 "&&t.length>=30)return{format:"webp",width:t.readUInt16LE(26)&16383,height:t.readUInt16LE(28)&16383};if(e==="VP8L"&&t.length>=25){const r=t.readUInt32LE(21);return{format:"webp",width:(r&16383)+1,height:(r>>14&16383)+1}}}async function K(t,e){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);const i=await s.stat(t);if(!e||!i.isDirectory())return[t];const o=await s.readdir(t),a=await Promise.all(o.map(c=>{const n=w.join(t,c);return K(n,!0)}));return[t,...a.flat()]}async function Rt(t){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);await D(t)}async function Dt(t){const e=await s.open(t,"r");try{const r=Buffer.alloc(512),{bytesRead:i}=await e.read(r,0,r.length,0),o=r.subarray(0,i);return xt(o)||vt(o)||Et(o)||St(o)}finally{await e.close()}}async function T({workspacePath:t,targetPath:e},r={}){const{requestedRoot:i,workspaceRoot:o}=await v(t),a=String(e||"").trim();if(!a)throw new Error("targetPath is required");const c=L(i,o,a),n=await D(c);if(!r.allowWorkspaceRoot&&n===o)throw new Error("Workspace root cannot be modified");return{workspaceRoot:o,resolvedTargetPath:n}}async function X(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),i=String(t.targetPath||"").trim();if(!i)return{workspaceRoot:r,resolvedTargetPath:r};const o=L(e,r,i);return await et(o)?{workspaceRoot:r,resolvedTargetPath:await s.realpath(o)}:(await s.realpath(w.dirname(o)),{workspaceRoot:r,resolvedTargetPath:o})}function V(t){const e=t.toLowerCase();return e.endsWith(".zip")?"zip":e.endsWith(".tar.gz")||e.endsWith(".tgz")?"tgz":e.endsWith(".tar")?"tar":e.endsWith(".gz")?"gz":null}function Y(t){return t.replace(/\.tar\.gz$/i,"").replace(/\.tgz$/i,"").replace(/\.zip$/i,"").replace(/\.tar$/i,"").replace(/\.gz$/i,"")}function Ft(t,e){const r=$(Y(e)||"extracted");return w.join(t,r)}function M(t,e){const r=String(e||"").replace(/\\/g,"/"),i=r.split("/").filter(Boolean);if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r))throw new Error(`Archive entry path is invalid: ${e}`);if(r.length>x.maxPathLength||i.length>x.maxPathDepth)throw new Error(`Archive entry path is too deep or too long: ${e}`);return C(t,w.join(t,r))}function Tt(t){const e=t.props?.pathBuffer;if(!e||t.props?.flags?.isUnicode)return t.path;const r=mt.decode(e);return!r||r.includes("\uFFFD")?t.path:r}async function J(t){const e=t.autodrain?.();e&&await new Promise((r,i)=>{e.on("close",r),e.on("end",r),e.on("finish",r),e.on("error",i)})}function N(t){if(t.entries+=1,t.entries>x.maxEntries)throw new Error(`Archive contains too many entries. Limit: ${x.maxEntries}`)}function Q(t,e){if(t.totalBytes+=e,e>x.maxFileBytes)throw new Error(`Archive entry exceeds max size. Limit: ${x.maxFileBytes} bytes`);if(t.totalBytes>x.maxTotalBytes)throw new Error(`Archive extraction exceeds total size. Limit: ${x.maxTotalBytes} bytes`)}async function tt(t,e,r){let i=0;t.on("data",o=>{const a=Buffer.isBuffer(o)?o.length:Buffer.byteLength(o);i+=a,(i>x.maxFileBytes||r.totalBytes+i>x.maxTotalBytes)&&t instanceof ht&&t.destroy(new Error("Archive extraction size limit exceeded"))}),await ut(t,O(e)),Q(r,i)}async function et(t){try{return await s.access(t),!0}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)==="ENOENT")return!1;throw e}}async function W({workspacePath:t,filePath:e}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim();if(!o)throw new Error("filePath is required");return{workspaceRoot:i,resolvedFilePath:L(r,i,o)}}async function Gt(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.targetPath||"").trim();if(!r){const{resolvedTargetPath:h}=await b(t);return rt(e,h)}const i=w.resolve(r);let o;try{o=await s.realpath(i)}catch{throw new Error(`Path not found: ${i}`)}if(!(await s.stat(o)).isDirectory())throw new Error(`Path is not a directory: ${i}`);const c=w.relative(e,o),n=c===""||!c.startsWith("..")&&!w.isAbsolute(c);return rt(e,n?o:i)}async function rt(t,e){if(!(await s.stat(e)).isDirectory())throw new Error(`Path is not a directory: ${e}`);const i=await s.readdir(e,{withFileTypes:!0}),o=await Promise.all(i.map(async a=>{const c=w.join(e,a.name),n=a.isFile()?(await s.stat(c)).size:void 0;return{name:a.name,path:u(c),isDirectory:a.isDirectory(),size:n}}));return{currentPath:u(e),workspacePath:u(t),items:o}}async function Ht(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=await s.readFile(i,"utf-8");return{workspacePath:u(e),filePath:u(i),content:a,mtimeMs:o.mtimeMs}}const it={maxEntries:1e5,maxDepth:32};async function zt(t){let e=0,r=0;async function i(o,a){if(a>=it.maxDepth)return;let c;try{c=await s.readdir(o,{withFileTypes:!0})}catch{return}for(const n of c){if(r+=1,r>it.maxEntries)return;if(n.isSymbolicLink())continue;const h=w.join(o,n.name);try{if(n.isDirectory())await i(h,a+1);else if(n.isFile()){const l=await s.stat(h);e+=l.size}}catch{}}}return await i(t,0),e}async function Kt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t,{allowWorkspaceRoot:!0}),[i,o]=await Promise.all([s.stat(r),s.lstat(r)]),a=i.isDirectory(),c=i.isFile()?await Dt(r):void 0,n=a?await zt(r):i.size;return{workspacePath:u(e),targetPath:u(r),name:w.basename(r),isDirectory:i.isDirectory(),isFile:i.isFile(),isSymbolicLink:o.isSymbolicLink(),size:n,mode:i.mode,modeOctal:H(i.mode),permissions:kt(i.mode),uid:i.uid,gid:i.gid,atimeMs:i.atimeMs,mtimeMs:i.mtimeMs,ctimeMs:i.ctimeMs,birthtimeMs:i.birthtimeMs,...c?{image:c}:{}}}async function Xt(t){const e=Pt(t.mode),r=!!t.recursive,{workspaceRoot:i,resolvedTargetPath:o}=await T(t),a=await K(o,r);for(const c of a)await Rt(c),await s.chmod(c,e);return{ok:!0,workspacePath:u(i),targetPath:u(o),mode:e,modeOctal:H(e),recursive:r,changedCount:a.length}}async function Vt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=w.extname(i).toLowerCase();if(a===".doc")return{workspacePath:u(e),filePath:u(i),kind:"unsupported",content:"",message:"\u6682\u4E0D\u652F\u6301\u65E7\u7248 .doc \u683C\u5F0F\u9884\u89C8\uFF0C\u8BF7\u53E6\u5B58\u4E3A .docx \u540E\u518D\u6253\u5F00\u3002",size:o.size,mtimeMs:o.mtimeMs};if(a!==".docx")throw new Error("Document preview only supports .docx files");return{workspacePath:u(e),filePath:u(i),kind:"html",content:"",size:o.size,mtimeMs:o.mtimeMs}}async function Yt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t);await s.mkdir(w.dirname(r),{recursive:!0}),await F(r),await s.writeFile(r,String(t.content??""),"utf-8");const i=await s.stat(r);return{ok:!0,workspacePath:u(e),filePath:u(r),mtimeMs:i.mtimeMs}}async function Jt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await b(t),i=$(t.entryName),o=w.join(r,i);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(c){if((typeof c=="object"&&c!==null?Reflect.get(c,"code"):void 0)!=="ENOENT")throw c}return t.isDirectory?await s.mkdir(o,{recursive:!1}):(await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await s.writeFile(o,"","utf-8")),{ok:!0,workspacePath:u(e),targetPath:u(o),isDirectory:t.isDirectory}}async function Qt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=$(t.newName),o=w.join(w.dirname(r),i);if(o===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)};await s.stat(r);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(a){if((typeof a=="object"&&a!==null?Reflect.get(a,"code"):void 0)!=="ENOENT")throw a}return await s.rename(r,o),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)}}async function te(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await b({workspacePath:t.workspacePath,targetPath:t.destinationPath});if(!(await s.stat(i.resolvedTargetPath)).isDirectory())throw new Error(`Destination is not a directory: ${i.resolvedTargetPath}`);if((await s.stat(r)).isDirectory()){const n=w.relative(r,i.resolvedTargetPath);if(n===""||!n.startsWith("..")&&!w.isAbsolute(n))throw new Error("Cannot move a directory into itself or its descendant")}const c=w.join(i.resolvedTargetPath,w.basename(r));if(c===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)};try{throw await s.access(c),new Error(`Path already exists: ${c}`)}catch(n){if((typeof n=="object"&&n!==null?Reflect.get(n,"code"):void 0)!=="ENOENT")throw n}return await s.rename(r,c),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)}}async function ee(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.parse(r).root;if(r===o)throw new Error("Filesystem root cannot be deleted");return i.isDirectory()?await s.rm(r,{recursive:!0,force:!1}):await s.unlink(r),{ok:!0,workspacePath:u(e),targetPath:u(r)}}async function re(t){if(!Array.isArray(t.files)||t.files.length===0)throw new Error("files are required");const{workspaceRoot:e,resolvedTargetPath:r}=await X(t);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);const o=[];for(const a of t.files){const c=B(a.originalname),n=gt(a.relativePath,a.originalname),h=w.join(r,n);await s.mkdir(w.dirname(h),{recursive:!0}),await F(h),await s.copyFile(a.path,h);let l;t.extractArchives&&V(h)&&(l=await Wt({workspacePath:e,archivePath:h,outputPath:Ft(r,c)})),o.push({fileName:c,targetPath:u(h),size:a.size,extracted:l})}return{ok:!0,workspacePath:u(e),targetPath:u(r),files:o}}async function ie(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.basename(r);return{workspacePath:u(e),targetPath:u(r),resolvedTargetPath:r,fileName:i.isDirectory()?`${o||"workspace"}.zip`:o,contentType:i.isDirectory()?"application/zip":Lt(r),isDirectory:i.isDirectory(),size:i.isDirectory()?void 0:i.size}}function Lt(t){const e=w.extname(t).toLowerCase();return{".svg":"image/svg+xml",".svgz":"image/svg+xml",".ico":"image/x-icon",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".avif":"image/avif",".txt":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".md":"text/markdown; charset=utf-8",".csv":"text/csv; charset=utf-8",".pdf":"application/pdf",".zip":"application/zip",".mp3":"audio/mpeg",".wav":"audio/wav",".mp4":"video/mp4",".webm":"video/webm"}[e]||"application/octet-stream"}async function oe(t,e){const r=new _({zlib:{level:9}}),i=new Promise((o,a)=>{e.on("close",o),e.on("finish",o),r.on("error",a),e.on("error",a)});r.pipe(e),r.directory(t,!1),await r.finalize(),await i}async function ae(t,e,r,i){const o=w.join(lt.tmpdir(),"agentswork-bridge-downloads");await s.mkdir(o,{recursive:!0});const a=(e||"workspace.zip").replace(/[^\w.-]/g,"_").replace(/\.zip$/i,"")||"workspace",c=w.join(o,`${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`),n=new _({zlib:{level:9}}),h=()=>n.pointer(),l=()=>n.abort(),f=O(c),d=new Promise((m,g)=>{f.on("close",m),f.on("finish",m),n.on("error",g),f.on("error",g)});d.catch(()=>{}),n.pipe(f);const y=setInterval(()=>{try{if(i?.()){l();return}r?.(h())}catch{}},200);try{return n.on("progress",()=>{i?.()&&l()}),n.directory(t,!1),i?.()&&l(),await n.finalize(),await d,r?.(h()),c}catch(m){throw await s.rm(c,{force:!0}).catch(()=>{}),m}finally{clearInterval(y)}}async function $t(t,e,r){let i=0,o;const a=q(t),c=a.pipe(pt.Parse({forceStream:!0}));try{for await(const n of c){if(o){await J(n);continue}const h=Tt(n);try{const l=M(e,h);if(N(r),n.type==="Directory"){await s.mkdir(l,{recursive:!0});continue}if(n.type!=="File")throw new Error(`Unsupported archive entry type: ${h}`);await s.mkdir(w.dirname(l),{recursive:!0}),await F(l),await tt(n,l,r),i+=1}catch(l){o=l,await J(n)}}}finally{a.destroy(),c.destroy()}if(o)throw o;return i}async function At(t,e,r,i){let o=0,a;const c=(n,h)=>{if(a)return!1;try{M(e,n),N(i);const l=String(h.type||"").toLowerCase();if(l==="symboliclink"||l==="link")throw new Error(`Archive links are not supported: ${n}`);if(l!=="file"&&l!=="oldfile"&&l!=="contiguousfile"&&l!=="directory")throw new Error(`Unsupported archive entry type: ${n}`);return typeof h.size=="number"&&Q(i,h.size),l!=="directory"&&(o+=1),!0}catch(l){return a=l,!1}};if(await ft.x({file:t,cwd:e,gzip:r,strict:!0,filter:(n,h)=>c(n,h)}),a)throw a;return o}async function Ct(t,e,r){const i=Y(w.basename(t)),o=M(e,i||"decompressed");return N(r),await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await tt(q(t).pipe(dt()),o,r),1}async function Wt(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),{resolvedTargetPath:i}=await X({workspacePath:t.workspacePath,targetPath:t.outputPath||""}),o=L(e,r,String(t.archivePath||"").trim()),a=await D(o);if(!(await s.stat(a)).isFile())throw new Error(`Archive path is not a file: ${a}`);if(await et(i)||await s.mkdir(i,{recursive:!0}),!(await s.stat(i)).isDirectory())throw new Error(`Output path is not a directory: ${i}`);const h=V(a);if(!h)throw new Error("Unsupported archive type. Supported: .zip, .tar, .tar.gz, .tgz, .gz");let l=0;const f={entries:0,totalBytes:0};return h==="zip"?l=await $t(a,i,f):h==="tar"||h==="tgz"?l=await At(a,i,h==="tgz",f):l=await Ct(a,i,f),{ok:!0,workspacePath:u(r),archivePath:u(a),targetPath:u(i),extractedEntries:l}}function ot(t){const e=t.match(/^(.*?)\{([^}]+)\}(.*)$/);if(!e)return[t];const[,r,i,o]=e;return i.split(",").flatMap(a=>ot(r+a.trim()+o))}function at(t,e){const r=String(e||"").trim();if(!r||r==="*"||r==="*.*")return!0;const i=t.toLowerCase();return ot(r.toLowerCase()).some(a=>{if(a==="*")return!0;const c=a.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/<<GLOBSTAR>>/g,".*");return new RegExp(`^${c}$`).test(i)})}function j(t){return t===".git"||t==="node_modules"||t===".svn"||t===".hg"}const nt=10*1024*1024,bt=1e3;async function ne(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=String(t.fileMask||"").trim(),a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:bt,c=i?r.toLowerCase():r,h=(t.mode==="filename"?"filename":"content")==="filename",l=[];let f=0,d=!1;async function y(m){if(d)return;let g;try{g=await s.readdir(m,{withFileTypes:!0})}catch{return}for(const p of g){if(d)return;const P=C(e,w.join(m,p.name));if(p.isSymbolicLink())continue;if(p.isDirectory()){if(j(p.name))continue;await y(P);continue}if(!p.isFile()||o&&!at(p.name,o))continue;f+=1;let k;try{k=await s.stat(P)}catch{continue}if(k.size>nt)continue;if(h){const E=(i?p.name.toLowerCase():p.name).indexOf(c);if(E!==-1&&(l.push({filePath:u(P),lineNumber:0,lineContent:p.name,matchStart:E,matchEnd:E+r.length}),l.length>=a)){d=!0;return}continue}let S;try{S=await s.readFile(P,"utf-8")}catch{continue}const z=S.split(/\r?\n/);for(let R=0;R<z.length;R+=1){const E=z[R],ct=i?E.toLowerCase():E;let U=0;for(;;){const A=ct.indexOf(c,U);if(A===-1)break;if(l.push({filePath:u(P),lineNumber:R+1,lineContent:E,matchStart:A,matchEnd:A+r.length}),l.length>=a){d=!0;return}U=A+1}}}}return await y(e),{workspacePath:u(e),keyword:r,totalFiles:f,totalMatches:l.length,matches:l,truncated:d}}const Bt=100,It=120;async function se(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=i?r.toLowerCase():r,a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:Bt,c=typeof t.maxDirectories=="number"&&t.maxDirectories>0?t.maxDirectories:It,n=String(t.rootPath||"").trim(),h=n?w.resolve(/^[A-Za-z]:$/.test(n)?`${n}/`:n):e;let l;try{l=await s.realpath(h)}catch{throw new Error(`Path not found: ${h}`)}if(!(await s.stat(l)).isDirectory())throw new Error(`Path is not a directory: ${h}`);const d=[],y=[l];let m=0,g=!1;for(;y.length>0&&d.length<a&&m<c;){const p=y.shift();m+=1;let P;try{P=await s.readdir(p,{withFileTypes:!0})}catch{continue}for(const k of P){if(d.length>=a){g=!0;break}if(k.isSymbolicLink())continue;const S=w.join(p,k.name);if(k.isDirectory()&&j(k.name))continue;const z=w.relative(l,S).replace(/\\/g,"/");(i?z.toLowerCase():z).includes(o)&&d.push({name:k.name,path:u(S),isDirectory:k.isDirectory()}),k.isDirectory()&&m<c&&y.push(S)}}return(m>=c||d.length>=a)&&(g=!0),d.sort((p,P)=>p.isDirectory===P.isDirectory?p.name.localeCompare(P.name):p.isDirectory?-1:1),{workspacePath:u(e),rootPath:u(l),keyword:r,items:d,truncated:g}}async function st(t,e,r,i){let o;try{o=await s.readFile(t,"utf-8")}catch{return{changed:!1,count:0}}const a=o;let c=0;if(i){const n=e.toLowerCase();let h=0;for(;;){const f=o.toLowerCase().indexOf(n,h);if(f===-1)break;o=o.slice(0,f)+r+o.slice(f+e.length),c+=1;const d=r.length||1;h=f+d}}else{let n=0;for(;;){const h=o.indexOf(e,n);if(h===-1)break;o=o.slice(0,h)+r+o.slice(h+e.length),c+=1;const l=r.length||1;n=h+l}}return o===a?{changed:!1,count:0}:(await F(t),await s.writeFile(t,o,"utf-8"),{changed:!0,count:c})}async function ce(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=String(t.replacement??""),o=!!t.ignoreCase,a=String(t.fileMask||"").trim(),c=String(t.filePath||"").trim();let n=0,h=0;if(c){const{resolvedFilePath:f}=await W({workspacePath:t.workspacePath,filePath:c}),d=await st(f,r,i,o);return d.changed&&(n=1,h=d.count),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}async function l(f){let d;try{d=await s.readdir(f,{withFileTypes:!0})}catch{return}for(const y of d){const m=C(e,w.join(f,y.name));if(y.isSymbolicLink())continue;if(y.isDirectory()){if(j(y.name))continue;await l(m);continue}if(!y.isFile()||a&&!at(y.name,a))continue;try{if((await s.stat(m)).size>nt)continue}catch{continue}const g=await st(m,r,i,o);g.changed&&(n+=1,h+=g.count)}}return await l(e),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}export{Xt as chmodWorkspaceEntry,Jt as createWorkspaceEntry,ee as deleteWorkspaceEntry,Wt as extractWorkspaceArchive,Kt as getWorkspaceEntryProperties,Gt as listWorkspaceDirectory,te as moveWorkspaceEntry,Vt as previewWorkspaceDocument,Ht as readWorkspaceFile,Qt as renameWorkspaceEntry,ce as replaceWorkspaceFiles,ie as resolveWorkspaceDownloadTarget,ne as searchWorkspaceFiles,se as searchWorkspacePaths,oe as streamWorkspaceDirectoryZip,re as uploadWorkspaceFiles,Yt as writeWorkspaceFile,ae as zipWorkspaceDirectoryToTemp};
|
|
1
|
+
import{createReadStream as q,createWriteStream as O,promises as s}from"node:fs";import lt from"node:os";import w from"node:path";import{Readable as ht}from"node:stream";import{pipeline as ut}from"node:stream/promises";import{TextDecoder as wt}from"node:util";import{createGunzip as dt}from"node:zlib";import*as ft from"tar";import pt from"unzipper";const{ZipArchive:_}=await import("archiver"),x={maxEntries:1e4,maxFileBytes:512*1024*1024,maxTotalBytes:2*1024*1024*1024,maxPathDepth:64,maxPathLength:4096},mt=new wt("gbk");function u(t){return String(t||"").replace(/\\/g,"/")}function Z(t){const e=w.resolve(String(t||"").trim());if(!e)throw new Error("workspacePath is required");return e}async function yt(t){const e=Z(t),r=await s.realpath(e);if(!(await s.stat(r)).isDirectory())throw new Error(`Workspace path is not a directory: ${e}`);return r}async function v(t){return{requestedRoot:Z(t),workspaceRoot:await yt(t)}}function C(t,e){const r=w.resolve(e),i=w.relative(t,r);if(i.startsWith("..")||w.isAbsolute(i))throw new Error(`Target path is outside workspace: ${r}`);return r}async function D(t){return s.realpath(t)}async function F(t){await s.realpath(w.dirname(t));try{if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${t}`)}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)!=="ENOENT")throw e}}function L(t,e,r){const i=w.resolve(t,r),o=w.relative(t,i);return o.startsWith("..")||w.isAbsolute(o)?i:C(e,w.join(e,o))}async function b({workspacePath:t,targetPath:e=""}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim(),a=o?L(r,i,o):i,c=await D(a);return{workspaceRoot:i,resolvedTargetPath:c}}function $(t){const e=String(t||"").trim();if(!e)throw new Error("entryName is required");if(e==="."||e==="..")throw new Error("entryName is invalid");if(e.includes("/")||e.includes("\\")||w.basename(e)!==e)throw new Error(`entryName must be a plain file or directory name: ${e}`);return e}function G(t){const e=String(t||"");if(!/[\u00c0-\u00ff]/.test(e))return e;const r=Buffer.from(e,"latin1").toString("utf8");return!r||r.includes("\uFFFD")?e:r}function B(t){const e=G(t);return $(w.basename(e.replace(/\\/g,"/")))}function gt(t,e){if(!t)return B(e);const i=G(String(t||e||"")).replace(/\\/g,"/").split("/").filter(Boolean).map(o=>$(o));return i.length===0?B(e):w.join(...i)}function H(t){return(t&4095).toString(8).padStart(4,"0")}function Pt(t){const e=String(t||"").trim();if(!/^[0-7]{3,4}$/.test(e))throw new Error("mode must be a 3 or 4 digit octal string");return Number.parseInt(e,8)}function I(t,e,r,i,o,a,c){const n=t&e?"r":"-",h=t&r?"w":"-",l=(t&i)!==0,d=(t&o)!==0?l?a:c:l?"x":"-";return`${n}${h}${d}`}function kt(t){return[I(t,256,128,64,2048,"s","S"),I(t,32,16,8,1024,"s","S"),I(t,4,2,1,512,"t","T")].join("")}function xt(t){if(!(t.length<24||t.toString("hex",0,8)!=="89504e470d0a1a0a"))return{format:"png",width:t.readUInt32BE(16),height:t.readUInt32BE(20)}}function vt(t){if(!(t.length<10||t.toString("ascii",0,6)!=="GIF87a"&&t.toString("ascii",0,6)!=="GIF89a"))return{format:"gif",width:t.readUInt16LE(6),height:t.readUInt16LE(8)}}function Et(t){if(t.length<4||t[0]!==255||t[1]!==216)return;let e=2;for(;e+9<t.length;){if(t[e]!==255){e+=1;continue}const r=t[e+1],i=t.readUInt16BE(e+2);if(i<2)return;if(r>=192&&r<=207&&![196,200,204].includes(r)&&e+8<t.length)return{format:"jpeg",height:t.readUInt16BE(e+5),width:t.readUInt16BE(e+7)};e+=2+i}}function St(t){if(t.length<30||t.toString("ascii",0,4)!=="RIFF"||t.toString("ascii",8,12)!=="WEBP")return;const e=t.toString("ascii",12,16);if(e==="VP8X"&&t.length>=30)return{format:"webp",width:1+t.readUIntLE(24,3),height:1+t.readUIntLE(27,3)};if(e==="VP8 "&&t.length>=30)return{format:"webp",width:t.readUInt16LE(26)&16383,height:t.readUInt16LE(28)&16383};if(e==="VP8L"&&t.length>=25){const r=t.readUInt32LE(21);return{format:"webp",width:(r&16383)+1,height:(r>>14&16383)+1}}}async function K(t,e){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);const i=await s.stat(t);if(!e||!i.isDirectory())return[t];const o=await s.readdir(t),a=await Promise.all(o.map(c=>{const n=w.join(t,c);return K(n,!0)}));return[t,...a.flat()]}async function Rt(t){if((await s.lstat(t)).isSymbolicLink())throw new Error(`Refusing to change permissions on symbolic link: ${t}`);await D(t)}async function Dt(t){const e=await s.open(t,"r");try{const r=Buffer.alloc(512),{bytesRead:i}=await e.read(r,0,r.length,0),o=r.subarray(0,i);return xt(o)||vt(o)||Et(o)||St(o)}finally{await e.close()}}async function T({workspacePath:t,targetPath:e},r={}){const{requestedRoot:i,workspaceRoot:o}=await v(t),a=String(e||"").trim();if(!a)throw new Error("targetPath is required");const c=L(i,o,a),n=await D(c);if(!r.allowWorkspaceRoot&&n===o)throw new Error("Workspace root cannot be modified");return{workspaceRoot:o,resolvedTargetPath:n}}async function X(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),i=String(t.targetPath||"").trim();if(!i)return{workspaceRoot:r,resolvedTargetPath:r};const o=L(e,r,i);return await et(o)?{workspaceRoot:r,resolvedTargetPath:await s.realpath(o)}:(await s.realpath(w.dirname(o)),{workspaceRoot:r,resolvedTargetPath:o})}function V(t){const e=t.toLowerCase();return e.endsWith(".zip")?"zip":e.endsWith(".tar.gz")||e.endsWith(".tgz")?"tgz":e.endsWith(".tar")?"tar":e.endsWith(".gz")?"gz":null}function Y(t){return t.replace(/\.tar\.gz$/i,"").replace(/\.tgz$/i,"").replace(/\.zip$/i,"").replace(/\.tar$/i,"").replace(/\.gz$/i,"")}function Ft(t,e){const r=$(Y(e)||"extracted");return w.join(t,r)}function M(t,e){const r=String(e||"").replace(/\\/g,"/"),i=r.split("/").filter(Boolean);if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r))throw new Error(`Archive entry path is invalid: ${e}`);if(r.length>x.maxPathLength||i.length>x.maxPathDepth)throw new Error(`Archive entry path is too deep or too long: ${e}`);return C(t,w.join(t,r))}function Tt(t){const e=t.props?.pathBuffer;if(!e||t.props?.flags?.isUnicode)return t.path;const r=mt.decode(e);return!r||r.includes("\uFFFD")?t.path:r}async function J(t){const e=t.autodrain?.();e&&await new Promise((r,i)=>{e.on("close",r),e.on("end",r),e.on("finish",r),e.on("error",i)})}function N(t){if(t.entries+=1,t.entries>x.maxEntries)throw new Error(`Archive contains too many entries. Limit: ${x.maxEntries}`)}function Q(t,e){if(t.totalBytes+=e,e>x.maxFileBytes)throw new Error(`Archive entry exceeds max size. Limit: ${x.maxFileBytes} bytes`);if(t.totalBytes>x.maxTotalBytes)throw new Error(`Archive extraction exceeds total size. Limit: ${x.maxTotalBytes} bytes`)}async function tt(t,e,r){let i=0;t.on("data",o=>{const a=Buffer.isBuffer(o)?o.length:Buffer.byteLength(o);i+=a,(i>x.maxFileBytes||r.totalBytes+i>x.maxTotalBytes)&&t instanceof ht&&t.destroy(new Error("Archive extraction size limit exceeded"))}),await ut(t,O(e)),Q(r,i)}async function et(t){try{return await s.access(t),!0}catch(e){if((typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0)==="ENOENT")return!1;throw e}}async function W({workspacePath:t,filePath:e}){const{requestedRoot:r,workspaceRoot:i}=await v(t),o=String(e||"").trim();if(!o)throw new Error("filePath is required");return{workspaceRoot:i,resolvedFilePath:L(r,i,o)}}async function Gt(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.targetPath||"").trim();if(!r){const{resolvedTargetPath:h}=await b(t);return rt(e,h)}const i=w.resolve(r);let o;try{o=await s.realpath(i)}catch{throw new Error(`Path not found: ${i}`)}if(!(await s.stat(o)).isDirectory())throw new Error(`Path is not a directory: ${i}`);const c=w.relative(e,o),n=c===""||!c.startsWith("..")&&!w.isAbsolute(c);return rt(e,n?o:i)}async function rt(t,e){if(!(await s.stat(e)).isDirectory())throw new Error(`Path is not a directory: ${e}`);const i=await s.readdir(e,{withFileTypes:!0}),o=await Promise.all(i.map(async a=>{const c=w.join(e,a.name),n=a.isFile()?(await s.stat(c)).size:void 0;return{name:a.name,path:u(c),isDirectory:a.isDirectory(),size:n}}));return{currentPath:u(e),workspacePath:u(t),items:o}}async function Ht(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=await s.readFile(i,"utf-8");return{workspacePath:u(e),filePath:u(i),content:a,mtimeMs:o.mtimeMs}}const it={maxEntries:1e5,maxDepth:32};async function zt(t){let e=0,r=0;async function i(o,a){if(a>=it.maxDepth)return;let c;try{c=await s.readdir(o,{withFileTypes:!0})}catch{return}for(const n of c){if(r+=1,r>it.maxEntries)return;if(n.isSymbolicLink())continue;const h=w.join(o,n.name);try{if(n.isDirectory())await i(h,a+1);else if(n.isFile()){const l=await s.stat(h);e+=l.size}}catch{}}}return await i(t,0),e}async function Kt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t,{allowWorkspaceRoot:!0}),[i,o]=await Promise.all([s.stat(r),s.lstat(r)]),a=i.isDirectory(),c=i.isFile()?await Dt(r):void 0,n=a?await zt(r):i.size;return{workspacePath:u(e),targetPath:u(r),name:w.basename(r),isDirectory:i.isDirectory(),isFile:i.isFile(),isSymbolicLink:o.isSymbolicLink(),size:n,mode:i.mode,modeOctal:H(i.mode),permissions:kt(i.mode),uid:i.uid,gid:i.gid,atimeMs:i.atimeMs,mtimeMs:i.mtimeMs,ctimeMs:i.ctimeMs,birthtimeMs:i.birthtimeMs,...c?{image:c}:{}}}async function Xt(t){const e=Pt(t.mode),r=!!t.recursive,{workspaceRoot:i,resolvedTargetPath:o}=await T(t),a=await K(o,r);for(const c of a)await Rt(c),await s.chmod(c,e);return{ok:!0,workspacePath:u(i),targetPath:u(o),mode:e,modeOctal:H(e),recursive:r,changedCount:a.length}}async function Vt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t),i=await D(r),o=await s.stat(i);if(!o.isFile())throw new Error(`Path is not a file: ${i}`);const a=w.extname(i).toLowerCase();if(a===".doc")return{workspacePath:u(e),filePath:u(i),kind:"unsupported",content:"",message:"\u6682\u4E0D\u652F\u6301\u65E7\u7248 .doc \u683C\u5F0F\u9884\u89C8\uFF0C\u8BF7\u53E6\u5B58\u4E3A .docx \u540E\u518D\u6253\u5F00\u3002",size:o.size,mtimeMs:o.mtimeMs};if(a!==".docx")throw new Error("Document preview only supports .docx files");return{workspacePath:u(e),filePath:u(i),kind:"html",content:"",size:o.size,mtimeMs:o.mtimeMs}}async function Yt(t){const{workspaceRoot:e,resolvedFilePath:r}=await W(t);await s.mkdir(w.dirname(r),{recursive:!0}),await F(r),await s.writeFile(r,String(t.content??""),"utf-8");const i=await s.stat(r);return{ok:!0,workspacePath:u(e),filePath:u(r),mtimeMs:i.mtimeMs}}async function Jt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await b(t),i=$(t.entryName),o=w.join(r,i);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(c){if((typeof c=="object"&&c!==null?Reflect.get(c,"code"):void 0)!=="ENOENT")throw c}return t.isDirectory?await s.mkdir(o,{recursive:!1}):(await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await s.writeFile(o,"","utf-8")),{ok:!0,workspacePath:u(e),targetPath:u(o),isDirectory:t.isDirectory}}async function Qt(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=$(t.newName),o=w.join(w.dirname(r),i);if(o===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)};await s.stat(r);try{throw await s.access(o),new Error(`Path already exists: ${o}`)}catch(a){if((typeof a=="object"&&a!==null?Reflect.get(a,"code"):void 0)!=="ENOENT")throw a}return await s.rename(r,o),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(o)}}async function te(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await b({workspacePath:t.workspacePath,targetPath:t.destinationPath});if(!(await s.stat(i.resolvedTargetPath)).isDirectory())throw new Error(`Destination is not a directory: ${i.resolvedTargetPath}`);if((await s.stat(r)).isDirectory()){const n=w.relative(r,i.resolvedTargetPath);if(n===""||!n.startsWith("..")&&!w.isAbsolute(n))throw new Error("Cannot move a directory into itself or its descendant")}const c=w.join(i.resolvedTargetPath,w.basename(r));if(c===r)return{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)};try{throw await s.access(c),new Error(`Path already exists: ${c}`)}catch(n){if((typeof n=="object"&&n!==null?Reflect.get(n,"code"):void 0)!=="ENOENT")throw n}return await s.rename(r,c),{ok:!0,workspacePath:u(e),sourcePath:u(r),targetPath:u(c),destinationPath:u(i.resolvedTargetPath)}}async function ee(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.parse(r).root;if(r===o)throw new Error("Filesystem root cannot be deleted");return i.isDirectory()?await s.rm(r,{recursive:!0,force:!1}):await s.unlink(r),{ok:!0,workspacePath:u(e),targetPath:u(r)}}async function re(t){if(!Array.isArray(t.files)||t.files.length===0)throw new Error("files are required");const{workspaceRoot:e,resolvedTargetPath:r}=await X(t);if(!(await s.stat(r)).isDirectory())throw new Error(`Path is not a directory: ${r}`);const o=[];for(const a of t.files){const c=B(a.originalname),n=gt(a.relativePath,a.originalname),h=w.join(r,n);await s.mkdir(w.dirname(h),{recursive:!0}),await F(h),await s.copyFile(a.path,h);let l;t.extractArchives&&V(h)&&(l=await Wt({workspacePath:e,archivePath:h,outputPath:Ft(r,c)})),o.push({fileName:c,targetPath:u(h),size:a.size,extracted:l})}return{ok:!0,workspacePath:u(e),targetPath:u(r),files:o}}async function ie(t){const{workspaceRoot:e,resolvedTargetPath:r}=await T(t),i=await s.stat(r),o=w.basename(r);return{workspacePath:u(e),targetPath:u(r),resolvedTargetPath:r,fileName:i.isDirectory()?`${o||"workspace"}.zip`:o,contentType:i.isDirectory()?"application/zip":Lt(r),isDirectory:i.isDirectory(),size:i.isDirectory()?void 0:i.size}}function Lt(t){const e=w.extname(t).toLowerCase();return{".svg":"image/svg+xml",".svgz":"image/svg+xml",".ico":"image/x-icon",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".avif":"image/avif",".txt":"text/plain; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".md":"text/markdown; charset=utf-8",".csv":"text/csv; charset=utf-8",".pdf":"application/pdf",".zip":"application/zip",".mp3":"audio/mpeg",".wav":"audio/wav",".mp4":"video/mp4",".webm":"video/webm"}[e]||"application/octet-stream"}async function oe(t,e){const r=new _({zlib:{level:9}}),i=new Promise((o,a)=>{e.on("close",o),e.on("finish",o),r.on("error",a),e.on("error",a)});r.pipe(e),r.directory(t,!1),await r.finalize(),await i}async function ae(t,e,r,i){const o=w.join(lt.tmpdir(),"agentswork-bridge-downloads");await s.mkdir(o,{recursive:!0});const a=(e||"workspace.zip").replace(/[^\w.-]/g,"_").replace(/\.zip$/i,"")||"workspace",c=w.join(o,`${a}-${Date.now()}-${Math.random().toString(36).slice(2,8)}.zip`),n=new _({zlib:{level:9}}),h=()=>n.pointer(),l=()=>n.abort(),f=O(c),d=new Promise((m,g)=>{f.on("close",m),f.on("finish",m),n.on("error",g),f.on("error",g)});d.catch(()=>{}),n.pipe(f);const y=setInterval(()=>{try{if(i?.()){l();return}r?.(h())}catch{}},200);try{return n.on("progress",()=>{i?.()&&l()}),n.directory(t,!1),i?.()&&l(),await n.finalize(),await d,r?.(h()),c}catch(m){throw await s.rm(c,{force:!0}).catch(()=>{}),m}finally{clearInterval(y)}}async function $t(t,e,r){let i=0,o;const a=q(t),c=a.pipe(pt.Parse({forceStream:!0}));try{for await(const n of c){if(o){await J(n);continue}const h=Tt(n);try{const l=M(e,h);if(N(r),n.type==="Directory"){await s.mkdir(l,{recursive:!0});continue}if(n.type!=="File")throw new Error(`Unsupported archive entry type: ${h}`);await s.mkdir(w.dirname(l),{recursive:!0}),await F(l),await tt(n,l,r),i+=1}catch(l){o=l,await J(n)}}}finally{a.destroy(),c.destroy()}if(o)throw o;return i}async function At(t,e,r,i){let o=0,a;const c=(n,h)=>{if(a)return!1;try{M(e,n),N(i);const l=String(h.type||"").toLowerCase();if(l==="symboliclink"||l==="link")throw new Error(`Archive links are not supported: ${n}`);if(l!=="file"&&l!=="oldfile"&&l!=="contiguousfile"&&l!=="directory")throw new Error(`Unsupported archive entry type: ${n}`);return typeof h.size=="number"&&Q(i,h.size),l!=="directory"&&(o+=1),!0}catch(l){return a=l,!1}};if(await ft.x({file:t,cwd:e,gzip:r,strict:!0,filter:(n,h)=>c(n,h)}),a)throw a;return o}async function Ct(t,e,r){const i=Y(w.basename(t)),o=M(e,i||"decompressed");return N(r),await s.mkdir(w.dirname(o),{recursive:!0}),await F(o),await tt(q(t).pipe(dt()),o,r),1}async function Wt(t){const{requestedRoot:e,workspaceRoot:r}=await v(t.workspacePath),{resolvedTargetPath:i}=await X({workspacePath:t.workspacePath,targetPath:t.outputPath||""}),o=L(e,r,String(t.archivePath||"").trim()),a=await D(o);if(!(await s.stat(a)).isFile())throw new Error(`Archive path is not a file: ${a}`);if(await et(i)||await s.mkdir(i,{recursive:!0}),!(await s.stat(i)).isDirectory())throw new Error(`Output path is not a directory: ${i}`);const h=V(a);if(!h)throw new Error("Unsupported archive type. Supported: .zip, .tar, .tar.gz, .tgz, .gz");let l=0;const f={entries:0,totalBytes:0};return h==="zip"?l=await $t(a,i,f):h==="tar"||h==="tgz"?l=await At(a,i,h==="tgz",f):l=await Ct(a,i,f),{ok:!0,workspacePath:u(r),archivePath:u(a),targetPath:u(i),extractedEntries:l}}function ot(t){const e=t.match(/^(.*?)\{([^}]+)\}(.*)$/);if(!e)return[t];const[,r,i,o]=e;return i.split(",").flatMap(a=>ot(r+a.trim()+o))}function at(t,e){const r=String(e||"").trim();if(!r||r==="*"||r==="*.*")return!0;const i=t.toLowerCase();return ot(r.toLowerCase()).some(a=>{if(a==="*")return!0;const c=a.replace(/\./g,"\\.").replace(/\*\*/g,"<<GLOBSTAR>>").replace(/\*/g,"[^/]*").replace(/\?/g,"[^/]").replace(/<<GLOBSTAR>>/g,".*");return new RegExp(`^${c}$`).test(i)})}function j(t){return t===".git"||t==="node_modules"||t===".svn"||t===".hg"}const nt=10*1024*1024,bt=1e3;async function ne(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=String(t.fileMask||"").trim(),a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:bt,c=i?r.toLowerCase():r,h=(t.mode==="filename"?"filename":"content")==="filename",l=[];let f=0,d=!1;async function y(m){if(d)return;let g;try{g=await s.readdir(m,{withFileTypes:!0})}catch{return}for(const p of g){if(d)return;const P=C(e,w.join(m,p.name));if(p.isSymbolicLink())continue;if(p.isDirectory()){if(j(p.name))continue;await y(P);continue}if(!p.isFile()||o&&!at(p.name,o))continue;f+=1;let k;try{k=await s.stat(P)}catch{continue}if(k.size>nt)continue;if(h){const E=(i?p.name.toLowerCase():p.name).indexOf(c);if(E!==-1&&(l.push({filePath:u(P),lineNumber:0,lineContent:p.name,matchStart:E,matchEnd:E+r.length}),l.length>=a)){d=!0;return}continue}let S;try{S=await s.readFile(P,"utf-8")}catch{continue}const z=S.split(/\r?\n/);for(let R=0;R<z.length;R+=1){const E=z[R],ct=i?E.toLowerCase():E;let U=0;for(;;){const A=ct.indexOf(c,U);if(A===-1)break;if(l.push({filePath:u(P),lineNumber:R+1,lineContent:E,matchStart:A,matchEnd:A+r.length}),l.length>=a){d=!0;return}U=A+1}}}}return await y(e),{workspacePath:u(e),keyword:r,totalFiles:f,totalMatches:l.length,matches:l,truncated:d}}const Bt=100,It=120;async function se(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=!!t.ignoreCase,o=i?r.toLowerCase():r,a=typeof t.maxResults=="number"&&t.maxResults>0?t.maxResults:Bt,c=typeof t.maxDirectories=="number"&&t.maxDirectories>0?t.maxDirectories:It,n=String(t.rootPath||"").trim(),h=n?w.resolve(/^[A-Za-z]:$/.test(n)?`${n}/`:n):e;let l;try{l=await s.realpath(h)}catch{throw new Error(`Path not found: ${h}`)}if(!(await s.stat(l)).isDirectory())throw new Error(`Path is not a directory: ${h}`);const d=[],y=[l];let m=0,g=!1;for(;y.length>0&&d.length<a&&m<c;){const p=y.shift();m+=1;let P;try{P=await s.readdir(p,{withFileTypes:!0})}catch{continue}for(const k of P){if(d.length>=a){g=!0;break}if(k.isSymbolicLink())continue;const S=w.join(p,k.name);if(k.isDirectory()&&j(k.name))continue;const z=w.relative(l,S).replace(/\\/g,"/");(i?z.toLowerCase():z).includes(o)&&d.push({name:k.name,path:u(S),isDirectory:k.isDirectory()}),k.isDirectory()&&m<c&&y.push(S)}}return(m>=c||d.length>=a)&&(g=!0),d.sort((p,P)=>p.isDirectory===P.isDirectory?p.name.localeCompare(P.name):p.isDirectory?-1:1),{workspacePath:u(e),rootPath:u(l),keyword:r,items:d,truncated:g}}async function st(t,e,r,i){let o;try{o=await s.readFile(t,"utf-8")}catch{return{changed:!1,count:0}}const a=o;let c=0;if(i){const n=e.toLowerCase();let h=0;for(;;){const f=o.toLowerCase().indexOf(n,h);if(f===-1)break;o=o.slice(0,f)+r+o.slice(f+e.length),c+=1;const d=r.length||1;h=f+d}}else{let n=0;for(;;){const h=o.indexOf(e,n);if(h===-1)break;o=o.slice(0,h)+r+o.slice(h+e.length),c+=1;const l=r.length||1;n=h+l}}return o===a?{changed:!1,count:0}:(await F(t),await s.writeFile(t,o,"utf-8"),{changed:!0,count:c})}async function ce(t){const{workspaceRoot:e}=await v(t.workspacePath),r=String(t.keyword||"").trim();if(!r)throw new Error("keyword is required");const i=String(t.replacement??""),o=!!t.ignoreCase,a=String(t.fileMask||"").trim(),c=String(t.filePath||"").trim();let n=0,h=0;if(c){const{resolvedFilePath:f}=await W({workspacePath:t.workspacePath,filePath:c}),d=await st(f,r,i,o);return d.changed&&(n=1,h=d.count),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}async function l(f){let d;try{d=await s.readdir(f,{withFileTypes:!0})}catch{return}for(const y of d){const m=C(e,w.join(f,y.name));if(y.isSymbolicLink())continue;if(y.isDirectory()){if(j(y.name))continue;await l(m);continue}if(!y.isFile()||a&&!at(y.name,a))continue;try{if((await s.stat(m)).size>nt)continue}catch{continue}const g=await st(m,r,i,o);g.changed&&(n+=1,h+=g.count)}}return await l(e),{workspacePath:u(e),keyword:r,replacement:i,changedFiles:n,changedMatches:h}}export{Xt as chmodWorkspaceEntry,Jt as createWorkspaceEntry,ee as deleteWorkspaceEntry,Wt as extractWorkspaceArchive,Kt as getWorkspaceEntryProperties,Gt as listWorkspaceDirectory,te as moveWorkspaceEntry,Vt as previewWorkspaceDocument,Ht as readWorkspaceFile,Qt as renameWorkspaceEntry,ce as replaceWorkspaceFiles,ie as resolveWorkspaceDownloadTarget,ne as searchWorkspaceFiles,se as searchWorkspacePaths,oe as streamWorkspaceDirectoryZip,re as uploadWorkspaceFiles,Yt as writeWorkspaceFile,ae as zipWorkspaceDirectoryToTemp};
|
|
2
2
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{watch as w,promises as l}from"node:fs";import s from"node:path";import{sendFileChanged as p}from"./session-output.js";const h=new Map,m=300;function n(t){return String(t||"").replace(/\\/g,"/")}async function P(t){const e=s.resolve(String(t.workspacePath||"").trim()),a=await l.realpath(e),o=s.resolve(String(t.filePath||"").trim()),i=s.relative(e,o),r=i.startsWith("..")||s.isAbsolute(i)?o:s.join(a,i),c=await l.realpath(r);if(!(await l.stat(c)).isFile())throw new Error(`Path is not a file: ${c}`);return{workspaceRoot:a,filePath:c}}function u(t,e){return`${n(t)}::${n(e)}`}function f(t,e){e.timer&&(clearTimeout(e.timer),e.timer=null),e.watcher.close(),h.delete(t)}async function k(t){const e=s.resolve(String(t.workspacePath||"").trim()),a=await l.realpath(e),o=s.resolve(String(t.filePath||"").trim()),i=s.relative(e,o),r=i.startsWith("..")||s.isAbsolute(i)?o:s.join(a,i);return u(a,r)}async function g(t,e){let a,o;try{const i=await l.stat(t.filePath);a=i.size,o=i.mtimeMs}catch{}await p({workspacePath:n(t.workspacePath),filePath:n(t.filePath),eventType:e,size:a,mtimeMs:o})}function y(t,e){t.timer&&clearTimeout(t.timer),t.timer=setTimeout(()=>{t.timer=null,g(t,e).catch(()=>{})},m)}async function C(t){const{workspaceRoot:e,filePath:a}=await P(t),o=u(e,a),i=h.get(o);if(i)i.refCount+=1;else{const r={watcher:w(a,c=>y(r,String(c||"change"))),workspacePath:e,filePath:a,timer:null,refCount:1};r.watcher.on("error",()=>f(o,r)),h.set(o,r)}return{ok:!0,workspacePath:n(e),filePath:n(a)}}async function R(t){const e=await k(t),a=h.get(e);return a&&(a.refCount-=1,a.refCount<=0&&f(e,a)),{ok:!0}}function S(){return h.size}export{S as getWorkspaceWatchCountForTests,R as unwatchWorkspaceFile,C as watchWorkspaceFile};
|
|
1
|
+
import{watch as w,promises as l}from"node:fs";import s from"node:path";import{sendFileChanged as p}from"./session-output.js";const h=new Map,m=300;function n(t){return String(t||"").replace(/\\/g,"/")}async function P(t){const e=s.resolve(String(t.workspacePath||"").trim()),a=await l.realpath(e),o=s.resolve(e,String(t.filePath||"").trim()),i=s.relative(e,o),r=i.startsWith("..")||s.isAbsolute(i)?o:s.join(a,i),c=await l.realpath(r);if(!(await l.stat(c)).isFile())throw new Error(`Path is not a file: ${c}`);return{workspaceRoot:a,filePath:c}}function u(t,e){return`${n(t)}::${n(e)}`}function f(t,e){e.timer&&(clearTimeout(e.timer),e.timer=null),e.watcher.close(),h.delete(t)}async function k(t){const e=s.resolve(String(t.workspacePath||"").trim()),a=await l.realpath(e),o=s.resolve(e,String(t.filePath||"").trim()),i=s.relative(e,o),r=i.startsWith("..")||s.isAbsolute(i)?o:s.join(a,i);return u(a,r)}async function g(t,e){let a,o;try{const i=await l.stat(t.filePath);a=i.size,o=i.mtimeMs}catch{}await p({workspacePath:n(t.workspacePath),filePath:n(t.filePath),eventType:e,size:a,mtimeMs:o})}function y(t,e){t.timer&&clearTimeout(t.timer),t.timer=setTimeout(()=>{t.timer=null,g(t,e).catch(()=>{})},m)}async function C(t){const{workspaceRoot:e,filePath:a}=await P(t),o=u(e,a),i=h.get(o);if(i)i.refCount+=1;else{const r={watcher:w(a,c=>y(r,String(c||"change"))),workspacePath:e,filePath:a,timer:null,refCount:1};r.watcher.on("error",()=>f(o,r)),h.set(o,r)}return{ok:!0,workspacePath:n(e),filePath:n(a)}}async function R(t){const e=await k(t),a=h.get(e);return a&&(a.refCount-=1,a.refCount<=0&&f(e,a)),{ok:!0}}function S(){return h.size}export{S as getWorkspaceWatchCountForTests,R as unwatchWorkspaceFile,C as watchWorkspaceFile};
|
|
2
2
|
|
|
@@ -8,6 +8,8 @@ export declare function sanitizeAgentId(agentId: string): string;
|
|
|
8
8
|
export declare function sanitizeArchiveFileName(fileName: string, fallback: string): string;
|
|
9
9
|
export declare function atomicWriteFile(targetPath: string, content: string): Promise<void>;
|
|
10
10
|
|
|
11
|
+
export declare function renameFileWithRetry(fromPath: string, toPath: string, attempts?: number): Promise<void>;
|
|
12
|
+
|
|
11
13
|
export declare function atomicWriteFileSync(targetPath: string, content: string): void;
|
|
12
14
|
export declare function atomicWriteJsonFile(targetPath: string, value: unknown): Promise<void>;
|
|
13
15
|
export declare function downloadSkillZip(skillPackage: SkillPackage, targetDir: string): Promise<DownloadResult | null>;
|