aws-runtime-bridge 1.9.153 → 1.9.168
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 +766 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +57 -6
- package/dist/adapter/AcodeSdkAdapter.js +4 -8
- 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 -20
- 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/acode-todos.js +1 -1
- 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/ltr.js +1 -1
- 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.d.ts +18 -74
- 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 +24 -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 +26 -2
- 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/services/workspace-watch.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/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 +4 -4
- package/package/acode/dist/background-command-tools.js +1 -1
- package/package/acode/dist/built-in-file-tools.d.ts +31 -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/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.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 +4 -1
- 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/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-environment.d.ts +2 -0
- package/package/acode/dist/runtime-environment.js +3 -2
- package/package/acode/dist/runtime.d.ts +124 -10
- package/package/acode/dist/runtime.js +27 -23
- 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-allocation.js +1 -1
- 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 +128 -0
- package/package/acode/dist/tool-group-manager.js +18 -0
- package/package/acode/dist/types.d.ts +20 -2
- package/package/acode/package.json +3 -3
- package/package/aws-client-agent-mcp/README.md +1 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +20 -32
- 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 +65 -10
- package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -30
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +42 -7
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +196 -21
- 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-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 +40 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
- 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 +56 -3
- package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
- package/package/aws-client-agent-mcp/package.json +2 -1
- package/package.json +1 -1
- package/package/acode/dist/capability-prompt.d.ts +0 -16
- package/package/acode/dist/capability-prompt.js +0 -3
- package/package/acode/dist/plugin-tools.d.ts +0 -14
- package/package/acode/dist/plugin-tools.js +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{EventEmitter as y}from"node:events";import{v4 as
|
|
2
|
-
`)):t}return this.sdkModule}buildCodexOptions(t){const n=A(process.env,t.envOverrides),e={env:n},s=n.CODEX_API_KEY||n.OPENAI_API_KEY;s&&(e.apiKey=s);const a=n.CODEX_BASE_URL||n.OPENAI_BASE_URL;a&&(e.baseUrl=a);const
|
|
3
|
-
`)}});break;case"error":this.emitEvent({type:"error",sessionId:t,timestamp:a,data:{text:e.message}});break}}emitTextDelta(t,n,e,s,a){const
|
|
1
|
+
import{EventEmitter as y}from"node:events";import{v4 as h}from"uuid";import{registerListenerWakeHook as T,unregisterListenerWakeHook as m}from"../services/browser-session-manager.js";import{IdlePollLoop as g}from"./idle-poll-loop.js";import{MESSAGE_POLLING_IDLE_PROMPT as _}from"./prompts.js";import{getToolActionInfo as E}from"./types.js";function v(i){return i instanceof Error&&"code"in i&&typeof i.code=="string"}function P(i,t){return v(i)&&i.code==="ERR_MODULE_NOT_FOUND"&&i.message.includes(t)}const d=1500;function f(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function D(i){return f(i)?i:{value:i}}function k(i){if(typeof i=="string")return i;try{return JSON.stringify(i)}catch{return String(i)}}function A(i,t){const n={};for(const[e,s]of Object.entries(i))typeof s=="string"&&(n[e]=s);return{...n,...t??{}}}function M(i){const t=[];let n="",e=null,s=!1;for(const a of i.trim()){if(s){n+=a,s=!1;continue}if(a==="\\"&&e!=="'"){s=!0;continue}if((a==='"'||a==="'")&&e===null){e=a;continue}if(a===e){e=null;continue}if(/\s/.test(a)&&e===null){n.length>0&&(t.push(n),n="");continue}n+=a}return s&&(n+="\\"),n.length>0&&t.push(n),t}function S(i){const t=(i||"").replace(/\\/g,"/").toLowerCase();return(t.split("/").pop()||t).replace(/\.(cmd|exe)$/i,"")}function O(i){return i.includes("/")||i.includes("\\")||/^[a-zA-Z]:/.test(i)}function w(i){const t=M(i||"codex");if(t.length===0)return{args:[]};const[n,e,...s]=t,a=S(n);return O(n)?{executablePath:n,args:t.slice(1)}:(a==="npx"||a==="pnpm"||a==="yarn"||a==="bun")&&S(e)==="codex"?{args:s}:a==="codex"?{args:t.slice(1)}:{executablePath:n,args:t.slice(1)}}function x(i){if(/^(true|1|yes)$/i.test(i))return!0;if(/^(false|0|no)$/i.test(i))return!1}function c(i){return i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'")?i.slice(1,-1):i}function L(i,t,n){const e=t.split(".").filter(Boolean);if(e.length===0)return;let s=i;for(const l of e.slice(0,-1)){const o=s[l];f(o)||(s[l]={}),s=s[l]}const a=c(n),r=x(a);s[e[e.length-1]]=r??a}function u(i,t,n){const e=i[t],s=`${n}=`;return e.startsWith(s)?{value:e.slice(s.length),nextIndex:t}:{value:i[t+1],nextIndex:t+1}}function b(i){const t={additionalDirectories:[],config:{}};for(let n=0;n<i.length;n++){const e=i[n];switch(e){case"--model":case"-m":{const s=u(i,n,e);t.model=s.value,n=s.nextIndex;break}case"--sandbox":{const s=u(i,n,e);(s.value==="read-only"||s.value==="workspace-write"||s.value==="danger-full-access")&&(t.sandboxMode=s.value),n=s.nextIndex;break}case"--skip-git-repo-check":t.skipGitRepoCheck=!0;break;case"--add-dir":{const s=u(i,n,e);s.value&&t.additionalDirectories.push(s.value),n=s.nextIndex;break}case"--config":case"-c":{const s=u(i,n,e);if(s.value){const a=s.value.indexOf("=");if(a>0){const r=s.value.slice(0,a),l=s.value.slice(a+1);if(r==="model_reasoning_effort"){const o=c(l);(o==="minimal"||o==="low"||o==="medium"||o==="high"||o==="xhigh")&&(t.modelReasoningEffort=o)}else if(r==="web_search"){const o=c(l);(o==="disabled"||o==="cached"||o==="live")&&(t.webSearchMode=o)}else if(r==="sandbox_workspace_write.network_access")t.networkAccessEnabled=x(c(l));else if(r==="approval_policy"){const o=c(l);(o==="never"||o==="on-request"||o==="on-failure"||o==="untrusted")&&(t.approvalPolicy=o)}else L(t.config,r,l)}}n=s.nextIndex;break}default:if(e.startsWith("--model="))t.model=e.slice(8);else if(e.startsWith("--sandbox=")){const s=e.slice(10);(s==="read-only"||s==="workspace-write"||s==="danger-full-access")&&(t.sandboxMode=s)}}}return t}function I(i){return{inputTokens:i?.input_tokens??0,outputTokens:i?.output_tokens??0}}class K extends y{constructor(){super(...arguments),this.providerId="codex",this.displayName="Codex",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,n){const e={sessionId:t,status:"starting",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};try{const s=await this.loadSdk(),a=new s.Codex(this.buildCodexOptions(n));this.warnUnsupportedMcpConfig(n);const r=a.startThread(this.buildThreadOptions(n)),l={adapterSession:e,config:n,thread:r,terminating:!1,currentAssistantText:"",emittedToolStarts:new Set,emittedTextLengths:new Map,emittedReasoningLengths:new Map,lastActivityAt:Date.now()};if(this.sessions.set(t,l),n.agentId){const o=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,o),T(n.agentId,o)}n.initialPrompt?queueMicrotask(()=>{this.sendMessage(t,n.initialPrompt).catch(o=>{const C=o instanceof Error?o.message:String(o),p=this.sessions.get(t);p&&(p.adapterSession.status="error"),this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Codex initial prompt failed: ${C}`}})})}):(e.status="waiting_input",this.emit("status-change",t,"waiting_input"))}catch(s){n.agentId&&m(n.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const a=s instanceof Error?s.message:String(s);throw e.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`Codex start failed: ${a}`}}),s}}async sendMessage(t,n){const e=this.sessions.get(t);if(!e)throw new Error(`Session ${t} not found`);if(e.runningTurn)throw new Error(`Session ${t} already has a running Codex turn`);const s={id:h(),sessionId:t,role:"user",content:n,timestamp:new Date().toISOString()};e.adapterSession.messages.push(s),this.emit("conversation-message",t,s),e.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t),e.lastActivityAt=Date.now();const a=new AbortController;e.currentAbortController=a,e.runningTurn=this.runTurn(t,e,n,a);try{await e.runningTurn}finally{e.runningTurn=void 0,e.currentAbortController=void 0}}async sendConfirmation(t,n){}async sendQuestionAnswer(t,n){}setIdleCommands(t,n){const e=this.sessions.get(t);e&&(e.idleCommands=n,e.adapterSession.status==="waiting_input"&&(n.idleInputCommand||n.nonInputCommand)&&this.startIdleDetection(t))}async abortCurrentTurn(t){this.sessions.get(t)?.currentAbortController?.abort()}async terminateSession(t){const n=this.sessions.get(t);n&&(this.stopIdleDetection(t),n.terminating=!0,n.currentAbortController?.abort(),n.adapterSession.status="terminated",this.emit("status-change",t,"terminated"),this.emitEvent({type:"session_complete",sessionId:t,timestamp:new Date().toISOString(),data:{exitCode:0}}),n.config.agentId&&m(n.config.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t),this.sessions.delete(t))}async resumeSession(t,n,e){const s=await this.loadSdk(),a=new s.Codex(this.buildCodexOptions(e));this.warnUnsupportedMcpConfig(e);const r=a.resumeThread(n,this.buildThreadOptions(e)),l={sessionId:t,providerSessionId:n,status:"waiting_input",messages:[],createdAt:new Date().toISOString(),totalUsage:{inputTokens:0,outputTokens:0}};this.sessions.set(t,{adapterSession:l,config:e,thread:r,terminating:!1,currentAssistantText:"",emittedToolStarts:new Set,emittedTextLengths:new Map,emittedReasoningLengths:new Map,lastActivityAt:Date.now()}),this.emit("status-change",t,"waiting_input")}getConversation(t){return this.sessions.get(t)?.adapterSession.messages??[]}hasSession(t){return this.sessions.has(t)}getProviderSessionId(t){return this.sessions.get(t)?.thread.id??void 0}getSessionStatus(t){return this.sessions.get(t)?.adapterSession.status}getSessionPid(t){}cleanup(){for(const[t]of this.sessions)this.terminateSession(t);this.sessions.clear()}async loadSdk(){if(!this.sdkModule)try{this.sdkModule=await import("@openai/codex-sdk")}catch(t){throw P(t,"@openai/codex-sdk")?new Error(["Codex SDK provider is not installed.","","aws-runtime-bridge keeps heavy provider SDKs optional to reduce global install size.",'To use SDK mode with command "codex", install:',""," npm install -g @openai/codex-sdk","","If aws-runtime-bridge is installed locally, install the SDK in the same project:",""," npm install @openai/codex-sdk","",`Original error: ${t instanceof Error?t.message:String(t)}`].join(`
|
|
2
|
+
`)):t}return this.sdkModule}buildCodexOptions(t){const n=A(process.env,t.envOverrides),e={env:n},s=n.CODEX_API_KEY||n.OPENAI_API_KEY;s&&(e.apiKey=s);const a=n.CODEX_BASE_URL||n.OPENAI_BASE_URL;a&&(e.baseUrl=a);const r=w(t.command);t.executablePath?e.codexPathOverride=t.executablePath:r.executablePath&&(e.codexPathOverride=r.executablePath);const l=b(r.args);return Object.keys(l.config).length>0&&(e.config=l.config),e}warnUnsupportedMcpConfig(t){const n=!!(t.extraMcpServers&&Object.keys(t.extraMcpServers).length>0);(t.mcpConfigPath||n)&&console.warn("[CodexSdkAdapter] Codex SDK ThreadOptions do not expose dynamic MCP server injection; mcpConfigPath/extraMcpServers are ignored for Codex SDK sessions.")}buildThreadOptions(t){const n=w(t.command),e=b(n.args),s={workingDirectory:t.workingDirectory,skipGitRepoCheck:e.skipGitRepoCheck??!1,approvalPolicy:e.approvalPolicy??(t.autoAccept?"never":"on-request")};return(t.model||e.model)&&(s.model=t.model??e.model),(t.additionalDirectories||e.additionalDirectories.length>0)&&(s.additionalDirectories=[...t.additionalDirectories??[],...e.additionalDirectories]),e.sandboxMode&&(s.sandboxMode=e.sandboxMode),e.modelReasoningEffort&&(s.modelReasoningEffort=e.modelReasoningEffort),e.networkAccessEnabled!==void 0&&(s.networkAccessEnabled=e.networkAccessEnabled),e.webSearchMode&&(s.webSearchMode=e.webSearchMode),e.webSearchEnabled!==void 0&&(s.webSearchEnabled=e.webSearchEnabled),s}async runTurn(t,n,e,s){try{const a=await n.thread.runStreamed(e,{signal:s.signal});for await(const r of a.events)this.handleThreadEvent(t,n,r)}catch(a){if(s.signal.aborted){if(!this.sessions.has(t)||n.terminating||n.adapterSession.status==="terminated")return;n.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input");return}const r=a instanceof Error?a.message:String(a);n.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:r}})}}handleThreadEvent(t,n,e){const s=new Date().toISOString();switch(e.type){case"thread.started":n.adapterSession.providerSessionId=e.thread_id;break;case"turn.started":n.adapterSession.status="thinking",this.emit("status-change",t,"thinking");break;case"item.started":case"item.updated":case"item.completed":this.handleThreadItem(t,n,e.item,e.type,s);break;case"turn.completed":this.completeTurn(t,n,e.usage,s);break;case"turn.failed":n.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:s,data:{text:e.error.message}});break;case"error":n.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:s,data:{text:e.message}});break}}handleThreadItem(t,n,e,s,a){switch(e.type){case"agent_message":this.emitTextDelta(t,n,e.id,e.text,a);break;case"reasoning":this.emitReasoningDelta(t,n,e.id,e.text,a);break;case"command_execution":this.handleToolLikeItem(t,n,{id:e.id,toolName:"bash",toolInput:{command:e.command},result:e.aggregated_output,isError:e.status==="failed",isRunning:e.status==="in_progress",eventType:s,timestamp:a});break;case"mcp_tool_call":{const r={mcpServer:e.server};this.handleToolLikeItem(t,n,{id:e.id,toolName:e.tool,toolInput:D(e.arguments),result:e.error?.message??k(e.result),isError:e.status==="failed",isRunning:e.status==="in_progress",eventType:s,timestamp:a,metadata:r});break}case"file_change":this.handleToolLikeItem(t,n,{id:e.id,toolName:"apply_patch",toolInput:{changes:e.changes},result:e.status,isError:e.status==="failed",isRunning:s!=="item.completed",eventType:s,timestamp:a});break;case"web_search":this.handleToolLikeItem(t,n,{id:e.id,toolName:"web_search",toolInput:{query:e.query},result:e.query,isError:!1,isRunning:s!=="item.completed",eventType:s,timestamp:a});break;case"todo_list":this.emitEvent({type:"thinking",sessionId:t,timestamp:a,data:{text:e.items.map(r=>`${r.completed?"\u2713":"\u2022"} ${r.text}`).join(`
|
|
3
|
+
`)}});break;case"error":this.emitEvent({type:"error",sessionId:t,timestamp:a,data:{text:e.message}});break}}emitTextDelta(t,n,e,s,a){const r=n.emittedTextLengths.get(e)??0,l=s.slice(r);n.emittedTextLengths.set(e,s.length),l&&(n.currentAssistantText+=l,this.emitEvent({type:"text_delta",sessionId:t,timestamp:a,data:{text:l}}))}emitReasoningDelta(t,n,e,s,a){const r=n.emittedReasoningLengths.get(e)??0,l=s.slice(r);n.emittedReasoningLengths.set(e,s.length),l&&this.emitEvent({type:"thinking",sessionId:t,timestamp:a,data:{text:l}})}handleToolLikeItem(t,n,e){if(!n.emittedToolStarts.has(e.id)){n.emittedToolStarts.add(e.id);const s={...E(e.toolName,e.toolInput,e.metadata),actionId:e.id,actionInput:k(e.toolInput)};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:e.timestamp,data:{toolName:e.toolName,toolInput:e.toolInput,toolUseId:e.id,...s}}),this.emit("status-change",t,"tool_using",{...s,usage:n.adapterSession.totalUsage}),n.adapterSession.messages.push({id:h(),sessionId:t,role:"tool_use",content:`${e.toolName}: ${JSON.stringify(e.toolInput).slice(0,100)}`,timestamp:e.timestamp,toolName:e.toolName,toolInput:e.toolInput,toolUseId:e.id})}e.isRunning||e.eventType!=="item.completed"||(this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:e.timestamp,data:{toolName:e.toolName,toolResult:e.result,isError:e.isError,toolUseId:e.id}}),n.emittedToolStarts.delete(e.id))}completeTurn(t,n,e,s){const a=I(e);n.adapterSession.totalUsage=a,n.currentAssistantText&&(n.adapterSession.messages.push({id:h(),sessionId:t,role:"assistant",content:n.currentAssistantText,timestamp:s}),n.currentAssistantText=""),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:s,data:{usage:a}}),n.adapterSession.status="waiting_input";const r=n.idleCommands?.idleInputCommand;!!(r&&this.isMessagePollingIdleCommand(r))?this.emit("status-change",t,"waiting_input",{actionType:"idle",actionLabel:"\u76D1\u542C\u6D88\u606F",actionDetail:"aws-mcp/poll_message",usage:a}):this.emit("status-change",t,"waiting_input"),n.lastActivityAt=Date.now(),this.startIdleDetection(t)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const n=this.sessions.get(t),e=n?.idleCommands?.idleInputCommand;if(!(!n||!e)){if(this.isMessagePollingIdleCommand(e)){n.idlePollLoop||(n.idlePollLoop=new g({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:s=>this.isMessagePollingIdleCommand(s),preDispatchHook:()=>null,dispatchPollingPrompt:(s,a)=>this.sendIdlePrompt(t,s,{keepWaitingStatus:!0,injected:a}),dispatchRegularIdleCommand:s=>this.sendIdlePrompt(t,s),pollDelayMs:d,regularIdleDelayMs:d})),n.idlePollLoop.start();return}n.idlePollLoop||(n.idlePollLoop=new g({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:s=>this.isMessagePollingIdleCommand(s),preDispatchHook:()=>null,dispatchPollingPrompt:(s,a)=>this.sendIdlePrompt(t,s,{keepWaitingStatus:!0,injected:a}),dispatchRegularIdleCommand:s=>this.sendIdlePrompt(t,s),pollDelayMs:d,regularIdleDelayMs:d})),n.lastActivityAt=Date.now(),this.armIdleCheck(t)}}stopIdleDetection(t){const n=this.sessions.get(t);n?.idlePollLoop?.stop(),n?.idleTimer&&(clearTimeout(n.idleTimer),n.idleTimer=void 0)}armIdleCheck(t){const n=this.sessions.get(t);if(!n)return;n.idleTimer&&clearTimeout(n.idleTimer);const e=setTimeout(()=>{n.idleTimer===e&&(n.idleTimer=void 0,this.armIdleCheck(t),this.checkIdleState(t))},500);n.idleTimer=e}checkIdleState(t){const n=this.sessions.get(t);if(!n||n.adapterSession.status!=="waiting_input"||!n.idleCommands?.idleInputCommand)return;const e=n.lastActivityAt??0;Date.now()-e<d||(n.lastActivityAt=Date.now(),this.sendIdlePrompt(t,n.idleCommands.idleInputCommand),this.stopIdleDetection(t))}async sendIdlePrompt(t,n,e){const s=this.sessions.get(t);if(!s||s.runningTurn)return;const a=e?.injected?n.trim():this.toIdlePrompt(n);if(!a)return;e?.keepWaitingStatus||(s.adapterSession.status="thinking",this.emit("status-change",t,"thinking"));const r=new AbortController;s.currentAbortController=r,s.runningTurn=this.runTurn(t,s,a,r);try{await s.runningTurn}finally{s.runningTurn=void 0,s.currentAbortController=void 0}}toIdlePrompt(t){const n=t.trim();return this.isMessagePollingIdleCommand(n)?_:n}isMessagePollingIdleCommand(t){const n=t.trim();if(!n)return!1;const e=n.toLowerCase();return e.includes("poll_message")||e.includes("get_message")||n.includes("\u53D6\u6D88\u606F")}}export{K as CodexSdkAdapter};
|
|
4
4
|
|
|
@@ -44,6 +44,8 @@ export declare class OpencodeSdkAdapter extends EventEmitter implements BaseProv
|
|
|
44
44
|
private syncTodosFromToolCall;
|
|
45
45
|
private emitEvent;
|
|
46
46
|
private startIdleDetection;
|
|
47
|
+
|
|
48
|
+
private armIdleCheck;
|
|
47
49
|
private stopIdleDetection;
|
|
48
50
|
private checkIdleState;
|
|
49
51
|
private toIdlePrompt;
|
|
@@ -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;
|
|
@@ -334,22 +371,6 @@ export declare abstract class BaseProviderAdapter extends EventEmitter {
|
|
|
334
371
|
|
|
335
372
|
abstract applyAgentFeatures?(agentId: string): Promise<void>;
|
|
336
373
|
|
|
337
|
-
abstract setBuiltInCapabilityTools?(agentId: string, capability: string, action: "expand" | "collapse"): Promise<{
|
|
338
|
-
sessions: number;
|
|
339
|
-
tools: number;
|
|
340
|
-
manifests?: Array<{
|
|
341
|
-
name: string;
|
|
342
|
-
description?: string;
|
|
343
|
-
inputSchema?: unknown;
|
|
344
|
-
}>;
|
|
345
|
-
}>;
|
|
346
|
-
|
|
347
|
-
abstract callBuiltInCapabilityTool?(agentId: string, capability: string, toolName: string, args: Record<string, unknown>): Promise<{
|
|
348
|
-
ok: boolean;
|
|
349
|
-
result?: unknown;
|
|
350
|
-
error?: string;
|
|
351
|
-
}>;
|
|
352
|
-
|
|
353
374
|
abstract resetContext?(sessionId: string): Promise<void>;
|
|
354
375
|
|
|
355
376
|
abstract terminateSession(sessionId: string): Promise<void>;
|
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,2 +1,2 @@
|
|
|
1
|
-
import{promises as c}from"node:fs";import
|
|
1
|
+
import{promises as c}from"node:fs";import l from"node:path";import{Router as m}from"express";import{getAcodeDataHome as p}from"../config.js";import{validateToken as g}from"../middleware/auth.js";import{createLogger as I}from"../utils/logger.js";const i=I("acode-todos"),u=m();function y(n){return String(n).replace(/[^a-zA-Z0-9_-]/g,"_")}function f(n){return l.join(p(),"todos",`${y(n)}.json`)}u.get("/acode-todos/:agentId",g,async(n,e)=>{const a=n.params.agentId,t=Array.isArray(a)?a[0]:a;if(!t||!String(t).trim()){e.status(400).json({ok:!1,error:"agentId is required"});return}const d=f(String(t));try{const o=await c.readFile(d,"utf-8"),r=JSON.parse(o),s=Array.isArray(r.todos)?r.todos:[];e.json({ok:!0,agentId:String(t),updatedAt:typeof r.updatedAt=="string"?r.updatedAt:null,background:typeof r.background=="string"?r.background:"",todos:s})}catch(o){if((typeof o=="object"&&o!==null?Reflect.get(o,"code"):void 0)==="ENOENT"){e.json({ok:!0,agentId:String(t),updatedAt:null,todos:[]});return}if(o instanceof SyntaxError){i.warn("[acode-todos] \u6587\u4EF6\u635F\u574F\uFF08JSON \u89E3\u6790\u5931\u8D25\uFF09: %s",d),e.json({ok:!0,agentId:String(t),updatedAt:null,todos:[]});return}const s=o;i.error("[acode-todos] \u8BFB\u53D6\u5931\u8D25: %s",s.message),e.status(500).json({ok:!1,error:s.message})}}),u.delete("/acode-todos/:agentId",g,async(n,e)=>{const a=n.params.agentId,t=Array.isArray(a)?a[0]:a;if(!t||!String(t).trim()){e.status(400).json({ok:!1,error:"agentId is required"});return}const d=f(String(t));try{await c.unlink(d),i.info("[acode-todos] \u5DF2\u91CD\u7F6E todo: agentId=%s, file=%s",t,d),e.json({ok:!0,agentId:String(t),removed:!0})}catch(o){if((typeof o=="object"&&o!==null?Reflect.get(o,"code"):void 0)==="ENOENT"){e.json({ok:!0,agentId:String(t),removed:!1});return}const s=o;i.error("[acode-todos] \u91CD\u7F6E\u5931\u8D25: %s",s.message),e.status(500).json({ok:!1,error:s.message})}});export{u as acodeTodosRouter};
|
|
2
2
|
|