aws-runtime-bridge 1.9.102 → 1.9.104

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.
Files changed (219) hide show
  1. package/README.md +2 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts +2 -0
  3. package/dist/adapter/AcodeSdkAdapter.js +3 -3
  4. package/dist/index.js +1 -1
  5. package/dist/remote-desktop/computer-use-backend.d.ts +111 -0
  6. package/dist/remote-desktop/computer-use-backend.js +1 -0
  7. package/dist/remote-desktop/types.d.ts +79 -0
  8. package/dist/routes/computer.d.ts +1 -0
  9. package/dist/routes/computer.js +2 -0
  10. package/dist/routes/file-change-diff.d.ts +27 -0
  11. package/dist/routes/file-change-diff.js +5 -0
  12. package/dist/routes/instance.js +2 -2
  13. package/dist/routes/pty.d.ts +2 -2
  14. package/dist/routes/pty.js +3 -3
  15. package/dist/routes/task-context.js +1 -1
  16. package/dist/routes/terminal.js +28 -28
  17. package/dist/services/auto-register.d.ts +1 -1
  18. package/dist/services/auto-register.js +1 -1
  19. package/dist/services/instance-features.d.ts +10 -0
  20. package/dist/services/instance-features.js +2 -0
  21. package/dist/services/sdk-tool-file-change-recorder.d.ts +12 -0
  22. package/dist/services/sdk-tool-file-change-recorder.js +2 -0
  23. package/dist/services/workspace-files.js +1 -1
  24. package/dist/services/workspaceTaskChangeWatcher.d.ts +9 -1
  25. package/dist/services/workspaceTaskChangeWatcher.js +3 -1
  26. package/node_modules/playwright/LICENSE +202 -0
  27. package/node_modules/playwright/NOTICE +5 -0
  28. package/node_modules/playwright/README.md +318 -0
  29. package/node_modules/playwright/ThirdPartyNotices.txt +14 -0
  30. package/node_modules/playwright/cli.js +19 -0
  31. package/node_modules/playwright/index.d.ts +17 -0
  32. package/node_modules/playwright/index.js +17 -0
  33. package/node_modules/playwright/index.mjs +18 -0
  34. package/node_modules/playwright/jsx-runtime.js +42 -0
  35. package/node_modules/playwright/jsx-runtime.mjs +21 -0
  36. package/node_modules/playwright/lib/agents/agentParser.js +89 -0
  37. package/node_modules/playwright/lib/agents/copilot-setup-steps.yml +34 -0
  38. package/node_modules/playwright/lib/agents/generateAgents.js +395 -0
  39. package/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md +31 -0
  40. package/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md +8 -0
  41. package/node_modules/playwright/lib/agents/playwright-test-generator.agent.md +88 -0
  42. package/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md +6 -0
  43. package/node_modules/playwright/lib/agents/playwright-test-healer.agent.md +56 -0
  44. package/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md +9 -0
  45. package/node_modules/playwright/lib/agents/playwright-test-planner.agent.md +74 -0
  46. package/node_modules/playwright/lib/cli/reportActions.js +78 -0
  47. package/node_modules/playwright/lib/cli/testActions.js +213 -0
  48. package/node_modules/playwright/lib/common/index.js +2957 -0
  49. package/node_modules/playwright/lib/common/index.js.txt +34 -0
  50. package/node_modules/playwright/lib/errorContext.js +129 -0
  51. package/node_modules/playwright/lib/globals.js +58 -0
  52. package/node_modules/playwright/lib/index.js +806 -0
  53. package/node_modules/playwright/lib/isomorphic.js +260 -0
  54. package/node_modules/playwright/lib/isomorphic.js.txt +9 -0
  55. package/node_modules/playwright/lib/loader/loaderProcessEntry.js +34 -0
  56. package/node_modules/playwright/lib/loader/loaderProcessEntry.js.txt +9 -0
  57. package/node_modules/playwright/lib/matchers/expect.js +13486 -0
  58. package/node_modules/playwright/lib/matchers/expect.js.LICENSE +640 -0
  59. package/node_modules/playwright/lib/matchers/expect.js.txt +67 -0
  60. package/node_modules/playwright/lib/mcp/test/browserBackend.js +125 -0
  61. package/node_modules/playwright/lib/mcp/test/generatorTools.js +122 -0
  62. package/node_modules/playwright/lib/mcp/test/plannerTools.js +150 -0
  63. package/node_modules/playwright/lib/mcp/test/seed.js +82 -0
  64. package/node_modules/playwright/lib/mcp/test/streams.js +44 -0
  65. package/node_modules/playwright/lib/mcp/test/testBackend.js +99 -0
  66. package/node_modules/playwright/lib/mcp/test/testContext.js +306 -0
  67. package/node_modules/playwright/lib/mcp/test/testTool.js +30 -0
  68. package/node_modules/playwright/lib/mcp/test/testTools.js +98 -0
  69. package/node_modules/playwright/lib/package.js +47 -0
  70. package/node_modules/playwright/lib/program.js +242 -0
  71. package/node_modules/playwright/lib/runner/index.js +8241 -0
  72. package/node_modules/playwright/lib/runner/index.js.txt +60 -0
  73. package/node_modules/playwright/lib/transform/babelBundle.js +72275 -0
  74. package/node_modules/playwright/lib/transform/babelBundle.js.LICENSE +2384 -0
  75. package/node_modules/playwright/lib/transform/babelBundle.js.txt +325 -0
  76. package/node_modules/playwright/lib/transform/esmLoader.js +8078 -0
  77. package/node_modules/playwright/lib/transform/esmLoader.js.LICENSE +355 -0
  78. package/node_modules/playwright/lib/transform/esmLoader.js.txt +60 -0
  79. package/node_modules/playwright/lib/util.js +373 -0
  80. package/node_modules/playwright/lib/worker/workerProcessEntry.js +1850 -0
  81. package/node_modules/playwright/lib/worker/workerProcessEntry.js.txt +19 -0
  82. package/node_modules/playwright/package.json +58 -0
  83. package/node_modules/playwright/test.d.ts +18 -0
  84. package/node_modules/playwright/test.js +24 -0
  85. package/node_modules/playwright/test.mjs +35 -0
  86. package/node_modules/playwright/types/test.d.ts +10848 -0
  87. package/node_modules/playwright/types/testReporter.d.ts +899 -0
  88. package/node_modules/playwright-core/LICENSE +202 -0
  89. package/node_modules/playwright-core/NOTICE +5 -0
  90. package/node_modules/playwright-core/README.md +3 -0
  91. package/node_modules/playwright-core/ThirdPartyNotices.txt +13 -0
  92. package/node_modules/playwright-core/bin/install_media_pack.ps1 +5 -0
  93. package/node_modules/playwright-core/bin/install_webkit_wsl.ps1 +33 -0
  94. package/node_modules/playwright-core/bin/reinstall_chrome_beta_linux.sh +42 -0
  95. package/node_modules/playwright-core/bin/reinstall_chrome_beta_mac.sh +13 -0
  96. package/node_modules/playwright-core/bin/reinstall_chrome_beta_win.ps1 +24 -0
  97. package/node_modules/playwright-core/bin/reinstall_chrome_stable_linux.sh +42 -0
  98. package/node_modules/playwright-core/bin/reinstall_chrome_stable_mac.sh +12 -0
  99. package/node_modules/playwright-core/bin/reinstall_chrome_stable_win.ps1 +24 -0
  100. package/node_modules/playwright-core/bin/reinstall_msedge_beta_linux.sh +48 -0
  101. package/node_modules/playwright-core/bin/reinstall_msedge_beta_mac.sh +11 -0
  102. package/node_modules/playwright-core/bin/reinstall_msedge_beta_win.ps1 +23 -0
  103. package/node_modules/playwright-core/bin/reinstall_msedge_dev_linux.sh +48 -0
  104. package/node_modules/playwright-core/bin/reinstall_msedge_dev_mac.sh +11 -0
  105. package/node_modules/playwright-core/bin/reinstall_msedge_dev_win.ps1 +23 -0
  106. package/node_modules/playwright-core/bin/reinstall_msedge_stable_linux.sh +48 -0
  107. package/node_modules/playwright-core/bin/reinstall_msedge_stable_mac.sh +11 -0
  108. package/node_modules/playwright-core/bin/reinstall_msedge_stable_win.ps1 +24 -0
  109. package/node_modules/playwright-core/browsers.json +75 -0
  110. package/node_modules/playwright-core/cli.js +21 -0
  111. package/node_modules/playwright-core/index.d.ts +17 -0
  112. package/node_modules/playwright-core/index.js +17 -0
  113. package/node_modules/playwright-core/index.mjs +28 -0
  114. package/node_modules/playwright-core/lib/bootstrap.js +88 -0
  115. package/node_modules/playwright-core/lib/coreBundle.js +74830 -0
  116. package/node_modules/playwright-core/lib/entry/cliDaemon.js +5 -0
  117. package/node_modules/playwright-core/lib/entry/dashboardApp.js +3 -0
  118. package/node_modules/playwright-core/lib/entry/mcp.js +10 -0
  119. package/node_modules/playwright-core/lib/entry/oopBrowserDownload.js +3 -0
  120. package/node_modules/playwright-core/lib/package.js +50 -0
  121. package/node_modules/playwright-core/lib/server/chromium/appIcon.png +0 -0
  122. package/node_modules/playwright-core/lib/server/electron/loader.js +118 -0
  123. package/node_modules/playwright-core/lib/serverRegistry.js +7347 -0
  124. package/node_modules/playwright-core/lib/serverRegistry.js.LICENSE +354 -0
  125. package/node_modules/playwright-core/lib/tools/cli-client/channelSessions.js +141 -0
  126. package/node_modules/playwright-core/lib/tools/cli-client/cli.js +6 -0
  127. package/node_modules/playwright-core/lib/tools/cli-client/help.json +708 -0
  128. package/node_modules/playwright-core/lib/tools/cli-client/minimist.js +128 -0
  129. package/node_modules/playwright-core/lib/tools/cli-client/output.js +343 -0
  130. package/node_modules/playwright-core/lib/tools/cli-client/program.js +404 -0
  131. package/node_modules/playwright-core/lib/tools/cli-client/registry.js +176 -0
  132. package/node_modules/playwright-core/lib/tools/cli-client/session.js +258 -0
  133. package/node_modules/playwright-core/lib/tools/dashboard/appIcon.png +0 -0
  134. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/SKILL.md +420 -0
  135. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
  136. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
  137. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
  138. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
  139. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
  140. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
  141. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
  142. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
  143. package/node_modules/playwright-core/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
  144. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/SKILL.md +143 -0
  145. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
  146. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/migration.md +85 -0
  147. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/react.md +67 -0
  148. package/node_modules/playwright-core/lib/tools/skills/playwright-component-testing/references/vue.md +75 -0
  149. package/node_modules/playwright-core/lib/tools/skills/playwright-trace/SKILL.md +171 -0
  150. package/node_modules/playwright-core/lib/tools/utils/extension.js +101 -0
  151. package/node_modules/playwright-core/lib/tools/utils/socketConnection.js +108 -0
  152. package/node_modules/playwright-core/lib/utilsBundle.js +90764 -0
  153. package/node_modules/playwright-core/lib/utilsBundle.js.LICENSE +2179 -0
  154. package/node_modules/playwright-core/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
  155. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
  156. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
  157. package/node_modules/playwright-core/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
  158. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-CyWAfh-p.js +11 -0
  159. package/node_modules/playwright-core/lib/vite/dashboard/assets/index-DhC616m4.css +1 -0
  160. package/node_modules/playwright-core/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
  161. package/node_modules/playwright-core/lib/vite/dashboard/index.html +29 -0
  162. package/node_modules/playwright-core/lib/vite/dashboard/playwright-logo.svg +24 -0
  163. package/node_modules/playwright-core/lib/vite/htmlReport/index.html +16 -0
  164. package/node_modules/playwright-core/lib/vite/htmlReport/report.css +2 -0
  165. package/node_modules/playwright-core/lib/vite/htmlReport/report.js +32 -0
  166. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
  167. package/node_modules/playwright-core/lib/vite/recorder/assets/codeMirrorModule-CwYYHbcZ.js +32 -0
  168. package/node_modules/playwright-core/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
  169. package/node_modules/playwright-core/lib/vite/recorder/assets/index-DYjdXIbE.js +129 -0
  170. package/node_modules/playwright-core/lib/vite/recorder/assets/index-l_lX622x.css +1 -0
  171. package/node_modules/playwright-core/lib/vite/recorder/index.html +29 -0
  172. package/node_modules/playwright-core/lib/vite/recorder/playwright-logo.svg +9 -0
  173. package/node_modules/playwright-core/lib/vite/traceViewer/assets/codeMirrorModule-By56iMx7.js +32 -0
  174. package/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-B34OrIms.js +181 -0
  175. package/node_modules/playwright-core/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
  176. package/node_modules/playwright-core/lib/vite/traceViewer/assets/xtermModule-COQkjINf.js +7 -0
  177. package/node_modules/playwright-core/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
  178. package/node_modules/playwright-core/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  179. package/node_modules/playwright-core/lib/vite/traceViewer/defaultSettingsView.BLFoOugd.css +1 -0
  180. package/node_modules/playwright-core/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
  181. package/node_modules/playwright-core/lib/vite/traceViewer/index.Dl36UVQT.js +1 -0
  182. package/node_modules/playwright-core/lib/vite/traceViewer/index.html +44 -0
  183. package/node_modules/playwright-core/lib/vite/traceViewer/manifest.webmanifest +16 -0
  184. package/node_modules/playwright-core/lib/vite/traceViewer/playwright-logo.svg +9 -0
  185. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
  186. package/node_modules/playwright-core/lib/vite/traceViewer/snapshot.html +10 -0
  187. package/node_modules/playwright-core/lib/vite/traceViewer/sw.bundle.js +4 -0
  188. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.C7UW1sC9.css +1 -0
  189. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.D962mr9b.js +5 -0
  190. package/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +18 -0
  191. package/node_modules/playwright-core/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
  192. package/node_modules/playwright-core/lib/webp_codec.LICENSE +173 -0
  193. package/node_modules/playwright-core/lib/webp_codec.wasm +0 -0
  194. package/node_modules/playwright-core/lib/xdg-open +1267 -0
  195. package/node_modules/playwright-core/package.json +34 -0
  196. package/node_modules/playwright-core/types/protocol.d.ts +24842 -0
  197. package/node_modules/playwright-core/types/structs.d.ts +47 -0
  198. package/node_modules/playwright-core/types/types.d.ts +26188 -0
  199. package/package/acode/dist/built-in-file-tools.d.ts +4 -0
  200. package/package/acode/dist/built-in-file-tools.js +2 -2
  201. package/package/acode/dist/runtime.d.ts +13 -0
  202. package/package/acode/dist/runtime.js +18 -18
  203. package/package/aws-client-agent-mcp/README.md +2 -2
  204. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +14 -4
  205. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  206. package/package/aws-client-agent-mcp/dist/agent-client.test.js +36 -36
  207. package/package/aws-client-agent-mcp/dist/config.js +1 -1
  208. package/package/aws-client-agent-mcp/dist/config.test.js +2 -2
  209. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +2 -0
  210. package/package/aws-client-agent-mcp/dist/mcp-server.js +21 -21
  211. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +35 -36
  212. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +6 -0
  213. package/package/aws-client-agent-mcp/dist/mcp-tools.js +25 -5
  214. package/package/aws-client-agent-mcp/dist/mcp-tools.test.js +17 -1
  215. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.test.js +1 -1
  216. package/package/aws-client-agent-mcp/dist/types.d.ts +14 -12
  217. package/package/aws-client-agent-mcp/dist/websocket-client.js +1 -1
  218. package/package.json +5 -3
  219. package/scripts/ensure-playwright-browser.mjs +118 -0
@@ -1,2 +1,2 @@
1
- import{EventEmitter as m}from"node:events";import c from"ws";import{logger as r}from"./logger.js";const f=9e3,T=3e4,b=1e3,l=100,u=3,d=3,k=50,g=1e3;class w extends m{ws=null;config;agentId=null;heartbeatTimer=null;heartbeatTimeoutTimer=null;reconnectAttempts=0;reconnectTimer=null;isManualClose=!1;websocketFactory;lastRefreshedToken=null;consecutiveRefreshFailures=0;logBatchQueue=[];logBatchTimer=null;logSequenceNumber=0;pendingLogBatches=new Map;isProcessingLogBatch=!1;processedMsgIds=new Map;constructor(e,t){super(),this.config=e,this.websocketFactory=t??(s=>new c(s))}connect(e){return new Promise((t,s)=>{this.prepareConnection(e);const n=this.buildWebSocketUrl(e);r.info(`[WebSocket] \u6B63\u5728\u8FDE\u63A5: ${this.maskRuntimeTokenInUrl(n)}`);const{rejectOnce:o,resolveOnce:i}=this.createSettledHandlers(t,s);try{this.ws=this.websocketFactory(n),this.setupWebSocketEventHandlers(this.ws,o,i)}catch(a){o(a instanceof Error?a:new Error(String(a)))}})}prepareConnection(e){this.agentId=e,this.isManualClose=!1,this.ws&&this.ws.readyState!==c.CLOSED&&(this.ws.removeAllListeners(),this.ws.terminate())}buildWebSocketUrl(e){const t=new URL(this.config.serverUrl);t.searchParams.set("agentId",e);const s=this.config.runtimeAccessToken?.trim();return s&&t.searchParams.set("runtimeAccessToken",s),t.toString()}maskRuntimeTokenInUrl(e){try{const t=new URL(e);return t.searchParams.has("runtimeAccessToken")&&t.searchParams.set("runtimeAccessToken","***"),t.toString()}catch{return e.replace(/([?&]runtimeAccessToken=)[^&]*/u,"$1***")}}createSettledHandlers(e,t){let s=!1;return{rejectOnce:i=>{s||(s=!0,t(i))},resolveOnce:()=>{s||(s=!0,e())}}}setupWebSocketEventHandlers(e,t,s){let n=!1;e.on("open",()=>{n=!0,this.handleWebSocketOpen(s)}),e.on("message",o=>this.handleWebSocketMessage(o)),e.on("pong",()=>this.markHeartbeatReceived()),e.on("close",(o,i)=>this.handleWebSocketClose(o,i,n,t)),e.on("error",o=>this.handleWebSocketError(o,n,t))}handleWebSocketOpen(e){r.info("[WebSocket] \u8FDE\u63A5\u5DF2\u5EFA\u7ACB"),this.reconnectAttempts=0,this.consecutiveRefreshFailures=0,this.lastRefreshedToken=null,this.clearReconnectTimer(),this.startHeartbeat(),this.emit("connected"),e()}handleWebSocketMessage(e){try{const t=JSON.parse(e.toString()),s=this.extractReliableMessageId(t),n=s!==null&&this.markMsgIdProcessed(s);if(this.acknowledgeReliableMessage(t),n){r.info("[WebSocket] \u5FFD\u7565\u91CD\u590D\u6295\u9012\u7684\u53EF\u9760\u6D88\u606F: msgId=%s, type=%s",s,t.type);return}this.handleMessage(t)}catch(t){const s=e.toString(),n=s.length>200?`${s.slice(0,200)}...(truncated, ${s.length} total)`:s;r.warn("[WebSocket] \u6D88\u606F\u89E3\u6790\u5931\u8D25, dataLength=%s, preview=%s:",s.length,n,t)}}extractReliableMessageId(e){const t=e.data;if(!t||typeof t!="object")return null;const s=t,n=String(s._msgId||"").trim(),o=s._requireAck===!0||s._requireAck==="true";return!n||!o?null:n}markMsgIdProcessed(e){if(this.processedMsgIds.has(e))return!0;if(this.processedMsgIds.set(e,Date.now()),this.processedMsgIds.size>g){let t=0;const s=this.processedMsgIds.size-g;for(const n of this.processedMsgIds.keys()){if(t>=s)break;this.processedMsgIds.delete(n),t++}}return!1}acknowledgeReliableMessage(e){const t=this.extractReliableMessageId(e);t&&this.send({type:"MESSAGE_ACK",data:{msgId:t},timestamp:new Date().toISOString()})}async handleWebSocketClose(e,t,s,n){const o=t.toString(),i=this.ws?.readyState;r.warn(`[WebSocket] \u8FDE\u63A5\u5173\u95ED: code=${e}, reason=${o}, readyState=${i}, opened=${s}, reconnectAttempts=${this.reconnectAttempts}`),this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.emit("disconnected",e,t),s||n(new Error(`WebSocket \u8FDE\u63A5\u5728\u5EFA\u7ACB\u524D\u5173\u95ED: code=${e}, reason=${o}`)),this.isManualClose||(e===1008?await this.handleTokenExpiredAndReconnect():this.scheduleReconnect())}async handleTokenExpiredAndReconnect(){const e=await this.refreshRuntimeTokenOnPolicyRejection();if(e==="refreshed"){r.info("[WebSocket] runtime token \u5DF2\u5237\u65B0\uFF0C\u4F7F\u7528\u65B0 token \u91CD\u8FDE"),this.consecutiveRefreshFailures=0,this.scheduleReconnect();return}if(e==="unchanged"){r.error("[WebSocket] bridge \u8FD4\u56DE token \u672A\u53D8\u5316\uFF0C\u4F46\u670D\u52A1\u7AEF\u4ECD\u4EE5 1008 \u62D2\u7EDD\uFF0C\u505C\u6B62\u91CD\u8FDE\uFF08\u9700\u4EBA\u5DE5\u6216 supervisor \u4ECB\u5165\uFF09"),this.emit("tokenRejected",this.config.runtimeAccessToken);return}if(this.consecutiveRefreshFailures+=1,this.consecutiveRefreshFailures>=d){r.error(`[WebSocket] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 ${this.consecutiveRefreshFailures} \u6B21\uFF0C\u505C\u6B62\u91CD\u8FDE\uFF08\u4EA4\u7531 supervisor \u91CD\u542F\uFF09`),this.emit("tokenRefreshFailed",this.consecutiveRefreshFailures);return}r.warn(`[WebSocket] runtime token \u5237\u65B0\u5931\u8D25\uFF0C\u7B2C ${this.consecutiveRefreshFailures}/${d} \u6B21\u5C1D\u8BD5\u91CD\u8FDE`),this.scheduleReconnect()}async refreshRuntimeTokenOnPolicyRejection(){const e=this.config.runtimeBridgeBaseUrl;if(!e||!this.agentId)return"failed";const t=this.config.runtimeAccessToken||"",s=this.config.mcpHttpRequestTimeoutMs??12e4,n=new AbortController,o=setTimeout(()=>n.abort(),s);try{const i=await fetch(`${e}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:this.agentId,currentToken:t,forceRefresh:!0}),signal:n.signal});if(!i.ok)return r.warn(`[WebSocket] bridge refresh-token \u8FD4\u56DE ${i.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),"failed";const h=(await i.json()).runtimeAccessToken;return!h||h===t?"unchanged":(this.config.runtimeAccessToken=h,this.lastRefreshedToken=t,r.info("[WebSocket] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),"refreshed")}catch(i){return i instanceof Error&&i.name==="AbortError"?r.warn(`[WebSocket] bridge refresh-token \u8D85\u65F6\uFF08${s}ms\uFF09`):(r.warn("[WebSocket] bridge refresh-token \u5F02\u5E38: %s",i instanceof Error?i.message:String(i)),i instanceof Error&&i.stack&&r.warn("[WebSocket] refresh-token \u5F02\u5E38\u5806\u6808:",i.stack.slice(0,2e3))),"failed"}finally{clearTimeout(o)}}handleWebSocketError(e,t,s){const n=this.ws?.readyState;r.error("[WebSocket] \u8FDE\u63A5\u9519\u8BEF: readyState=%s, opened=%s, reconnectAttempts=%s, message=%s",n,t,this.reconnectAttempts,e.message),r.error("[WebSocket] \u9519\u8BEF\u5806\u6808:",e.stack?.slice(0,2e3)),this.emit("error",e),t||s(e)}disconnect(){this.isManualClose=!0,this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.clearReconnectTimer(),this.ws&&(this.ws.readyState===c.OPEN&&this.ws.close(1e3,"Agent logout"),this.ws=null),this.agentId=null,r.info("[WebSocket] \u5DF2\u65AD\u5F00\u8FDE\u63A5")}send(e){const t=this.ws?.readyState;if(!this.ws||t!==c.OPEN)return r.warn("[WebSocket] \u8FDE\u63A5\u672A\u5EFA\u7ACB\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F: readyState=%s, isManualClose=%s, agentId=%s",t,this.isManualClose,this.agentId),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(s){return r.error("[WebSocket] send() \u53D1\u9001\u6D88\u606F\u5F02\u5E38: readyState=%s, error=%s",t,s),!1}}sendMcpNodeLog(e){return this.isConnected()?(this.logBatchQueue.push(e),this.logBatchTimer||(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l)),!0):!1}flushLogBatch(){if(this.logBatchQueue.length===0||this.isProcessingLogBatch)return;const e=this.logBatchQueue.splice(0,k);if(e.length===0)return;this.isProcessingLogBatch=!0,this.logSequenceNumber+=1;const t=this.logSequenceNumber;new Promise((n,o)=>{this.pendingLogBatches.set(t,{logs:e,sequenceNumber:t,retryCount:0,resolve:n,reject:o})}).then(()=>{this.isProcessingLogBatch=!1,this.logBatchQueue.length>0&&(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l))}).catch(()=>{this.isProcessingLogBatch=!1}),this.sendLogBatch(t)}sendLogBatch(e){const t=this.pendingLogBatches.get(e);if(!t)return;this.send({type:"MCP_NODE_LOG_BATCH",data:{sequenceNumber:e,logs:t.logs},timestamp:new Date().toISOString()})||this.handleLogBatchSendFailure(e)}handleLogBatchSendFailure(e){const t=this.pendingLogBatches.get(e);t&&(t.retryCount+=1,t.retryCount<=u?(r.warn(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u7B2C ${t.retryCount} \u6B21\u91CD\u8BD5`),setTimeout(()=>{this.sendLogBatch(e)},l*t.retryCount)):(r.error(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u5DF2\u91CD\u8BD5 ${u} \u6B21\uFF0C\u4E22\u5F03`),this.pendingLogBatches.delete(e),t.reject(new Error(`\u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25`))))}handleLogAck(e){const s=Number(e?.ackSequenceNumber);if(!s||!this.pendingLogBatches.has(s))return;const n=this.pendingLogBatches.get(s);n&&(this.pendingLogBatches.delete(s),n.resolve())}isConnected(){return this.ws!==null&&this.ws.readyState===c.OPEN}handleMessage(e){switch(e.type){case"GROUP_MSG":this.emit("groupMessage",e.data);break;case"DM_MSG":this.emit("directMessage",e.data);break;case"ONLINE_CHANGE":this.emit("onlineChange",e.data);break;case"HEARTBEAT":this.markHeartbeatReceived();break;case"PROFILE_INFO":r.info("[WebSocket] \u6536\u5230 PROFILE_INFO \u6D88\u606F"),this.emit("profileInfo",e.data);break;case"AGENT_STATUS":r.info("[WebSocket] \u6536\u5230 AGENT_STATUS \u6D88\u606F"),this.emit("agentStatus",e.data);break;case"LOG_ACK":this.handleLogAck(e.data);break;case"GROUP_READ_RECEIPT":case"DM_READ_RECEIPT":case"TERMINAL_OUTPUT":case"TERMINAL_STATUS":case"MCP_NODE_LOG":case"AGENT_EVENTS_DELTA":break;default:r.warn("[WebSocket] \u672A\u77E5\u6D88\u606F\u7C7B\u578B:",e.type)}}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.isConnected()&&(this.ensureHeartbeatTimeout(),this.sendProtocolPing(),this.send({type:"HEARTBEAT",data:"ping",timestamp:new Date().toISOString()}))},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.clearHeartbeatTimeout()}sendProtocolPing(){if(!(!this.ws||this.ws.readyState!==c.OPEN))try{this.ws.ping()}catch(e){r.warn("[WebSocket] \u534F\u8BAE\u5C42 ping \u53D1\u9001\u5931\u8D25\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u91CD\u8FDE:",e instanceof Error?e.message:String(e)),this.ws.terminate()}}markHeartbeatReceived(){this.clearHeartbeatTimeout()}ensureHeartbeatTimeout(){this.heartbeatTimeoutTimer||(this.heartbeatTimeoutTimer=setTimeout(()=>{this.heartbeatTimeoutTimer=null,!(!this.ws||this.ws.readyState!==c.OPEN)&&(r.warn(`[WebSocket] ${this.resolveHeartbeatTimeout()}ms \u672A\u6536\u5230\u5FC3\u8DF3\u54CD\u5E94\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u89E6\u53D1\u91CD\u8FDE`),this.ws.terminate())},this.resolveHeartbeatTimeout()))}clearHeartbeatTimeout(){this.heartbeatTimeoutTimer&&(clearTimeout(this.heartbeatTimeoutTimer),this.heartbeatTimeoutTimer=null)}resolveHeartbeatTimeout(){return this.config.heartbeatTimeout??f}scheduleReconnect(){const e=this.config.maxReconnectAttempts!==-1;if(e&&this.reconnectAttempts>=this.config.maxReconnectAttempts){r.error("[WebSocket] \u91CD\u8FDE\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u653E\u5F03\u91CD\u8FDE"),this.emit("reconnectFailed");return}if(this.reconnectTimer)return;this.reconnectAttempts++;const t=Math.min(this.config.reconnectInterval*Math.pow(2,this.reconnectAttempts-1),this.config.reconnectMaxInterval??T),s=Math.random()*(this.config.reconnectJitterMs??b),n=Math.round(t+s),o=e?`\u7B2C ${this.reconnectAttempts}/${this.config.maxReconnectAttempts} \u6B21`:`\u7B2C ${this.reconnectAttempts} \u6B21\uFF08\u65E0\u9650\u91CD\u8BD5\u6A21\u5F0F\uFF09`;r.warn(`[WebSocket] ${n}ms \u540E\u5C1D\u8BD5${o}\u91CD\u8FDE (base=${Math.round(t)}ms, jitter=+${Math.round(s)}ms)...`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.agentId&&this.connect(this.agentId).catch(i=>{const a=i instanceof Error?i.message:String(i),h=i instanceof Error?i.stack:void 0;r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25 (attempt #%s), \u7EE7\u7EED\u91CD\u8BD5: %s",this.reconnectAttempts,a),h&&r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25\u5806\u6808:",h.slice(0,2e3)),this.scheduleReconnect()})},n)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}}export{w as WebSocketClient};
1
+ import{EventEmitter as m}from"node:events";import a from"ws";import{logger as r}from"./logger.js";const f=9e3,T=3e4,b=1e3,l=100,u=3,d=3,k=50,g=1e3;class R extends m{ws=null;config;agentId=null;heartbeatTimer=null;heartbeatTimeoutTimer=null;reconnectAttempts=0;reconnectTimer=null;isManualClose=!1;websocketFactory;lastRefreshedToken=null;consecutiveRefreshFailures=0;logBatchQueue=[];logBatchTimer=null;logSequenceNumber=0;pendingLogBatches=new Map;isProcessingLogBatch=!1;processedMsgIds=new Map;constructor(e,t){super(),this.config=e,this.websocketFactory=t??(s=>new a(s))}connect(e){return new Promise((t,s)=>{this.prepareConnection(e);const n=this.buildWebSocketUrl(e);r.info(`[WebSocket] \u6B63\u5728\u8FDE\u63A5: ${this.maskRuntimeTokenInUrl(n)}`);const{rejectOnce:o,resolveOnce:i}=this.createSettledHandlers(t,s);try{this.ws=this.websocketFactory(n),this.setupWebSocketEventHandlers(this.ws,o,i)}catch(c){o(c instanceof Error?c:new Error(String(c)))}})}prepareConnection(e){this.agentId=e,this.isManualClose=!1,this.ws&&this.ws.readyState!==a.CLOSED&&(this.ws.removeAllListeners(),this.ws.terminate())}buildWebSocketUrl(e){const t=new URL(this.config.serverUrl);t.searchParams.set("agentId",e);const s=this.config.runtimeAccessToken?.trim();return s&&t.searchParams.set("runtimeAccessToken",s),t.toString()}maskRuntimeTokenInUrl(e){try{const t=new URL(e);return t.searchParams.has("runtimeAccessToken")&&t.searchParams.set("runtimeAccessToken","***"),t.toString()}catch{return e.replace(/([?&]runtimeAccessToken=)[^&]*/u,"$1***")}}createSettledHandlers(e,t){let s=!1;return{rejectOnce:i=>{s||(s=!0,t(i))},resolveOnce:()=>{s||(s=!0,e())}}}setupWebSocketEventHandlers(e,t,s){let n=!1;e.on("open",()=>{n=!0,this.handleWebSocketOpen(s)}),e.on("message",o=>this.handleWebSocketMessage(o)),e.on("pong",()=>this.markHeartbeatReceived()),e.on("close",(o,i)=>this.handleWebSocketClose(o,i,n,t)),e.on("error",o=>this.handleWebSocketError(o,n,t))}handleWebSocketOpen(e){r.info("[WebSocket] \u8FDE\u63A5\u5DF2\u5EFA\u7ACB"),this.reconnectAttempts=0,this.consecutiveRefreshFailures=0,this.lastRefreshedToken=null,this.clearReconnectTimer(),this.startHeartbeat(),this.emit("connected"),e()}handleWebSocketMessage(e){try{const t=JSON.parse(e.toString()),s=this.extractReliableMessageId(t),n=s!==null&&this.markMsgIdProcessed(s);if(this.acknowledgeReliableMessage(t),n){r.info("[WebSocket] \u5FFD\u7565\u91CD\u590D\u6295\u9012\u7684\u53EF\u9760\u6D88\u606F: msgId=%s, type=%s",s,t.type);return}this.handleMessage(t)}catch(t){const s=e.toString(),n=s.length>200?`${s.slice(0,200)}...(truncated, ${s.length} total)`:s;r.warn("[WebSocket] \u6D88\u606F\u89E3\u6790\u5931\u8D25, dataLength=%s, preview=%s:",s.length,n,t)}}extractReliableMessageId(e){const t=e.data;if(!t||typeof t!="object")return null;const s=t,n=String(s._msgId||"").trim(),o=s._requireAck===!0||s._requireAck==="true";return!n||!o?null:n}markMsgIdProcessed(e){if(this.processedMsgIds.has(e))return!0;if(this.processedMsgIds.set(e,Date.now()),this.processedMsgIds.size>g){let t=0;const s=this.processedMsgIds.size-g;for(const n of this.processedMsgIds.keys()){if(t>=s)break;this.processedMsgIds.delete(n),t++}}return!1}acknowledgeReliableMessage(e){const t=this.extractReliableMessageId(e);t&&this.send({type:"MESSAGE_ACK",data:{msgId:t},timestamp:new Date().toISOString()})}async handleWebSocketClose(e,t,s,n){const o=t.toString(),i=this.ws?.readyState;r.warn(`[WebSocket] \u8FDE\u63A5\u5173\u95ED: code=${e}, reason=${o}, readyState=${i}, opened=${s}, reconnectAttempts=${this.reconnectAttempts}`),this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.emit("disconnected",e,t),s||n(new Error(`WebSocket \u8FDE\u63A5\u5728\u5EFA\u7ACB\u524D\u5173\u95ED: code=${e}, reason=${o}`)),this.isManualClose||(e===1008?await this.handleTokenExpiredAndReconnect():this.scheduleReconnect())}async handleTokenExpiredAndReconnect(){const e=await this.refreshRuntimeTokenOnPolicyRejection();if(e==="refreshed"){r.info("[WebSocket] runtime token \u5DF2\u5237\u65B0\uFF0C\u4F7F\u7528\u65B0 token \u91CD\u8FDE"),this.consecutiveRefreshFailures=0,this.scheduleReconnect();return}if(e==="unchanged"){r.error("[WebSocket] bridge \u8FD4\u56DE token \u672A\u53D8\u5316\uFF0C\u4F46\u670D\u52A1\u7AEF\u4ECD\u4EE5 1008 \u62D2\u7EDD\uFF0C\u505C\u6B62\u91CD\u8FDE\uFF08\u9700\u4EBA\u5DE5\u6216 supervisor \u4ECB\u5165\uFF09"),this.emit("tokenRejected",this.config.runtimeAccessToken);return}if(this.consecutiveRefreshFailures+=1,this.consecutiveRefreshFailures>=d){r.error(`[WebSocket] runtime token \u5237\u65B0\u8FDE\u7EED\u5931\u8D25 ${this.consecutiveRefreshFailures} \u6B21\uFF0C\u505C\u6B62\u91CD\u8FDE\uFF08\u4EA4\u7531 supervisor \u91CD\u542F\uFF09`),this.emit("tokenRefreshFailed",this.consecutiveRefreshFailures);return}r.warn(`[WebSocket] runtime token \u5237\u65B0\u5931\u8D25\uFF0C\u7B2C ${this.consecutiveRefreshFailures}/${d} \u6B21\u5C1D\u8BD5\u91CD\u8FDE`),this.scheduleReconnect()}async refreshRuntimeTokenOnPolicyRejection(){const e=this.config.runtimeBridgeBaseUrl;if(!e||!this.agentId)return"failed";const t=this.config.runtimeAccessToken||"",s=this.config.mcpHttpRequestTimeoutMs??12e4,n=new AbortController,o=setTimeout(()=>n.abort(),s);try{const i=await fetch(`${e}/runtime/binding/refresh-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agentId:this.agentId,currentToken:t,forceRefresh:!0}),signal:n.signal});if(!i.ok)return r.warn(`[WebSocket] bridge refresh-token \u8FD4\u56DE ${i.status}\uFF0C\u65E0\u6CD5\u5237\u65B0`),"failed";const h=(await i.json()).runtimeAccessToken;return!h||h===t?"unchanged":(this.config.runtimeAccessToken=h,this.lastRefreshedToken=t,r.info("[WebSocket] runtimeAccessToken \u5DF2\u901A\u8FC7 bridge refresh \u66F4\u65B0"),"refreshed")}catch(i){return i instanceof Error&&i.name==="AbortError"?r.warn(`[WebSocket] bridge refresh-token \u8D85\u65F6\uFF08${s}ms\uFF09`):(r.warn("[WebSocket] bridge refresh-token \u5F02\u5E38: %s",i instanceof Error?i.message:String(i)),i instanceof Error&&i.stack&&r.warn("[WebSocket] refresh-token \u5F02\u5E38\u5806\u6808:",i.stack.slice(0,2e3))),"failed"}finally{clearTimeout(o)}}handleWebSocketError(e,t,s){const n=this.ws?.readyState;r.error("[WebSocket] \u8FDE\u63A5\u9519\u8BEF: readyState=%s, opened=%s, reconnectAttempts=%s, message=%s",n,t,this.reconnectAttempts,e.message),r.error("[WebSocket] \u9519\u8BEF\u5806\u6808:",e.stack?.slice(0,2e3)),this.emit("error",e),t||s(e)}disconnect(){this.isManualClose=!0,this.stopHeartbeat(),this.clearHeartbeatTimeout(),this.clearReconnectTimer(),this.ws&&(this.ws.readyState===a.OPEN&&this.ws.close(1e3,"Agent logout"),this.ws=null),this.agentId=null,r.info("[WebSocket] \u5DF2\u65AD\u5F00\u8FDE\u63A5")}send(e){const t=this.ws?.readyState;if(!this.ws||t!==a.OPEN)return r.warn("[WebSocket] \u8FDE\u63A5\u672A\u5EFA\u7ACB\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F: readyState=%s, isManualClose=%s, agentId=%s",t,this.isManualClose,this.agentId),!1;try{return this.ws.send(JSON.stringify(e)),!0}catch(s){return r.error("[WebSocket] send() \u53D1\u9001\u6D88\u606F\u5F02\u5E38: readyState=%s, error=%s",t,s),!1}}sendMcpNodeLog(e){return this.isConnected()?(this.logBatchQueue.push(e),this.logBatchTimer||(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l)),!0):!1}flushLogBatch(){if(this.logBatchQueue.length===0||this.isProcessingLogBatch)return;const e=this.logBatchQueue.splice(0,k);if(e.length===0)return;this.isProcessingLogBatch=!0,this.logSequenceNumber+=1;const t=this.logSequenceNumber;new Promise((n,o)=>{this.pendingLogBatches.set(t,{logs:e,sequenceNumber:t,retryCount:0,resolve:n,reject:o})}).then(()=>{this.isProcessingLogBatch=!1,this.logBatchQueue.length>0&&(this.logBatchTimer=setTimeout(()=>{this.logBatchTimer=null,this.flushLogBatch()},l))}).catch(()=>{this.isProcessingLogBatch=!1}),this.sendLogBatch(t)}sendLogBatch(e){const t=this.pendingLogBatches.get(e);if(!t)return;this.send({type:"MCP_NODE_LOG_BATCH",data:{sequenceNumber:e,logs:t.logs},timestamp:new Date().toISOString()})||this.handleLogBatchSendFailure(e)}handleLogBatchSendFailure(e){const t=this.pendingLogBatches.get(e);t&&(t.retryCount+=1,t.retryCount<=u?(r.warn(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u7B2C ${t.retryCount} \u6B21\u91CD\u8BD5`),setTimeout(()=>{this.sendLogBatch(e)},l*t.retryCount)):(r.error(`[WebSocket] \u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25\uFF0C\u5DF2\u91CD\u8BD5 ${u} \u6B21\uFF0C\u4E22\u5F03`),this.pendingLogBatches.delete(e),t.reject(new Error(`\u65E5\u5FD7\u6279\u6B21 #${e} \u53D1\u9001\u5931\u8D25`))))}handleLogAck(e){const s=Number(e?.ackSequenceNumber);if(!s||!this.pendingLogBatches.has(s))return;const n=this.pendingLogBatches.get(s);n&&(this.pendingLogBatches.delete(s),n.resolve())}isConnected(){return this.ws!==null&&this.ws.readyState===a.OPEN}handleMessage(e){switch(e.type){case"GROUP_MSG":this.emit("groupMessage",e.data);break;case"DM_MSG":this.emit("directMessage",e.data);break;case"ONLINE_CHANGE":this.emit("onlineChange",e.data);break;case"HEARTBEAT":this.markHeartbeatReceived();break;case"PROFILE_INFO":r.info("[WebSocket] \u6536\u5230 PROFILE_INFO \u6D88\u606F"),this.emit("profileInfo",e.data);break;case"AGENT_CONFIG":r.info("[WebSocket] \u6536\u5230 AGENT_CONFIG \u6D88\u606F"),this.emit("agentConfig",e.data);break;case"AGENT_STATUS":r.info("[WebSocket] \u6536\u5230 AGENT_STATUS \u6D88\u606F"),this.emit("agentStatus",e.data);break;case"LOG_ACK":this.handleLogAck(e.data);break;case"GROUP_READ_RECEIPT":case"DM_READ_RECEIPT":case"TERMINAL_OUTPUT":case"TERMINAL_STATUS":case"MCP_NODE_LOG":case"AGENT_EVENTS_DELTA":break;default:r.warn("[WebSocket] \u672A\u77E5\u6D88\u606F\u7C7B\u578B:",e.type)}}startHeartbeat(){this.stopHeartbeat(),this.heartbeatTimer=setInterval(()=>{this.isConnected()&&(this.ensureHeartbeatTimeout(),this.sendProtocolPing(),this.send({type:"HEARTBEAT",data:"ping",timestamp:new Date().toISOString()}))},this.config.heartbeatInterval)}stopHeartbeat(){this.heartbeatTimer&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null),this.clearHeartbeatTimeout()}sendProtocolPing(){if(!(!this.ws||this.ws.readyState!==a.OPEN))try{this.ws.ping()}catch(e){r.warn("[WebSocket] \u534F\u8BAE\u5C42 ping \u53D1\u9001\u5931\u8D25\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u91CD\u8FDE:",e instanceof Error?e.message:String(e)),this.ws.terminate()}}markHeartbeatReceived(){this.clearHeartbeatTimeout()}ensureHeartbeatTimeout(){this.heartbeatTimeoutTimer||(this.heartbeatTimeoutTimer=setTimeout(()=>{this.heartbeatTimeoutTimer=null,!(!this.ws||this.ws.readyState!==a.OPEN)&&(r.warn(`[WebSocket] ${this.resolveHeartbeatTimeout()}ms \u672A\u6536\u5230\u5FC3\u8DF3\u54CD\u5E94\uFF0C\u7EC8\u6B62\u8FDE\u63A5\u5E76\u89E6\u53D1\u91CD\u8FDE`),this.ws.terminate())},this.resolveHeartbeatTimeout()))}clearHeartbeatTimeout(){this.heartbeatTimeoutTimer&&(clearTimeout(this.heartbeatTimeoutTimer),this.heartbeatTimeoutTimer=null)}resolveHeartbeatTimeout(){return this.config.heartbeatTimeout??f}scheduleReconnect(){const e=this.config.maxReconnectAttempts!==-1;if(e&&this.reconnectAttempts>=this.config.maxReconnectAttempts){r.error("[WebSocket] \u91CD\u8FDE\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650\uFF0C\u653E\u5F03\u91CD\u8FDE"),this.emit("reconnectFailed");return}if(this.reconnectTimer)return;this.reconnectAttempts++;const t=Math.min(this.config.reconnectInterval*Math.pow(2,this.reconnectAttempts-1),this.config.reconnectMaxInterval??T),s=Math.random()*(this.config.reconnectJitterMs??b),n=Math.round(t+s),o=e?`\u7B2C ${this.reconnectAttempts}/${this.config.maxReconnectAttempts} \u6B21`:`\u7B2C ${this.reconnectAttempts} \u6B21\uFF08\u65E0\u9650\u91CD\u8BD5\u6A21\u5F0F\uFF09`;r.warn(`[WebSocket] ${n}ms \u540E\u5C1D\u8BD5${o}\u91CD\u8FDE (base=${Math.round(t)}ms, jitter=+${Math.round(s)}ms)...`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.agentId&&this.connect(this.agentId).catch(i=>{const c=i instanceof Error?i.message:String(i),h=i instanceof Error?i.stack:void 0;r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25 (attempt #%s), \u7EE7\u7EED\u91CD\u8BD5: %s",this.reconnectAttempts,c),h&&r.warn("[WebSocket] \u91CD\u8FDE\u5931\u8D25\u5806\u6808:",h.slice(0,2e3)),this.scheduleReconnect()})},n)}clearReconnectTimer(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null)}}export{R as WebSocketClient};
2
2
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aws-runtime-bridge",
3
- "version": "1.9.102",
3
+ "version": "1.9.104",
4
4
  "description": "AgentsWorkStudio runtime bridge service for machine-level agent runtime integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,6 +12,7 @@
12
12
  "files": [
13
13
  "dist",
14
14
  "scripts/ensure-bin-executable.mjs",
15
+ "scripts/ensure-playwright-browser.mjs",
15
16
  "package/aws-client-agent-mcp/dist",
16
17
  "package/aws-client-agent-mcp/package.json",
17
18
  "package/aws-client-agent-mcp/README.md",
@@ -23,7 +24,8 @@
23
24
  "package/cc-switch-sdk/README.md"
24
25
  ],
25
26
  "bundleDependencies": [
26
- "@cc-switch/sdk"
27
+ "@cc-switch/sdk",
28
+ "playwright"
27
29
  ],
28
30
  "optionalDependencies": {
29
31
  "node-windows": "^1.0.0-beta.8"
@@ -38,7 +40,7 @@
38
40
  "build:all": "npm run build:sdk && npm run build:acode && npm run build:agent-mcp",
39
41
  "prebuild": "npm run build:all",
40
42
  "build": "tsc -p tsconfig.json && node scripts/minify-dist.mjs",
41
- "postinstall": "node scripts/ensure-bin-executable.mjs",
43
+ "postinstall": "node scripts/ensure-bin-executable.mjs && node scripts/ensure-playwright-browser.mjs",
42
44
  "pretypecheck": "npm run build:all",
43
45
  "typecheck": "tsc -p tsconfig.json --noEmit",
44
46
  "prestart": "npm run build:sdk && npm run build:agent-mcp && npm run build:acode",
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * postinstall 钩子:确保 Playwright Chromium 已就绪。
4
+ *
5
+ * 背景:npm 包不携带浏览器二进制,Linux 上安装 bridge 后 agent 启动浏览器会报
6
+ * 「Playwright 浏览器没有安装」。本脚本在 npm install 时自动下载 Chromium,
7
+ * 保证 `npm install -g aws-runtime-bridge` 后浏览器立即可用。
8
+ *
9
+ * 策略:
10
+ * - Linux + root(如 sudo npm install -g):`install --with-deps chromium`,
11
+ * 浏览器内核与系统依赖(libnss3 等)一步到位;--with-deps 失败时回退为仅下载内核。
12
+ * - Linux 非 root:仅下载内核,缺系统库时输出可操作的 sudo 提示。
13
+ * - 其他平台(Windows/macOS):`install chromium`(系统库由系统自带)。
14
+ * - 幂等:playwright 检测到浏览器已安装时直接跳过,重复安装无副作用。
15
+ * - 容错:任何失败仅警告并给出手动命令,绝不阻断 npm 安装。
16
+ * - 跳过:设置环境变量 AWS_BRIDGE_SKIP_PLAYWRIGHT_INSTALL=1。
17
+ */
18
+ import { execFile } from "node:child_process";
19
+ import { createRequire } from "node:module";
20
+ import { dirname, join } from "node:path";
21
+ import { promisify } from "node:util";
22
+
23
+ const execFileAsync = promisify(execFile);
24
+ const require = createRequire(import.meta.url);
25
+
26
+ /** 下载超时:Chromium 约 150MB,慢网络下允许 15 分钟。 */
27
+ const INSTALL_TIMEOUT_MS = 15 * 60 * 1000;
28
+
29
+ /** 定位 playwright 包的 CLI 入口(兼容 npm hoist 与嵌套安装两种布局)。 */
30
+ function resolvePlaywrightCliPath() {
31
+ try {
32
+ const packageJsonPath = require.resolve("playwright/package.json");
33
+ return join(dirname(packageJsonPath), "cli.js");
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ async function runInstall(cliPath, args) {
40
+ const { stdout, stderr } = await execFileAsync(
41
+ process.execPath,
42
+ [cliPath, ...args],
43
+ {
44
+ timeout: INSTALL_TIMEOUT_MS,
45
+ maxBuffer: 16 * 1024 * 1024,
46
+ windowsHide: true,
47
+ },
48
+ );
49
+ return `${stdout ?? ""}${stderr ?? ""}`.trim();
50
+ }
51
+
52
+ function errorBrief(error) {
53
+ const err = error;
54
+ const detail =
55
+ `${err?.stdout ?? ""}${err?.stderr ?? ""}`.trim() || err?.message || String(error);
56
+ return detail.slice(0, 300);
57
+ }
58
+
59
+ async function main() {
60
+ if (process.env.AWS_BRIDGE_SKIP_PLAYWRIGHT_INSTALL === "1") {
61
+ console.log(
62
+ "[aws-runtime-bridge] AWS_BRIDGE_SKIP_PLAYWRIGHT_INSTALL=1,跳过 Playwright Chromium 自动安装",
63
+ );
64
+ return;
65
+ }
66
+
67
+ const cliPath = resolvePlaywrightCliPath();
68
+ if (!cliPath) {
69
+ console.warn(
70
+ "[aws-runtime-bridge] 未找到 playwright 包,跳过 Chromium 自动安装(浏览器功能将不可用,可手动执行 npx playwright install chromium)",
71
+ );
72
+ return;
73
+ }
74
+
75
+ const isLinux = process.platform === "linux";
76
+ const isRoot =
77
+ typeof process.getuid === "function" && process.getuid() === 0;
78
+
79
+ console.log(
80
+ "[aws-runtime-bridge] 正在准备 Playwright Chromium(首次安装需下载约 150MB,请耐心等待)...",
81
+ );
82
+
83
+ // Linux + root:连系统依赖一起装(sudo npm install -g 场景一步到位)
84
+ if (isLinux && isRoot) {
85
+ try {
86
+ await runInstall(cliPath, ["install", "--with-deps", "chromium"]);
87
+ console.log("[aws-runtime-bridge] Playwright Chromium 与系统依赖安装完成");
88
+ return;
89
+ } catch (error) {
90
+ console.warn(
91
+ `[aws-runtime-bridge] 系统依赖安装失败(${errorBrief(error)}),回退为仅下载浏览器内核...`,
92
+ );
93
+ }
94
+ } else if (isLinux) {
95
+ console.log(
96
+ "[aws-runtime-bridge] 非 root 环境,仅下载浏览器内核;若后续提示缺少系统依赖,请执行:sudo npx playwright install --with-deps chromium",
97
+ );
98
+ }
99
+
100
+ try {
101
+ await runInstall(cliPath, ["install", "chromium"]);
102
+ console.log("[aws-runtime-bridge] Playwright Chromium 安装完成");
103
+ } catch (error) {
104
+ console.warn(
105
+ "[aws-runtime-bridge] Playwright Chromium 自动安装失败,可稍后手动执行:npx playwright install chromium",
106
+ );
107
+ console.warn(
108
+ " (Linux 提示缺少系统库时:sudo npx playwright install --with-deps chromium)",
109
+ );
110
+ console.warn(` 失败原因:${errorBrief(error)}`);
111
+ }
112
+ }
113
+
114
+ main().catch((error) => {
115
+ console.warn(
116
+ `[aws-runtime-bridge] Playwright Chromium 自动安装异常:${errorBrief(error)}`,
117
+ );
118
+ });