aws-runtime-bridge 1.9.162 → 1.9.169
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 +324 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +31 -3
- package/dist/adapter/AcodeSdkAdapter.js +4 -9
- package/dist/adapter/ClaudeSdkAdapter.d.ts +2 -0
- package/dist/adapter/ClaudeSdkAdapter.js +3 -3
- package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
- package/dist/adapter/CodexSdkAdapter.js +3 -3
- package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
- package/dist/adapter/OpencodeSdkAdapter.js +3 -3
- package/dist/adapter/prompts.d.ts +1 -1
- package/dist/adapter/prompts.js +1 -1
- package/dist/adapter/types.d.ts +41 -4
- package/dist/adapter/types.js +1 -1
- package/dist/browser/frame-encode.d.ts +25 -0
- package/dist/browser/frame-encode.js +2 -0
- package/dist/browser/screencast-differ.d.ts +2 -3
- package/dist/browser/screencast-differ.js +1 -1
- package/dist/browser/screencast-manager.js +1 -1
- package/dist/browser/types.d.ts +5 -1
- package/dist/browser/types.js +1 -1
- package/dist/desktop/desktop-mcp-client.js +2 -2
- package/dist/routes/background-tasks.js +3 -3
- package/dist/routes/capabilities.js +1 -1
- package/dist/routes/dashboard.d.ts +2 -0
- package/dist/routes/dashboard.js +4 -4
- package/dist/routes/git.js +22 -22
- package/dist/routes/instance.js +1 -1
- package/dist/routes/launch.js +10 -10
- package/dist/routes/mcp-extra.js +2 -2
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.js +1 -1
- package/dist/routes/plugins.js +1 -1
- package/dist/routes/pty.d.ts +11 -3
- package/dist/routes/pty.js +3 -3
- package/dist/routes/runtime-binding.js +1 -1
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/skills.js +1 -1
- package/dist/routes/sub-agents.js +8 -8
- package/dist/routes/terminal.d.ts +16 -2
- package/dist/routes/terminal.js +34 -36
- package/dist/services/agent-process-manager.js +1 -1
- package/dist/services/agent-pty-manager.js +4 -4
- package/dist/services/aws-client-agent-mcp.js +2 -2
- package/dist/services/capability-config.d.ts +8 -0
- package/dist/services/capability-config.js +2 -2
- package/dist/services/desktop-mcp-manager.d.ts +3 -1
- package/dist/services/desktop-mcp-manager.js +1 -1
- package/dist/services/instance-ai-config-service.js +1 -1
- package/dist/services/instance-features.d.ts +10 -0
- package/dist/services/instance-features.js +1 -1
- package/dist/services/instance-init-service.js +1 -1
- package/dist/services/launch-manager.d.ts +9 -1
- package/dist/services/launch-manager.js +6 -6
- package/dist/services/launch-metrics.d.ts +1 -1
- package/dist/services/launch-metrics.js +4 -3
- package/dist/services/mcp-deploy.d.ts +4 -0
- package/dist/services/mcp-env-injector.d.ts +12 -0
- package/dist/services/mcp-env-injector.js +2 -0
- package/dist/services/mcp-launch-binding-queue.d.ts +8 -0
- package/dist/services/mcp-launch-binding-queue.js +1 -1
- package/dist/services/orphan-monitor.js +1 -1
- package/dist/services/panel-env.d.ts +6 -2
- package/dist/services/panel-env.js +1 -1
- package/dist/services/plugin-manager.js +9 -9
- package/dist/services/process-detector.d.ts +23 -3
- package/dist/services/process-detector.js +13 -13
- package/dist/services/runtime-resources-snapshot.d.ts +3 -0
- package/dist/services/runtime-resources-snapshot.js +3 -0
- package/dist/services/session-output.d.ts +13 -0
- package/dist/services/session-output.js +4 -4
- package/dist/services/tunnel-client.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/utils/env-safety.d.ts +15 -0
- package/dist/utils/env-safety.js +2 -0
- package/dist/utils/lifecycle-log.d.ts +2 -0
- package/dist/utils/lifecycle-log.js +3 -0
- package/dist/utils/mcp-utils.js +1 -1
- package/package/acode/dist/background-command-manager.js +4 -4
- package/package/acode/dist/built-in-file-tools.d.ts +13 -0
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/builtins/shellCommandPreparation.d.ts +2 -0
- package/package/acode/dist/builtins/shellCommandPreparation.js +2 -2
- package/package/acode/dist/compaction.d.ts +10 -0
- package/package/acode/dist/compaction.js +6 -6
- package/package/acode/dist/context-overflow.js +1 -1
- package/package/acode/dist/index.d.ts +1 -0
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/mcpToolNames.d.ts +4 -0
- package/package/acode/dist/mcpToolNames.js +1 -1
- package/package/acode/dist/runtime-environment.d.ts +2 -0
- package/package/acode/dist/runtime-environment.js +3 -2
- package/package/acode/dist/runtime.d.ts +68 -8
- package/package/acode/dist/runtime.js +28 -27
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/tool-allocation.js +1 -1
- package/package/acode/dist/tool-group-manager.d.ts +12 -0
- package/package/acode/dist/tool-group-manager.js +8 -4
- package/package/acode/dist/types.d.ts +8 -0
- package/package/acode/package.json +1 -1
- package/package/aws-client-agent-mcp/README.md +1 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +22 -8
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +10 -0
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -1
- package/package/aws-client-agent-mcp/dist/logger.js +2 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +19 -2
- package/package/aws-client-agent-mcp/dist/mcp-server.js +18 -18
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +15 -4
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +79 -29
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/memory-store.js +3 -3
- package/package/aws-client-agent-mcp/dist/message-buffer.js +1 -1
- package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +15 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +1 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js +1 -1
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +4 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +2 -2
- package/package/aws-client-agent-mcp/dist/types.d.ts +52 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package/aws-client-agent-mcp/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{spawn as
|
|
2
|
-
`)):t}return this.sdkModule}async waitForServer(t,e,s,
|
|
3
|
-
`).trim();return
|
|
1
|
+
import{spawn as T}from"node:child_process";import{EventEmitter as E}from"node:events";import*as S from"node:fs";import*as x from"node:net";import*as A from"node:os";import*as g from"node:path";import{v4 as P}from"uuid";import{getAcodeDataHome as _}from"../config.js";import{registerListenerWakeHook as M,unregisterListenerWakeHook as D}from"../services/browser-session-manager.js";import{logger as $}from"../utils/logger.js";import{BRIDGE_PACKAGE_ROOT as L,importBridgeSdkPackage as N}from"../utils/sdk-package-loader.js";import{IdlePollLoop as C}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as R}from"./prompts.js";import{getToolActionInfo as I,redactTransientClipboardPastePaths as O,redactTransientClipboardPastePathsInValue as U}from"./types.js";function j(d){if(d&&g.isAbsolute(d)&&S.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||A.homedir(),s=process.env.LOCALAPPDATA||"",o=[g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),g.join(s,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const i of o){const r=g.join(i,"opencode.exe");if(S.existsSync(r))return r}const n=[g.join(e,"AppData","Roaming","npm"),g.join(e,"AppData","Local","Volta","bin")];for(const i of n)for(const r of["opencode.cmd","opencode.exe","opencode"]){const a=g.join(i,r);if(S.existsSync(a))return a}}return t}async function H(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(s=>{const o=x.createServer();o.once("error",()=>s(!1)),o.once("listening",()=>{o.close(()=>s(!0))}),o.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function W(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function F(d,t){return W(d)&&d.code==="ERR_MODULE_NOT_FOUND"&&d.message.includes(t)}function v(d){if(!d||!d.trim())return;const t=d.trim(),e=t.indexOf("/");return e>0?{providerID:t.slice(0,e),modelID:t.slice(e+1)}:{modelID:t}}class Y extends E{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){const s={adapterSession:{sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}},config:e,sseActive:!1,pendingPermissions:new Map,emittedToolStarts:new Set,workingDirectory:e.workingDirectory,userMessageIds:new Set,currentAssistantText:"",seenTextPartIds:new Set};if(this.sessions.set(t,s),e.agentId){const o=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,o),M(e.agentId,o)}this.emit("status-change",t,"starting");try{const o=await H();s.port=o;const n=j(e.command),i=n.endsWith(".cmd")||n.endsWith(".CMD")||process.platform==="win32"&&!g.isAbsolute(n),r={...process.env,...e.envOverrides},a={},m=v(e.model),h=e.model;m?.modelID&&h!==null&&h!==void 0&&(a.model=h.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(r.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),$.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=T(n,["serve","--port",String(o)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:r,shell:i});s.serverProcess=l,s.startupOutput=[],l.stdout?.on("data",u=>{const k=u.toString();this.recordStartupOutput(s,k)}),l.stderr?.on("data",u=>{const k=u.toString();this.recordStartupOutput(s,k)}),l.on("error",u=>{console.error("[OpencodeSdkAdapter] Server process error:",u),s.adapterSession.status!=="terminated"&&(s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${u.message}`}}))}),l.on("exit",u=>{s.sseActive=!1});const p=new Promise(u=>{l.once("exit",(k,b)=>u({code:k,signal:b}))}),c=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${o}`});s.client=c,await Promise.race([this.waitForServer(c,e.workingDirectory,1e4,o),p.then(u=>{throw new Error(this.formatStartupExitMessage(u,s.startupOutput))})]);const y=(await c.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!y?.id)throw new Error("OpenCode session.create() did not return an ID");s.opencodeSessionId=y.id,s.adapterSession.providerSessionId=y.id,this.startSseLoop(t,s),s.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:s.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(o){e.agentId&&D(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const n=o instanceof Error?o.message:String(o);throw console.error("[OpencodeSdkAdapter] startSession failed:",o),s.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode start failed: ${n}`}}),o}}async sendMessage(t,e,s){const o=this.sessions.get(t);if(!o)throw new Error(`Session ${t} not found`);if(!o.client||!o.opencodeSessionId)throw new Error(`Session ${t} not ready`);const n={id:P(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};o.adapterSession.messages.push(n),this.emit("conversation-message",t,n),s?.keepWaitingStatus||(o.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const i=v(o.config.model),r={parts:[{type:"text",text:e}]};i?.providerID&&i?.modelID&&(r.model={providerID:i.providerID,modelID:i.modelID}),await o.client.session.prompt({path:{id:o.opencodeSessionId},body:r,query:{directory:o.workingDirectory}})}catch(i){const r=i instanceof Error?i.message:String(i);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:r}})}}async sendConfirmation(t,e){const s=this.sessions.get(t);if(!s?.client||!s.opencodeSessionId)return;const o=e?"once":"reject",n=s.opencodeSessionId;for(const[i]of s.pendingPermissions)try{await s.client.postSessionIdPermissionsPermissionId({path:{id:n,permissionID:i},body:{response:o},query:{directory:s.workingDirectory}})}catch(r){console.warn("[OpencodeSdkAdapter] Permission response failed:",r)}s.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const s=this.sessions.get(t);s&&(s.idleCommands=e,s.adapterSession.status==="waiting_input"&&(e.idleInputCommand||e.nonInputCommand)&&this.startIdleDetection(t))}async abortCurrentTurn(t){const e=this.sessions.get(t);if(!(!e?.client||!e.opencodeSessionId))try{await e.client.session.abort({path:{id:e.opencodeSessionId},query:{directory:e.workingDirectory}})}catch(s){console.warn("[OpencodeSdkAdapter] Abort failed:",s)}}async terminateSession(t){const e=this.sessions.get(t);if(e){if(this.stopIdleDetection(t),e.sseActive=!1,e.sseAbortController?.abort(),e.serverProcess)try{e.serverProcess.kill()}catch{}e.adapterSession.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent({type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}),e.config.agentId&&D(e.config.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.sessions.delete(t)}}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.opencodeSessionId}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getSessionPid(t){const e=this.sessions.get(t);if(e)return e.serverProcess?.pid}cleanup(){for(const[t]of this.sessions)try{this.terminateSession(t)}catch{}this.sessions.clear()}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await N("@opencode-ai/sdk")}catch(t){throw F(t,"@opencode-ai/sdk")?new Error(["OpenCode SDK provider is not installed.","","aws-runtime-bridge keeps Codex/OpenCode provider SDKs optional to reduce default install size.",'To use SDK mode with command "opencode", install the SDK into the aws-runtime-bridge package root:',"",` npm install --prefix "${L}" @opencode-ai/sdk@latest opencode-ai@latest`,"","If aws-runtime-bridge is installed locally, run the same command with that local package path.","",`Original error: ${t instanceof Error?t.message:String(t)}`].join(`
|
|
2
|
+
`)):t}return this.sdkModule}async waitForServer(t,e,s,o){const n=Date.now()+s;for(;Date.now()<n;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(i=>setTimeout(i,300))}throw new Error(`OpenCode server (port ${o}) did not start within ${s}ms`)}recordStartupOutput(t,e){const s=e.trim();s&&(t.startupOutput=[...t.startupOutput??[],s].slice(-8))}formatStartupExitMessage(t,e){const s=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,o=(e??[]).join(`
|
|
3
|
+
`).trim();return o?`OpenCode server exited during startup (${s}): ${o}`:`OpenCode server exited during startup (${s}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(s=>{const o=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${o}`}})})}startSseLoop(t,e){e.sseActive=!0;const s=new AbortController;e.sseAbortController=s,this.runSseLoop(t,e,s).catch(o=>{s.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",o)})}async runSseLoop(t,e,s){if(e.client)try{const o=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:s.signal});for await(const n of o.stream){if(!e.sseActive||s.signal.aborted)break;this.handleOpenCodeEvent(t,e,n)}}catch(o){if(s.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",o)}}handleOpenCodeEvent(t,e,s){const o=new Date().toISOString(),n=e.opencodeSessionId;switch(s.type){case"message.updated":{const i=s.properties.info;if(i.sessionID!==n)break;if(i.role==="user")e.userMessageIds.add(i.id);else if(i.role==="assistant"){const r=i.tokens;r&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,r.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,r.output))}break}case"message.part.updated":{const{part:i,delta:r}=s.properties;if(i.sessionID!==n||e.userMessageIds.has(i.messageID))break;this.handlePartUpdate(t,e,i,r,o);break}case"session.idle":{if(s.properties.sessionID!==n)break;if(e.currentAssistantText){const a={id:P(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:o};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:o,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const i=e.idleCommands?.idleInputCommand;!!(i&&this.isMessagePollingIdleCommand(i))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:e.adapterSession.totalUsage}):this.emit("status-change",t,"waiting_input",{usage:e.adapterSession.totalUsage}),this.startIdleDetection(t);break}case"permission.updated":{const i=s.properties;if(i.sessionID!==n)break;const r=i.id;e.pendingPermissions.set(r,i),e.config.autoAccept&&e.client&&n?e.client.postSessionIdPermissionsPermissionId({path:{id:n,permissionID:r},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(r)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:o,data:{permissionPrompt:i.title,toolName:i.type}});break}case"session.error":{const{sessionID:i,error:r}=s.properties;if(i&&i!==n)break;let a="OpenCode session error";if(r){const m=r.data;typeof m?.message=="string"?a=`${r.name}: ${m.message}`:a=r.name}this.emitEvent({type:"error",sessionId:t,timestamp:o,data:{text:a}});break}}}handlePartUpdate(t,e,s,o,n){switch(s.type){case"text":{let i;if(o!==void 0)i=o,e.seenTextPartIds.add(s.id);else if(!e.seenTextPartIds.has(s.id))i=s.text,i&&e.seenTextPartIds.add(s.id);else break;if(!i)break;e.currentAssistantText+=i,this.emitEvent({type:"text_delta",sessionId:t,timestamp:n,data:{text:i}});break}case"reasoning":{const i=o??s.text;if(!i)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:n,data:{text:i}});break}case"tool":{const i=s.callID,r=s.tool,a=s.state,m=a.input,h=s.metadata,l=U(m),p=l&&typeof l=="object"&&!Array.isArray(l)?l:{},f=()=>{if(e.emittedToolStarts.has(i))return;e.emittedToolStarts.add(i);const c={...I(r,m,h),actionId:i};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:n,data:{toolName:r,toolInput:p,toolUseId:i,...c}}),e.adapterSession.messages.push({id:P(),sessionId:t,role:"tool_use",content:`${r}: ${JSON.stringify(p).slice(0,100)}`,timestamp:n,toolName:r,toolInput:p,toolUseId:i})};if(a.status==="running"){f();const c={...I(r,m,h),actionId:i};this.emit("status-change",t,"tool_using",{...c,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(r==="todowrite"||r==="todo_write")&&this.syncTodosFromToolCall(e,m).catch(w=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",w)}),f();const c=O(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:n,data:{toolName:r,toolResult:c,isError:!1,toolUseId:i}}),e.emittedToolStarts.delete(i)}else if(a.status==="error"){f();const c=O(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:n,data:{toolName:r,toolResult:c,isError:!0,toolUseId:i}}),e.emittedToolStarts.delete(i)}break}}}getTodoStoreDir(){return g.join(_(),"todos")}async syncTodosFromToolCall(t,e){const s=t.config.agentId;if(!s)return;const o=e.todos;if(!Array.isArray(o)||o.length===0)return;const n=[];for(const l of o)if(l&&typeof l=="object"){const p=l,f=typeof p.content=="string"?p.content.trim():"",c=typeof p.status=="string"?p.status:"",w=typeof p.priority=="string"?p.priority:"";f&&c&&w&&n.push({content:f,status:c,priority:w})}if(n.length===0)return;const i=String(s).replace(/[^a-zA-Z0-9_-]/g,"_"),r=this.getTodoStoreDir(),a=g.join(r,`${i}.json`),m={agentId:s,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:n};await S.promises.mkdir(r,{recursive:!0});const h=`${a}.tmp`;await S.promises.writeFile(h,JSON.stringify(m,null,2),"utf-8"),await S.promises.rename(h,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),s=e?.idleCommands?.idleInputCommand;if(!(!e||!s)){if(this.isMessagePollingIdleCommand(s)){e.idlePollLoop||(e.idlePollLoop=new C({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendMessage(t,n?o.trim():this.toIdlePrompt(o),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendMessage(t,this.toIdlePrompt(o)),pollDelayMs:1500})),e.idlePollLoop.start();return}e.idlePollLoop||(e.idlePollLoop=new C({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:o=>this.isMessagePollingIdleCommand(o),preDispatchHook:()=>null,dispatchPollingPrompt:(o,n)=>this.sendMessage(t,n?o.trim():this.toIdlePrompt(o),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:o=>this.sendMessage(t,this.toIdlePrompt(o)),pollDelayMs:1500})),this.armIdleCheck(t)}}armIdleCheck(t){const e=this.sessions.get(t);if(!e)return;e.idleTimer&&clearTimeout(e.idleTimer);const s=setTimeout(()=>{e.idleTimer===s&&(e.idleTimer=void 0,this.armIdleCheck(t),this.checkIdleState(t))},500);e.idleTimer=s}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearTimeout(e.idleTimer),e.idleTimer=void 0)}checkIdleState(t){const e=this.sessions.get(t);!e||e.adapterSession.status!=="waiting_input"||e.idleCommands?.idleInputCommand&&(this.sendMessage(t,this.toIdlePrompt(e.idleCommands.idleInputCommand)),this.stopIdleDetection(t))}toIdlePrompt(t){const e=t.trim();return this.isMessagePollingIdleCommand(e)?R:e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const s=e.toLowerCase();return s.includes("poll_message")||s.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Y as OpencodeSdkAdapter};
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
export declare const MESSAGE_POLLING_IDLE_PROMPT = "\
|
|
2
|
+
export declare const MESSAGE_POLLING_IDLE_PROMPT = "\u7EE7\u7EED\u5B8C\u6210\u5DE5\u4F5C\uFF0C\u5426\u5219\u8C03\u7528poll_message\u76D1\u542C\u6D88\u606F";
|
package/dist/adapter/prompts.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const
|
|
1
|
+
const _="\u7EE7\u7EED\u5B8C\u6210\u5DE5\u4F5C\uFF0C\u5426\u5219\u8C03\u7528poll_message\u76D1\u542C\u6D88\u606F";export{_ as MESSAGE_POLLING_IDLE_PROMPT};
|
|
2
2
|
|
package/dist/adapter/types.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import { EventEmitter } from "node:events";
|
|
3
3
|
export type SessionStatus = "starting" | "thinking" | "tool_using" | "waiting_input" | "completed" | "terminated" | "error" | "compacting";
|
|
4
|
-
export type ProviderEventType = "ai_request" | "text_delta" | "thinking" | "command_output" | "tool_use_start" | "tool_use_end" | "permission_request" | "ask_user_question" | "exit_plan_mode" | "turn_complete" | "session_complete" | "error" | "context_compaction" | "runtime_capabilities" | "background_command_completed";
|
|
4
|
+
export type ProviderEventType = "ai_request" | "text_delta" | "thinking" | "command_output" | "tool_use_start" | "tool_use_end" | "permission_request" | "ask_user_question" | "exit_plan_mode" | "turn_complete" | "session_complete" | "error" | "context_compaction" | "runtime_capabilities" | "tool_batch_start" | "tool_batch_metrics" | "background_command_completed";
|
|
5
5
|
|
|
6
|
-
export type ToolActionType = "skill" | "mcp" | "idle" | "edit_file" | "write_file" | "read_file" | "bash" | "search" | "web" | "ai_request" | "lsp" | "notebook" | "other" | "context_compaction" | "runtime_capabilities" | "background_command";
|
|
6
|
+
export type ToolActionType = "skill" | "mcp" | "idle" | "edit_file" | "write_file" | "read_file" | "bash" | "search" | "web" | "ai_request" | "lsp" | "notebook" | "other" | "context_compaction" | "runtime_capabilities" | "tool_batch" | "background_command";
|
|
7
7
|
|
|
8
8
|
export interface ToolActionInfo {
|
|
9
9
|
|
|
@@ -55,7 +55,13 @@ export interface RuntimeStatusActionInfo {
|
|
|
55
55
|
actionResult?: string;
|
|
56
56
|
actionId?: string;
|
|
57
57
|
|
|
58
|
+
actionError?: string;
|
|
59
|
+
|
|
58
60
|
parentId?: string;
|
|
61
|
+
|
|
62
|
+
batchId?: string;
|
|
63
|
+
|
|
64
|
+
batchMetrics?: RuntimeToolBatchMetrics;
|
|
59
65
|
usage?: RuntimeTokenUsage;
|
|
60
66
|
}
|
|
61
67
|
export interface ProviderEvent {
|
|
@@ -84,8 +90,6 @@ export interface ProviderEvent {
|
|
|
84
90
|
|
|
85
91
|
lastUserMessagePreview?: string;
|
|
86
92
|
|
|
87
|
-
requestBody?: string;
|
|
88
|
-
|
|
89
93
|
toolName?: string;
|
|
90
94
|
|
|
91
95
|
rawToolName?: string;
|
|
@@ -130,6 +134,8 @@ export interface ProviderEvent {
|
|
|
130
134
|
|
|
131
135
|
actionResult?: string;
|
|
132
136
|
|
|
137
|
+
actionError?: string;
|
|
138
|
+
|
|
133
139
|
sequence?: number;
|
|
134
140
|
|
|
135
141
|
cwd?: string;
|
|
@@ -139,6 +145,14 @@ export interface ProviderEvent {
|
|
|
139
145
|
commandLineCount?: number;
|
|
140
146
|
|
|
141
147
|
capabilities?: RuntimeCapabilities;
|
|
148
|
+
|
|
149
|
+
batchId?: string;
|
|
150
|
+
|
|
151
|
+
batchToolCount?: number;
|
|
152
|
+
|
|
153
|
+
batchToolNames?: string[];
|
|
154
|
+
|
|
155
|
+
batchMetrics?: RuntimeToolBatchMetrics;
|
|
142
156
|
};
|
|
143
157
|
}
|
|
144
158
|
|
|
@@ -177,6 +191,25 @@ export interface RuntimeCapabilities {
|
|
|
177
191
|
skillGroups?: RuntimeSkillGroup[];
|
|
178
192
|
}
|
|
179
193
|
|
|
194
|
+
export interface RuntimeToolBatchMetrics {
|
|
195
|
+
|
|
196
|
+
toolCount: number;
|
|
197
|
+
|
|
198
|
+
parallelism: number;
|
|
199
|
+
|
|
200
|
+
speedup: number;
|
|
201
|
+
|
|
202
|
+
wallClockMs: number;
|
|
203
|
+
|
|
204
|
+
totalWaitMs?: number;
|
|
205
|
+
|
|
206
|
+
contentionCount: number;
|
|
207
|
+
|
|
208
|
+
failureCount?: number;
|
|
209
|
+
|
|
210
|
+
maxConcurrentObserved?: number;
|
|
211
|
+
}
|
|
212
|
+
|
|
180
213
|
export interface AdapterInstanceAiConfig {
|
|
181
214
|
model?: string;
|
|
182
215
|
baseURL?: string;
|
|
@@ -218,6 +251,10 @@ export interface AdapterSessionConfig {
|
|
|
218
251
|
|
|
219
252
|
memory?: string;
|
|
220
253
|
|
|
254
|
+
resumeContext?: string;
|
|
255
|
+
|
|
256
|
+
resumeTranscript?: unknown[];
|
|
257
|
+
|
|
221
258
|
model?: string;
|
|
222
259
|
|
|
223
260
|
maxTurns?: number;
|
package/dist/adapter/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EventEmitter as S}from"node:events";const m="[temp clipboard paste file]",
|
|
1
|
+
import{EventEmitter as S}from"node:events";const m="[temp clipboard paste file]",y=/[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi,P=/\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi,w=/mini-term-clipboard[\\/]paste-\d+\.txt/gi;function d(t){return t.replace(y,m).replace(P,m).replace(w,m)}function $(t){const e=t.trim().replace(/^(["'])(.*)\1$/,"$2");return[y,P,w].some(c=>{c.lastIndex=0;const i=c.exec(e);return!!(i&&i[0]===e)})}function u(t){return typeof t=="string"?d(t):Array.isArray(t)?t.map(e=>u(e)):t&&typeof t=="object"?Object.fromEntries(Object.entries(t).map(([e,c])=>[e,u(c)])):t}const h={get_colleague:"aws-mcp",get_group_rooms:"aws-mcp",list_project_members:"aws-mcp",get_profile:"aws-mcp",hire_colleague:"aws-mcp",send_group:"aws-mcp",send_private:"aws-mcp",poll_message:"aws-mcp",get_message:"aws-mcp",get_dm_history:"aws-mcp",get_group_history:"aws-mcp",my_task:"aws-mcp",submit_task_result:"aws-mcp"},C=new Set(["aws-mcp","aws-mcp-dev","agents-work-studio"]);function g(t,e){const c=h[e.toLowerCase()];return c&&C.has(t.toLowerCase())?c:t}function L(t){const e=t.trim();if(!e)return e;if(e.includes("__")){const i=e.split("__").filter(Boolean);if(i.length>=3&&i[0].toLowerCase()==="mcp"){const f=i[1],o=i.slice(2).join("__");return`${g(f,o)}/${o}`}if(i.length>=2){const f=i[0],o=i.slice(1).join("__");return`${g(f,o)}/${o}`}}const c=h[e.toLowerCase()];return c?`${c}/${e}`:e}function k(t,e){return t?e?`${g(t,e)}/${e}`:t:e}const E=500;function p(t,e=E){return!t||t.length<=e?t:`${t.slice(0,e)}...\uFF08\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\uFF09`}function j(t,e,c){if(!t)return{actionType:"other",actionLabel:"\u8C03\u7528\u5DE5\u5177"};const i=t.toLowerCase(),f=i.replace(/[_-]/g,""),A=(i.startsWith("mcp__")?i.split("__").slice(2).join("__"):i.startsWith("builtin__")?i.split("__").slice(1).join("__"):i.includes("-mcp__")?i.slice(i.indexOf("-mcp__")+6):i.includes("/")?i.split("/").filter(Boolean).at(-1)||i:i.includes("__")&&i.split("__").pop()||i).replace(/[_-]/g,""),D=a=>Array.isArray(a)?a.map(r=>String(r??"").trim()).filter(r=>r.length>0):[],n=(...a)=>{for(const r of a){if(typeof r=="string"&&r.trim())return d(r);if(Array.isArray(r)&&r.length>0){const l=r[0];if(typeof l=="string"&&l.trim())return d(l)}}},s=(...a)=>{const r=a.map(l=>l.replace(/[_-]/g,""));return r.includes(f)||r.includes(A)},T=D(e?.load_skills);if((i==="task"||i==="task()")&&T.length>0)return{actionType:"skill",actionLabel:"\u52A0\u8F7D\u6280\u80FD",actionDetail:T.join(", ")};if(i==="skill"||i==="load_skill"||i==="disclosecontext"||i.includes("skill")&&!i.startsWith("mcp__")&&!i.includes("mcp_")){let a="";if(Array.isArray(e?.load_skills)&&e.load_skills.length>0)a=e.load_skills.join(", ");else if(typeof e?.skill=="string")a=e.skill;else if(typeof e?.name=="string")a=e.name;else if(e?.args&&typeof e.args=="object"){const r=e.args;typeof r.name=="string"?a=r.name:typeof r.skill=="string"&&(a=r.skill)}return{actionType:"skill",actionLabel:"\u4F7F\u7528\u6280\u80FD",actionDetail:a||void 0}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const a=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(a)}}if(s("poll_message","get_message"))return{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:L(t)};if(s("create_meeting"))return{actionType:"idle",actionLabel:"\u7B49\u5F85\u4F1A\u8BAE\u5F00\u59CB",actionDetail:L(t)};if(s("ask_user_question","askuserquestion"))return{actionType:"other",actionLabel:"\u7B49\u5F85\u56DE\u7B54"};if(c?.mcpServer){const a=c.mcpServer;return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(a,t||"")}}const b=h[t];if(b)return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:`${b}/${t}`};if(i.startsWith("mcp__")||i.includes("-mcp__")||i.includes("mcp_")&&!i.includes("skill")||i==="kiropowers"){let a="",r="";if(i.startsWith("mcp__")){const _=t.split("__");a=_[1]||"",r=_.slice(2).join("__")||""}else if(i.includes("-mcp__")){const _=i.indexOf("-mcp__");a=i.substring(0,_+4),r=i.substring(_+6)}else i==="kiropowers"?(a="kiro",r=e?.powerName||e?.action||""):(a="mcp",r=t);return{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:k(a,r)||t}}if(s("edit","editfile","strreplace","editcode","apply_patch","multiedit","replace"))return{actionType:"edit_file",actionLabel:"\u7F16\u8F91\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("write","writefile","fswrite"))return{actionType:"write_file",actionLabel:"\u5199\u5165\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.target_file,e?.targetFile)};if(s("read","readfile","readcode","readmultiplefiles","read_file"))return Array.isArray(e?.paths)?{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:`${e.paths.length}\u4E2A\u6587\u4EF6`}:{actionType:"read_file",actionLabel:"\u8BFB\u53D6\u6587\u4EF6",actionDetail:n(e?.file_path,e?.filePath,e?.path,e?.paths,e?.target_file,e?.targetFile)};if(s("bash","shell","command","executepwsh","controlpwshprocess","execute","run_command","execute_command")){const a=n(e?.command,e?.cmd,e?.argv);return{actionType:"bash",actionLabel:"\u6267\u884C\u547D\u4EE4",actionDetail:p(a)}}if(i==="glob"||i==="grep"||i==="find"||i==="search"||i==="grepsearch"||i==="filesearch"){const a=e?.query||e?.pattern;return{actionType:"search",actionLabel:"\u641C\u7D22\u6587\u4EF6",actionDetail:p(a)}}if(i==="webfetch"||i==="websearch"||i==="fetch"||i==="http"||i==="remote_web_search"){const a=e?.url||e?.query;return{actionType:"web",actionLabel:"\u7F51\u7EDC\u8BF7\u6C42",actionDetail:p(a)}}return i.startsWith("lsp")||i.includes("language_server")?{actionType:"lsp",actionLabel:"LSP\u64CD\u4F5C"}:i==="notebookedit"||i.includes("notebook")?{actionType:"notebook",actionLabel:"\u7F16\u8F91Notebook"}:{actionType:"mcp",actionLabel:"\u8C03\u7528MCP",actionDetail:t}}class R extends S{}export{R as BaseProviderAdapter,L as getCanonicalMcpDetail,j as getToolActionInfo,$ as isTransientClipboardPasteFilePath,d as redactTransientClipboardPastePaths,u as redactTransientClipboardPastePathsInValue};
|
|
2
2
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ImageFormat } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export interface RawImageFactory {
|
|
5
|
+
(input: Buffer, options: {
|
|
6
|
+
raw: {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
channels: 1 | 2 | 3 | 4;
|
|
10
|
+
};
|
|
11
|
+
}): {
|
|
12
|
+
jpeg: (options?: {
|
|
13
|
+
quality?: number;
|
|
14
|
+
}) => {
|
|
15
|
+
toBuffer: () => Promise<Buffer>;
|
|
16
|
+
};
|
|
17
|
+
png: (options?: {
|
|
18
|
+
compressionLevel?: number;
|
|
19
|
+
}) => {
|
|
20
|
+
toBuffer: () => Promise<Buffer>;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare function encodeRawImage(sharp: RawImageFactory, raw: Buffer, width: number, height: number, format: ImageFormat, quality: number): Promise<Buffer>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { type ScreencastDiffFrame } from "./types.js";
|
|
1
|
+
import { type ImageFormat, type ScreencastDiffFrame } from "./types.js";
|
|
3
2
|
|
|
4
3
|
export declare function getSharpLoadStatus(): string;
|
|
5
4
|
export declare class ScreencastDiffer {
|
|
@@ -25,7 +24,7 @@ export declare class ScreencastDiffer {
|
|
|
25
24
|
|
|
26
25
|
isSharpReady(): boolean;
|
|
27
26
|
|
|
28
|
-
processFrame(jpegBuffer: Buffer, width: number, height: number, quality: number): Promise<ScreencastDiffFrame | null>;
|
|
27
|
+
processFrame(jpegBuffer: Buffer, width: number, height: number, quality: number, sourceFormat?: ImageFormat): Promise<ScreencastDiffFrame | null>;
|
|
29
28
|
|
|
30
29
|
private emitFullFrame;
|
|
31
30
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{TILE_DIFF_CONFIG as E}from"./types.js";const
|
|
1
|
+
import{encodeRawImage as _}from"./frame-encode.js";import{TILE_DIFF_CONFIG as E}from"./types.js";const b=3,L=15;let D=null,W="pending",I=null;async function k(){return D||(I||(I=(async()=>{try{const s=await import("sharp");return D=s.default??s,W="ok",D}catch(s){return W="failed",console.warn("[browser-screencast] sharp \u52A0\u8F7D\u5931\u8D25\uFF0C\u964D\u7EA7\u5168\u5E27\u6A21\u5F0F:",s instanceof Error?s.message:s),null}})()),I)}async function A(){return k()}function z(){return W}function N(s,t,a,e,f,p,c,g){if(!t||t.length!==s.length||a<=0||e<=0)return Number.MAX_SAFE_INTEGER;const y=Math.max(0,f),l=Math.max(0,p),i=Math.min(a,f+c),r=Math.min(e,p+g),J=a*4,{sampleStep:w,diffThreshold:F}=E;let M=0;for(let x=l;x<r;x+=w){const C=x*J;for(let H=y;H<i;H+=w){const d=C+H*4;Math.abs(s[d]-t[d])+Math.abs(s[d+1]-t[d+1])+Math.abs(s[d+2]-t[d+2])>F&&M++}}return M}function O(s,t,a,e,f,p){if(!s||t<=0||f<=0||p<=0)return null;const c=Math.max(0,a),g=Math.max(0,e),y=Math.min(t,a+f),l=Math.min(Math.floor(s.length/4/t),e+p),i=y-c,r=l-g;if(i<=0||r<=0)return null;const J=t*4,w=Buffer.allocUnsafe(i*r*4);for(let F=0;F<r;F++){const M=(g+F)*J+c*4;s.copy(w,F*i*4,M,M+i*4)}return w}async function G(s,t,a){const e=new Array(s.length);let f=0;const p=Math.max(1,Math.min(t,s.length));return await Promise.all(Array.from({length:p},async()=>{for(;;){const c=f++;if(c>=s.length)return;e[c]=await a(s[c])}})),e}class K{constructor(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0,this.sharpReady=!1,this.sharpCheckDone=!1,A().then(t=>{this.sharpReady=t!==null,this.sharpCheckDone=!0})}isSharpReady(){return this.sharpReady}async processFrame(t,a,e,f,p="jpeg"){if(!this.sharpCheckDone||!this.sharpReady)return this.emitFullFrame(t,a,e);const c=D;if(!c)return this.emitFullFrame(t,a,e);try{if(this.lastRaw&&this.lastJpeg&&this.lastJpegWidth===a&&this.lastJpegHeight===e&&this.lastJpeg.length===t.length&&this.lastJpeg.equals(t))return null;if(this.highDynamicMode)if(this.highDynamicFrameCount++,this.highDynamicFrameCount<L&&!(this.lastJpegWidth===a&&this.lastJpegHeight===e))this.highDynamicMode=!1;else{if(this.highDynamicFrameCount<L)return this.lastRaw=null,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,this.lastWidth||a,this.lastHeight||e);this.highDynamicMode=!1,this.highDynamicFrameCount=0}const g=await c(t).ensureAlpha().raw().toBuffer({resolveWithObject:!0}),y=g.data,l=g.info.width,i=g.info.height;if(!this.lastRaw||this.lastWidth!==l||this.lastHeight!==i)return this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.emitFullFrame(t,l,i);const{tileSize:r,minChangedSamples:J,fullFrameFallbackRatio:w,encodeConcurrency:F}=E,M=Math.max(1,Math.ceil(l/r)),x=Math.max(1,Math.ceil(i/r)),C=M*x,H=[];let d=0;for(let n=0;n<x;n++)for(let u=0;u<M;u++){const o=u*r,h=n*r,m=Math.min(r,l-o),R=Math.min(r,i-h);N(y,this.lastRaw,l,i,o,h,m,R)>=J&&(H.push({x:o,y:h,w:m,h:R}),d++)}if(d===0)return null;if(d>=Math.ceil(C*w))return this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,this.consecutiveFullFrames++,this.consecutiveFullFrames>=b&&(this.highDynamicMode=!0,this.highDynamicFrameCount=0),this.emitFullFrame(t,l,i);this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0;const S=[];for(let n=0;n<x;n++){let u=0;const o=H.filter(h=>Math.floor(h.y/r)===n);for(o.sort((h,m)=>h.x-m.x);u<o.length;){let h=u;for(;h+1<o.length&&o[h+1].x===o[h].x+o[h].w;)h++;const m=o[u],R=o[h];S.push({x:m.x,y:m.y,w:R.x+R.w-m.x,h:m.h}),u=h+1}}const T=(await G(S,F,async n=>{const u=Math.min(n.w,l-n.x),o=Math.min(n.h,i-n.y),h=O(y,l,n.x,n.y,u,o);if(!h)return null;try{const m=await _(c,h,u,o,p,f);return{x:n.x,y:n.y,w:u,h:o,data:m}}catch{return null}})).filter(n=>n!==null);return T.length===0?null:(this.lastRaw=y,this.lastWidth=l,this.lastHeight=i,this.lastJpeg=t,this.lastJpegWidth=a,this.lastJpegHeight=e,{kind:"tile",width:l,height:i,tiles:T})}catch(g){return console.warn("[browser-screencast] tile diff \u5F02\u5E38\uFF0C\u56DE\u9000\u5168\u5E27:",g),this.emitFullFrame(t,a,e)}}emitFullFrame(t,a,e){return{kind:"full",width:a,height:e,data:t}}reset(){this.lastRaw=null,this.lastWidth=0,this.lastHeight=0,this.lastJpeg=null,this.lastJpegWidth=0,this.lastJpegHeight=0,this.consecutiveFullFrames=0,this.highDynamicMode=!1,this.highDynamicFrameCount=0}dispose(){this.reset()}}export{K as ScreencastDiffer,z as getSharpLoadStatus};
|
|
2
2
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{encodeBrowserFrame as d,isIncrementalBinaryFrame as m}from"./browser-frame-encode.js";import{ScreencastDiffer as g}from"./screencast-differ.js";import{QUALITY_PRESETS as y}from"./types.js";const
|
|
1
|
+
import{encodeBrowserFrame as d,isIncrementalBinaryFrame as m}from"./browser-frame-encode.js";import{ScreencastDiffer as g}from"./screencast-differ.js";import{QUALITY_PRESETS as y}from"./types.js";const f=y.original,F=1,p=f.format,w=30;class x{constructor(t){this.currentPage=null,this.currentSession=null,this.isRunning=!1,this.subscribers=new Set,this.differ=null,this.tileMode=!0,this.frameSeq=0,this.pipeline=Promise.resolve(),this.latestEvent=null,this.draining=!1,this.lastProcessStartedAt=0,this.seedCaptureInFlight=!1,this.lastDeviceWidth=0,this.lastDeviceHeight=0,this.lastGeometryWarnAt=0,this.config={quality:t?.quality??f.quality,maxWidth:t?.maxWidth??f.maxWidth,maxHeight:t?.maxHeight??f.maxHeight,everyNthFrame:t?.everyNthFrame??F,maxFramesPerSecond:t?.maxFramesPerSecond??w,format:t?.format??p,tileMode:t?.tileMode??!0},this.tileMode=this.config.tileMode,this.frameIntervalMs=1e3/Math.max(1,this.config.maxFramesPerSecond),this.tileMode&&(this.differ=new g)}enqueue(t){const e=this.pipeline.then(t);return this.pipeline=e.then(()=>{},()=>{}),e}subscribe(t){if(this.subscribers.add(t),this.subscribers.size===1&&this.currentPage&&!this.isRunning&&this.start(this.currentPage).catch(()=>{}),this.differ&&this.currentPage){let e=!1;if(this.lastFrame?.binaryFrame?m(this.lastFrame.binaryFrame)&&(this.lastFrame=void 0,this.differ.reset(),e=!0):this.tileMode&&(this.differ.reset(),e=!0),e&&!this.seedCaptureInFlight){const s=this.currentPage;this.seedCaptureInFlight=!0,this.forceCaptureAndPush(s).catch(()=>{}).finally(()=>{this.seedCaptureInFlight=!1})}}if(this.lastFrame){const e=this.lastFrame;setImmediate(()=>{if(this.subscribers.has(t))try{t(e)}catch{}})}return()=>{this.subscribers.delete(t)}}async start(t){if(this.currentPage===t&&this.isRunning)return;this.currentPage&&this.currentPage!==t&&await this.stop(this.currentPage),this.currentPage=t;let e;try{e=await t.context().newCDPSession(t)}catch(s){throw this.isRunning=!1,new Error(`Failed to create CDPSession for screencast: ${s instanceof Error?s.message:String(s)}`)}this.currentSession=e,e.on("Page.screencastFrame",s=>{this.handleScreencastFrame(s,t)});try{await e.send("Page.startScreencast",{format:this.config.format,...this.config.format==="jpeg"?{quality:this.config.quality}:{},maxWidth:this.config.maxWidth,maxHeight:this.config.maxHeight,everyNthFrame:this.config.everyNthFrame,...this.config.maxFramesPerSecond?{maxFramesPerSecond:this.config.maxFramesPerSecond}:{}}),this.isRunning=!0}catch(s){try{await e.detach()}catch{}throw this.currentSession=null,this.isRunning=!1,new Error(`Failed to start screencast: ${s instanceof Error?s.message:String(s)}`)}}handleScreencastFrame(t,e){if(this.ackFrame(t),e===this.currentPage){if(this.subscribers.size===0){this.lastFrame=void 0;return}this.latestEvent={event:t,page:e},this.draining||(this.draining=!0,this.drainPendingFrames())}}async drainPendingFrames(){try{for(;this.latestEvent;){const{event:t,page:e}=this.latestEvent;this.latestEvent=null;const s=this.frameIntervalMs-(Date.now()-this.lastProcessStartedAt);s>0&&await new Promise(i=>setTimeout(i,s)),this.lastProcessStartedAt=Date.now(),await this.enqueue(()=>this.processScreencastFrame(t,e))}}catch{}finally{this.draining=!1}}ackFrame(t){this.currentSession&&t.sessionId&&this.currentSession.send("Page.screencastFrameAck",{sessionId:t.sessionId}).catch(()=>{})}async processScreencastFrame(t,e){if(e!==this.currentPage)return;const s=t.data??"",i=t.metadata?.deviceWidth??0,r=t.metadata?.deviceHeight??0;let n="";try{n=e.url()}catch{}if(i>0&&r>0&&this.lastDeviceWidth>0&&this.lastDeviceHeight>0&&(i!==this.lastDeviceWidth||r!==this.lastDeviceHeight)){this.differ?.reset();const a=Date.now();a-this.lastGeometryWarnAt>=1e3&&(this.lastGeometryWarnAt=a,console.warn(`[browser-screencast] \u9875\u9762\u51E0\u4F55\u53D8\u5316 ${this.lastDeviceWidth}x${this.lastDeviceHeight} -> ${i}x${r}\uFF0C\u91CD\u7F6E\u5DEE\u5206\u57FA\u51C6`))}if(i>0&&r>0&&(this.lastDeviceWidth=i,this.lastDeviceHeight=r),this.tileMode&&this.differ&&s){const a=Buffer.from(s,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality,this.config.format);if(!c)return;const u=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:u};this.lastFrame=o;for(const l of this.subscribers)try{l(o)}catch{}return}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,base64:s,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async stop(t){if(this.currentPage!==t)return;const e=this.currentSession;if(e){try{await e.send("Page.stopScreencast")}catch{}try{await e.detach()}catch{}}this.currentSession=null,this.isRunning=!1,this.currentPage=null,this.latestEvent=null,this.differ?.reset()}async stopAll(){this.currentPage&&await this.stop(this.currentPage)}async capture(t){if(this.lastFrame&&this.currentPage===t)return this.lastFrame;try{const s=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64"),i=`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,r=t.viewportSize();return{dataUrl:i,base64:s,width:r?.width??0,height:r?.height??0,timestamp:Date.now(),url:t.url()}}catch{return}}getLastFrame(){return this.lastFrame}getCurrentCdpSession(){return this.currentSession??void 0}async restartAfterNavigation(t){if(this.currentPage===t)try{await this.stop(t)}catch{}let e=!1;for(let s=0;s<2;s++)try{await this.start(t),e=!0;break}catch{s===0&&await new Promise(i=>setTimeout(i,300))}e||(this.isRunning=!1,this.currentSession=null,this.currentPage=null),await this.forceCaptureAndPush(t).catch(()=>{})}async updateQuality(t){this.config={...this.config,format:t.format,quality:t.quality,maxWidth:t.maxWidth,maxHeight:t.maxHeight},this.differ?.reset();const e=this.currentPage;if(!e||!this.isRunning)return!1;try{await this.stop(e)}catch{}try{await this.start(e)}catch{return!1}return this.forceCaptureAndPush(e).catch(()=>{}),!0}async forceCaptureAndPush(t){!t||t.isClosed()||await this.enqueue(()=>this.doForceCaptureAndPush(t))}async doForceCaptureAndPush(t){let e;const s=t.viewportSize(),i=s?.width??0,r=s?.height??0;if(this.currentSession)try{e=(await this.currentSession.send("Page.captureScreenshot",{format:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).data}catch{}if(!e)try{e=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64")}catch{return}let n="";try{n=t.url()}catch{}if(this.tileMode&&this.differ&&e){this.differ.reset();const a=Buffer.from(e,"base64"),c=await this.differ.processFrame(a,i,r,this.config.quality,this.config.format);if(c){const u=d(c,this.frameSeq++,{url:n}),o={dataUrl:"",base64:"",width:i,height:r,timestamp:Date.now(),url:n,binaryFrame:u};this.lastFrame=o;for(const l of this.subscribers)try{l(o)}catch{}return}}const h={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${e}`,base64:e,width:i,height:r,timestamp:Date.now(),url:n};this.lastFrame=h;for(const a of this.subscribers)try{a(h)}catch{}}async dispose(){await this.stopAll(),this.latestEvent=null,this.differ?.dispose(),this.differ=null,this.subscribers.clear(),this.lastFrame=void 0}}export{x as ScreencastManager};
|
|
2
2
|
|
package/dist/browser/types.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export declare function parseBrowserKey(key: string): {
|
|
|
77
77
|
browserId: string;
|
|
78
78
|
} | null;
|
|
79
79
|
|
|
80
|
+
export type ImageFormat = "jpeg" | "png";
|
|
81
|
+
|
|
80
82
|
export interface ScreencastConfig {
|
|
81
83
|
|
|
82
84
|
quality?: number;
|
|
@@ -89,7 +91,7 @@ export interface ScreencastConfig {
|
|
|
89
91
|
|
|
90
92
|
maxFramesPerSecond?: number;
|
|
91
93
|
|
|
92
|
-
format?:
|
|
94
|
+
format?: ImageFormat;
|
|
93
95
|
|
|
94
96
|
tileMode?: boolean;
|
|
95
97
|
}
|
|
@@ -184,6 +186,8 @@ export type QualityPreset = "original" | "hd" | "smooth";
|
|
|
184
186
|
|
|
185
187
|
export interface QualityPresetConfig {
|
|
186
188
|
|
|
189
|
+
format: ImageFormat;
|
|
190
|
+
|
|
187
191
|
quality: number;
|
|
188
192
|
|
|
189
193
|
maxWidth: number;
|
package/dist/browser/types.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e="default";function r(t,o){return`${t}::${o}`}function n(t){const o=t.indexOf("::");return o<0?null:{agentId:t.slice(0,o),browserId:t.slice(o+2)}}const S=8,_=4,i=5,s=0,E=0,x=7891,
|
|
1
|
+
const e="default";function r(t,o){return`${t}::${o}`}function n(t){const o=t.indexOf("::");return o<0?null:{agentId:t.slice(0,o),browserId:t.slice(o+2)}}const S=8,_=4,i=5,s=0,E=0,x=7891,a="127.0.0.1",c=6*1024*1024,p=10*1e3,T=30*1e3,I=60*1e3,l={original:{format:"png",quality:0,maxWidth:1280,maxHeight:800},hd:{format:"jpeg",quality:80,maxWidth:1024,maxHeight:640},smooth:{format:"jpeg",quality:60,maxWidth:800,maxHeight:500}};function m(t){return t==="original"||t==="hd"||t==="smooth"}const d={tileSize:160,sampleStep:8,diffThreshold:24,minChangedSamples:1,fullFrameFallbackRatio:.5,encodeConcurrency:8};export{e as DEFAULT_BROWSER_ID,I as IDLE_CHECK_INTERVAL_MS,E as IDLE_TIMEOUT_MS,i as MAX_PAGES_PER_SESSION,S as MAX_SESSIONS,_ as MAX_SESSIONS_PER_AGENT,l as QUALITY_PRESETS,s as SESSION_TIMEOUT_MS,d as TILE_DIFF_CONFIG,p as WS_DEFAULT_HEARTBEAT_MS,T as WS_DEFAULT_IDLE_TIMEOUT_MS,c as WS_DEFAULT_MAX_SEND_BYTES,a as WS_HOST,x as WS_PORT,m as isQualityPreset,r as makeBrowserKey,n as parseBrowserKey};
|
|
2
2
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{Client as T}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as g}from"@modelcontextprotocol/sdk/client/stdio.js";const
|
|
2
|
-
`);return
|
|
1
|
+
import{Client as T}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as g}from"@modelcontextprotocol/sdk/client/stdio.js";import{sanitizeEnvForChild as w}from"../utils/env-safety.js";const E=100,y=15e3;class C{constructor(n){this.client=null,this.transport=null,this.stderrLines=[],this.closed=!1,this.closing=!1,this.options=n}isConnected(){return!this.closed&&this.client!==null}getRecentStderr(n=20){return this.stderrLines.slice(-n)}async start(){const{command:n,args:i,cwd:t}=this.options,e=new g({command:n,args:i??[],...t?{cwd:t}:{},env:L({...process.env,...w(this.options.env)}),stderr:"pipe"}),c=this.options.maxStderrLines??E;try{const r=e.stderr;if(r){let l="";r.setEncoding?.("utf8"),r.on("data",a=>{const m=typeof a=="string"?a:Buffer.from(a).toString("utf8");l+=m;const h=l.split(/\r?\n/);l=h.pop()??"";for(const d of h)d.trim()&&(this.stderrLines.push(d),this.stderrLines.length>c&&this.stderrLines.splice(0,this.stderrLines.length-c))})}}catch{}e.onclose=()=>{this.closed||this.closing||(this.closed=!0,this.client=null,this.transport=null,this.options.onUnexpectedClose?.(null))},e.onerror=()=>{};const o=new T({name:"aws-runtime-bridge",version:"1.0.0"}),p=this.options.initTimeoutMs??y;await u(o.connect(e),p,"nuphus-mcp initialize timeout");const{tools:f}=await u(o.listTools(),p,"nuphus-mcp listTools timeout");return this.client=o,this.transport=e,this.closed=!1,f.map(r=>({name:r.name,...r.description?{description:r.description}:{},inputSchema:r.inputSchema??{type:"object",properties:{}}}))}async callTool(n,i,t){const e=this.client;if(!e||this.closed)throw new Error("nuphus-mcp connection is not active");const c=await u(e.callTool({name:n,arguments:i},void 0,{timeout:t}),t+5e3,`nuphus-mcp tool ${n} timeout after ${t}ms`);return S(c)}async close(){if(this.closing||this.closed)return;this.closing=!0,this.closed=!0;const n=this.client;this.client=null,this.transport=null;try{await n?.close()}catch{}this.closing=!1}}function S(s){const i=(Array.isArray(s?.content)?s.content:[]).filter(t=>t?.type==="text").map(t=>t.text);if(i.length>0){const t=i.join(`
|
|
2
|
+
`);return s?.isError?`nuphus-mcp tool error: ${t}`:t}return JSON.stringify(s??{})}function L(s){const n={};for(const[i,t]of Object.entries(s))t!==void 0&&(n[i]=t);return n}function u(s,n,i){return new Promise((t,e)=>{const c=setTimeout(()=>e(new Error(i)),n);s.then(o=>{clearTimeout(c),t(o)},o=>{clearTimeout(c),e(o instanceof Error?o:new Error(String(o)))})})}export{C as DesktopMcpConnection,S as callToolResultToText};
|
|
3
3
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{promises as S}from"node:fs";import y from"node:path";import{pathToFileURL as C}from"node:url";import{Router as j}from"express";import{getAcodeDataHome as T}from"../config.js";import{validateToken as k}from"../middleware/auth.js";import{getAcodeBgManager as h}from"../services/acode-bg-manager.js";import{getReleasedAcodeEntryPath as
|
|
2
|
-
`);return n>0&&a.shift(),{text:a.slice(-t),fileExists:!0,truncated:r<s}}finally{await o.close()}}p.get("/acode-bg-tasks/:agentId/:taskId/output",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId),i=Math.min(2e3,Math.max(100,Number(e.query.tailLines)||500));try{const s=await h();if(s){const r=s.getTaskOutputSnapshot(d,o);if(r){t.json({ok:!0,source:"memory",...w(r)});return}}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5FEB\u7167\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",s?.message)}try{const s=await I();if(!s){t.status(503).json({ok:!1,error:"store unavailable"});return}const r=await s.readSession(d);if(!r){t.status(404).json({ok:!1,error:"task_not_found"});return}const n=r.tasks.find(f=>f.taskId===o);if(!n){t.status(404).json({ok:!1,error:"task_not_found"});return}const{text:u,fileExists:c,truncated:a}=await x(n.outputPath,i);t.json({ok:!0,source:"file",taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:u,nextSeq:0,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:a||!c})}catch(s){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95\u8BFB\u53D6\u5931\u8D25: %s",s?.message),t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] output \u8BFB\u53D6\u5931\u8D25: %s",d?.message),t.status(500).json({ok:!1,error:"internal_error"})})}),p.get("/acode-bg-tasks/:agentId/:taskId/stream",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId);t.status(200),t.set({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.flushHeaders?.();const i=(u,c)=>{t.writableEnded||t.destroyed||(c!==void 0&&t.write(`id: ${c}
|
|
1
|
+
import{promises as S}from"node:fs";import y from"node:path";import{pathToFileURL as C}from"node:url";import{Router as j}from"express";import{getAcodeDataHome as T}from"../config.js";import{validateToken as k}from"../middleware/auth.js";import{noteDashboardActivity as B}from"./dashboard.js";import{getAcodeBgManager as h}from"../services/acode-bg-manager.js";import{getReleasedAcodeEntryPath as E}from"../services/acode-package.js";import{createLogger as _}from"../utils/logger.js";import{listPtySessions as L}from"./pty.js";let m=null;function I(){return m||(m=(async()=>{try{const e=E(),t=y.join(y.dirname(e),"background-command-store.js"),d=await import(C(t).href);return d.BackgroundCommandStore?new d.BackgroundCommandStore:(l.warn("[acode-bg-tasks] BackgroundCommandStore \u4E0D\u53EF\u7528,\u78C1\u76D8\u515C\u5E95\u7981\u7528"),null)}catch(e){return l.warn("[acode-bg-tasks] \u52A0\u8F7D BackgroundCommandStore \u5931\u8D25: %s",e?.message),null}})().then(e=>(e||(m=null),e)),m)}const l=_("acode-bg-tasks"),p=j();function v(e){return String(e).replace(/[^a-zA-Z0-9_-]/g,"_")}function P(e){return y.join(T(),"bg-tasks",v(e),"state.json")}p.get("/acode-bg-tasks/:agentId",k,async(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}try{const s=await h();if(s&&typeof s.listTasksWithReconcile=="function"){const r=e.query.status&&String(e.query.status)!=="all"?String(e.query.status):void 0,n=await s.listTasksWithReconcile(String(o),r);t.json({ok:!0,agentId:String(o),updatedAt:Date.now(),tasks:n});return}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5BF9\u8D26\u5217\u8868\u5931\u8D25\uFF0C\u964D\u7EA7\u78C1\u76D8\u8BFB\u53D6: %s",s?.message)}const i=P(String(o));try{const s=await S.readFile(i,"utf-8"),r=JSON.parse(s),u=(Array.isArray(r.tasks)?r.tasks:[]).map(c=>{const a=c;return{taskId:a.taskId,status:a.status,command:a.commandPreview??a.command,commandPreview:a.commandPreview,description:typeof a.description=="string"?a.description:void 0,cwd:a.cwd,startedAt:a.startedAt,finishedAt:a.finishedAt,exitCode:a.exitCode,signal:a.signal,outputLineCount:a.outputLineCount,outputBytes:a.outputBytes}});t.json({ok:!0,agentId:String(o),updatedAt:typeof r.updatedAt=="number"?r.updatedAt:null,tasks:u})}catch(s){if((typeof s=="object"&&s!==null?Reflect.get(s,"code"):void 0)==="ENOENT"){t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}if(s instanceof SyntaxError){l.warn("[acode-bg-tasks] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",i),t.json({ok:!0,agentId:String(o),updatedAt:null,tasks:[]});return}const n=s;l.error("[acode-bg-tasks] \u8BFB\u53D6\u5931\u8D25: %s",n.message),t.status(500).json({ok:!1,error:n.message})}}),p.get("/acode-agent-pty-sessions/:agentId",k,(e,t)=>{const d=e.params.agentId,o=Array.isArray(d)?d[0]:d;if(!o||!String(o).trim()){t.status(400).json({ok:!1,error:"agentId is required"});return}const i=String(o),r=L().filter(n=>n.ownerUserId===i);t.json({ok:!0,agentId:i,sessions:r})});const N=15e3;function w(e){return{taskId:e.taskId,status:e.status,exitCode:e.exitCode,signal:e.signal,startedAt:e.startedAt,finishedAt:e.finishedAt,command:e.command,lines:e.lines,nextSeq:e.nextSeq,totalLines:e.totalLines,totalBytes:e.totalBytes,truncated:e.truncated}}async function x(e,t){let o=null;try{o=await S.open(e,"r")}catch(i){if(i?.code==="ENOENT")return{text:[],fileExists:!1,truncated:!1};throw i}try{const s=(await o.stat()).size;if(s===0)return{text:[],fileExists:!0,truncated:!1};const r=Math.min(s,2097152),n=s-r,u=Buffer.alloc(r);await o.read(u,0,r,n);const a=u.toString("utf-8").split(`
|
|
2
|
+
`);return n>0&&a.shift(),{text:a.slice(-t),fileExists:!0,truncated:r<s}}finally{await o.close()}}p.get("/acode-bg-tasks/:agentId/:taskId/output",k,(e,t)=>{(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId),i=Math.min(2e3,Math.max(100,Number(e.query.tailLines)||500));try{const s=await h();if(s){const r=s.getTaskOutputSnapshot(d,o);if(r){t.json({ok:!0,source:"memory",...w(r)});return}}}catch(s){l.warn("[acode-bg-tasks] \u5185\u5B58\u5FEB\u7167\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",s?.message)}try{const s=await I();if(!s){t.status(503).json({ok:!1,error:"store unavailable"});return}const r=await s.readSession(d);if(!r){t.status(404).json({ok:!1,error:"task_not_found"});return}const n=r.tasks.find(f=>f.taskId===o);if(!n){t.status(404).json({ok:!1,error:"task_not_found"});return}const{text:u,fileExists:c,truncated:a}=await x(n.outputPath,i);t.json({ok:!0,source:"file",taskId:n.taskId,status:n.status,exitCode:n.exitCode,signal:n.signal,startedAt:n.startedAt,finishedAt:n.finishedAt,command:n.command,lines:u,nextSeq:0,totalLines:n.outputLineCount,totalBytes:n.outputBytes,truncated:a||!c})}catch(s){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95\u8BFB\u53D6\u5931\u8D25: %s",s?.message),t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] output \u8BFB\u53D6\u5931\u8D25: %s",d?.message),t.status(500).json({ok:!1,error:"internal_error"})})}),p.get("/acode-bg-tasks/:agentId/:taskId/stream",k,(e,t)=>{B(),(async()=>{const d=String(e.params.agentId),o=String(e.params.taskId);t.status(200),t.set({"Content-Type":"text/event-stream","Cache-Control":"no-cache, no-transform",Connection:"keep-alive","X-Accel-Buffering":"no"}),t.flushHeaders?.();const i=(u,c)=>{t.writableEnded||t.destroyed||(c!==void 0&&t.write(`id: ${c}
|
|
3
3
|
`),t.write(`data: ${JSON.stringify(u)}
|
|
4
4
|
|
|
5
5
|
`))};let s,r=null,n=null;try{s=await h(),s&&(r=s,n=s.getTaskOutputSnapshot(d,o))}catch(u){l.warn("[acode-bg-tasks] \u5185\u5B58\u8BFB\u53D6\u5931\u8D25,\u964D\u7EA7\u8D70\u78C1\u76D8: %s",u?.message)}if(n){if(!r){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}if(i({type:"snapshot",source:"memory",...w(n)}),n.status!=="running"){i({type:"done",status:n.status,exitCode:n.exitCode,signal:n.signal}),t.end();return}let u=null,c=!1;const a=()=>{c||(c=!0,u?.(),clearInterval(f))},f=setInterval(()=>{if(t.writableEnded||t.destroyed){a();return}try{t.write(`: ping
|
|
6
6
|
|
|
7
|
-
`)}catch{a()}},
|
|
7
|
+
`)}catch{a()}},N);if(f.unref?.(),u=r.subscribeTaskOutput(d,o,{onLine:g=>i({type:"output",stream:g.stream,text:g.text,seq:g.seq},g.seq),onDone:g=>{i({type:"done",status:g.status,exitCode:g.exitCode,signal:g.signal}),a(),t.end()}}),!u){i({type:"done",status:n.status,exitCode:n.exitCode,signal:n.signal}),a(),t.end();return}e.on("close",()=>{a(),t.writableEnded||t.end()}),e.on("aborted",()=>a());return}try{const u=await I();if(!u){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const c=await u.readSession(d);if(!c){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const a=c.tasks.find(b=>b.taskId===o);if(!a){i({type:"done",status:"killed",exitCode:null,signal:null}),t.end();return}const{text:f,fileExists:g,truncated:A}=await x(a.outputPath,500);i({type:"snapshot",source:"file",taskId:a.taskId,status:a.status,exitCode:a.exitCode,signal:a.signal,startedAt:a.startedAt,finishedAt:a.finishedAt,command:a.command,lines:f,nextSeq:0,totalLines:a.outputLineCount,totalBytes:a.outputBytes,truncated:A||!g}),i({type:"done",status:a.status,exitCode:a.exitCode,signal:a.signal}),t.end()}catch(u){l.error("[acode-bg-tasks] \u78C1\u76D8\u515C\u5E95 stream \u5931\u8D25: %s",u?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})}})().catch(d=>{l.error("[acode-bg-tasks] stream \u5EFA\u7ACB\u5931\u8D25: %s",d?.message),t.headersSent?t.end():t.status(500).json({ok:!1,error:"internal_error"})})});export{p as backgroundTasksRouter};
|
|
8
8
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Router as
|
|
1
|
+
import{Router as n}from"express";import{validateToken as p}from"../middleware/auth.js";import{getEffective as m,getEffectiveSource as c}from"../services/capability-config.js";import{mcpDeployManager as d}from"../services/mcp-deploy.js";import{pluginManager as f}from"../services/plugin-manager.js";import{skillManager as g}from"../services/skill-manager.js";import{createLogger as u}from"../utils/logger.js";const y=u("capabilities"),k=n();function r(s,o,t){const e={};for(const a of t)e[a]={enabled:m(s,o,a),source:c(s,o,a)};return e}k.post("/capabilities/state",p,async(s,o)=>{const t=String((s.body??{})?.agentId??"").trim();if(!t){o.status(400).json({ok:!1,error:"agentId is required"});return}try{const e=g.listDeployed().map(i=>i.skillName),a=d.listDeployed().map(i=>i.name),l=(await f.listDeployed()).map(i=>i.pluginName);o.json({ok:!0,agentId:t,skills:r(t,"skills",e),mcp:r(t,"mcp",a),plugins:r(t,"plugins",l),deployedSkills:e,deployedMcp:a,deployedPlugins:l})}catch(e){y.warn("[capabilities/state] \u8BFB\u53D6\u80FD\u529B\u72B6\u6001\u5931\u8D25: %s",e.message),o.status(500).json({ok:!1,error:e.message||"read capability state failed"})}});export{k as capabilitiesRouter};
|
|
2
2
|
|