aws-runtime-bridge 1.9.135 → 1.9.139

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 (884) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +10 -0
  2. package/dist/adapter/AcodeSdkAdapter.js +5 -5
  3. package/dist/adapter/ClaudeSdkAdapter.js +3 -3
  4. package/dist/adapter/CodexSdkAdapter.js +3 -3
  5. package/dist/adapter/OpencodeSdkAdapter.js +3 -3
  6. package/dist/browser/browser-pool.js +1 -1
  7. package/dist/browser/built-in-browser-tools.d.ts +1 -2
  8. package/dist/browser/built-in-browser-tools.js +1 -1
  9. package/dist/browser/ws-server.js +1 -1
  10. package/dist/config.d.ts +4 -0
  11. package/dist/config.js +2 -2
  12. package/dist/index.js +1 -1
  13. package/dist/middleware/auth.js +1 -1
  14. package/dist/remote-desktop/computer-control.d.ts +1 -1
  15. package/dist/remote-desktop/index.d.ts +1 -1
  16. package/dist/remote-desktop/index.js +2 -2
  17. package/dist/remote-desktop/session-manager.d.ts +2 -2
  18. package/dist/remote-desktop/session-manager.js +1 -1
  19. package/dist/remote-desktop/system-backend.js +3 -3
  20. package/dist/routes/ai-sources.js +1 -1
  21. package/dist/routes/background-tasks.js +1 -1
  22. package/dist/routes/browser-listeners.js +1 -1
  23. package/dist/routes/capabilities.d.ts +2 -0
  24. package/dist/routes/capabilities.js +2 -0
  25. package/dist/routes/dashboard.js +1 -1
  26. package/dist/routes/file-change-diff.js +3 -3
  27. package/dist/routes/file-diff-rollback.js +1 -1
  28. package/dist/routes/file-snapshot.js +1 -1
  29. package/dist/routes/git.js +1 -1
  30. package/dist/routes/instance.d.ts +0 -1
  31. package/dist/routes/instance.js +1 -1
  32. package/dist/routes/launch.js +1 -1
  33. package/dist/routes/mcp-extra.d.ts +2 -0
  34. package/dist/routes/mcp-extra.js +3 -0
  35. package/dist/routes/mcp.d.ts +1 -0
  36. package/dist/routes/mcp.js +1 -1
  37. package/dist/routes/plugins.d.ts +2 -0
  38. package/dist/routes/plugins.js +2 -0
  39. package/dist/routes/properties.js +1 -1
  40. package/dist/routes/pty.d.ts +1 -1
  41. package/dist/routes/pty.js +1 -1
  42. package/dist/routes/runtime-binding.js +1 -1
  43. package/dist/routes/skills.d.ts +1 -0
  44. package/dist/routes/skills.js +1 -1
  45. package/dist/routes/sub-agents.js +1 -1
  46. package/dist/routes/task-context.js +1 -1
  47. package/dist/routes/terminal.js +25 -25
  48. package/dist/routes/yml.js +1 -1
  49. package/dist/services/access-control.js +1 -1
  50. package/dist/services/acode-bg-manager.js +1 -1
  51. package/dist/services/agent-capability-sync.d.ts +7 -0
  52. package/dist/services/agent-capability-sync.js +2 -0
  53. package/dist/services/agent-process-manager.d.ts +1 -1
  54. package/dist/services/agent-process-manager.js +1 -1
  55. package/{package/cc-switch-sdk/dist → dist}/services/ai-config-service.d.ts +3 -0
  56. package/dist/services/ai-config-service.js +4 -0
  57. package/dist/services/ai-source-apply.d.ts +1 -1
  58. package/dist/services/ai-source-apply.js +1 -1
  59. package/dist/services/auto-register.js +1 -1
  60. package/dist/services/bridge-package-publish-hooks.js +1 -1
  61. package/dist/services/browser-session-manager.d.ts +3 -3
  62. package/dist/services/browser-session-manager.js +1 -1
  63. package/dist/services/capability-config.d.ts +21 -0
  64. package/dist/services/capability-config.js +3 -0
  65. package/dist/services/cli-commands.js +2 -2
  66. package/dist/services/desktop-mcp-manager.js +1 -1
  67. package/dist/services/fileSnapshotStore.js +1 -1
  68. package/dist/services/instance-ai-config-service.d.ts +1 -0
  69. package/dist/services/instance-ai-config-service.js +1 -1
  70. package/dist/services/instance-features.d.ts +21 -0
  71. package/dist/services/instance-features.js +1 -1
  72. package/dist/services/instance-init-service.d.ts +7 -4
  73. package/dist/services/instance-init-service.js +1 -1
  74. package/dist/services/instance-state.js +1 -1
  75. package/dist/services/jdk-scanner.js +1 -1
  76. package/dist/services/launch-manager.js +1 -1
  77. package/dist/services/legacy-path-migration.d.ts +2 -0
  78. package/dist/services/legacy-path-migration.js +1 -1
  79. package/dist/services/lifecycle-state.js +2 -2
  80. package/dist/services/mcp-deploy.d.ts +49 -0
  81. package/dist/services/mcp-deploy.js +4 -0
  82. package/dist/services/orphan-monitor.js +1 -1
  83. package/dist/services/plugin-event-buffer.d.ts +49 -0
  84. package/dist/services/plugin-event-buffer.js +2 -0
  85. package/dist/services/plugin-manager.d.ts +262 -0
  86. package/dist/services/plugin-manager.js +16 -0
  87. package/dist/services/plugin-package.d.ts +8 -0
  88. package/dist/services/plugin-package.js +2 -0
  89. package/dist/services/process-detail.js +2 -2
  90. package/dist/services/process-detector.js +10 -10
  91. package/dist/services/process-registry.js +1 -1
  92. package/dist/services/process-top.js +2 -2
  93. package/dist/services/runtime-binding.js +4 -4
  94. package/dist/services/sdk-tool-file-change-recorder.js +1 -1
  95. package/dist/services/skill-manager.d.ts +41 -0
  96. package/dist/services/skill-manager.js +3 -0
  97. package/dist/services/startup-config-wizard.js +6 -6
  98. package/dist/services/system-metrics.js +1 -1
  99. package/dist/services/tunnel-client.js +1 -1
  100. package/dist/services/update-notifier.js +2 -2
  101. package/dist/services/windows-service-manager.js +1 -1
  102. package/dist/services/workspace-files.js +1 -1
  103. package/dist/services/workspaceTaskChangeWatcher.js +3 -3
  104. package/dist/types.d.ts +11 -61
  105. package/dist/utils/file-utils.d.ts +9 -6
  106. package/dist/utils/file-utils.js +2 -2
  107. package/dist/utils/instance-ai-config-debug-logger.js +1 -1
  108. package/dist/utils/mcp-utils.d.ts +1 -37
  109. package/dist/utils/mcp-utils.js +1 -1
  110. package/dist/utils/yaml-utils.js +1 -1
  111. package/package/acode/dist/built-in-file-tools.js +2 -2
  112. package/package/acode/dist/commands/commandRegistry.d.ts +2 -0
  113. package/package/acode/dist/commands/commandRegistry.js +1 -1
  114. package/package/acode/dist/index.d.ts +2 -0
  115. package/package/acode/dist/index.js +1 -1
  116. package/package/acode/dist/plugin-tools.d.ts +14 -0
  117. package/package/acode/dist/plugin-tools.js +9 -0
  118. package/package/acode/dist/plugin-types.d.ts +119 -0
  119. package/package/acode/dist/runtime.d.ts +4 -0
  120. package/package/acode/dist/runtime.js +19 -19
  121. package/package/acode/dist/sub-agent-manager.js +1 -1
  122. package/package/acode/dist/types.d.ts +5 -0
  123. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +9 -1
  124. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  125. package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
  126. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +10 -0
  127. package/package/aws-client-agent-mcp/dist/mcp-server.js +21 -21
  128. package/package/aws-client-agent-mcp/dist/mcp-tools.js +2 -4
  129. package/package/aws-client-agent-mcp/dist/memory-tools.js +12 -14
  130. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -1
  131. package/package/aws-client-agent-mcp/dist/server-memory-store.js +1 -1
  132. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +2 -0
  133. package/package/aws-client-agent-mcp/dist/status-reporter.js +3 -2
  134. package/package/aws-client-agent-mcp/dist/types.d.ts +22 -0
  135. package/package.json +4 -10
  136. package/dist/adapters/cc-switch/common.d.ts +0 -41
  137. package/dist/adapters/cc-switch/common.js +0 -2
  138. package/dist/adapters/cc-switch/index.d.ts +0 -19
  139. package/dist/adapters/cc-switch/index.js +0 -2
  140. package/dist/adapters/cc-switch/mcp-acode.d.ts +0 -10
  141. package/dist/adapters/cc-switch/mcp-acode.js +0 -2
  142. package/dist/adapters/cc-switch/mcp-claude.d.ts +0 -10
  143. package/dist/adapters/cc-switch/mcp-claude.js +0 -2
  144. package/dist/adapters/cc-switch/mcp-claudecode.d.ts +0 -10
  145. package/dist/adapters/cc-switch/mcp-claudecode.js +0 -2
  146. package/dist/adapters/cc-switch/mcp-codex.d.ts +0 -10
  147. package/dist/adapters/cc-switch/mcp-codex.js +0 -11
  148. package/dist/adapters/cc-switch/mcp-opencode.d.ts +0 -14
  149. package/dist/adapters/cc-switch/mcp-opencode.js +0 -2
  150. package/dist/adapters/cc-switch/mcp-placeholder.d.ts +0 -9
  151. package/dist/adapters/cc-switch/mcp-placeholder.js +0 -2
  152. package/dist/adapters/cc-switch/skill-acode.d.ts +0 -5
  153. package/dist/adapters/cc-switch/skill-acode.js +0 -2
  154. package/dist/adapters/cc-switch/skill-claude.d.ts +0 -5
  155. package/dist/adapters/cc-switch/skill-claude.js +0 -2
  156. package/dist/adapters/cc-switch/skill-claudecode.d.ts +0 -5
  157. package/dist/adapters/cc-switch/skill-claudecode.js +0 -2
  158. package/dist/adapters/cc-switch/skill-codex.d.ts +0 -4
  159. package/dist/adapters/cc-switch/skill-codex.js +0 -2
  160. package/dist/adapters/cc-switch/skill-directory.d.ts +0 -9
  161. package/dist/adapters/cc-switch/skill-directory.js +0 -3
  162. package/dist/adapters/cc-switch/skill-opencode.d.ts +0 -5
  163. package/dist/adapters/cc-switch/skill-opencode.js +0 -2
  164. package/dist/adapters/cc-switch/skill-placeholder.d.ts +0 -9
  165. package/dist/adapters/cc-switch/skill-placeholder.js +0 -2
  166. package/dist/services/cc-switch-sdk.d.ts +0 -17
  167. package/dist/services/cc-switch-sdk.js +0 -2
  168. package/dist/services/instance-service.d.ts +0 -78
  169. package/dist/services/instance-service.js +0 -2
  170. package/node_modules/@cc-switch/sdk/README.md +0 -541
  171. package/node_modules/@cc-switch/sdk/dist/constants.d.ts +0 -8
  172. package/node_modules/@cc-switch/sdk/dist/constants.js +0 -2
  173. package/node_modules/@cc-switch/sdk/dist/errors.d.ts +0 -5
  174. package/node_modules/@cc-switch/sdk/dist/errors.js +0 -2
  175. package/node_modules/@cc-switch/sdk/dist/index.d.ts +0 -5
  176. package/node_modules/@cc-switch/sdk/dist/index.js +0 -2
  177. package/node_modules/@cc-switch/sdk/dist/schemas.d.ts +0 -7
  178. package/node_modules/@cc-switch/sdk/dist/schemas.js +0 -2
  179. package/node_modules/@cc-switch/sdk/dist/sdk.d.ts +0 -59
  180. package/node_modules/@cc-switch/sdk/dist/sdk.js +0 -2
  181. package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts +0 -81
  182. package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.js +0 -4
  183. package/node_modules/@cc-switch/sdk/dist/services/mcp-model.d.ts +0 -16
  184. package/node_modules/@cc-switch/sdk/dist/services/mcp-model.js +0 -2
  185. package/node_modules/@cc-switch/sdk/dist/services/mcp-service.d.ts +0 -17
  186. package/node_modules/@cc-switch/sdk/dist/services/mcp-service.js +0 -2
  187. package/node_modules/@cc-switch/sdk/dist/services/skill-model.d.ts +0 -16
  188. package/node_modules/@cc-switch/sdk/dist/services/skill-model.js +0 -2
  189. package/node_modules/@cc-switch/sdk/dist/services/skill-service.d.ts +0 -16
  190. package/node_modules/@cc-switch/sdk/dist/services/skill-service.js +0 -2
  191. package/node_modules/@cc-switch/sdk/dist/state.d.ts +0 -3
  192. package/node_modules/@cc-switch/sdk/dist/state.js +0 -2
  193. package/node_modules/@cc-switch/sdk/dist/types.d.ts +0 -78
  194. package/node_modules/@cc-switch/sdk/dist/utils/fs.d.ts +0 -10
  195. package/node_modules/@cc-switch/sdk/dist/utils/fs.js +0 -3
  196. package/node_modules/@cc-switch/sdk/dist/utils/id.d.ts +0 -3
  197. package/node_modules/@cc-switch/sdk/dist/utils/id.js +0 -2
  198. package/node_modules/@cc-switch/sdk/package.json +0 -31
  199. package/node_modules/zod/LICENSE +0 -21
  200. package/node_modules/zod/README.md +0 -208
  201. package/node_modules/zod/index.cjs +0 -33
  202. package/node_modules/zod/index.d.cts +0 -4
  203. package/node_modules/zod/index.d.ts +0 -4
  204. package/node_modules/zod/index.js +0 -4
  205. package/node_modules/zod/locales/index.cjs +0 -17
  206. package/node_modules/zod/locales/index.d.cts +0 -1
  207. package/node_modules/zod/locales/index.d.ts +0 -1
  208. package/node_modules/zod/locales/index.js +0 -1
  209. package/node_modules/zod/locales/package.json +0 -6
  210. package/node_modules/zod/mini/index.cjs +0 -17
  211. package/node_modules/zod/mini/index.d.cts +0 -1
  212. package/node_modules/zod/mini/index.d.ts +0 -1
  213. package/node_modules/zod/mini/index.js +0 -1
  214. package/node_modules/zod/mini/package.json +0 -6
  215. package/node_modules/zod/package.json +0 -135
  216. package/node_modules/zod/src/index.ts +0 -4
  217. package/node_modules/zod/src/locales/index.ts +0 -1
  218. package/node_modules/zod/src/mini/index.ts +0 -1
  219. package/node_modules/zod/src/v3/ZodError.ts +0 -330
  220. package/node_modules/zod/src/v3/benchmarks/datetime.ts +0 -58
  221. package/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts +0 -80
  222. package/node_modules/zod/src/v3/benchmarks/index.ts +0 -59
  223. package/node_modules/zod/src/v3/benchmarks/ipv4.ts +0 -57
  224. package/node_modules/zod/src/v3/benchmarks/object.ts +0 -69
  225. package/node_modules/zod/src/v3/benchmarks/primitives.ts +0 -162
  226. package/node_modules/zod/src/v3/benchmarks/realworld.ts +0 -63
  227. package/node_modules/zod/src/v3/benchmarks/string.ts +0 -55
  228. package/node_modules/zod/src/v3/benchmarks/union.ts +0 -80
  229. package/node_modules/zod/src/v3/errors.ts +0 -13
  230. package/node_modules/zod/src/v3/external.ts +0 -6
  231. package/node_modules/zod/src/v3/helpers/enumUtil.ts +0 -17
  232. package/node_modules/zod/src/v3/helpers/errorUtil.ts +0 -8
  233. package/node_modules/zod/src/v3/helpers/parseUtil.ts +0 -176
  234. package/node_modules/zod/src/v3/helpers/partialUtil.ts +0 -34
  235. package/node_modules/zod/src/v3/helpers/typeAliases.ts +0 -2
  236. package/node_modules/zod/src/v3/helpers/util.ts +0 -224
  237. package/node_modules/zod/src/v3/index.ts +0 -4
  238. package/node_modules/zod/src/v3/locales/en.ts +0 -124
  239. package/node_modules/zod/src/v3/standard-schema.ts +0 -113
  240. package/node_modules/zod/src/v3/tests/Mocker.ts +0 -54
  241. package/node_modules/zod/src/v3/tests/all-errors.test.ts +0 -157
  242. package/node_modules/zod/src/v3/tests/anyunknown.test.ts +0 -28
  243. package/node_modules/zod/src/v3/tests/array.test.ts +0 -71
  244. package/node_modules/zod/src/v3/tests/async-parsing.test.ts +0 -388
  245. package/node_modules/zod/src/v3/tests/async-refinements.test.ts +0 -46
  246. package/node_modules/zod/src/v3/tests/base.test.ts +0 -29
  247. package/node_modules/zod/src/v3/tests/bigint.test.ts +0 -55
  248. package/node_modules/zod/src/v3/tests/branded.test.ts +0 -53
  249. package/node_modules/zod/src/v3/tests/catch.test.ts +0 -220
  250. package/node_modules/zod/src/v3/tests/coerce.test.ts +0 -133
  251. package/node_modules/zod/src/v3/tests/complex.test.ts +0 -56
  252. package/node_modules/zod/src/v3/tests/custom.test.ts +0 -31
  253. package/node_modules/zod/src/v3/tests/date.test.ts +0 -32
  254. package/node_modules/zod/src/v3/tests/deepmasking.test.ts +0 -186
  255. package/node_modules/zod/src/v3/tests/default.test.ts +0 -112
  256. package/node_modules/zod/src/v3/tests/description.test.ts +0 -33
  257. package/node_modules/zod/src/v3/tests/discriminated-unions.test.ts +0 -315
  258. package/node_modules/zod/src/v3/tests/enum.test.ts +0 -80
  259. package/node_modules/zod/src/v3/tests/error.test.ts +0 -551
  260. package/node_modules/zod/src/v3/tests/firstparty.test.ts +0 -87
  261. package/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts +0 -21
  262. package/node_modules/zod/src/v3/tests/function.test.ts +0 -257
  263. package/node_modules/zod/src/v3/tests/generics.test.ts +0 -48
  264. package/node_modules/zod/src/v3/tests/instanceof.test.ts +0 -37
  265. package/node_modules/zod/src/v3/tests/intersection.test.ts +0 -110
  266. package/node_modules/zod/src/v3/tests/language-server.source.ts +0 -76
  267. package/node_modules/zod/src/v3/tests/language-server.test.ts +0 -207
  268. package/node_modules/zod/src/v3/tests/literal.test.ts +0 -36
  269. package/node_modules/zod/src/v3/tests/map.test.ts +0 -110
  270. package/node_modules/zod/src/v3/tests/masking.test.ts +0 -4
  271. package/node_modules/zod/src/v3/tests/mocker.test.ts +0 -19
  272. package/node_modules/zod/src/v3/tests/nan.test.ts +0 -21
  273. package/node_modules/zod/src/v3/tests/nativeEnum.test.ts +0 -87
  274. package/node_modules/zod/src/v3/tests/nullable.test.ts +0 -42
  275. package/node_modules/zod/src/v3/tests/number.test.ts +0 -176
  276. package/node_modules/zod/src/v3/tests/object-augmentation.test.ts +0 -29
  277. package/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts +0 -29
  278. package/node_modules/zod/src/v3/tests/object.test.ts +0 -434
  279. package/node_modules/zod/src/v3/tests/optional.test.ts +0 -42
  280. package/node_modules/zod/src/v3/tests/parseUtil.test.ts +0 -23
  281. package/node_modules/zod/src/v3/tests/parser.test.ts +0 -41
  282. package/node_modules/zod/src/v3/tests/partials.test.ts +0 -243
  283. package/node_modules/zod/src/v3/tests/pickomit.test.ts +0 -111
  284. package/node_modules/zod/src/v3/tests/pipeline.test.ts +0 -29
  285. package/node_modules/zod/src/v3/tests/preprocess.test.ts +0 -186
  286. package/node_modules/zod/src/v3/tests/primitive.test.ts +0 -440
  287. package/node_modules/zod/src/v3/tests/promise.test.ts +0 -90
  288. package/node_modules/zod/src/v3/tests/readonly.test.ts +0 -194
  289. package/node_modules/zod/src/v3/tests/record.test.ts +0 -171
  290. package/node_modules/zod/src/v3/tests/recursive.test.ts +0 -197
  291. package/node_modules/zod/src/v3/tests/refine.test.ts +0 -313
  292. package/node_modules/zod/src/v3/tests/safeparse.test.ts +0 -27
  293. package/node_modules/zod/src/v3/tests/set.test.ts +0 -142
  294. package/node_modules/zod/src/v3/tests/standard-schema.test.ts +0 -83
  295. package/node_modules/zod/src/v3/tests/string.test.ts +0 -916
  296. package/node_modules/zod/src/v3/tests/transformer.test.ts +0 -233
  297. package/node_modules/zod/src/v3/tests/tuple.test.ts +0 -90
  298. package/node_modules/zod/src/v3/tests/unions.test.ts +0 -57
  299. package/node_modules/zod/src/v3/tests/validations.test.ts +0 -133
  300. package/node_modules/zod/src/v3/tests/void.test.ts +0 -15
  301. package/node_modules/zod/src/v3/types.ts +0 -5138
  302. package/node_modules/zod/src/v4/classic/checks.ts +0 -31
  303. package/node_modules/zod/src/v4/classic/coerce.ts +0 -27
  304. package/node_modules/zod/src/v4/classic/compat.ts +0 -70
  305. package/node_modules/zod/src/v4/classic/errors.ts +0 -82
  306. package/node_modules/zod/src/v4/classic/external.ts +0 -50
  307. package/node_modules/zod/src/v4/classic/index.ts +0 -5
  308. package/node_modules/zod/src/v4/classic/iso.ts +0 -90
  309. package/node_modules/zod/src/v4/classic/parse.ts +0 -82
  310. package/node_modules/zod/src/v4/classic/schemas.ts +0 -2197
  311. package/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts +0 -26
  312. package/node_modules/zod/src/v4/classic/tests/array.test.ts +0 -264
  313. package/node_modules/zod/src/v4/classic/tests/assignability.test.ts +0 -210
  314. package/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts +0 -381
  315. package/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts +0 -68
  316. package/node_modules/zod/src/v4/classic/tests/base.test.ts +0 -7
  317. package/node_modules/zod/src/v4/classic/tests/bigint.test.ts +0 -54
  318. package/node_modules/zod/src/v4/classic/tests/brand.test.ts +0 -63
  319. package/node_modules/zod/src/v4/classic/tests/catch.test.ts +0 -276
  320. package/node_modules/zod/src/v4/classic/tests/coalesce.test.ts +0 -20
  321. package/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts +0 -573
  322. package/node_modules/zod/src/v4/classic/tests/codec.test.ts +0 -562
  323. package/node_modules/zod/src/v4/classic/tests/coerce.test.ts +0 -160
  324. package/node_modules/zod/src/v4/classic/tests/continuability.test.ts +0 -352
  325. package/node_modules/zod/src/v4/classic/tests/custom.test.ts +0 -40
  326. package/node_modules/zod/src/v4/classic/tests/date.test.ts +0 -31
  327. package/node_modules/zod/src/v4/classic/tests/datetime.test.ts +0 -302
  328. package/node_modules/zod/src/v4/classic/tests/default.test.ts +0 -365
  329. package/node_modules/zod/src/v4/classic/tests/description.test.ts +0 -32
  330. package/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts +0 -661
  331. package/node_modules/zod/src/v4/classic/tests/enum.test.ts +0 -285
  332. package/node_modules/zod/src/v4/classic/tests/error-utils.test.ts +0 -595
  333. package/node_modules/zod/src/v4/classic/tests/error.test.ts +0 -711
  334. package/node_modules/zod/src/v4/classic/tests/file.test.ts +0 -96
  335. package/node_modules/zod/src/v4/classic/tests/firstparty.test.ts +0 -179
  336. package/node_modules/zod/src/v4/classic/tests/function.test.ts +0 -308
  337. package/node_modules/zod/src/v4/classic/tests/generics.test.ts +0 -72
  338. package/node_modules/zod/src/v4/classic/tests/hash.test.ts +0 -68
  339. package/node_modules/zod/src/v4/classic/tests/index.test.ts +0 -844
  340. package/node_modules/zod/src/v4/classic/tests/instanceof.test.ts +0 -34
  341. package/node_modules/zod/src/v4/classic/tests/intersection.test.ts +0 -171
  342. package/node_modules/zod/src/v4/classic/tests/json.test.ts +0 -108
  343. package/node_modules/zod/src/v4/classic/tests/lazy.test.ts +0 -227
  344. package/node_modules/zod/src/v4/classic/tests/literal.test.ts +0 -117
  345. package/node_modules/zod/src/v4/classic/tests/map.test.ts +0 -196
  346. package/node_modules/zod/src/v4/classic/tests/nan.test.ts +0 -21
  347. package/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts +0 -168
  348. package/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts +0 -101
  349. package/node_modules/zod/src/v4/classic/tests/nullable.test.ts +0 -22
  350. package/node_modules/zod/src/v4/classic/tests/number.test.ts +0 -270
  351. package/node_modules/zod/src/v4/classic/tests/object.test.ts +0 -609
  352. package/node_modules/zod/src/v4/classic/tests/optional.test.ts +0 -136
  353. package/node_modules/zod/src/v4/classic/tests/partial.test.ts +0 -340
  354. package/node_modules/zod/src/v4/classic/tests/pickomit.test.ts +0 -127
  355. package/node_modules/zod/src/v4/classic/tests/pipe.test.ts +0 -101
  356. package/node_modules/zod/src/v4/classic/tests/prefault.test.ts +0 -74
  357. package/node_modules/zod/src/v4/classic/tests/preprocess.test.ts +0 -282
  358. package/node_modules/zod/src/v4/classic/tests/primitive.test.ts +0 -175
  359. package/node_modules/zod/src/v4/classic/tests/promise.test.ts +0 -81
  360. package/node_modules/zod/src/v4/classic/tests/prototypes.test.ts +0 -23
  361. package/node_modules/zod/src/v4/classic/tests/readonly.test.ts +0 -252
  362. package/node_modules/zod/src/v4/classic/tests/record.test.ts +0 -356
  363. package/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts +0 -582
  364. package/node_modules/zod/src/v4/classic/tests/refine.test.ts +0 -605
  365. package/node_modules/zod/src/v4/classic/tests/registries.test.ts +0 -204
  366. package/node_modules/zod/src/v4/classic/tests/set.test.ts +0 -181
  367. package/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts +0 -57
  368. package/node_modules/zod/src/v4/classic/tests/string-formats.test.ts +0 -125
  369. package/node_modules/zod/src/v4/classic/tests/string.test.ts +0 -1080
  370. package/node_modules/zod/src/v4/classic/tests/stringbool.test.ts +0 -106
  371. package/node_modules/zod/src/v4/classic/tests/template-literal.test.ts +0 -763
  372. package/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts +0 -2622
  373. package/node_modules/zod/src/v4/classic/tests/transform.test.ts +0 -361
  374. package/node_modules/zod/src/v4/classic/tests/tuple.test.ts +0 -163
  375. package/node_modules/zod/src/v4/classic/tests/union.test.ts +0 -181
  376. package/node_modules/zod/src/v4/classic/tests/validations.test.ts +0 -283
  377. package/node_modules/zod/src/v4/classic/tests/void.test.ts +0 -12
  378. package/node_modules/zod/src/v4/core/api.ts +0 -1621
  379. package/node_modules/zod/src/v4/core/checks.ts +0 -1287
  380. package/node_modules/zod/src/v4/core/config.ts +0 -15
  381. package/node_modules/zod/src/v4/core/core.ts +0 -115
  382. package/node_modules/zod/src/v4/core/doc.ts +0 -44
  383. package/node_modules/zod/src/v4/core/errors.ts +0 -413
  384. package/node_modules/zod/src/v4/core/index.ts +0 -14
  385. package/node_modules/zod/src/v4/core/json-schema.ts +0 -147
  386. package/node_modules/zod/src/v4/core/parse.ts +0 -195
  387. package/node_modules/zod/src/v4/core/regexes.ts +0 -177
  388. package/node_modules/zod/src/v4/core/registries.ts +0 -97
  389. package/node_modules/zod/src/v4/core/schemas.ts +0 -4317
  390. package/node_modules/zod/src/v4/core/standard-schema.ts +0 -64
  391. package/node_modules/zod/src/v4/core/tests/extend.test.ts +0 -18
  392. package/node_modules/zod/src/v4/core/tests/index.test.ts +0 -46
  393. package/node_modules/zod/src/v4/core/tests/locales/be.test.ts +0 -124
  394. package/node_modules/zod/src/v4/core/tests/locales/en.test.ts +0 -22
  395. package/node_modules/zod/src/v4/core/tests/locales/es.test.ts +0 -181
  396. package/node_modules/zod/src/v4/core/tests/locales/ru.test.ts +0 -128
  397. package/node_modules/zod/src/v4/core/tests/locales/tr.test.ts +0 -69
  398. package/node_modules/zod/src/v4/core/to-json-schema.ts +0 -1044
  399. package/node_modules/zod/src/v4/core/util.ts +0 -910
  400. package/node_modules/zod/src/v4/core/versions.ts +0 -5
  401. package/node_modules/zod/src/v4/core/zsf.ts +0 -323
  402. package/node_modules/zod/src/v4/index.ts +0 -4
  403. package/node_modules/zod/src/v4/locales/ar.ts +0 -125
  404. package/node_modules/zod/src/v4/locales/az.ts +0 -121
  405. package/node_modules/zod/src/v4/locales/be.ts +0 -184
  406. package/node_modules/zod/src/v4/locales/bg.ts +0 -136
  407. package/node_modules/zod/src/v4/locales/ca.ts +0 -127
  408. package/node_modules/zod/src/v4/locales/cs.ts +0 -142
  409. package/node_modules/zod/src/v4/locales/da.ts +0 -141
  410. package/node_modules/zod/src/v4/locales/de.ts +0 -124
  411. package/node_modules/zod/src/v4/locales/en.ts +0 -127
  412. package/node_modules/zod/src/v4/locales/eo.ts +0 -125
  413. package/node_modules/zod/src/v4/locales/es.ts +0 -159
  414. package/node_modules/zod/src/v4/locales/fa.ts +0 -134
  415. package/node_modules/zod/src/v4/locales/fi.ts +0 -131
  416. package/node_modules/zod/src/v4/locales/fr-CA.ts +0 -126
  417. package/node_modules/zod/src/v4/locales/fr.ts +0 -124
  418. package/node_modules/zod/src/v4/locales/he.ts +0 -125
  419. package/node_modules/zod/src/v4/locales/hu.ts +0 -126
  420. package/node_modules/zod/src/v4/locales/id.ts +0 -125
  421. package/node_modules/zod/src/v4/locales/index.ts +0 -47
  422. package/node_modules/zod/src/v4/locales/is.ts +0 -127
  423. package/node_modules/zod/src/v4/locales/it.ts +0 -125
  424. package/node_modules/zod/src/v4/locales/ja.ts +0 -122
  425. package/node_modules/zod/src/v4/locales/ka.ts +0 -138
  426. package/node_modules/zod/src/v4/locales/kh.ts +0 -7
  427. package/node_modules/zod/src/v4/locales/km.ts +0 -126
  428. package/node_modules/zod/src/v4/locales/ko.ts +0 -131
  429. package/node_modules/zod/src/v4/locales/lt.ts +0 -265
  430. package/node_modules/zod/src/v4/locales/mk.ts +0 -127
  431. package/node_modules/zod/src/v4/locales/ms.ts +0 -124
  432. package/node_modules/zod/src/v4/locales/nl.ts +0 -126
  433. package/node_modules/zod/src/v4/locales/no.ts +0 -124
  434. package/node_modules/zod/src/v4/locales/ota.ts +0 -125
  435. package/node_modules/zod/src/v4/locales/pl.ts +0 -126
  436. package/node_modules/zod/src/v4/locales/ps.ts +0 -133
  437. package/node_modules/zod/src/v4/locales/pt.ts +0 -123
  438. package/node_modules/zod/src/v4/locales/ru.ts +0 -184
  439. package/node_modules/zod/src/v4/locales/sl.ts +0 -126
  440. package/node_modules/zod/src/v4/locales/sv.ts +0 -127
  441. package/node_modules/zod/src/v4/locales/ta.ts +0 -125
  442. package/node_modules/zod/src/v4/locales/th.ts +0 -126
  443. package/node_modules/zod/src/v4/locales/tr.ts +0 -121
  444. package/node_modules/zod/src/v4/locales/ua.ts +0 -7
  445. package/node_modules/zod/src/v4/locales/uk.ts +0 -126
  446. package/node_modules/zod/src/v4/locales/ur.ts +0 -126
  447. package/node_modules/zod/src/v4/locales/vi.ts +0 -125
  448. package/node_modules/zod/src/v4/locales/yo.ts +0 -131
  449. package/node_modules/zod/src/v4/locales/zh-CN.ts +0 -123
  450. package/node_modules/zod/src/v4/locales/zh-TW.ts +0 -125
  451. package/node_modules/zod/src/v4/mini/checks.ts +0 -32
  452. package/node_modules/zod/src/v4/mini/coerce.ts +0 -22
  453. package/node_modules/zod/src/v4/mini/external.ts +0 -40
  454. package/node_modules/zod/src/v4/mini/index.ts +0 -3
  455. package/node_modules/zod/src/v4/mini/iso.ts +0 -62
  456. package/node_modules/zod/src/v4/mini/parse.ts +0 -14
  457. package/node_modules/zod/src/v4/mini/schemas.ts +0 -1725
  458. package/node_modules/zod/src/v4/mini/tests/assignability.test.ts +0 -129
  459. package/node_modules/zod/src/v4/mini/tests/brand.test.ts +0 -51
  460. package/node_modules/zod/src/v4/mini/tests/checks.test.ts +0 -144
  461. package/node_modules/zod/src/v4/mini/tests/codec.test.ts +0 -529
  462. package/node_modules/zod/src/v4/mini/tests/computed.test.ts +0 -36
  463. package/node_modules/zod/src/v4/mini/tests/error.test.ts +0 -22
  464. package/node_modules/zod/src/v4/mini/tests/functions.test.ts +0 -43
  465. package/node_modules/zod/src/v4/mini/tests/index.test.ts +0 -899
  466. package/node_modules/zod/src/v4/mini/tests/number.test.ts +0 -95
  467. package/node_modules/zod/src/v4/mini/tests/object.test.ts +0 -200
  468. package/node_modules/zod/src/v4/mini/tests/prototypes.test.ts +0 -43
  469. package/node_modules/zod/src/v4/mini/tests/recursive-types.test.ts +0 -275
  470. package/node_modules/zod/src/v4/mini/tests/string.test.ts +0 -315
  471. package/node_modules/zod/src/v4-mini/index.ts +0 -1
  472. package/node_modules/zod/v3/ZodError.cjs +0 -138
  473. package/node_modules/zod/v3/ZodError.d.cts +0 -164
  474. package/node_modules/zod/v3/ZodError.d.ts +0 -164
  475. package/node_modules/zod/v3/ZodError.js +0 -133
  476. package/node_modules/zod/v3/errors.cjs +0 -17
  477. package/node_modules/zod/v3/errors.d.cts +0 -5
  478. package/node_modules/zod/v3/errors.d.ts +0 -5
  479. package/node_modules/zod/v3/errors.js +0 -9
  480. package/node_modules/zod/v3/external.cjs +0 -22
  481. package/node_modules/zod/v3/external.d.cts +0 -6
  482. package/node_modules/zod/v3/external.d.ts +0 -6
  483. package/node_modules/zod/v3/external.js +0 -6
  484. package/node_modules/zod/v3/helpers/enumUtil.cjs +0 -2
  485. package/node_modules/zod/v3/helpers/enumUtil.d.cts +0 -8
  486. package/node_modules/zod/v3/helpers/enumUtil.d.ts +0 -8
  487. package/node_modules/zod/v3/helpers/enumUtil.js +0 -1
  488. package/node_modules/zod/v3/helpers/errorUtil.cjs +0 -9
  489. package/node_modules/zod/v3/helpers/errorUtil.d.cts +0 -9
  490. package/node_modules/zod/v3/helpers/errorUtil.d.ts +0 -9
  491. package/node_modules/zod/v3/helpers/errorUtil.js +0 -6
  492. package/node_modules/zod/v3/helpers/parseUtil.cjs +0 -124
  493. package/node_modules/zod/v3/helpers/parseUtil.d.cts +0 -78
  494. package/node_modules/zod/v3/helpers/parseUtil.d.ts +0 -78
  495. package/node_modules/zod/v3/helpers/parseUtil.js +0 -109
  496. package/node_modules/zod/v3/helpers/partialUtil.cjs +0 -2
  497. package/node_modules/zod/v3/helpers/partialUtil.d.cts +0 -8
  498. package/node_modules/zod/v3/helpers/partialUtil.d.ts +0 -8
  499. package/node_modules/zod/v3/helpers/partialUtil.js +0 -1
  500. package/node_modules/zod/v3/helpers/typeAliases.cjs +0 -2
  501. package/node_modules/zod/v3/helpers/typeAliases.d.cts +0 -2
  502. package/node_modules/zod/v3/helpers/typeAliases.d.ts +0 -2
  503. package/node_modules/zod/v3/helpers/typeAliases.js +0 -1
  504. package/node_modules/zod/v3/helpers/util.cjs +0 -137
  505. package/node_modules/zod/v3/helpers/util.d.cts +0 -85
  506. package/node_modules/zod/v3/helpers/util.d.ts +0 -85
  507. package/node_modules/zod/v3/helpers/util.js +0 -133
  508. package/node_modules/zod/v3/index.cjs +0 -33
  509. package/node_modules/zod/v3/index.d.cts +0 -4
  510. package/node_modules/zod/v3/index.d.ts +0 -4
  511. package/node_modules/zod/v3/index.js +0 -4
  512. package/node_modules/zod/v3/locales/en.cjs +0 -112
  513. package/node_modules/zod/v3/locales/en.d.cts +0 -3
  514. package/node_modules/zod/v3/locales/en.d.ts +0 -3
  515. package/node_modules/zod/v3/locales/en.js +0 -109
  516. package/node_modules/zod/v3/package.json +0 -6
  517. package/node_modules/zod/v3/standard-schema.cjs +0 -2
  518. package/node_modules/zod/v3/standard-schema.d.cts +0 -102
  519. package/node_modules/zod/v3/standard-schema.d.ts +0 -102
  520. package/node_modules/zod/v3/standard-schema.js +0 -1
  521. package/node_modules/zod/v3/types.cjs +0 -3777
  522. package/node_modules/zod/v3/types.d.cts +0 -1034
  523. package/node_modules/zod/v3/types.d.ts +0 -1034
  524. package/node_modules/zod/v3/types.js +0 -3695
  525. package/node_modules/zod/v4/classic/checks.cjs +0 -32
  526. package/node_modules/zod/v4/classic/checks.d.cts +0 -1
  527. package/node_modules/zod/v4/classic/checks.d.ts +0 -1
  528. package/node_modules/zod/v4/classic/checks.js +0 -1
  529. package/node_modules/zod/v4/classic/coerce.cjs +0 -47
  530. package/node_modules/zod/v4/classic/coerce.d.cts +0 -17
  531. package/node_modules/zod/v4/classic/coerce.d.ts +0 -17
  532. package/node_modules/zod/v4/classic/coerce.js +0 -17
  533. package/node_modules/zod/v4/classic/compat.cjs +0 -61
  534. package/node_modules/zod/v4/classic/compat.d.cts +0 -50
  535. package/node_modules/zod/v4/classic/compat.d.ts +0 -50
  536. package/node_modules/zod/v4/classic/compat.js +0 -31
  537. package/node_modules/zod/v4/classic/errors.cjs +0 -74
  538. package/node_modules/zod/v4/classic/errors.d.cts +0 -30
  539. package/node_modules/zod/v4/classic/errors.d.ts +0 -30
  540. package/node_modules/zod/v4/classic/errors.js +0 -48
  541. package/node_modules/zod/v4/classic/external.cjs +0 -70
  542. package/node_modules/zod/v4/classic/external.d.cts +0 -13
  543. package/node_modules/zod/v4/classic/external.d.ts +0 -13
  544. package/node_modules/zod/v4/classic/external.js +0 -18
  545. package/node_modules/zod/v4/classic/index.cjs +0 -33
  546. package/node_modules/zod/v4/classic/index.d.cts +0 -4
  547. package/node_modules/zod/v4/classic/index.d.ts +0 -4
  548. package/node_modules/zod/v4/classic/index.js +0 -4
  549. package/node_modules/zod/v4/classic/iso.cjs +0 -60
  550. package/node_modules/zod/v4/classic/iso.d.cts +0 -22
  551. package/node_modules/zod/v4/classic/iso.d.ts +0 -22
  552. package/node_modules/zod/v4/classic/iso.js +0 -30
  553. package/node_modules/zod/v4/classic/package.json +0 -6
  554. package/node_modules/zod/v4/classic/parse.cjs +0 -41
  555. package/node_modules/zod/v4/classic/parse.d.cts +0 -31
  556. package/node_modules/zod/v4/classic/parse.d.ts +0 -31
  557. package/node_modules/zod/v4/classic/parse.js +0 -15
  558. package/node_modules/zod/v4/classic/schemas.cjs +0 -1151
  559. package/node_modules/zod/v4/classic/schemas.d.cts +0 -673
  560. package/node_modules/zod/v4/classic/schemas.d.ts +0 -673
  561. package/node_modules/zod/v4/classic/schemas.js +0 -1040
  562. package/node_modules/zod/v4/core/api.cjs +0 -1060
  563. package/node_modules/zod/v4/core/api.d.cts +0 -295
  564. package/node_modules/zod/v4/core/api.d.ts +0 -295
  565. package/node_modules/zod/v4/core/api.js +0 -925
  566. package/node_modules/zod/v4/core/checks.cjs +0 -595
  567. package/node_modules/zod/v4/core/checks.d.cts +0 -278
  568. package/node_modules/zod/v4/core/checks.d.ts +0 -278
  569. package/node_modules/zod/v4/core/checks.js +0 -569
  570. package/node_modules/zod/v4/core/core.cjs +0 -74
  571. package/node_modules/zod/v4/core/core.d.cts +0 -52
  572. package/node_modules/zod/v4/core/core.d.ts +0 -52
  573. package/node_modules/zod/v4/core/core.js +0 -67
  574. package/node_modules/zod/v4/core/doc.cjs +0 -39
  575. package/node_modules/zod/v4/core/doc.d.cts +0 -14
  576. package/node_modules/zod/v4/core/doc.d.ts +0 -14
  577. package/node_modules/zod/v4/core/doc.js +0 -35
  578. package/node_modules/zod/v4/core/errors.cjs +0 -213
  579. package/node_modules/zod/v4/core/errors.d.cts +0 -210
  580. package/node_modules/zod/v4/core/errors.d.ts +0 -210
  581. package/node_modules/zod/v4/core/errors.js +0 -182
  582. package/node_modules/zod/v4/core/index.cjs +0 -43
  583. package/node_modules/zod/v4/core/index.d.cts +0 -14
  584. package/node_modules/zod/v4/core/index.d.ts +0 -14
  585. package/node_modules/zod/v4/core/index.js +0 -14
  586. package/node_modules/zod/v4/core/json-schema.cjs +0 -2
  587. package/node_modules/zod/v4/core/json-schema.d.cts +0 -88
  588. package/node_modules/zod/v4/core/json-schema.d.ts +0 -88
  589. package/node_modules/zod/v4/core/json-schema.js +0 -1
  590. package/node_modules/zod/v4/core/package.json +0 -6
  591. package/node_modules/zod/v4/core/parse.cjs +0 -131
  592. package/node_modules/zod/v4/core/parse.d.cts +0 -49
  593. package/node_modules/zod/v4/core/parse.d.ts +0 -49
  594. package/node_modules/zod/v4/core/parse.js +0 -93
  595. package/node_modules/zod/v4/core/regexes.cjs +0 -136
  596. package/node_modules/zod/v4/core/regexes.d.cts +0 -78
  597. package/node_modules/zod/v4/core/regexes.d.ts +0 -78
  598. package/node_modules/zod/v4/core/regexes.js +0 -127
  599. package/node_modules/zod/v4/core/registries.cjs +0 -57
  600. package/node_modules/zod/v4/core/registries.d.cts +0 -35
  601. package/node_modules/zod/v4/core/registries.d.ts +0 -35
  602. package/node_modules/zod/v4/core/registries.js +0 -52
  603. package/node_modules/zod/v4/core/schemas.cjs +0 -1986
  604. package/node_modules/zod/v4/core/schemas.d.cts +0 -1113
  605. package/node_modules/zod/v4/core/schemas.d.ts +0 -1113
  606. package/node_modules/zod/v4/core/schemas.js +0 -1955
  607. package/node_modules/zod/v4/core/standard-schema.cjs +0 -2
  608. package/node_modules/zod/v4/core/standard-schema.d.cts +0 -55
  609. package/node_modules/zod/v4/core/standard-schema.d.ts +0 -55
  610. package/node_modules/zod/v4/core/standard-schema.js +0 -1
  611. package/node_modules/zod/v4/core/to-json-schema.cjs +0 -920
  612. package/node_modules/zod/v4/core/to-json-schema.d.cts +0 -90
  613. package/node_modules/zod/v4/core/to-json-schema.d.ts +0 -90
  614. package/node_modules/zod/v4/core/to-json-schema.js +0 -915
  615. package/node_modules/zod/v4/core/util.cjs +0 -658
  616. package/node_modules/zod/v4/core/util.d.cts +0 -197
  617. package/node_modules/zod/v4/core/util.d.ts +0 -197
  618. package/node_modules/zod/v4/core/util.js +0 -601
  619. package/node_modules/zod/v4/core/versions.cjs +0 -8
  620. package/node_modules/zod/v4/core/versions.d.cts +0 -5
  621. package/node_modules/zod/v4/core/versions.d.ts +0 -5
  622. package/node_modules/zod/v4/core/versions.js +0 -5
  623. package/node_modules/zod/v4/index.cjs +0 -22
  624. package/node_modules/zod/v4/index.d.cts +0 -3
  625. package/node_modules/zod/v4/index.d.ts +0 -3
  626. package/node_modules/zod/v4/index.js +0 -3
  627. package/node_modules/zod/v4/locales/ar.cjs +0 -143
  628. package/node_modules/zod/v4/locales/ar.d.cts +0 -5
  629. package/node_modules/zod/v4/locales/ar.d.ts +0 -4
  630. package/node_modules/zod/v4/locales/ar.js +0 -116
  631. package/node_modules/zod/v4/locales/az.cjs +0 -142
  632. package/node_modules/zod/v4/locales/az.d.cts +0 -5
  633. package/node_modules/zod/v4/locales/az.d.ts +0 -4
  634. package/node_modules/zod/v4/locales/az.js +0 -115
  635. package/node_modules/zod/v4/locales/be.cjs +0 -191
  636. package/node_modules/zod/v4/locales/be.d.cts +0 -5
  637. package/node_modules/zod/v4/locales/be.d.ts +0 -4
  638. package/node_modules/zod/v4/locales/be.js +0 -164
  639. package/node_modules/zod/v4/locales/bg.cjs +0 -156
  640. package/node_modules/zod/v4/locales/bg.d.cts +0 -5
  641. package/node_modules/zod/v4/locales/bg.d.ts +0 -5
  642. package/node_modules/zod/v4/locales/bg.js +0 -128
  643. package/node_modules/zod/v4/locales/ca.cjs +0 -145
  644. package/node_modules/zod/v4/locales/ca.d.cts +0 -5
  645. package/node_modules/zod/v4/locales/ca.d.ts +0 -4
  646. package/node_modules/zod/v4/locales/ca.js +0 -118
  647. package/node_modules/zod/v4/locales/cs.cjs +0 -162
  648. package/node_modules/zod/v4/locales/cs.d.cts +0 -5
  649. package/node_modules/zod/v4/locales/cs.d.ts +0 -4
  650. package/node_modules/zod/v4/locales/cs.js +0 -135
  651. package/node_modules/zod/v4/locales/da.cjs +0 -158
  652. package/node_modules/zod/v4/locales/da.d.cts +0 -5
  653. package/node_modules/zod/v4/locales/da.d.ts +0 -4
  654. package/node_modules/zod/v4/locales/da.js +0 -131
  655. package/node_modules/zod/v4/locales/de.cjs +0 -143
  656. package/node_modules/zod/v4/locales/de.d.cts +0 -5
  657. package/node_modules/zod/v4/locales/de.d.ts +0 -4
  658. package/node_modules/zod/v4/locales/de.js +0 -116
  659. package/node_modules/zod/v4/locales/en.cjs +0 -145
  660. package/node_modules/zod/v4/locales/en.d.cts +0 -5
  661. package/node_modules/zod/v4/locales/en.d.ts +0 -5
  662. package/node_modules/zod/v4/locales/en.js +0 -117
  663. package/node_modules/zod/v4/locales/eo.cjs +0 -144
  664. package/node_modules/zod/v4/locales/eo.d.cts +0 -5
  665. package/node_modules/zod/v4/locales/eo.d.ts +0 -5
  666. package/node_modules/zod/v4/locales/eo.js +0 -116
  667. package/node_modules/zod/v4/locales/es.cjs +0 -176
  668. package/node_modules/zod/v4/locales/es.d.cts +0 -5
  669. package/node_modules/zod/v4/locales/es.d.ts +0 -4
  670. package/node_modules/zod/v4/locales/es.js +0 -149
  671. package/node_modules/zod/v4/locales/fa.cjs +0 -149
  672. package/node_modules/zod/v4/locales/fa.d.cts +0 -5
  673. package/node_modules/zod/v4/locales/fa.d.ts +0 -4
  674. package/node_modules/zod/v4/locales/fa.js +0 -122
  675. package/node_modules/zod/v4/locales/fi.cjs +0 -149
  676. package/node_modules/zod/v4/locales/fi.d.cts +0 -5
  677. package/node_modules/zod/v4/locales/fi.d.ts +0 -4
  678. package/node_modules/zod/v4/locales/fi.js +0 -122
  679. package/node_modules/zod/v4/locales/fr-CA.cjs +0 -144
  680. package/node_modules/zod/v4/locales/fr-CA.d.cts +0 -5
  681. package/node_modules/zod/v4/locales/fr-CA.d.ts +0 -4
  682. package/node_modules/zod/v4/locales/fr-CA.js +0 -117
  683. package/node_modules/zod/v4/locales/fr.cjs +0 -143
  684. package/node_modules/zod/v4/locales/fr.d.cts +0 -5
  685. package/node_modules/zod/v4/locales/fr.d.ts +0 -4
  686. package/node_modules/zod/v4/locales/fr.js +0 -116
  687. package/node_modules/zod/v4/locales/he.cjs +0 -144
  688. package/node_modules/zod/v4/locales/he.d.cts +0 -5
  689. package/node_modules/zod/v4/locales/he.d.ts +0 -4
  690. package/node_modules/zod/v4/locales/he.js +0 -117
  691. package/node_modules/zod/v4/locales/hu.cjs +0 -144
  692. package/node_modules/zod/v4/locales/hu.d.cts +0 -5
  693. package/node_modules/zod/v4/locales/hu.d.ts +0 -4
  694. package/node_modules/zod/v4/locales/hu.js +0 -117
  695. package/node_modules/zod/v4/locales/id.cjs +0 -143
  696. package/node_modules/zod/v4/locales/id.d.cts +0 -5
  697. package/node_modules/zod/v4/locales/id.d.ts +0 -4
  698. package/node_modules/zod/v4/locales/id.js +0 -116
  699. package/node_modules/zod/v4/locales/index.cjs +0 -100
  700. package/node_modules/zod/v4/locales/index.d.cts +0 -47
  701. package/node_modules/zod/v4/locales/index.d.ts +0 -47
  702. package/node_modules/zod/v4/locales/index.js +0 -47
  703. package/node_modules/zod/v4/locales/is.cjs +0 -145
  704. package/node_modules/zod/v4/locales/is.d.cts +0 -5
  705. package/node_modules/zod/v4/locales/is.d.ts +0 -5
  706. package/node_modules/zod/v4/locales/is.js +0 -117
  707. package/node_modules/zod/v4/locales/it.cjs +0 -144
  708. package/node_modules/zod/v4/locales/it.d.cts +0 -5
  709. package/node_modules/zod/v4/locales/it.d.ts +0 -4
  710. package/node_modules/zod/v4/locales/it.js +0 -117
  711. package/node_modules/zod/v4/locales/ja.cjs +0 -142
  712. package/node_modules/zod/v4/locales/ja.d.cts +0 -5
  713. package/node_modules/zod/v4/locales/ja.d.ts +0 -4
  714. package/node_modules/zod/v4/locales/ja.js +0 -115
  715. package/node_modules/zod/v4/locales/ka.cjs +0 -153
  716. package/node_modules/zod/v4/locales/ka.d.cts +0 -5
  717. package/node_modules/zod/v4/locales/ka.d.ts +0 -5
  718. package/node_modules/zod/v4/locales/ka.js +0 -125
  719. package/node_modules/zod/v4/locales/kh.cjs +0 -12
  720. package/node_modules/zod/v4/locales/kh.d.cts +0 -5
  721. package/node_modules/zod/v4/locales/kh.d.ts +0 -5
  722. package/node_modules/zod/v4/locales/kh.js +0 -5
  723. package/node_modules/zod/v4/locales/km.cjs +0 -144
  724. package/node_modules/zod/v4/locales/km.d.cts +0 -5
  725. package/node_modules/zod/v4/locales/km.d.ts +0 -4
  726. package/node_modules/zod/v4/locales/km.js +0 -117
  727. package/node_modules/zod/v4/locales/ko.cjs +0 -148
  728. package/node_modules/zod/v4/locales/ko.d.cts +0 -5
  729. package/node_modules/zod/v4/locales/ko.d.ts +0 -4
  730. package/node_modules/zod/v4/locales/ko.js +0 -121
  731. package/node_modules/zod/v4/locales/lt.cjs +0 -258
  732. package/node_modules/zod/v4/locales/lt.d.cts +0 -5
  733. package/node_modules/zod/v4/locales/lt.d.ts +0 -5
  734. package/node_modules/zod/v4/locales/lt.js +0 -230
  735. package/node_modules/zod/v4/locales/mk.cjs +0 -145
  736. package/node_modules/zod/v4/locales/mk.d.cts +0 -5
  737. package/node_modules/zod/v4/locales/mk.d.ts +0 -4
  738. package/node_modules/zod/v4/locales/mk.js +0 -118
  739. package/node_modules/zod/v4/locales/ms.cjs +0 -143
  740. package/node_modules/zod/v4/locales/ms.d.cts +0 -5
  741. package/node_modules/zod/v4/locales/ms.d.ts +0 -4
  742. package/node_modules/zod/v4/locales/ms.js +0 -116
  743. package/node_modules/zod/v4/locales/nl.cjs +0 -144
  744. package/node_modules/zod/v4/locales/nl.d.cts +0 -5
  745. package/node_modules/zod/v4/locales/nl.d.ts +0 -4
  746. package/node_modules/zod/v4/locales/nl.js +0 -117
  747. package/node_modules/zod/v4/locales/no.cjs +0 -143
  748. package/node_modules/zod/v4/locales/no.d.cts +0 -5
  749. package/node_modules/zod/v4/locales/no.d.ts +0 -4
  750. package/node_modules/zod/v4/locales/no.js +0 -116
  751. package/node_modules/zod/v4/locales/ota.cjs +0 -144
  752. package/node_modules/zod/v4/locales/ota.d.cts +0 -5
  753. package/node_modules/zod/v4/locales/ota.d.ts +0 -4
  754. package/node_modules/zod/v4/locales/ota.js +0 -117
  755. package/node_modules/zod/v4/locales/package.json +0 -6
  756. package/node_modules/zod/v4/locales/pl.cjs +0 -144
  757. package/node_modules/zod/v4/locales/pl.d.cts +0 -5
  758. package/node_modules/zod/v4/locales/pl.d.ts +0 -4
  759. package/node_modules/zod/v4/locales/pl.js +0 -117
  760. package/node_modules/zod/v4/locales/ps.cjs +0 -149
  761. package/node_modules/zod/v4/locales/ps.d.cts +0 -5
  762. package/node_modules/zod/v4/locales/ps.d.ts +0 -4
  763. package/node_modules/zod/v4/locales/ps.js +0 -122
  764. package/node_modules/zod/v4/locales/pt.cjs +0 -143
  765. package/node_modules/zod/v4/locales/pt.d.cts +0 -5
  766. package/node_modules/zod/v4/locales/pt.d.ts +0 -4
  767. package/node_modules/zod/v4/locales/pt.js +0 -116
  768. package/node_modules/zod/v4/locales/ru.cjs +0 -191
  769. package/node_modules/zod/v4/locales/ru.d.cts +0 -5
  770. package/node_modules/zod/v4/locales/ru.d.ts +0 -4
  771. package/node_modules/zod/v4/locales/ru.js +0 -164
  772. package/node_modules/zod/v4/locales/sl.cjs +0 -144
  773. package/node_modules/zod/v4/locales/sl.d.cts +0 -5
  774. package/node_modules/zod/v4/locales/sl.d.ts +0 -4
  775. package/node_modules/zod/v4/locales/sl.js +0 -117
  776. package/node_modules/zod/v4/locales/sv.cjs +0 -145
  777. package/node_modules/zod/v4/locales/sv.d.cts +0 -5
  778. package/node_modules/zod/v4/locales/sv.d.ts +0 -4
  779. package/node_modules/zod/v4/locales/sv.js +0 -118
  780. package/node_modules/zod/v4/locales/ta.cjs +0 -144
  781. package/node_modules/zod/v4/locales/ta.d.cts +0 -5
  782. package/node_modules/zod/v4/locales/ta.d.ts +0 -4
  783. package/node_modules/zod/v4/locales/ta.js +0 -117
  784. package/node_modules/zod/v4/locales/th.cjs +0 -144
  785. package/node_modules/zod/v4/locales/th.d.cts +0 -5
  786. package/node_modules/zod/v4/locales/th.d.ts +0 -4
  787. package/node_modules/zod/v4/locales/th.js +0 -117
  788. package/node_modules/zod/v4/locales/tr.cjs +0 -143
  789. package/node_modules/zod/v4/locales/tr.d.cts +0 -5
  790. package/node_modules/zod/v4/locales/tr.d.ts +0 -5
  791. package/node_modules/zod/v4/locales/tr.js +0 -115
  792. package/node_modules/zod/v4/locales/ua.cjs +0 -12
  793. package/node_modules/zod/v4/locales/ua.d.cts +0 -5
  794. package/node_modules/zod/v4/locales/ua.d.ts +0 -5
  795. package/node_modules/zod/v4/locales/ua.js +0 -5
  796. package/node_modules/zod/v4/locales/uk.cjs +0 -144
  797. package/node_modules/zod/v4/locales/uk.d.cts +0 -5
  798. package/node_modules/zod/v4/locales/uk.d.ts +0 -4
  799. package/node_modules/zod/v4/locales/uk.js +0 -117
  800. package/node_modules/zod/v4/locales/ur.cjs +0 -144
  801. package/node_modules/zod/v4/locales/ur.d.cts +0 -5
  802. package/node_modules/zod/v4/locales/ur.d.ts +0 -4
  803. package/node_modules/zod/v4/locales/ur.js +0 -117
  804. package/node_modules/zod/v4/locales/vi.cjs +0 -143
  805. package/node_modules/zod/v4/locales/vi.d.cts +0 -5
  806. package/node_modules/zod/v4/locales/vi.d.ts +0 -4
  807. package/node_modules/zod/v4/locales/vi.js +0 -116
  808. package/node_modules/zod/v4/locales/yo.cjs +0 -142
  809. package/node_modules/zod/v4/locales/yo.d.cts +0 -5
  810. package/node_modules/zod/v4/locales/yo.d.ts +0 -4
  811. package/node_modules/zod/v4/locales/yo.js +0 -115
  812. package/node_modules/zod/v4/locales/zh-CN.cjs +0 -143
  813. package/node_modules/zod/v4/locales/zh-CN.d.cts +0 -5
  814. package/node_modules/zod/v4/locales/zh-CN.d.ts +0 -4
  815. package/node_modules/zod/v4/locales/zh-CN.js +0 -116
  816. package/node_modules/zod/v4/locales/zh-TW.cjs +0 -144
  817. package/node_modules/zod/v4/locales/zh-TW.d.cts +0 -5
  818. package/node_modules/zod/v4/locales/zh-TW.d.ts +0 -4
  819. package/node_modules/zod/v4/locales/zh-TW.js +0 -117
  820. package/node_modules/zod/v4/mini/checks.cjs +0 -34
  821. package/node_modules/zod/v4/mini/checks.d.cts +0 -1
  822. package/node_modules/zod/v4/mini/checks.d.ts +0 -1
  823. package/node_modules/zod/v4/mini/checks.js +0 -1
  824. package/node_modules/zod/v4/mini/coerce.cjs +0 -47
  825. package/node_modules/zod/v4/mini/coerce.d.cts +0 -7
  826. package/node_modules/zod/v4/mini/coerce.d.ts +0 -7
  827. package/node_modules/zod/v4/mini/coerce.js +0 -17
  828. package/node_modules/zod/v4/mini/external.cjs +0 -62
  829. package/node_modules/zod/v4/mini/external.d.cts +0 -11
  830. package/node_modules/zod/v4/mini/external.d.ts +0 -11
  831. package/node_modules/zod/v4/mini/external.js +0 -13
  832. package/node_modules/zod/v4/mini/index.cjs +0 -32
  833. package/node_modules/zod/v4/mini/index.d.cts +0 -3
  834. package/node_modules/zod/v4/mini/index.d.ts +0 -3
  835. package/node_modules/zod/v4/mini/index.js +0 -3
  836. package/node_modules/zod/v4/mini/iso.cjs +0 -60
  837. package/node_modules/zod/v4/mini/iso.d.cts +0 -22
  838. package/node_modules/zod/v4/mini/iso.d.ts +0 -22
  839. package/node_modules/zod/v4/mini/iso.js +0 -30
  840. package/node_modules/zod/v4/mini/package.json +0 -6
  841. package/node_modules/zod/v4/mini/parse.cjs +0 -16
  842. package/node_modules/zod/v4/mini/parse.d.cts +0 -1
  843. package/node_modules/zod/v4/mini/parse.d.ts +0 -1
  844. package/node_modules/zod/v4/mini/parse.js +0 -1
  845. package/node_modules/zod/v4/mini/schemas.cjs +0 -892
  846. package/node_modules/zod/v4/mini/schemas.d.cts +0 -407
  847. package/node_modules/zod/v4/mini/schemas.d.ts +0 -407
  848. package/node_modules/zod/v4/mini/schemas.js +0 -775
  849. package/node_modules/zod/v4/package.json +0 -6
  850. package/node_modules/zod/v4-mini/index.cjs +0 -17
  851. package/node_modules/zod/v4-mini/index.d.cts +0 -1
  852. package/node_modules/zod/v4-mini/index.d.ts +0 -1
  853. package/node_modules/zod/v4-mini/index.js +0 -1
  854. package/node_modules/zod/v4-mini/package.json +0 -6
  855. package/package/cc-switch-sdk/README.md +0 -541
  856. package/package/cc-switch-sdk/dist/constants.d.ts +0 -8
  857. package/package/cc-switch-sdk/dist/constants.js +0 -2
  858. package/package/cc-switch-sdk/dist/errors.d.ts +0 -5
  859. package/package/cc-switch-sdk/dist/errors.js +0 -2
  860. package/package/cc-switch-sdk/dist/index.d.ts +0 -5
  861. package/package/cc-switch-sdk/dist/index.js +0 -2
  862. package/package/cc-switch-sdk/dist/schemas.d.ts +0 -7
  863. package/package/cc-switch-sdk/dist/schemas.js +0 -2
  864. package/package/cc-switch-sdk/dist/sdk.d.ts +0 -59
  865. package/package/cc-switch-sdk/dist/sdk.js +0 -2
  866. package/package/cc-switch-sdk/dist/services/ai-config-service.js +0 -4
  867. package/package/cc-switch-sdk/dist/services/mcp-model.d.ts +0 -16
  868. package/package/cc-switch-sdk/dist/services/mcp-model.js +0 -2
  869. package/package/cc-switch-sdk/dist/services/mcp-service.d.ts +0 -17
  870. package/package/cc-switch-sdk/dist/services/mcp-service.js +0 -2
  871. package/package/cc-switch-sdk/dist/services/skill-model.d.ts +0 -16
  872. package/package/cc-switch-sdk/dist/services/skill-model.js +0 -2
  873. package/package/cc-switch-sdk/dist/services/skill-service.d.ts +0 -16
  874. package/package/cc-switch-sdk/dist/services/skill-service.js +0 -2
  875. package/package/cc-switch-sdk/dist/state.d.ts +0 -3
  876. package/package/cc-switch-sdk/dist/state.js +0 -2
  877. package/package/cc-switch-sdk/dist/types.d.ts +0 -78
  878. package/package/cc-switch-sdk/dist/types.js +0 -1
  879. package/package/cc-switch-sdk/dist/utils/fs.d.ts +0 -10
  880. package/package/cc-switch-sdk/dist/utils/fs.js +0 -3
  881. package/package/cc-switch-sdk/dist/utils/id.d.ts +0 -3
  882. package/package/cc-switch-sdk/dist/utils/id.js +0 -2
  883. package/package/cc-switch-sdk/package.json +0 -31
  884. /package/{node_modules/@cc-switch/sdk/dist/types.js → package/acode/dist/plugin-types.js} +0 -0
@@ -1,4 +1,4 @@
1
- import{spawn as A}from"node:child_process";import{EventEmitter as E}from"node:events";import*as w from"node:fs";import*as x from"node:net";import*as T from"node:os";import*as h from"node:path";import{v4 as y}from"uuid";import{BRIDGE_PACKAGE_ROOT as _,importBridgeSdkPackage as $}from"../utils/sdk-package-loader.js";import{getAcodeDataHome as M}from"../config.js";import{logger as L}from"../utils/logger.js";import{IdlePollLoop as O}from"./idle-poll-loop.js";import{getToolActionInfo as D,redactTransientClipboardPastePaths as P,redactTransientClipboardPastePathsInValue as C}from"./types.js";import{registerListenerWakeHook as j,unregisterListenerWakeHook as I}from"../services/browser-session-manager.js";function N(d){if(d&&h.isAbsolute(d)&&w.existsSync(d))return d;const t=d?.trim()||"opencode";if(process.platform==="win32"){const e=process.env.USERPROFILE||process.env.HOME||T.homedir(),o=process.env.LOCALAPPDATA||"",r=[h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64","bin"),h.join(o,"Volta","tools","shared","opencode-ai","node_modules","opencode-windows-x64-baseline","bin")];for(const s of r){const n=h.join(s,"opencode.exe");if(w.existsSync(n))return console.log(`[OpencodeSdkAdapter] Found opencode.exe: ${n}`),n}const i=[h.join(e,"AppData","Roaming","npm"),h.join(e,"AppData","Local","Volta","bin")];for(const s of i)for(const n of["opencode.cmd","opencode.exe","opencode"]){const a=h.join(s,n);if(w.existsSync(a))return console.log(`[OpencodeSdkAdapter] Found ${n}: ${a}`),a}}return t}async function R(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(o=>{const r=x.createServer();r.once("error",()=>o(!1)),r.once("listening",()=>{r.close(()=>o(!0))}),r.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function U(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function H(d,t){return U(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 Q extends E{constructor(){super(...arguments),this.providerId="opencode",this.displayName="OpenCode",this.sessions=new Map,this.listenerWakeHooks=new Map}async startSession(t,e){console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8 OpenCode SDK \u4F1A\u8BDD \u2605\u2605\u2605 sessionId="${t}", workingDirectory="${e.workingDirectory}"`);const o={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,o),e.agentId){const r=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,r),j(e.agentId,r)}this.emit("status-change",t,"starting");try{const r=await R();o.port=r,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u4F7F\u7528\u7AEF\u53E3 \u2605\u2605\u2605 port=${r}`);const i=N(e.command);console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 \u542F\u52A8\u547D\u4EE4 \u2605\u2605\u2605 command="${i}"`);const s=i.endsWith(".cmd")||i.endsWith(".CMD")||process.platform==="win32"&&!h.isAbsolute(i);console.log(`[OpencodeSdkAdapter] shell=${s}`);const n={...process.env,...e.envOverrides},a={};v(e.model)?.modelID&&(a.model=e.model.trim()),e.systemPrompt&&typeof e.systemPrompt=="string"&&(a.systemPrompt=e.systemPrompt),Object.keys(a).length>0&&(n.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),L.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=A(i,["serve","--port",String(r)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:n,shell:s});o.serverProcess=l,o.startupOutput=[],l.stdout?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stdout: ${f.slice(0,200)}`)}),l.stderr?.on("data",c=>{const f=c.toString();this.recordStartupOutput(o,f),console.debug(`[OpencodeSdkAdapter] serve stderr: ${f.slice(0,200)}`)}),l.on("error",c=>{console.error("[OpencodeSdkAdapter] Server process error:",c),o.adapterSession.status!=="terminated"&&(o.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode server error: ${c.message}`}}))}),l.on("exit",c=>{console.log(`[OpencodeSdkAdapter] Server exited with code ${c}`),o.sseActive=!1});const p=new Promise(c=>{l.once("exit",(f,b)=>c({code:f,signal:b}))}),g=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${r}`});o.client=g,await Promise.race([this.waitForServer(g,e.workingDirectory,1e4,r),p.then(c=>{throw new Error(this.formatStartupExitMessage(c,o.startupOutput))})]),console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode server ready \u2605\u2605\u2605 port=${r}`);const k=(await g.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!k?.id)throw new Error("OpenCode session.create() did not return an ID");o.opencodeSessionId=k.id,o.adapterSession.providerSessionId=k.id,console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 OpenCode \u4F1A\u8BDD\u521B\u5EFA\u6210\u529F \u2605\u2605\u2605 sessionId="${k.id}"`),this.startSseLoop(t,o),o.adapterSession.status="waiting_input",this.emit("status-change",t,"waiting_input",{usage:o.adapterSession.totalUsage}),e.initialPrompt&&this.dispatchInitialPrompt(t,e.initialPrompt)}catch(r){e.agentId&&I(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const i=r instanceof Error?r.message:String(r);throw console.error("[OpencodeSdkAdapter] startSession failed:",r),o.adapterSession.status="error",this.emit("status-change",t,"error"),this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode start failed: ${i}`}}),r}}async sendMessage(t,e,o){const r=this.sessions.get(t);if(!r)throw new Error(`Session ${t} not found`);if(!r.client||!r.opencodeSessionId)throw new Error(`Session ${t} not ready`);const i={id:y(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};r.adapterSession.messages.push(i),this.emit("conversation-message",t,i),o?.keepWaitingStatus||(r.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const s=v(r.config.model),n={parts:[{type:"text",text:e}]};s?.providerID&&s?.modelID&&(n.model={providerID:s.providerID,modelID:s.modelID},console.log(`[OpencodeSdkAdapter] \u2605\u2605\u2605 per-message model \u2605\u2605\u2605 provider=${s.providerID}, model=${s.modelID}`)),await r.client.session.prompt({path:{id:r.opencodeSessionId},body:n,query:{directory:r.workingDirectory}})}catch(s){const n=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:n}})}}async sendConfirmation(t,e){const o=this.sessions.get(t);if(!o?.client||!o.opencodeSessionId)return;const r=e?"once":"reject",i=o.opencodeSessionId;for(const[s]of o.pendingPermissions)try{await o.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:s},body:{response:r},query:{directory:o.workingDirectory}})}catch(n){console.warn("[OpencodeSdkAdapter] Permission response failed:",n)}o.pendingPermissions.clear()}async sendQuestionAnswer(t,e){}setIdleCommands(t,e){const o=this.sessions.get(t);o&&(o.idleCommands=e,o.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(o){console.warn("[OpencodeSdkAdapter] Abort failed:",o)}}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&&I(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 $("@opencode-ai/sdk")}catch(t){throw H(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 "${_}" @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,o,r){const i=Date.now()+o;for(;Date.now()<i;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(s=>setTimeout(s,300))}throw new Error(`OpenCode server (port ${r}) did not start within ${o}ms`)}recordStartupOutput(t,e){const o=e.trim();o&&(t.startupOutput=[...t.startupOutput??[],o].slice(-8))}formatStartupExitMessage(t,e){const o=t.signal?`signal ${t.signal}`:`code ${t.code??"unknown"}`,r=(e??[]).join(`
3
- `).trim();return r?`OpenCode server exited during startup (${o}): ${r}`:`OpenCode server exited during startup (${o}). Please check whether opencode serve can run in this workspace.`}dispatchInitialPrompt(t,e){this.sendMessage(t,e).catch(o=>{const r=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const o=new AbortController;e.sseAbortController=o,this.runSseLoop(t,e,o).catch(r=>{o.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,o){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:o.signal});for await(const i of r.stream){if(!e.sseActive||o.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(o.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,o){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(o.type){case"message.updated":{const s=o.properties.info;if(s.sessionID!==i)break;if(s.role==="user")e.userMessageIds.add(s.id);else if(s.role==="assistant"){const n=s.tokens;n&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,n.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,n.output))}break}case"message.part.updated":{const{part:s,delta:n}=o.properties;if(s.sessionID!==i||e.userMessageIds.has(s.messageID))break;this.handlePartUpdate(t,e,s,n,r);break}case"session.idle":{if(o.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:y(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:r};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:r,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const s=e.idleCommands?.idleInputCommand;!!(s&&this.isMessagePollingIdleCommand(s))?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 s=o.properties;if(s.sessionID!==i)break;const n=s.id;e.pendingPermissions.set(n,s),e.config.autoAccept&&e.client&&i?e.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:n},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(n)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:r,data:{permissionPrompt:s.title,toolName:s.type}});break}case"session.error":{const{sessionID:s,error:n}=o.properties;if(s&&s!==i)break;let a="OpenCode session error";if(n){const u=n.data;typeof u?.message=="string"?a=`${n.name}: ${u.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,o,r,i){switch(o.type){case"text":{let s;if(r!==void 0)s=r,e.seenTextPartIds.add(o.id);else if(!e.seenTextPartIds.has(o.id))s=o.text,s&&e.seenTextPartIds.add(o.id);else break;if(!s)break;e.currentAssistantText+=s,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:s}});break}case"reasoning":{const s=r??o.text;if(!s)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:s}});break}case"tool":{const s=o.callID,n=o.tool,a=o.state,u=a.input,l=o.metadata;l&&Object.keys(l).length>0&&console.log(`[OpencodeSdkAdapter] Tool "${n}" metadata:`,JSON.stringify(C(l)));const p=C(u),S=p&&typeof p=="object"&&!Array.isArray(p)?p:{},g=()=>{if(e.emittedToolStarts.has(s))return;e.emittedToolStarts.add(s);const m={...D(n,u,l),actionId:s};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:i,data:{toolName:n,toolInput:S,toolUseId:s,...m}}),e.adapterSession.messages.push({id:y(),sessionId:t,role:"tool_use",content:`${n}: ${JSON.stringify(S).slice(0,100)}`,timestamp:i,toolName:n,toolInput:S,toolUseId:s})};if(a.status==="running"){g();const m={...D(n,u,l),actionId:s};this.emit("status-change",t,"tool_using",{...m,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(n==="todowrite"||n==="todo_write")&&this.syncTodosFromToolCall(e,u).catch(k=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",k)}),g();const m=P(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!1,toolUseId:s}}),e.emittedToolStarts.delete(s)}else if(a.status==="error"){g();const m=P(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:m,isError:!0,toolUseId:s}}),e.emittedToolStarts.delete(s)}break}}}getTodoStoreDir(){return h.join(M(),"todos")}async syncTodosFromToolCall(t,e){const o=t.config.agentId;if(!o)return;const r=e.todos;if(!Array.isArray(r)||r.length===0)return;const i=[];for(const p of r)if(p&&typeof p=="object"){const S=typeof p.content=="string"?p.content.trim():"",g=typeof p.status=="string"?p.status:"",m=typeof p.priority=="string"?p.priority:"";S&&g&&m&&i.push({content:S,status:g,priority:m})}if(i.length===0)return;const s=String(o).replace(/[^a-zA-Z0-9_-]/g,"_"),n=this.getTodoStoreDir(),a=h.join(n,`${s}.json`),u={agentId:o,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:i};await w.promises.mkdir(n,{recursive:!0});const l=`${a}.tmp`;await w.promises.writeFile(l,JSON.stringify(u,null,2),"utf-8"),await w.promises.rename(l,a)}emitEvent(t){this.emit("event",t)}startIdleDetection(t){this.stopIdleDetection(t);const e=this.sessions.get(t),o=e?.idleCommands?.idleInputCommand;if(!e||!o)return;if(this.isMessagePollingIdleCommand(o)){e.idlePollLoop||(e.idlePollLoop=new O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500})),e.idlePollLoop.start();return}e.idlePollLoop||(e.idlePollLoop=new O({getStatus:()=>this.sessions.get(t)?.adapterSession.status,getCommand:()=>this.sessions.get(t)?.idleCommands?.idleInputCommand,isPollingCommand:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,s)=>this.sendMessage(t,s?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500}));const r=setInterval(()=>{this.checkIdleState(t)},500);e.idleTimer=r}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearInterval(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)?"\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002":e}isMessagePollingIdleCommand(t){const e=t.trim();if(!e)return!1;const o=e.toLowerCase();return o.includes("poll_message")||o.includes("get_message")||e.includes("\u53D6\u6D88\u606F")}}export{Q as OpencodeSdkAdapter};
1
+ import{spawn as E}from"node:child_process";import{EventEmitter as x}from"node:events";import*as S from"node:fs";import*as T 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 U}from"../utils/sdk-package-loader.js";import{IdlePollLoop as C}from"./idle-poll-loop.js";import{getToolActionInfo as I,redactTransientClipboardPastePaths as O,redactTransientClipboardPastePathsInValue as j}from"./types.js";function N(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||"",r=[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 o of r){const n=g.join(o,"opencode.exe");if(S.existsSync(n))return n}const i=[g.join(e,"AppData","Roaming","npm"),g.join(e,"AppData","Local","Volta","bin")];for(const o of i)for(const n of["opencode.cmd","opencode.exe","opencode"]){const a=g.join(o,n);if(S.existsSync(a))return a}}return t}async function R(d=14096){for(let t=d;t<d+100;t++)if(await new Promise(s=>{const r=T.createServer();r.once("error",()=>s(!1)),r.once("listening",()=>{r.close(()=>s(!0))}),r.listen(t,"127.0.0.1")}))return t;throw new Error(`No available port found in range ${d}\u2013${d+99}`)}function H(d){return d instanceof Error&&"code"in d&&typeof d.code=="string"}function W(d,t){return H(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 Z extends x{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 r=()=>{this.sessions.get(t)?.idlePollLoop?.start()};this.listenerWakeHooks.set(t,r),M(e.agentId,r)}this.emit("status-change",t,"starting");try{const r=await R();s.port=r;const i=N(e.command),o=i.endsWith(".cmd")||i.endsWith(".CMD")||process.platform==="win32"&&!g.isAbsolute(i),n={...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&&(n.OPENCODE_CONFIG_CONTENT=JSON.stringify(a),$.info(`[OpencodeSdkAdapter] OPENCODE_CONFIG_CONTENT keys=${Object.keys(a).join(",")}`));const l=E(i,["serve","--port",String(r)],{cwd:e.workingDirectory,stdio:["ignore","pipe","pipe"],env:n,shell:o});s.serverProcess=l,s.startupOutput=[],l.stdout?.on("data",u=>{const y=u.toString();this.recordStartupOutput(s,y)}),l.stderr?.on("data",u=>{const y=u.toString();this.recordStartupOutput(s,y)}),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 c=new Promise(u=>{l.once("exit",(y,b)=>u({code:y,signal:b}))}),p=(await this.loadSdk()).createOpencodeClient({baseUrl:`http://127.0.0.1:${r}`});s.client=p,await Promise.race([this.waitForServer(p,e.workingDirectory,1e4,r),c.then(u=>{throw new Error(this.formatStartupExitMessage(u,s.startupOutput))})]);const k=(await p.session.create({body:{title:`aws-bridge-${t.slice(0,8)}`},query:{directory:e.workingDirectory}})).data;if(!k?.id)throw new Error("OpenCode session.create() did not return an ID");s.opencodeSessionId=k.id,s.adapterSession.providerSessionId=k.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(r){e.agentId&&D(e.agentId,this.listenerWakeHooks.get(t)),this.listenerWakeHooks.delete(t);const i=r instanceof Error?r.message:String(r);throw console.error("[OpencodeSdkAdapter] startSession failed:",r),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: ${i}`}}),r}}async sendMessage(t,e,s){const r=this.sessions.get(t);if(!r)throw new Error(`Session ${t} not found`);if(!r.client||!r.opencodeSessionId)throw new Error(`Session ${t} not ready`);const i={id:P(),sessionId:t,role:"user",content:e,timestamp:new Date().toISOString()};r.adapterSession.messages.push(i),this.emit("conversation-message",t,i),s?.keepWaitingStatus||(r.adapterSession.status="thinking",this.emit("status-change",t,"thinking"),this.stopIdleDetection(t));try{const o=v(r.config.model),n={parts:[{type:"text",text:e}]};o?.providerID&&o?.modelID&&(n.model={providerID:o.providerID,modelID:o.modelID}),await r.client.session.prompt({path:{id:r.opencodeSessionId},body:n,query:{directory:r.workingDirectory}})}catch(o){const n=o instanceof Error?o.message:String(o);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:n}})}}async sendConfirmation(t,e){const s=this.sessions.get(t);if(!s?.client||!s.opencodeSessionId)return;const r=e?"once":"reject",i=s.opencodeSessionId;for(const[o]of s.pendingPermissions)try{await s.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:o},body:{response:r},query:{directory:s.workingDirectory}})}catch(n){console.warn("[OpencodeSdkAdapter] Permission response failed:",n)}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 U("@opencode-ai/sdk")}catch(t){throw W(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,r){const i=Date.now()+s;for(;Date.now()<i;){try{if((await t.session.list({query:{directory:e}})).data!==void 0)return}catch{}await new Promise(o=>setTimeout(o,300))}throw new Error(`OpenCode server (port ${r}) 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"}`,r=(e??[]).join(`
3
+ `).trim();return r?`OpenCode server exited during startup (${s}): ${r}`:`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 r=s instanceof Error?s.message:String(s);this.emitEvent({type:"error",sessionId:t,timestamp:new Date().toISOString(),data:{text:`OpenCode initial prompt failed: ${r}`}})})}startSseLoop(t,e){e.sseActive=!0;const s=new AbortController;e.sseAbortController=s,this.runSseLoop(t,e,s).catch(r=>{s.signal.aborted||console.error("[OpencodeSdkAdapter] SSE loop error:",r)})}async runSseLoop(t,e,s){if(e.client)try{const r=await e.client.event.subscribe({query:{directory:e.workingDirectory},signal:s.signal});for await(const i of r.stream){if(!e.sseActive||s.signal.aborted)break;this.handleOpenCodeEvent(t,e,i)}}catch(r){if(s.signal.aborted)return;console.error("[OpencodeSdkAdapter] SSE stream ended:",r)}}handleOpenCodeEvent(t,e,s){const r=new Date().toISOString(),i=e.opencodeSessionId;switch(s.type){case"message.updated":{const o=s.properties.info;if(o.sessionID!==i)break;if(o.role==="user")e.userMessageIds.add(o.id);else if(o.role==="assistant"){const n=o.tokens;n&&(e.adapterSession.totalUsage.inputTokens=Math.max(e.adapterSession.totalUsage.inputTokens,n.input),e.adapterSession.totalUsage.outputTokens=Math.max(e.adapterSession.totalUsage.outputTokens,n.output))}break}case"message.part.updated":{const{part:o,delta:n}=s.properties;if(o.sessionID!==i||e.userMessageIds.has(o.messageID))break;this.handlePartUpdate(t,e,o,n,r);break}case"session.idle":{if(s.properties.sessionID!==i)break;if(e.currentAssistantText){const a={id:P(),sessionId:t,role:"assistant",content:e.currentAssistantText,timestamp:r};e.adapterSession.messages.push(a),e.currentAssistantText=""}e.seenTextPartIds.clear(),this.emitEvent({type:"turn_complete",sessionId:t,timestamp:r,data:{usage:e.adapterSession.totalUsage}}),e.adapterSession.status="waiting_input";const o=e.idleCommands?.idleInputCommand;!!(o&&this.isMessagePollingIdleCommand(o))?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 o=s.properties;if(o.sessionID!==i)break;const n=o.id;e.pendingPermissions.set(n,o),e.config.autoAccept&&e.client&&i?e.client.postSessionIdPermissionsPermissionId({path:{id:i,permissionID:n},body:{response:"once"},query:{directory:e.workingDirectory}}).then(()=>{e.pendingPermissions.delete(n)}).catch(a=>{console.warn("[OpencodeSdkAdapter] Auto-accept permission failed:",a)}):this.emitEvent({type:"permission_request",sessionId:t,timestamp:r,data:{permissionPrompt:o.title,toolName:o.type}});break}case"session.error":{const{sessionID:o,error:n}=s.properties;if(o&&o!==i)break;let a="OpenCode session error";if(n){const m=n.data;typeof m?.message=="string"?a=`${n.name}: ${m.message}`:a=n.name}this.emitEvent({type:"error",sessionId:t,timestamp:r,data:{text:a}});break}}}handlePartUpdate(t,e,s,r,i){switch(s.type){case"text":{let o;if(r!==void 0)o=r,e.seenTextPartIds.add(s.id);else if(!e.seenTextPartIds.has(s.id))o=s.text,o&&e.seenTextPartIds.add(s.id);else break;if(!o)break;e.currentAssistantText+=o,this.emitEvent({type:"text_delta",sessionId:t,timestamp:i,data:{text:o}});break}case"reasoning":{const o=r??s.text;if(!o)break;this.emitEvent({type:"thinking",sessionId:t,timestamp:i,data:{text:o}});break}case"tool":{const o=s.callID,n=s.tool,a=s.state,m=a.input,h=s.metadata,l=j(m),c=l&&typeof l=="object"&&!Array.isArray(l)?l:{},f=()=>{if(e.emittedToolStarts.has(o))return;e.emittedToolStarts.add(o);const p={...I(n,m,h),actionId:o};this.emitEvent({type:"tool_use_start",sessionId:t,timestamp:i,data:{toolName:n,toolInput:c,toolUseId:o,...p}}),e.adapterSession.messages.push({id:P(),sessionId:t,role:"tool_use",content:`${n}: ${JSON.stringify(c).slice(0,100)}`,timestamp:i,toolName:n,toolInput:c,toolUseId:o})};if(a.status==="running"){f();const p={...I(n,m,h),actionId:o};this.emit("status-change",t,"tool_using",{...p,usage:e.adapterSession.totalUsage})}else if(a.status==="completed"){(n==="todowrite"||n==="todo_write")&&this.syncTodosFromToolCall(e,m).catch(w=>{console.warn("[OpencodeSdkAdapter] \u540C\u6B65 todo \u5230\u6587\u4EF6\u5931\u8D25:",w)}),f();const p=O(a.output);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:p,isError:!1,toolUseId:o}}),e.emittedToolStarts.delete(o)}else if(a.status==="error"){f();const p=O(a.error);this.emitEvent({type:"tool_use_end",sessionId:t,timestamp:i,data:{toolName:n,toolResult:p,isError:!0,toolUseId:o}}),e.emittedToolStarts.delete(o)}break}}}getTodoStoreDir(){return g.join(_(),"todos")}async syncTodosFromToolCall(t,e){const s=t.config.agentId;if(!s)return;const r=e.todos;if(!Array.isArray(r)||r.length===0)return;const i=[];for(const l of r)if(l&&typeof l=="object"){const c=l,f=typeof c.content=="string"?c.content.trim():"",p=typeof c.status=="string"?c.status:"",w=typeof c.priority=="string"?c.priority:"";f&&p&&w&&i.push({content:f,status:p,priority:w})}if(i.length===0)return;const o=String(s).replace(/[^a-zA-Z0-9_-]/g,"_"),n=this.getTodoStoreDir(),a=g.join(n,`${o}.json`),m={agentId:s,updatedAt:new Date().toISOString(),background:"OpenCode runtime todos",todos:i};await S.promises.mkdir(n,{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)return;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:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,o)=>this.sendMessage(t,o?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),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:i=>this.isMessagePollingIdleCommand(i),preDispatchHook:()=>null,dispatchPollingPrompt:(i,o)=>this.sendMessage(t,o?i.trim():this.toIdlePrompt(i),{keepWaitingStatus:!0}),dispatchRegularIdleCommand:i=>this.sendMessage(t,this.toIdlePrompt(i)),pollDelayMs:1500}));const r=setInterval(()=>{this.checkIdleState(t)},500);e.idleTimer=r}stopIdleDetection(t){const e=this.sessions.get(t);e?.idlePollLoop?.stop(),e?.idleTimer&&(clearInterval(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)?"\u7CFB\u7EDF\u63D0\u9192\uFF1A\u5982\u679C\u4EFB\u52A1\u5DF2\u5B8C\u6210\u6216\u6CA1\u6709\u5176\u5B83\u8981\u505A\u7684\uFF0C\u5148\u8C03\u7528 poll_message \u5DE5\u5177\u963B\u585E\u7B49\u5F85\u65B0\u6D88\u606F\u548C\u6D41\u7A0B\u7EBF\u4EFB\u52A1\u63D0\u9192\uFF1B\u6536\u5230\u6D41\u7A0B\u4EFB\u52A1\u63D0\u9192\u540E\u8C03\u7528 my_task \u67E5\u770B\u5DF2\u7531\u540E\u53F0\u9759\u9ED8\u62A2\u5360\u7684\u4EFB\u52A1\u8BE6\u60C5\u5E76\u76F4\u63A5\u5904\u7406\uFF1B\u5B8C\u6210\u4EFB\u52A1\u540E\u8C03\u7528 submit_task_result \u63D0\u4EA4\u7ED3\u679C\uFF0C\u7136\u540E\u7EE7\u7EED poll_message\u3002 \u8C03\u7528 submit_task_result \u65F6\u8BF7\u4E00\u5E76\u4F20\u5165 changeLog\uFF08\u672C\u6B21\u5904\u7406\u7684\u6587\u4EF6/\u5185\u5BB9\u53D8\u66F4\u65E5\u5FD7\uFF0C\u5305\u542B operation \u4E0E path\uFF09\uFF0C\u7528\u4E8E AI \u56DE\u9000\u3002":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{Z as OpencodeSdkAdapter};
4
4
 
@@ -1,2 +1,2 @@
1
- import{chromium as x}from"playwright";import{formatBrowserLaunchError as _,installPlaywrightChromium as $,isBrowserMissingError as D}from"./browser-bootstrap.js";import{BrowserProfileStore as H}from"./browser-profile-store.js";import{ListenerStore as b}from"./listener-store.js";import{PageListenerManager as k}from"./page-listener-manager.js";import{ScreencastManager as B}from"./screencast-manager.js";import{buildStealthInitScript as L,STEALTH_LAUNCH_ARGS as O,STEALTH_IGNORE_ARGS as N}from"./stealth.js";import{StepArchive as R}from"./step-archive.js";import{DEFAULT_BROWSER_ID as l,IDLE_CHECK_INTERVAL_MS as K,IDLE_TIMEOUT_MS as z,MAX_PAGES_PER_SESSION as U,MAX_SESSIONS as I,MAX_SESSIONS_PER_AGENT as M,SESSION_TIMEOUT_MS as W,makeBrowserKey as G}from"./types.js";const q=1280,V=720;class X{onSessionClose(e){this.sessionCloseHandlers.push(e)}getSsrfConfig(){return this.config.ssrfConfig}setListenerTriggerHook(e){this.listenerTriggerHook=e}resolveKey(e,s){if(!e||typeof e!="string")throw new Error("scopeKey must be a non-empty string");const i=s&&s.trim()?s.trim():l;if(i.includes("::"))throw new Error(`browserId must not contain "::" (reserved separator): ${i}`);return G(e,i)}constructor(e){this.sessions=new Map,this.idleTimer=null,this.sessionCloseHandlers=[],this.listenerTriggerHook=null,this.config={headless:e?.headless??!0,executablePath:e?.executablePath,viewportWidth:e?.viewportWidth??q,viewportHeight:e?.viewportHeight??V,maxPagesPerSession:e?.maxPagesPerSession??U,maxSessionDurationMs:e?.maxSessionDurationMs??W,idleTimeoutMs:e?.idleTimeoutMs??z,launchArgs:e?.launchArgs,screencastConfig:e?.screencastConfig,archiveConfig:e?.archiveConfig,ssrfConfig:e?.ssrfConfig,userAgent:e?.userAgent,locale:e?.locale,timezone:e?.timezone,profileDir:e?.profileDir,stealth:e?.stealth??!0},this.profileStore=e?.profileDir?new H({profileDir:e.profileDir}):null,this.listenerStore=e?.profileDir?new b({listenerDir:e.profileDir}):null}async launch(e,s,i,t){const r=t??`agent:${e}`,n=this.resolveKey(r,s);if(this.sessions.has(n))throw new Error(`Browser session already exists for ${e}/${s??l}`);if(this.sessions.size>=I)throw new Error(`BrowserPool reached MAX_SESSIONS=${I}; close existing sessions before launching new ones`);let c=0;for(const o of this.sessions.values())o.agentId===e&&(c+=1);if(c>=M)throw new Error(`BrowserPool reached MAX_SESSIONS_PER_AGENT=${M} for agent ${e}; close some browser sessions first`);const h={headless:this.config.headless};this.config.executablePath&&(h.executablePath=this.config.executablePath);const d=[`--window-size=${this.config.viewportWidth},${this.config.viewportHeight}`];this.config.stealth?(h.ignoreDefaultArgs=[...N],h.args=[...d,...O,...this.config.launchArgs??[]]):this.config.launchArgs&&this.config.launchArgs.length>0?h.args=[...d,...this.config.launchArgs]:h.args=[...d];const p=await this.launchChromium(h);let m=this.config.userAgent,P;if(this.config.stealth)try{const o=await p.newBrowserCDPSession(),f=await o.send("Browser.getVersion"),g=f.product?.match(/Chrome\/(\d+)/);g&&(P=g[1]),!m&&f.userAgent&&(m=String(f.userAgent).replace(/HeadlessChrome\/([\d.]+)/g,"Chrome/$1")),await o.detach().catch(()=>{})}catch{}const w={viewport:{width:this.config.viewportWidth,height:this.config.viewportHeight}};if(m&&(w.userAgent=m),this.config.locale&&(w.locale=this.config.locale),this.config.timezone&&(w.timezoneId=this.config.timezone),this.profileStore)try{let o=await this.profileStore.load(r);!o&&r!==e&&(o=await this.profileStore.load(e),o&&await this.profileStore.save(r,o)),o&&(w.storageState=o)}catch{}const v=await p.newContext(w).catch(async o=>{throw await p.close().catch(()=>{}),o});this.config.stealth&&await v.addInitScript(L(P??"126")).catch(()=>{});const S=await v.newPage().catch(async o=>{throw await p.close().catch(()=>{}),o}),A=new B(this.config.screencastConfig),C=new R(this.config.archiveConfig),T=new k(e,s?.trim()||l,{onTrigger:(o,f)=>{const g=this.listenerTriggerHook;if(g)try{g(e,s?.trim()||l,o,f)}catch{}},store:this.listenerStore,scopeKey:r});try{await A.start(S)}catch{}try{const o=S;o.screencast?.showActions&&await o.screencast.showActions({cursor:"pointer"})}catch{}const E=Date.now(),a={agentId:e,scopeKey:r,browserId:s?.trim()||l,title:i?.trim()||"\u6D4F\u89C8\u5668\u4F1A\u8BDD",browser:p,context:v,pages:[S],activePageIndex:0,screencast:A,archive:C,listenerManager:T,launchedAt:E,lastActivityAt:E,humanTakeover:!1,qualityPreset:"original"};v.on("page",o=>{if(a.pages.length>=this.config.maxPagesPerSession){o.close().catch(()=>{});return}a.pages.push(o);const f=a.pages.length-1;this.setActivePage(e,f,a.browserId).catch(()=>{}),o.on("close",()=>{const g=a.pages.indexOf(o);if(g!==-1){if(a.pages.splice(g,1),a.pages.length===0){this.close(e,a.browserId).catch(()=>{});return}a.activePageIndex>=a.pages.length?a.activePageIndex=a.pages.length-1:g<a.activePageIndex&&(a.activePageIndex-=1)}})});try{await T.attach(S)}catch{}return this.sessions.set(n,a),this.ensureIdleTimer(),this.profileStore&&(a.autoSaveTimer=setInterval(async()=>{try{const o=await a.context.storageState();await this.profileStore.save(a.scopeKey,o)}catch{}},3e4),a.autoSaveTimer.unref&&a.autoSaveTimer.unref()),a}async launchChromium(e){try{return await x.launch(e)}catch(s){if(this.config.executablePath||!D(s))throw s;const i=await $();try{return await x.launch(e)}catch(t){throw _(t instanceof Error?t:new Error(String(t)),i)}}}get(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i)return t}async getOrLaunch(e,s,i,t){const r=t??`agent:${e}`,n=this.resolveKey(r,s),c=this.sessions.get(n);return c||this.launch(e,s,i,t)}async close(e,s){const i=s&&s.trim()?s.trim():l;let t,r;for(const[c,h]of this.sessions)if(h.agentId===e&&h.browserId===i){t=c,r=h;break}if(!t||!r)return;const n=r;n.autoSaveTimer&&(clearInterval(n.autoSaveTimer),n.autoSaveTimer=void 0);try{await n.screencast.dispose()}catch{}try{await n.listenerManager.dispose()}catch{}if(n.archive.clear(),this.profileStore)try{const c=await n.context.storageState();await this.profileStore.save(n.scopeKey,c)}catch{}try{await n.browser.close()}catch{}this.sessions.delete(t);for(const c of this.sessionCloseHandlers)try{c(e,i)}catch{}this.sessions.size===0&&this.stopIdleTimer()}async closeByAgent(e){if(!e)return;const s=[];for(const[i,t]of this.sessions)t.agentId===e&&s.push(i);await Promise.all(s.map(i=>{const r=this.sessions.get(i)?.browserId;return this.close(e,r)}))}async collectListenerEvents(e){if(!e)return[];const s=[];for(const i of this.sessions.values()){if(i.agentId!==e)continue;await i.listenerManager.scanExistsAtPoll();const t=i.listenerManager.collectEvents();t.length>0&&s.push(...t)}return s.sort((i,t)=>i.triggeredAt-t.triggeredAt),s}getActivePage(e,s){const i=this.requireSession(e,s),t=i.pages[i.activePageIndex];if(!t||t.isClosed())throw new Error(`No active page for agent ${e}/${i.browserId} (index ${i.activePageIndex})`);return t}async setActivePage(e,s,i){const t=this.requireSession(e,i);if(!Number.isInteger(s)||s<0||s>=t.pages.length)throw new Error(`Page index ${s} out of range (0..${t.pages.length-1}) for agent ${e}/${t.browserId}`);if(t.activePageIndex===s)return t.pages[s];const r=t.pages[t.activePageIndex];if(r&&!r.isClosed())try{await t.screencast.stop(r)}catch{}t.activePageIndex=s;const n=t.pages[s];try{await t.screencast.start(n)}catch{}try{await t.listenerManager.reattach(n)}catch{}return this.touchActivity(e,i),n}async newPage(e,s){const i=this.requireSession(e,s);if(i.pages.length>=this.config.maxPagesPerSession)throw new Error(`Agent ${e}/${i.browserId} reached maxPagesPerSession=${this.config.maxPagesPerSession}; close a tab first`);const t=await i.context.newPage();i.pages.push(t);const r=i.pages.length-1;return this.touchActivity(e,s),this.setActivePage(e,r,s)}async closePage(e,s,i){const t=this.requireSession(e,i);if(!Number.isInteger(s)||s<0||s>=t.pages.length)throw new Error(`Page index ${s} out of range (0..${t.pages.length-1}) for agent ${e}/${t.browserId}`);const r=t.pages[s];if(s===t.activePageIndex)try{await t.screencast.stop(r)}catch{}try{await r.close()}catch{}if(t.pages.splice(s,1),t.pages.length===0){await this.close(e,i);return}t.activePageIndex>=t.pages.length?t.activePageIndex=t.pages.length-1:s<t.activePageIndex&&(t.activePageIndex-=1);const n=t.pages[t.activePageIndex];if(!n.isClosed()){try{await t.screencast.start(n)}catch{}try{await t.listenerManager.reattach(n)}catch{}}this.touchActivity(e,i)}listSessions(e){const s=[];for(const i of this.sessions.values()){if(e&&i.agentId!==e)continue;const t=i.pages[i.activePageIndex];let r="",n="";if(t&&!t.isClosed())try{r=t.url()}catch{}s.push({agentId:i.agentId,browserId:i.browserId,title:i.title,pageCount:i.pages.length,activePageIndex:i.activePageIndex,launchedAt:i.launchedAt,lastActivityAt:i.lastActivityAt,currentUrl:r,currentTitle:n})}return s}touchActivity(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i){t.lastActivityAt=Date.now();return}}async dispose(){this.stopIdleTimer();const e=Array.from(this.sessions.keys());await Promise.all(e.map(s=>{const i=this.sessions.get(s);return i?this.close(i.agentId,i.browserId):Promise.resolve()}))}requireSession(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i)return t;throw new Error(`Browser session not launched for ${e}/${s??l}`)}ensureIdleTimer(){this.idleTimer||this.config.idleTimeoutMs<=0&&this.config.maxSessionDurationMs<=0||(this.idleTimer=setInterval(()=>{this.checkIdleSessions()},K),this.idleTimer.unref&&this.idleTimer.unref())}stopIdleTimer(){this.idleTimer&&(clearInterval(this.idleTimer),this.idleTimer=null)}async checkIdleSessions(){const e=Date.now(),s=[];for(const i of this.sessions.values()){if(i.humanTakeover)continue;const t=e-i.lastActivityAt,r=e-i.launchedAt;if(this.config.idleTimeoutMs>0&&t>this.config.idleTimeoutMs){s.push(i);continue}this.config.maxSessionDurationMs>0&&r>this.config.maxSessionDurationMs&&s.push(i)}await Promise.all(s.map(i=>this.close(i.agentId,i.browserId)))}}let u=null;function ie(y){return u||(u=new X(y)),u}async function re(){u&&(await u.dispose(),u=null)}export{X as BrowserPool,re as disposeBrowserPool,ie as getBrowserPool};
1
+ import{chromium as $}from"playwright";import{formatBrowserLaunchError as _,installPlaywrightChromium as D,isBrowserMissingError as b}from"./browser-bootstrap.js";import{BrowserProfileStore as H}from"./browser-profile-store.js";import{ListenerStore as k}from"./listener-store.js";import{PageListenerManager as B}from"./page-listener-manager.js";import{ScreencastManager as L}from"./screencast-manager.js";import{buildStealthInitScript as N,STEALTH_LAUNCH_ARGS as O,STEALTH_IGNORE_ARGS as R}from"./stealth.js";import{StepArchive as K}from"./step-archive.js";import{DEFAULT_BROWSER_ID as l,IDLE_CHECK_INTERVAL_MS as z,IDLE_TIMEOUT_MS as U,MAX_PAGES_PER_SESSION as W,MAX_SESSIONS as I,MAX_SESSIONS_PER_AGENT as M,SESSION_TIMEOUT_MS as G,makeBrowserKey as q}from"./types.js";const V=1280,X=720;class F{onSessionClose(e){this.sessionCloseHandlers.push(e)}getSsrfConfig(){return this.config.ssrfConfig}setListenerTriggerHook(e){this.listenerTriggerHook=e}resolveKey(e,s){if(!e||typeof e!="string")throw new Error("scopeKey must be a non-empty string");const i=s&&s.trim()?s.trim():l;if(i.includes("::"))throw new Error(`browserId must not contain "::" (reserved separator): ${i}`);return q(e,i)}constructor(e){this.sessions=new Map,this.idleTimer=null,this.sessionCloseHandlers=[],this.listenerTriggerHook=null,this.config={headless:e?.headless??!0,executablePath:e?.executablePath,viewportWidth:e?.viewportWidth??V,viewportHeight:e?.viewportHeight??X,maxPagesPerSession:e?.maxPagesPerSession??W,maxSessionDurationMs:e?.maxSessionDurationMs??G,idleTimeoutMs:e?.idleTimeoutMs??U,launchArgs:e?.launchArgs,screencastConfig:e?.screencastConfig,archiveConfig:e?.archiveConfig,ssrfConfig:e?.ssrfConfig,userAgent:e?.userAgent,locale:e?.locale,timezone:e?.timezone,profileDir:e?.profileDir,stealth:e?.stealth??!0},this.profileStore=e?.profileDir?new H({profileDir:e.profileDir}):null,this.listenerStore=e?.profileDir?new k({listenerDir:e.profileDir}):null}async launch(e,s,i,t){const r=t??`agent:${e}`,o=this.resolveKey(r,s);if(this.sessions.has(o))throw new Error(`Browser session already exists for ${e}/${s??l}`);if(this.sessions.size>=I)throw new Error(`BrowserPool reached MAX_SESSIONS=${I}; close existing sessions before launching new ones`);let c=0;for(const n of this.sessions.values())n.agentId===e&&(c+=1);if(c>=M)throw new Error(`BrowserPool reached MAX_SESSIONS_PER_AGENT=${M} for agent ${e}; close some browser sessions first`);const h={headless:this.config.headless};this.config.executablePath&&(h.executablePath=this.config.executablePath);const S=[`--window-size=${this.config.viewportWidth},${this.config.viewportHeight}`];this.config.stealth?(h.ignoreDefaultArgs=[...R],h.args=[...S,...O,...this.config.launchArgs??[]]):this.config.launchArgs&&this.config.launchArgs.length>0?h.args=[...S,...this.config.launchArgs]:h.args=[...S];const w=await this.launchChromium(h);let m=this.config.userAgent,y;if(this.config.stealth)try{const n=await w.newBrowserCDPSession(),f=await n.send("Browser.getVersion"),g=f.product?.match(/Chrome\/(\d+)/);g&&(y=g[1]),!m&&f.userAgent&&(m=String(f.userAgent).replace(/HeadlessChrome\/([\d.]+)/g,"Chrome/$1")),await n.detach().catch(()=>{})}catch{}const p={viewport:{width:this.config.viewportWidth,height:this.config.viewportHeight}};if(m&&(p.userAgent=m),this.config.locale&&(p.locale=this.config.locale),this.config.timezone&&(p.timezoneId=this.config.timezone),this.profileStore)try{let n=await this.profileStore.load(r);!n&&r!==e&&(n=await this.profileStore.load(e),n&&await this.profileStore.save(r,n)),n&&(p.storageState=n)}catch{}const d=await w.newContext(p).catch(async n=>{throw await w.close().catch(()=>{}),n});this.config.stealth&&await d.addInitScript(N(y??"126")).catch(()=>{});const v=await d.newPage().catch(async n=>{throw await w.close().catch(()=>{}),n}),A=new L(this.config.screencastConfig),C=new K(this.config.archiveConfig),T=new B(e,s?.trim()||l,{onTrigger:(n,f)=>{const g=this.listenerTriggerHook;if(g)try{g(e,s?.trim()||l,n,f)}catch{}},store:this.listenerStore,scopeKey:r});try{await A.start(v)}catch{}try{const n=v;n.screencast?.showActions&&await n.screencast.showActions({cursor:"pointer"})}catch{}const E=Date.now(),a={agentId:e,scopeKey:r,browserId:s?.trim()||l,title:i?.trim()||"\u6D4F\u89C8\u5668\u4F1A\u8BDD",browser:w,context:d,pages:[v],activePageIndex:0,screencast:A,archive:C,listenerManager:T,launchedAt:E,lastActivityAt:E,humanTakeover:!1,qualityPreset:"original"};d.on("page",n=>{if(a.pages.length>=this.config.maxPagesPerSession){n.close().catch(()=>{});return}a.pages.push(n);const f=a.pages.length-1;this.setActivePage(e,f,a.browserId).catch(()=>{}),n.on("close",()=>{const g=a.pages.indexOf(n);if(g!==-1){if(a.pages.splice(g,1),a.pages.length===0){this.close(e,a.browserId).catch(()=>{});return}a.activePageIndex>=a.pages.length?a.activePageIndex=a.pages.length-1:g<a.activePageIndex&&(a.activePageIndex-=1)}})});try{await T.attach(v)}catch{}this.sessions.set(o,a),this.ensureIdleTimer();const x=this.profileStore;return x&&(a.autoSaveTimer=setInterval(async()=>{try{const n=await a.context.storageState();await x.save(a.scopeKey,n)}catch{}},3e4),a.autoSaveTimer.unref&&a.autoSaveTimer.unref()),a}async launchChromium(e){try{return await $.launch(e)}catch(s){if(this.config.executablePath||!b(s))throw s;const i=await D();try{return await $.launch(e)}catch(t){throw _(t instanceof Error?t:new Error(String(t)),i)}}}get(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i)return t}async getOrLaunch(e,s,i,t){const r=t??`agent:${e}`,o=this.resolveKey(r,s),c=this.sessions.get(o);return c||this.launch(e,s,i,t)}async close(e,s){const i=s&&s.trim()?s.trim():l;let t,r;for(const[c,h]of this.sessions)if(h.agentId===e&&h.browserId===i){t=c,r=h;break}if(!t||!r)return;const o=r;o.autoSaveTimer&&(clearInterval(o.autoSaveTimer),o.autoSaveTimer=void 0);try{await o.screencast.dispose()}catch{}try{await o.listenerManager.dispose()}catch{}if(o.archive.clear(),this.profileStore)try{const c=await o.context.storageState();await this.profileStore.save(o.scopeKey,c)}catch{}try{await o.browser.close()}catch{}this.sessions.delete(t);for(const c of this.sessionCloseHandlers)try{c(e,i)}catch{}this.sessions.size===0&&this.stopIdleTimer()}async closeByAgent(e){if(!e)return;const s=[];for(const[i,t]of this.sessions)t.agentId===e&&s.push(i);await Promise.all(s.map(i=>{const r=this.sessions.get(i)?.browserId;return this.close(e,r)}))}async collectListenerEvents(e){if(!e)return[];const s=[];for(const i of this.sessions.values()){if(i.agentId!==e)continue;await i.listenerManager.scanExistsAtPoll();const t=i.listenerManager.collectEvents();t.length>0&&s.push(...t)}return s.sort((i,t)=>i.triggeredAt-t.triggeredAt),s}getActivePage(e,s){const i=this.requireSession(e,s),t=i.pages[i.activePageIndex];if(!t||t.isClosed())throw new Error(`No active page for agent ${e}/${i.browserId} (index ${i.activePageIndex})`);return t}async setActivePage(e,s,i){const t=this.requireSession(e,i);if(!Number.isInteger(s)||s<0||s>=t.pages.length)throw new Error(`Page index ${s} out of range (0..${t.pages.length-1}) for agent ${e}/${t.browserId}`);if(t.activePageIndex===s){const c=t.pages[s];if(c==null)throw new Error(`Page index ${s} out of range for agent ${e}/${t.browserId}`);return c}const r=t.pages[t.activePageIndex];if(r&&!r.isClosed())try{await t.screencast.stop(r)}catch{}t.activePageIndex=s;const o=t.pages[s];if(o==null)throw new Error(`Page index ${s} out of range for agent ${e}/${t.browserId}`);try{await t.screencast.start(o)}catch{}try{await t.listenerManager.reattach(o)}catch{}return this.touchActivity(e,i),o}async newPage(e,s){const i=this.requireSession(e,s);if(i.pages.length>=this.config.maxPagesPerSession)throw new Error(`Agent ${e}/${i.browserId} reached maxPagesPerSession=${this.config.maxPagesPerSession}; close a tab first`);const t=await i.context.newPage();i.pages.push(t);const r=i.pages.length-1;return this.touchActivity(e,s),this.setActivePage(e,r,s)}async closePage(e,s,i){const t=this.requireSession(e,i);if(!Number.isInteger(s)||s<0||s>=t.pages.length)throw new Error(`Page index ${s} out of range (0..${t.pages.length-1}) for agent ${e}/${t.browserId}`);const r=t.pages[s];if(r==null)throw new Error(`Page index ${s} out of range for agent ${e}/${t.browserId}`);if(s===t.activePageIndex)try{await t.screencast.stop(r)}catch{}try{await r.close()}catch{}if(t.pages.splice(s,1),t.pages.length===0){await this.close(e,i);return}t.activePageIndex>=t.pages.length?t.activePageIndex=t.pages.length-1:s<t.activePageIndex&&(t.activePageIndex-=1);const o=t.pages[t.activePageIndex];if(o==null)throw new Error(`No active page for agent ${e}/${t.browserId}`);if(!o.isClosed()){try{await t.screencast.start(o)}catch{}try{await t.listenerManager.reattach(o)}catch{}}this.touchActivity(e,i)}listSessions(e){const s=[];for(const i of this.sessions.values()){if(e&&i.agentId!==e)continue;const t=i.pages[i.activePageIndex];let r="";const o="";if(t&&!t.isClosed())try{r=t.url()}catch{}s.push({agentId:i.agentId,browserId:i.browserId,title:i.title,pageCount:i.pages.length,activePageIndex:i.activePageIndex,launchedAt:i.launchedAt,lastActivityAt:i.lastActivityAt,currentUrl:r,currentTitle:o})}return s}touchActivity(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i){t.lastActivityAt=Date.now();return}}async dispose(){this.stopIdleTimer();const e=Array.from(this.sessions.keys());await Promise.all(e.map(s=>{const i=this.sessions.get(s);return i?this.close(i.agentId,i.browserId):Promise.resolve()}))}requireSession(e,s){const i=s&&s.trim()?s.trim():l;for(const t of this.sessions.values())if(t.agentId===e&&t.browserId===i)return t;throw new Error(`Browser session not launched for ${e}/${s??l}`)}ensureIdleTimer(){this.idleTimer||this.config.idleTimeoutMs<=0&&this.config.maxSessionDurationMs<=0||(this.idleTimer=setInterval(()=>{this.checkIdleSessions()},z),this.idleTimer.unref&&this.idleTimer.unref())}stopIdleTimer(){this.idleTimer&&(clearInterval(this.idleTimer),this.idleTimer=null)}async checkIdleSessions(){const e=Date.now(),s=[];for(const i of this.sessions.values()){if(i.humanTakeover)continue;const t=e-i.lastActivityAt,r=e-i.launchedAt;if(this.config.idleTimeoutMs>0&&t>this.config.idleTimeoutMs){s.push(i);continue}this.config.maxSessionDurationMs>0&&r>this.config.maxSessionDurationMs&&s.push(i)}await Promise.all(s.map(i=>this.close(i.agentId,i.browserId)))}}let u=null;function re(P){return u||(u=new F(P)),u}async function oe(){u&&(await u.dispose(),u=null)}export{F as BrowserPool,oe as disposeBrowserPool,re as getBrowserPool};
2
2
 
@@ -1,8 +1,7 @@
1
1
 
2
- import type { JsonObject } from "./types.js";
3
2
  import type { BrowserPool } from "./browser-pool.js";
3
+ import type { SsrfConfig, JsonObject } from "./types.js";
4
4
  import type { BrowserWsServer } from "./ws-server.js";
5
- import type { SsrfConfig } from "./types.js";
6
5
 
7
6
  export interface BrowserToolExecutionContext {
8
7
  readonly toolCallId?: string;
@@ -1,2 +1,2 @@
1
- import{resolveSsrfConfig as E,validateUrlWithDns as M}from"./ssrf-guard.js";import{locateElement as q}from"./element-locator.js";import{serializeSnapshot as P,buildRefMap as j}from"./snapshot-serializer.js";import{DEFAULT_BROWSER_ID as k}from"./types.js";const X=3e4,$=1e4;function oe(v){const{pool:b,wsServer:_}=v,U=v.agentId,N=v.scopeKey,D=E({perAgent:v.ssrfConfig,pool:b.getSsrfConfig()});function u(e){const r=(typeof e.agentId=="string"&&e.agentId.trim()?e.agentId.trim():void 0)??U;if(!r)throw new Error("agentId is required: pass via createBuiltInBrowserTools({agentId}) or tool args.agentId");const n=typeof e.browserId=="string"&&e.browserId.trim()?e.browserId.trim():k,s=typeof e.title=="string"&&e.title.trim()?e.title.trim():void 0,o=N??`agent:${r}`;return{agentId:r,browserId:n,title:s,scopeKey:o}}function B(e,t){const r=b.get(e,t);if(!r)throw new Error(`Browser session not launched for ${e}/${t}. Call browser_launch first.`);if(r.humanTakeover)throw new Error(`Human takeover active for ${e}/${t}. Release takeover before calling browser tools.`);return b.touchActivity(e,t),r}function m(e,t){return{session:B(e,t),page:b.getActivePage(e,t)}}function p(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}function I(e,t){if(e)try{e.archive.record(t)}catch{}}function x(e){const t={};for(const[r,n]of Object.entries(e))n!==void 0&&(t[r]=n);return t}const S=new Map;function A(e,t){return`${e}:${t}`}function C(e,t,r){return S.get(A(e,t))?.get(r)}function R(e,t,r){S.set(A(e,t),j(r))}return v.pool.onSessionClose((e,t)=>{S.delete(A(e,t))}),[{kind:"builtin",toolName:"browser_launch",exposedName:"browser_launch",description:"Launch a headless browser session for the current agent. Returns wsUrl for live JPEG frame streaming (open in browser to watch the agent operate). Pass browserId to start a separate browser instance (independent cookies/cache/storage). Default browserId is 'default'. Must be called before any other browser_* tool. The session is automatically reclaimed after 10 minutes of inactivity. title is required and should briefly describe the intent of this browser session (e.g. '\u641C\u7D22\u7ADE\u54C1\u4EF7\u683C', '\u767B\u5F55\u7BA1\u7406\u540E\u53F0').",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional if configured at factory time). Used to isolate browser sessions across agents."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default'). Same agent can have multiple browserIds (each = independent chromium process)."},title:{type:"string",description:"Brief human-readable title describing the intent of this browser session (e.g. '\u641C\u7D22\u7ADE\u54C1\u4EF7\u683C', '\u767B\u5F55\u7BA1\u7406\u540E\u53F0'). Required \u2014 used as tab label in dashboard."}},required:["title"]},async execute(e){try{const{agentId:t,browserId:r,title:n,scopeKey:s}=u(e),o=await b.getOrLaunch(t,r,n,s),l=o.pages[o.activePageIndex].viewportSize(),c={ok:!0,agentId:t,browserId:o.browserId,title:o.title,viewport:{width:l?.width??0,height:l?.height??0}};return _&&(c.wsUrl=_.getUrl(t,o.browserId)),c}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_navigate",exposedName:"browser_navigate",description:"Navigate the active page to a URL. Waits for DOMContentLoaded (30s timeout). Access to private/loopback addresses is allowed by default (configurable).",inputSchema:{type:"object",properties:{url:{type:"string",description:"Target URL (http/https only). Private IP ranges are allowed by default, can be disabled via ssrfConfig."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["url"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.url=="string"?e.url:"";if(!o)return{ok:!1,error:"url is required"};const i=await M(o,D),l=s.url(),c=Date.now();await s.goto(i,{waitUntil:"domcontentloaded",timeout:X});const a=s.url();try{await n.listenerManager.reattach(s)}catch{}let d="";try{d=await s.title()}catch{}return I(n,{tool:"browser_navigate",args:x({url:i,browserId:r}),beforeUrl:l,afterUrl:a,durationMs:Date.now()-c}),{ok:!0,url:i,finalUrl:a,title:d,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_snapshot",exposedName:"browser_snapshot",description:"Capture the active page's accessibility tree as YAML (Playwright ariaSnapshot mode=ai). Interactive elements get [ref=eXX] markers \u2014 pass the eXX string to browser_click / browser_type / browser_select. Re-snapshot after navigation (refs are invalidated on page change). Output truncated to maxChars (default 16000).",inputSchema:{type:"object",properties:{maxChars:{type:"number",description:"Max chars to return (default 16000)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{page:n}=m(t,r),s=typeof e.maxChars=="number"&&e.maxChars>0?Math.floor(e.maxChars):void 0,o=await P(n,{maxChars:s});R(t,r,o);let i="";try{i=await n.title()}catch{}return{ok:!0,snapshot:o,url:n.url(),title:i,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_click",exposedName:"browser_click",description:"Click an element identified by ref (from browser_snapshot), text (getByText), role+name (getByRole), or CSS selector. ref is preferred, but text/role are more stable on SPA pages where refs invalidate frequently. If ref fails, the system auto-falls back to the cached role+name from the last snapshot and retries the snapshot once. 10s timeout.",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5' (preferred)."},text:{type:"string",description:"Locate element by visible text (getByText). More stable than ref on SPA pages, e.g. 'javaok'."},role:{type:"string",description:"Locate element by ARIA role (e.g. button, link, textbox, listitem). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role' (e.g. role=button + name='Submit')."},selector:{type:"string",description:"CSS selector (subset: tag/.class/#id/[attr]/descendant/>)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.text=="string"&&e.text.trim()?e.text.trim():void 0,l=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,c=typeof e.name=="string"&&e.name?e.name:void 0,a=typeof e.selector=="string"?e.selector:void 0;if(o===void 0&&i===void 0&&l===void 0&&!a)return{ok:!1,error:"Either 'ref', 'text', 'role', or 'selector' is required for browser_click"};const d=o!==void 0?C(t,r,o):void 0,h=await q(s,{ref:o,text:i,role:l,name:c,selector:a,refFallback:d}),w=s.url(),y=Date.now();await h.click({timeout:$});const f=s.url(),g=o!==void 0?`ref=${o}`:i!==void 0?`text=${i}`:l!==void 0?`role=${l}`:`selector=${a}`;return I(n,{tool:"browser_click",args:x({ref:o,text:i,role:l,name:c,selector:a,browserId:r}),beforeUrl:w,afterUrl:f,durationMs:Date.now()-y}),{ok:!0,clicked:g,url:f,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_type",exposedName:"browser_type",description:"Type text into an input identified by ref, role+name (getByRole), or CSS selector. Note: 'text' param is the text to type (not for locating); use 'role'+'name' to locate the input. clear=true (default) clears the field first. delay adds per-keystroke delay (ms).",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5'."},role:{type:"string",description:"Locate input by ARIA role (e.g. textbox, searchbox). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role'."},selector:{type:"string",description:"CSS selector subset."},text:{type:"string",description:"Text to type (required)."},clear:{type:"boolean",description:"Clear field before typing (default true)."},delay:{type:"number",description:"Per-keystroke delay in ms (default 0)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["text"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,l=typeof e.name=="string"&&e.name?e.name:void 0,c=typeof e.selector=="string"?e.selector:void 0,a=typeof e.text=="string"?e.text:"";if(!a)return{ok:!1,error:"text is required for browser_type"};if(o===void 0&&i===void 0&&!c)return{ok:!1,error:"Either 'ref', 'role', or 'selector' is required for browser_type"};const d=e.clear!==!1,h=typeof e.delay=="number"&&e.delay>=0?e.delay:0,w=o!==void 0?C(t,r,o):void 0,y=await q(s,{ref:o,role:i,name:l,selector:c,refFallback:w}),f=s.url(),g=Date.now();d&&await y.fill(""),await y.type(a,{delay:h});const T=s.url();return I(n,{tool:"browser_type",args:x({ref:o,role:i,name:l,selector:c,text:a,clear:d,delay:h,browserId:r}),beforeUrl:f,afterUrl:T,durationMs:Date.now()-g}),{ok:!0,typed:a.length,url:T,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_select",exposedName:"browser_select",description:"Select an option in a <select> element identified by ref, text (getByText), role+name (getByRole), or CSS selector. value is the option value (string).",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5'."},text:{type:"string",description:"Locate element by visible text (getByText)."},role:{type:"string",description:"Locate element by ARIA role (e.g. combobox, listbox). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role'."},selector:{type:"string",description:"CSS selector subset."},value:{type:"string",description:"Option value to select (required)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["value"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.text=="string"&&e.text.trim()?e.text.trim():void 0,l=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,c=typeof e.name=="string"&&e.name?e.name:void 0,a=typeof e.selector=="string"?e.selector:void 0,d=typeof e.value=="string"?e.value:e.value!==void 0&&e.value!==null?String(e.value):"";if(!d)return{ok:!1,error:"value is required for browser_select"};if(o===void 0&&i===void 0&&l===void 0&&!a)return{ok:!1,error:"Either 'ref', 'text', 'role', or 'selector' is required for browser_select"};const h=o!==void 0?C(t,r,o):void 0,w=await q(s,{ref:o,text:i,role:l,name:c,selector:a,refFallback:h}),y=s.url(),f=Date.now();await w.selectOption(d);const g=s.url();return I(n,{tool:"browser_select",args:x({ref:o,text:i,role:l,name:c,selector:a,value:d,browserId:r}),beforeUrl:y,afterUrl:g,durationMs:Date.now()-f}),{ok:!0,selected:d,url:g,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_press_key",exposedName:"browser_press_key",description:"Press a keyboard key on the active page. Examples: 'Enter', 'Escape', 'Tab', 'Control+a', 'ArrowDown'. See Playwright key names for full list.",inputSchema:{type:"object",properties:{key:{type:"string",description:"Key or chord (e.g. 'Enter', 'Control+a')."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["key"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.key=="string"?e.key:"";if(!o)return{ok:!1,error:"key is required for browser_press_key"};const i=s.url(),l=Date.now();await s.keyboard.press(o);const c=s.url();return I(n,{tool:"browser_press_key",args:x({key:o,browserId:r}),beforeUrl:i,afterUrl:c,durationMs:Date.now()-l}),{ok:!0,key:o,url:c,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_scroll",exposedName:"browser_scroll",description:"Scroll the active page. Provide x/y for absolute scroll-to, OR deltaX/deltaY for relative wheel scroll. If both provided, x/y wins.",inputSchema:{type:"object",properties:{x:{type:"number",description:"Absolute scrollX (window.scrollTo)."},y:{type:"number",description:"Absolute scrollY (window.scrollTo)."},deltaX:{type:"number",description:"Relative wheel delta X."},deltaY:{type:"number",description:"Relative wheel delta Y."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.x=="number"&&Number.isFinite(e.x)||typeof e.y=="number"&&Number.isFinite(e.y),i=typeof e.deltaX=="number"&&Number.isFinite(e.deltaX)||typeof e.deltaY=="number"&&Number.isFinite(e.deltaY);if(!o&&!i)return{ok:!1,error:"Provide x/y (absolute) or deltaX/deltaY (relative) for browser_scroll"};const l=s.url(),c=Date.now();let a=0,d=0;if(o){const w=typeof e.x=="number"?e.x:0,y=typeof e.y=="number"?e.y:0;await s.evaluate(([g,T])=>globalThis.scrollTo(g,T),[w,y]);const f=await s.evaluate(()=>globalThis);a=f.scrollX,d=f.scrollY}else{const w=typeof e.deltaX=="number"?e.deltaX:0,y=typeof e.deltaY=="number"?e.deltaY:0;await s.mouse.wheel(w,y);const f=await s.evaluate(()=>globalThis);a=f.scrollX,d=f.scrollY}const h=s.url();return I(n,{tool:"browser_scroll",args:x({x:e.x,y:e.y,deltaX:e.deltaX,deltaY:e.deltaY,browserId:r}),beforeUrl:l,afterUrl:h,durationMs:Date.now()-c}),{ok:!0,scrollX:a,scrollY:d,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_screenshot",exposedName:"browser_screenshot",description:"Capture a single screenshot of the active page. The screenshot is returned as an image attachment (inlined into the conversation so you can see it; requires a model with image input). fullPage=true captures the entire scrollable page (may be large).",inputSchema:{type:"object",properties:{fullPage:{type:"boolean",description:"Capture entire scrollable page (default false)."},format:{type:"string",enum:["jpeg","png"],description:"Image format (default 'jpeg')."},quality:{type:"number",description:"JPEG quality 0-100 (default 80, ignored for png)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{page:n}=m(t,r),s=e.fullPage===!0,o=e.format==="png"||e.format==="jpeg"?e.format:"jpeg",i=typeof e.quality=="number"&&e.quality>=0&&e.quality<=100?e.quality:80,c=(await n.screenshot({fullPage:s,type:o,quality:o==="jpeg"?i:void 0})).toString("base64"),a=n.viewportSize();return{ok:!0,attachments:[{type:"image",name:`screenshot.${o}`,mediaType:`image/${o}`,base64Data:c}],width:a?.width??0,height:a?.height??0,url:n.url(),browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_close",exposedName:"browser_close",description:"Close the default browser session (browserId='default') for the current agent. Returns the step archive (recent operations). To close a non-default browser session, use browser_session_close({browserId}).",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t}=u(e),r=b.get(t,k);if(!r)return{ok:!1,error:`Browser session not launched for ${t}/${k}. Call browser_launch first.`};const n=r.archive.toJSON();return await b.close(t,k),{ok:!0,browserId:k,archive:n}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_list_sessions",exposedName:"browser_list_sessions",description:"List all browser sessions for the current agent. Returns an array of {browserId, pageCount, currentUrl, currentTitle, launchedAt, lastActivityAt}. Use this to discover which browserIds are currently active before calling browser_session_close.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t}=u(e),r=b.listSessions(t);return{ok:!0,agentId:t,sessions:r.map(n=>({browserId:n.browserId,pageCount:n.pageCount,activePageIndex:n.activePageIndex,currentUrl:n.currentUrl,currentTitle:n.currentTitle,launchedAt:n.launchedAt,lastActivityAt:n.lastActivityAt,wsUrl:_?_.getUrl(t,n.browserId):void 0}))}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_session_close",exposedName:"browser_session_close",description:"Close a specific browser session by browserId for the current agent. Returns the step archive of that session. Use browser_list_sessions to enumerate active browserIds. For the default session, you can also call browser_close (alias for browser_session_close with browserId='default').",inputSchema:{type:"object",properties:{browserId:{type:"string",description:"Browser instance ID to close (default 'default'). Required for non-default sessions."},agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),n=b.get(t,r);if(!n)return{ok:!1,error:`Browser session not launched for ${t}/${r}. Call browser_launch first.`};const s=n.archive.toJSON();return await b.close(t,r),{ok:!0,browserId:r,archive:s}}catch(t){return p(t)}}}].map(e=>({...e,category:"browser"}))}export{oe as createBuiltInBrowserTools};
1
+ import{locateElement as q}from"./element-locator.js";import{serializeSnapshot as E,buildRefMap as M}from"./snapshot-serializer.js";import{resolveSsrfConfig as P,validateUrlWithDns as j}from"./ssrf-guard.js";import{DEFAULT_BROWSER_ID as k}from"./types.js";const X=3e4,$=1e4;function oe(v){const{pool:b,wsServer:_}=v,U=v.agentId,N=v.scopeKey,D=P({perAgent:v.ssrfConfig,pool:b.getSsrfConfig()});function u(e){const r=(typeof e.agentId=="string"&&e.agentId.trim()?e.agentId.trim():void 0)??U;if(!r)throw new Error("agentId is required: pass via createBuiltInBrowserTools({agentId}) or tool args.agentId");const n=typeof e.browserId=="string"&&e.browserId.trim()?e.browserId.trim():k,s=typeof e.title=="string"&&e.title.trim()?e.title.trim():void 0,o=N??`agent:${r}`;return{agentId:r,browserId:n,title:s,scopeKey:o}}function B(e,t){const r=b.get(e,t);if(!r)throw new Error(`Browser session not launched for ${e}/${t}. Call browser_launch first.`);if(r.humanTakeover)throw new Error(`Human takeover active for ${e}/${t}. Release takeover before calling browser tools.`);return b.touchActivity(e,t),r}function m(e,t){return{session:B(e,t),page:b.getActivePage(e,t)}}function p(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}function I(e,t){if(e)try{e.archive.record(t)}catch{}}function x(e){const t={};for(const[r,n]of Object.entries(e))n!==void 0&&(t[r]=n);return t}const S=new Map;function A(e,t){return`${e}:${t}`}function C(e,t,r){return S.get(A(e,t))?.get(r)}function R(e,t,r){S.set(A(e,t),M(r))}return v.pool.onSessionClose((e,t)=>{S.delete(A(e,t))}),[{kind:"builtin",toolName:"browser_launch",exposedName:"browser_launch",description:"Launch a headless browser session for the current agent. Returns wsUrl for live JPEG frame streaming (open in browser to watch the agent operate). Pass browserId to start a separate browser instance (independent cookies/cache/storage). Default browserId is 'default'. Must be called before any other browser_* tool. The session is automatically reclaimed after 10 minutes of inactivity. title is required and should briefly describe the intent of this browser session (e.g. '\u641C\u7D22\u7ADE\u54C1\u4EF7\u683C', '\u767B\u5F55\u7BA1\u7406\u540E\u53F0').",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional if configured at factory time). Used to isolate browser sessions across agents."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default'). Same agent can have multiple browserIds (each = independent chromium process)."},title:{type:"string",description:"Brief human-readable title describing the intent of this browser session (e.g. '\u641C\u7D22\u7ADE\u54C1\u4EF7\u683C', '\u767B\u5F55\u7BA1\u7406\u540E\u53F0'). Required \u2014 used as tab label in dashboard."}},required:["title"]},async execute(e){try{const{agentId:t,browserId:r,title:n,scopeKey:s}=u(e),o=await b.getOrLaunch(t,r,n,s),i=o.pages[o.activePageIndex];if(i==null)return{ok:!1,error:`No active page for agent ${t}`};const l=i.viewportSize(),c={ok:!0,agentId:t,browserId:o.browserId,title:o.title,viewport:{width:l?.width??0,height:l?.height??0}};return _&&(c.wsUrl=_.getUrl(t,o.browserId)),c}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_navigate",exposedName:"browser_navigate",description:"Navigate the active page to a URL. Waits for DOMContentLoaded (30s timeout). Access to private/loopback addresses is allowed by default (configurable).",inputSchema:{type:"object",properties:{url:{type:"string",description:"Target URL (http/https only). Private IP ranges are allowed by default, can be disabled via ssrfConfig."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["url"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.url=="string"?e.url:"";if(!o)return{ok:!1,error:"url is required"};const i=await j(o,D),l=s.url(),c=Date.now();await s.goto(i,{waitUntil:"domcontentloaded",timeout:X});const a=s.url();try{await n.listenerManager.reattach(s)}catch{}let d="";try{d=await s.title()}catch{}return I(n,{tool:"browser_navigate",args:x({url:i,browserId:r}),beforeUrl:l,afterUrl:a,durationMs:Date.now()-c}),{ok:!0,url:i,finalUrl:a,title:d,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_snapshot",exposedName:"browser_snapshot",description:"Capture the active page's accessibility tree as YAML (Playwright ariaSnapshot mode=ai). Interactive elements get [ref=eXX] markers \u2014 pass the eXX string to browser_click / browser_type / browser_select. Re-snapshot after navigation (refs are invalidated on page change). Output truncated to maxChars (default 16000).",inputSchema:{type:"object",properties:{maxChars:{type:"number",description:"Max chars to return (default 16000)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{page:n}=m(t,r),s=typeof e.maxChars=="number"&&e.maxChars>0?Math.floor(e.maxChars):void 0,o=await E(n,{maxChars:s});R(t,r,o);let i="";try{i=await n.title()}catch{}return{ok:!0,snapshot:o,url:n.url(),title:i,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_click",exposedName:"browser_click",description:"Click an element identified by ref (from browser_snapshot), text (getByText), role+name (getByRole), or CSS selector. ref is preferred, but text/role are more stable on SPA pages where refs invalidate frequently. If ref fails, the system auto-falls back to the cached role+name from the last snapshot and retries the snapshot once. 10s timeout.",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5' (preferred)."},text:{type:"string",description:"Locate element by visible text (getByText). More stable than ref on SPA pages, e.g. 'javaok'."},role:{type:"string",description:"Locate element by ARIA role (e.g. button, link, textbox, listitem). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role' (e.g. role=button + name='Submit')."},selector:{type:"string",description:"CSS selector (subset: tag/.class/#id/[attr]/descendant/>)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.text=="string"&&e.text.trim()?e.text.trim():void 0,l=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,c=typeof e.name=="string"&&e.name?e.name:void 0,a=typeof e.selector=="string"?e.selector:void 0;if(o===void 0&&i===void 0&&l===void 0&&!a)return{ok:!1,error:"Either 'ref', 'text', 'role', or 'selector' is required for browser_click"};const d=o!==void 0?C(t,r,o):void 0,h=await q(s,{ref:o,text:i,role:l,name:c,selector:a,refFallback:d}),w=s.url(),y=Date.now();await h.click({timeout:$});const f=s.url(),g=o!==void 0?`ref=${o}`:i!==void 0?`text=${i}`:l!==void 0?`role=${l}`:`selector=${a}`;return I(n,{tool:"browser_click",args:x({ref:o,text:i,role:l,name:c,selector:a,browserId:r}),beforeUrl:w,afterUrl:f,durationMs:Date.now()-y}),{ok:!0,clicked:g,url:f,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_type",exposedName:"browser_type",description:"Type text into an input identified by ref, role+name (getByRole), or CSS selector. Note: 'text' param is the text to type (not for locating); use 'role'+'name' to locate the input. clear=true (default) clears the field first. delay adds per-keystroke delay (ms).",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5'."},role:{type:"string",description:"Locate input by ARIA role (e.g. textbox, searchbox). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role'."},selector:{type:"string",description:"CSS selector subset."},text:{type:"string",description:"Text to type (required)."},clear:{type:"boolean",description:"Clear field before typing (default true)."},delay:{type:"number",description:"Per-keystroke delay in ms (default 0)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["text"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,l=typeof e.name=="string"&&e.name?e.name:void 0,c=typeof e.selector=="string"?e.selector:void 0,a=typeof e.text=="string"?e.text:"";if(!a)return{ok:!1,error:"text is required for browser_type"};if(o===void 0&&i===void 0&&!c)return{ok:!1,error:"Either 'ref', 'role', or 'selector' is required for browser_type"};const d=e.clear!==!1,h=typeof e.delay=="number"&&e.delay>=0?e.delay:0,w=o!==void 0?C(t,r,o):void 0,y=await q(s,{ref:o,role:i,name:l,selector:c,refFallback:w}),f=s.url(),g=Date.now();d&&await y.fill(""),await y.type(a,{delay:h});const T=s.url();return I(n,{tool:"browser_type",args:x({ref:o,role:i,name:l,selector:c,text:a,clear:d,delay:h,browserId:r}),beforeUrl:f,afterUrl:T,durationMs:Date.now()-g}),{ok:!0,typed:a.length,url:T,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_select",exposedName:"browser_select",description:"Select an option in a <select> element identified by ref, text (getByText), role+name (getByRole), or CSS selector. value is the option value (string).",inputSchema:{type:"object",properties:{ref:{type:"string",description:"Element ref from browser_snapshot, e.g. 'e5'."},text:{type:"string",description:"Locate element by visible text (getByText)."},role:{type:"string",description:"Locate element by ARIA role (e.g. combobox, listbox). Use with 'name'."},name:{type:"string",description:"Accessible name to combine with 'role'."},selector:{type:"string",description:"CSS selector subset."},value:{type:"string",description:"Option value to select (required)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["value"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.ref=="string"&&e.ref.trim()?e.ref.trim():void 0,i=typeof e.text=="string"&&e.text.trim()?e.text.trim():void 0,l=typeof e.role=="string"&&e.role.trim()?e.role.trim():void 0,c=typeof e.name=="string"&&e.name?e.name:void 0,a=typeof e.selector=="string"?e.selector:void 0,d=typeof e.value=="string"?e.value:e.value!==void 0&&e.value!==null?String(e.value):"";if(!d)return{ok:!1,error:"value is required for browser_select"};if(o===void 0&&i===void 0&&l===void 0&&!a)return{ok:!1,error:"Either 'ref', 'text', 'role', or 'selector' is required for browser_select"};const h=o!==void 0?C(t,r,o):void 0,w=await q(s,{ref:o,text:i,role:l,name:c,selector:a,refFallback:h}),y=s.url(),f=Date.now();await w.selectOption(d);const g=s.url();return I(n,{tool:"browser_select",args:x({ref:o,text:i,role:l,name:c,selector:a,value:d,browserId:r}),beforeUrl:y,afterUrl:g,durationMs:Date.now()-f}),{ok:!0,selected:d,url:g,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_press_key",exposedName:"browser_press_key",description:"Press a keyboard key on the active page. Examples: 'Enter', 'Escape', 'Tab', 'Control+a', 'ArrowDown'. See Playwright key names for full list.",inputSchema:{type:"object",properties:{key:{type:"string",description:"Key or chord (e.g. 'Enter', 'Control+a')."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:["key"]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.key=="string"?e.key:"";if(!o)return{ok:!1,error:"key is required for browser_press_key"};const i=s.url(),l=Date.now();await s.keyboard.press(o);const c=s.url();return I(n,{tool:"browser_press_key",args:x({key:o,browserId:r}),beforeUrl:i,afterUrl:c,durationMs:Date.now()-l}),{ok:!0,key:o,url:c,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_scroll",exposedName:"browser_scroll",description:"Scroll the active page. Provide x/y for absolute scroll-to, OR deltaX/deltaY for relative wheel scroll. If both provided, x/y wins.",inputSchema:{type:"object",properties:{x:{type:"number",description:"Absolute scrollX (window.scrollTo)."},y:{type:"number",description:"Absolute scrollY (window.scrollTo)."},deltaX:{type:"number",description:"Relative wheel delta X."},deltaY:{type:"number",description:"Relative wheel delta Y."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{session:n,page:s}=m(t,r),o=typeof e.x=="number"&&Number.isFinite(e.x)||typeof e.y=="number"&&Number.isFinite(e.y),i=typeof e.deltaX=="number"&&Number.isFinite(e.deltaX)||typeof e.deltaY=="number"&&Number.isFinite(e.deltaY);if(!o&&!i)return{ok:!1,error:"Provide x/y (absolute) or deltaX/deltaY (relative) for browser_scroll"};const l=s.url(),c=Date.now();let a=0,d=0;if(o){const w=typeof e.x=="number"?e.x:0,y=typeof e.y=="number"?e.y:0;await s.evaluate(([g,T])=>globalThis.scrollTo(g,T),[w,y]);const f=await s.evaluate(()=>globalThis);a=f.scrollX,d=f.scrollY}else{const w=typeof e.deltaX=="number"?e.deltaX:0,y=typeof e.deltaY=="number"?e.deltaY:0;await s.mouse.wheel(w,y);const f=await s.evaluate(()=>globalThis);a=f.scrollX,d=f.scrollY}const h=s.url();return I(n,{tool:"browser_scroll",args:x({x:e.x,y:e.y,deltaX:e.deltaX,deltaY:e.deltaY,browserId:r}),beforeUrl:l,afterUrl:h,durationMs:Date.now()-c}),{ok:!0,scrollX:a,scrollY:d,browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_screenshot",exposedName:"browser_screenshot",description:"Capture a single screenshot of the active page. The screenshot is returned as an image attachment (inlined into the conversation so you can see it; requires a model with image input). fullPage=true captures the entire scrollable page (may be large).",inputSchema:{type:"object",properties:{fullPage:{type:"boolean",description:"Capture entire scrollable page (default false)."},format:{type:"string",enum:["jpeg","png"],description:"Image format (default 'jpeg')."},quality:{type:"number",description:"JPEG quality 0-100 (default 80, ignored for png)."},agentId:{type:"string",description:"Agent identifier (optional)."},browserId:{type:"string",description:"Browser instance ID (optional, default 'default')."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),{page:n}=m(t,r),s=e.fullPage===!0,o=e.format==="png"||e.format==="jpeg"?e.format:"jpeg",i=typeof e.quality=="number"&&e.quality>=0&&e.quality<=100?e.quality:80,c=(await n.screenshot({fullPage:s,type:o,quality:o==="jpeg"?i:void 0})).toString("base64"),a=n.viewportSize();return{ok:!0,attachments:[{type:"image",name:`screenshot.${o}`,mediaType:`image/${o}`,base64Data:c}],width:a?.width??0,height:a?.height??0,url:n.url(),browserId:r}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_close",exposedName:"browser_close",description:"Close the default browser session (browserId='default') for the current agent. Returns the step archive (recent operations). To close a non-default browser session, use browser_session_close({browserId}).",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t}=u(e),r=b.get(t,k);if(!r)return{ok:!1,error:`Browser session not launched for ${t}/${k}. Call browser_launch first.`};const n=r.archive.toJSON();return await b.close(t,k),{ok:!0,browserId:k,archive:n}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_list_sessions",exposedName:"browser_list_sessions",description:"List all browser sessions for the current agent. Returns an array of {browserId, pageCount, currentUrl, currentTitle, launchedAt, lastActivityAt}. Use this to discover which browserIds are currently active before calling browser_session_close.",inputSchema:{type:"object",properties:{agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t}=u(e),r=b.listSessions(t);return{ok:!0,agentId:t,sessions:r.map(n=>({browserId:n.browserId,pageCount:n.pageCount,activePageIndex:n.activePageIndex,currentUrl:n.currentUrl,currentTitle:n.currentTitle,launchedAt:n.launchedAt,lastActivityAt:n.lastActivityAt,wsUrl:_?_.getUrl(t,n.browserId):void 0}))}}catch(t){return p(t)}}},{kind:"builtin",toolName:"browser_session_close",exposedName:"browser_session_close",description:"Close a specific browser session by browserId for the current agent. Returns the step archive of that session. Use browser_list_sessions to enumerate active browserIds. For the default session, you can also call browser_close (alias for browser_session_close with browserId='default').",inputSchema:{type:"object",properties:{browserId:{type:"string",description:"Browser instance ID to close (default 'default'). Required for non-default sessions."},agentId:{type:"string",description:"Agent identifier (optional)."}},required:[]},async execute(e){try{const{agentId:t,browserId:r}=u(e),n=b.get(t,r);if(!n)return{ok:!1,error:`Browser session not launched for ${t}/${r}. Call browser_launch first.`};const s=n.archive.toJSON();return await b.close(t,r),{ok:!0,browserId:r,archive:s}}catch(t){return p(t)}}}].map(e=>({...e,category:"browser"}))}export{oe as createBuiltInBrowserTools};
2
2
 
@@ -1,2 +1,2 @@
1
- import{WebSocketServer as m,WebSocket as p}from"ws";import{installPickerOverlay as w,removePickerOverlay as b,pickElementAt as k,pickElementParent as v}from"./element-picker.js";import{InputDispatcher as _}from"./input-dispatcher.js";import{DEFAULT_BROWSER_ID as f}from"./types.js";import{WS_DEFAULT_HEARTBEAT_MS as S,WS_DEFAULT_IDLE_TIMEOUT_MS as I,WS_DEFAULT_MAX_SEND_BYTES as P,WS_HOST as C,WS_PORT as T,isQualityPreset as A,QUALITY_PRESETS as J}from"./types.js";const $="localhost";class E{constructor(e,t){this.wss=null,this.clients=new Set,this.mainHeartbeat=null,this.lastCursorQueryAt=0,this.lastCursor=null,this.pool=e,this.config={port:t?.port??T,host:t?.host??C,maxSendBytes:t?.maxSendBytes??P,idleTimeoutMs:t?.idleTimeoutMs??I,heartbeatMs:t?.heartbeatMs??S},this.inputDispatcher=new _(e),this.serverPort=this.config.port,this.pool.onSessionClose((r,i)=>{this.inputDispatcher.clearSession(r,i)})}start(){return this.wss?Promise.resolve({port:this.serverPort,host:this.config.host}):this.tryStart(this.config.port).catch(e=>{if(this.config.port===0)throw e;return console.warn(`[browser-ws] port ${this.config.port} bind failed (${e.message}); falling back to OS-assigned port`),this.tryStart(0)})}tryStart(e){return new Promise((t,r)=>{const i=new m({host:this.config.host,port:e,verifyClient:(o,n)=>{if(!o.origin){n(!0);return}/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(o.origin)?n(!0):n(!1,403,"origin not allowed")}});i.on("listening",()=>{const o=i.address(),n=typeof o=="object"&&o?o.port:e;this.serverPort=n,this.wss=i,this.attachHandlers(i),this.startMainHeartbeat(),t({port:n,host:this.config.host})}),i.on("error",o=>{this.wss||r(o)})})}async stop(){this.stopMainHeartbeat();for(const e of Array.from(this.clients))this.closeClient(e,1001,"server shutting down");this.wss&&(await new Promise(e=>{this.wss.close(()=>e())}),this.wss=null)}getPort(){return this.serverPort}getUrl(e,t){const r=this.config.host==="0.0.0.0"?$:this.config.host,i=t&&t.trim()?t.trim():f;return i===f?`ws://${r}:${this.serverPort}/agent/${encodeURIComponent(e)}`:`ws://${r}:${this.serverPort}/agent/${encodeURIComponent(e)}/${encodeURIComponent(i)}`}attachHandlers(e){e.on("connection",(t,r)=>{this.handleConnection(t,r).catch(()=>{try{t.close(1011,"internal error")}catch{}})})}async handleConnection(e,t){const r=new URL(t.url||"/","http://internal"),i=r.pathname.match(/^\/agent\/([^/]+)(?:\/([^/]+))?$/);if(!i){this.sendJson(e,{type:"error",message:`Invalid path; expected /agent/{agentId} or /agent/{agentId}/{browserId}, got ${r.pathname}`}),e.close(1008,"invalid path");return}const o=decodeURIComponent(i[1]),n=i[2]?decodeURIComponent(i[2]):f,s=this.pool.get(o,n);if(!s){this.sendJson(e,{type:"error",message:`Browser session not launched for ${o}/${n}. Call browser_launch first.`}),e.close(1008,"session not launched");return}const a={agentId:o,browserId:s.browserId,clientId:`${o}::${s.browserId}::${Date.now()}::${Math.random().toString(36).slice(2,8)}`,socket:e,heartbeatTimer:null,lastPongAt:Date.now(),unsubscribe:null},l=s.screencast.subscribe(h=>{this.sendFrame(e,h)});a.unsubscribe=l,e.on("pong",()=>{a.lastPongAt=Date.now()}),e.on("message",h=>{try{const y=h.toString("utf-8"),d=JSON.parse(y);if(d.type==="ping"){a.lastPongAt=Date.now(),this.sendJson(e,{type:"pong"});return}if(d.type==="input"&&typeof d.action=="string"){this.handleInputMessage(a,s,d.action,d);return}}catch{}}),e.on("close",()=>{this.closeClient(a,1e3,"client closed")}),e.on("error",()=>{this.closeClient(a,1011,"socket error")}),this.clients.add(a),this.sendJson(e,{type:"ready",agentId:o,browserId:s.browserId,viewport:{width:s.pages[s.activePageIndex]?.viewportSize()?.width??0,height:s.pages[s.activePageIndex]?.viewportSize()?.height??0},qualityPreset:s.qualityPreset,takeover:s.humanTakeover===!0});const c=s.pages[s.activePageIndex];c&&!c.isClosed()&&s.screencast.forceCaptureAndPush(c).catch(()=>{})}async handleInputMessage(e,t,r,i){if(this.pool.touchActivity(e.agentId,e.browserId),r==="takeover"){const n=this.inputDispatcher.acquireTakeover(e.agentId,e.browserId,e.clientId);this.sendJson(e.socket,{type:"takeover_state",active:n?!0:t.humanTakeover,ok:n,error:n?void 0:"another client is taking over"});return}if(r==="release_takeover"){this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),this.sendJson(e.socket,{type:"takeover_state",active:!1,ok:!0});return}if(r==="set_quality"){const n=i.preset;if(!A(n)){this.sendJson(e.socket,{type:"quality_changed",ok:!1,error:`invalid preset: ${String(i.preset)}`});return}const s=J[n];let a=!1;try{a=await t.screencast.updateQuality(s)}catch{a=!1}a&&(t.qualityPreset=n),this.sendJson(e.socket,{type:"quality_changed",preset:n,ok:a});return}if(r==="resync"){const n=t.pages[t.activePageIndex];n&&!n.isClosed()&&await t.screencast.forceCaptureAndPush(n);return}if(r==="go_back"||r==="go_forward"||r==="reload"){if(!t.humanTakeover||t.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"not in takeover mode"});return}const n=t.pages[t.activePageIndex];if(!n||n.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"active page is closed"});return}try{let s=!0,a="";try{a=n.url()}catch{}if(r==="go_back"?s=await n.goBack({waitUntil:"domcontentloaded",timeout:15e3}):r==="go_forward"?s=await n.goForward({waitUntil:"domcontentloaded",timeout:15e3}):await n.reload({waitUntil:"domcontentloaded",timeout:15e3}),s===null){let l="";try{l=n.url()}catch{}l&&l!==a&&(s=!0)}if(s===null&&r==="go_back"){const l=t.pages.indexOf(n);if(l>0){await this.pool.closePage(e.agentId,l,e.browserId);const c=t.pages[t.activePageIndex];c&&!c.isClosed()&&await t.screencast.forceCaptureAndPush(c).catch(()=>{}),this.sendJson(e.socket,{type:"input_result",ok:!0,action:r});return}}if(s===null){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:r==="go_back"?"no previous page in history":"no next page in history"});return}await new Promise(l=>setTimeout(l,200)),await t.screencast.restartAfterNavigation(n),this.sendJson(e.socket,{type:"input_result",ok:!0,action:r})}catch(s){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:s instanceof Error?s.message:String(s)})}return}if(r==="picker_start"||r==="picker_move"||r==="picker_stop"||r==="picker_parent"){if(!t.humanTakeover||t.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"not in takeover mode"});return}const n=t.pages[t.activePageIndex];if(!n||n.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"active page is closed"});return}try{if(r==="picker_start")await w(n);else if(r==="picker_stop")await b(n);else if(r==="picker_parent"){const s=await v(n);this.sendJson(e.socket,{type:"picker_result",selector:s.selector,found:s.found,tag:s.tag,text:s.text})}else{const s=typeof i.x=="number"?i.x:0,a=typeof i.y=="number"?i.y:0,l=await k(n,s,a);this.sendJson(e.socket,{type:"picker_result",selector:l.selector,found:l.found,tag:l.tag,text:l.text})}this.sendJson(e.socket,{type:"input_result",ok:!0,action:r})}catch(s){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:s instanceof Error?s.message:String(s)})}return}const o=await this.inputDispatcher.dispatch(e.agentId,e.browserId,r,i);r==="mousemove"&&o.ok&&this.queryAndPushCursor(e,t,i),r==="press_key"&&o.ok&&typeof i.key=="string"&&(i.key==="Control+c"||i.key==="Meta+c")&&this.queryAndPushSelection(e,t),this.sendJson(e.socket,{type:"input_result",ok:o.ok,action:r,error:o.error})}async queryAndPushSelection(e,t){const r=t.pages[t.activePageIndex];if(!(!r||r.isClosed()))try{const i=await r.evaluate(()=>globalThis.getSelection?.()?.toString()??"");typeof i=="string"&&i.length>0&&this.sendJson(e.socket,{type:"selection_text",text:i})}catch{}}async queryAndPushCursor(e,t,r){const i=typeof r.x=="number"?r.x:void 0,o=typeof r.y=="number"?r.y:void 0;if(i===void 0||o===void 0)return;const n=Date.now();if(n-this.lastCursorQueryAt<60)return;this.lastCursorQueryAt=n;const s=t.pages[t.activePageIndex];if(!(!s||s.isClosed()))try{const a=await s.evaluate(l=>{const c=globalThis,h=c.document?.elementFromPoint(l.x,l.y);return h?c.window?.getComputedStyle(h)?.cursor??"default":"default"},{x:i,y:o});typeof a=="string"&&a!==this.lastCursor&&(this.lastCursor=a,this.sendJson(e.socket,{type:"cursor_changed",cursor:a}))}catch{}}sendFrame(e,t){if(e.readyState!==p.OPEN)return;if(t.binaryFrame){const o=t.binaryFrame.length;if(o>this.config.maxSendBytes){console.warn(`[browser-ws] binary frame ${o} bytes exceeds maxSendBytes ${this.config.maxSendBytes}; dropping`);return}try{e.send(t.binaryFrame)}catch{}return}const r=JSON.stringify({type:"frame",frame:t}),i=Buffer.byteLength(r,"utf-8");if(i>this.config.maxSendBytes){console.warn(`[browser-ws] frame payload ${i} bytes exceeds maxSendBytes ${this.config.maxSendBytes}; dropping`);return}try{e.send(r)}catch{}}sendJson(e,t){if(e.readyState===p.OPEN)try{e.send(JSON.stringify(t))}catch{}}closeClient(e,t,r){if(this.clients.has(e)){if(this.clients.delete(e),e.unsubscribe){try{e.unsubscribe()}catch{}e.unsubscribe=null}if(this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.socket.readyState===p.OPEN)try{e.socket.close(t,r)}catch{}}}startMainHeartbeat(){this.mainHeartbeat||(this.mainHeartbeat=setInterval(()=>{const e=Date.now();for(const t of Array.from(this.clients)){if(t.socket.readyState===p.OPEN)try{t.socket.ping()}catch{}e-t.lastPongAt>this.config.idleTimeoutMs&&this.closeClient(t,1001,"idle timeout")}},this.config.heartbeatMs),this.mainHeartbeat.unref&&this.mainHeartbeat.unref())}stopMainHeartbeat(){this.mainHeartbeat&&(clearInterval(this.mainHeartbeat),this.mainHeartbeat=null)}broadcastListenerUpdate(e,t,r){const i={type:"listener_update",agentId:e,browserId:t,listeners:r};for(const o of this.clients)o.agentId===e&&o.browserId===t&&this.sendJson(o.socket,i)}broadcastListenerTriggered(e,t,r){const i={type:"listener_triggered",agentId:e,browserId:t,...r};for(const o of this.clients)o.agentId===e&&o.browserId===t&&this.sendJson(o.socket,i)}}let u=null;async function O(g,e){return u||(u=new E(g,e),await u.start()),u}async function F(){u&&(await u.stop(),u=null)}export{E as BrowserWsServer,O as getBrowserWsServer,F as stopBrowserWsServer};
1
+ import{WebSocketServer as m,WebSocket as p}from"ws";import{installPickerOverlay as w,removePickerOverlay as b,pickElementAt as k,pickElementParent as v}from"./element-picker.js";import{InputDispatcher as _}from"./input-dispatcher.js";import{DEFAULT_BROWSER_ID as f}from"./types.js";import{WS_DEFAULT_HEARTBEAT_MS as S,WS_DEFAULT_IDLE_TIMEOUT_MS as I,WS_DEFAULT_MAX_SEND_BYTES as P,WS_HOST as C,WS_PORT as T,isQualityPreset as A,QUALITY_PRESETS as J}from"./types.js";const $="localhost";class E{constructor(e,t){this.wss=null,this.clients=new Set,this.mainHeartbeat=null,this.lastCursorQueryAt=0,this.lastCursor=null,this.pool=e,this.config={port:t?.port??T,host:t?.host??C,maxSendBytes:t?.maxSendBytes??P,idleTimeoutMs:t?.idleTimeoutMs??I,heartbeatMs:t?.heartbeatMs??S},this.inputDispatcher=new _(e),this.serverPort=this.config.port,this.pool.onSessionClose((r,i)=>{this.inputDispatcher.clearSession(r,i)})}start(){return this.wss?Promise.resolve({port:this.serverPort,host:this.config.host}):this.tryStart(this.config.port).catch(e=>{if(this.config.port===0)throw e;return console.warn(`[browser-ws] port ${this.config.port} bind failed (${e.message}); falling back to OS-assigned port`),this.tryStart(0)})}tryStart(e){return new Promise((t,r)=>{const i=new m({host:this.config.host,port:e,verifyClient:(o,n)=>{if(!o.origin){n(!0);return}/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(o.origin)?n(!0):n(!1,403,"origin not allowed")}});i.on("listening",()=>{const o=i.address(),n=typeof o=="object"&&o?o.port:e;this.serverPort=n,this.wss=i,this.attachHandlers(i),this.startMainHeartbeat(),t({port:n,host:this.config.host})}),i.on("error",o=>{this.wss||r(o)})})}async stop(){this.stopMainHeartbeat();for(const e of Array.from(this.clients))this.closeClient(e,1001,"server shutting down");if(this.wss){const e=this.wss;await new Promise(t=>{e.close(()=>t())}),this.wss=null}}getPort(){return this.serverPort}getUrl(e,t){const r=this.config.host==="0.0.0.0"?$:this.config.host,i=t&&t.trim()?t.trim():f;return i===f?`ws://${r}:${this.serverPort}/agent/${encodeURIComponent(e)}`:`ws://${r}:${this.serverPort}/agent/${encodeURIComponent(e)}/${encodeURIComponent(i)}`}attachHandlers(e){e.on("connection",(t,r)=>{this.handleConnection(t,r).catch(()=>{try{t.close(1011,"internal error")}catch{}})})}async handleConnection(e,t){const r=new URL(t.url||"/","http://internal"),i=r.pathname.match(/^\/agent\/([^/]+)(?:\/([^/]+))?$/);if(!i){this.sendJson(e,{type:"error",message:`Invalid path; expected /agent/{agentId} or /agent/{agentId}/{browserId}, got ${r.pathname}`}),e.close(1008,"invalid path");return}const o=decodeURIComponent(i[1]??""),n=i[2]?decodeURIComponent(i[2]):f,s=this.pool.get(o,n);if(!s){this.sendJson(e,{type:"error",message:`Browser session not launched for ${o}/${n}. Call browser_launch first.`}),e.close(1008,"session not launched");return}const a={agentId:o,browserId:s.browserId,clientId:`${o}::${s.browserId}::${Date.now()}::${Math.random().toString(36).slice(2,8)}`,socket:e,heartbeatTimer:null,lastPongAt:Date.now(),unsubscribe:null},l=s.screencast.subscribe(h=>{this.sendFrame(e,h)});a.unsubscribe=l,e.on("pong",()=>{a.lastPongAt=Date.now()}),e.on("message",h=>{try{const y=h.toString("utf-8"),d=JSON.parse(y);if(d.type==="ping"){a.lastPongAt=Date.now(),this.sendJson(e,{type:"pong"});return}if(d.type==="input"&&typeof d.action=="string"){this.handleInputMessage(a,s,d.action,d);return}}catch{}}),e.on("close",()=>{this.closeClient(a,1e3,"client closed")}),e.on("error",()=>{this.closeClient(a,1011,"socket error")}),this.clients.add(a),this.sendJson(e,{type:"ready",agentId:o,browserId:s.browserId,viewport:{width:s.pages[s.activePageIndex]?.viewportSize()?.width??0,height:s.pages[s.activePageIndex]?.viewportSize()?.height??0},qualityPreset:s.qualityPreset,takeover:s.humanTakeover===!0});const c=s.pages[s.activePageIndex];c&&!c.isClosed()&&s.screencast.forceCaptureAndPush(c).catch(()=>{})}async handleInputMessage(e,t,r,i){if(this.pool.touchActivity(e.agentId,e.browserId),r==="takeover"){const n=this.inputDispatcher.acquireTakeover(e.agentId,e.browserId,e.clientId);this.sendJson(e.socket,{type:"takeover_state",active:n?!0:t.humanTakeover,ok:n,error:n?void 0:"another client is taking over"});return}if(r==="release_takeover"){this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),this.sendJson(e.socket,{type:"takeover_state",active:!1,ok:!0});return}if(r==="set_quality"){const n=i.preset;if(!A(n)){this.sendJson(e.socket,{type:"quality_changed",ok:!1,error:`invalid preset: ${String(i.preset)}`});return}const s=J[n];let a=!1;try{a=await t.screencast.updateQuality(s)}catch{a=!1}a&&(t.qualityPreset=n),this.sendJson(e.socket,{type:"quality_changed",preset:n,ok:a});return}if(r==="resync"){const n=t.pages[t.activePageIndex];n&&!n.isClosed()&&await t.screencast.forceCaptureAndPush(n);return}if(r==="go_back"||r==="go_forward"||r==="reload"){if(!t.humanTakeover||t.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"not in takeover mode"});return}const n=t.pages[t.activePageIndex];if(!n||n.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"active page is closed"});return}try{let s=!0,a="";try{a=n.url()}catch{}if(r==="go_back"?s=await n.goBack({waitUntil:"domcontentloaded",timeout:15e3}):r==="go_forward"?s=await n.goForward({waitUntil:"domcontentloaded",timeout:15e3}):await n.reload({waitUntil:"domcontentloaded",timeout:15e3}),s===null){let l="";try{l=n.url()}catch{}l&&l!==a&&(s=!0)}if(s===null&&r==="go_back"){const l=t.pages.indexOf(n);if(l>0){await this.pool.closePage(e.agentId,l,e.browserId);const c=t.pages[t.activePageIndex];c&&!c.isClosed()&&await t.screencast.forceCaptureAndPush(c).catch(()=>{}),this.sendJson(e.socket,{type:"input_result",ok:!0,action:r});return}}if(s===null){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:r==="go_back"?"no previous page in history":"no next page in history"});return}await new Promise(l=>setTimeout(l,200)),await t.screencast.restartAfterNavigation(n),this.sendJson(e.socket,{type:"input_result",ok:!0,action:r})}catch(s){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:s instanceof Error?s.message:String(s)})}return}if(r==="picker_start"||r==="picker_move"||r==="picker_stop"||r==="picker_parent"){if(!t.humanTakeover||t.takeoverClientId!==e.clientId){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"not in takeover mode"});return}const n=t.pages[t.activePageIndex];if(!n||n.isClosed()){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:"active page is closed"});return}try{if(r==="picker_start")await w(n);else if(r==="picker_stop")await b(n);else if(r==="picker_parent"){const s=await v(n);this.sendJson(e.socket,{type:"picker_result",selector:s.selector,found:s.found,tag:s.tag,text:s.text})}else{const s=typeof i.x=="number"?i.x:0,a=typeof i.y=="number"?i.y:0,l=await k(n,s,a);this.sendJson(e.socket,{type:"picker_result",selector:l.selector,found:l.found,tag:l.tag,text:l.text})}this.sendJson(e.socket,{type:"input_result",ok:!0,action:r})}catch(s){this.sendJson(e.socket,{type:"input_result",ok:!1,action:r,error:s instanceof Error?s.message:String(s)})}return}const o=await this.inputDispatcher.dispatch(e.agentId,e.browserId,r,i);r==="mousemove"&&o.ok&&this.queryAndPushCursor(e,t,i),r==="press_key"&&o.ok&&typeof i.key=="string"&&(i.key==="Control+c"||i.key==="Meta+c")&&this.queryAndPushSelection(e,t),this.sendJson(e.socket,{type:"input_result",ok:o.ok,action:r,error:o.error})}async queryAndPushSelection(e,t){const r=t.pages[t.activePageIndex];if(!(!r||r.isClosed()))try{const i=await r.evaluate(()=>globalThis.getSelection?.()?.toString()??"");typeof i=="string"&&i.length>0&&this.sendJson(e.socket,{type:"selection_text",text:i})}catch{}}async queryAndPushCursor(e,t,r){const i=typeof r.x=="number"?r.x:void 0,o=typeof r.y=="number"?r.y:void 0;if(i===void 0||o===void 0)return;const n=Date.now();if(n-this.lastCursorQueryAt<60)return;this.lastCursorQueryAt=n;const s=t.pages[t.activePageIndex];if(!(!s||s.isClosed()))try{const a=await s.evaluate(l=>{const c=globalThis,h=c.document?.elementFromPoint(l.x,l.y);return h?c.window?.getComputedStyle(h)?.cursor??"default":"default"},{x:i,y:o});typeof a=="string"&&a!==this.lastCursor&&(this.lastCursor=a,this.sendJson(e.socket,{type:"cursor_changed",cursor:a}))}catch{}}sendFrame(e,t){if(e.readyState!==p.OPEN)return;if(t.binaryFrame){const o=t.binaryFrame.length;if(o>this.config.maxSendBytes){console.warn(`[browser-ws] binary frame ${o} bytes exceeds maxSendBytes ${this.config.maxSendBytes}; dropping`);return}try{e.send(t.binaryFrame)}catch{}return}const r=JSON.stringify({type:"frame",frame:t}),i=Buffer.byteLength(r,"utf-8");if(i>this.config.maxSendBytes){console.warn(`[browser-ws] frame payload ${i} bytes exceeds maxSendBytes ${this.config.maxSendBytes}; dropping`);return}try{e.send(r)}catch{}}sendJson(e,t){if(e.readyState===p.OPEN)try{e.send(JSON.stringify(t))}catch{}}closeClient(e,t,r){if(this.clients.has(e)){if(this.clients.delete(e),e.unsubscribe){try{e.unsubscribe()}catch{}e.unsubscribe=null}if(this.inputDispatcher.releaseTakeover(e.agentId,e.browserId,e.clientId),e.heartbeatTimer&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=null),e.socket.readyState===p.OPEN)try{e.socket.close(t,r)}catch{}}}startMainHeartbeat(){this.mainHeartbeat||(this.mainHeartbeat=setInterval(()=>{const e=Date.now();for(const t of Array.from(this.clients)){if(t.socket.readyState===p.OPEN)try{t.socket.ping()}catch{}e-t.lastPongAt>this.config.idleTimeoutMs&&this.closeClient(t,1001,"idle timeout")}},this.config.heartbeatMs),this.mainHeartbeat.unref&&this.mainHeartbeat.unref())}stopMainHeartbeat(){this.mainHeartbeat&&(clearInterval(this.mainHeartbeat),this.mainHeartbeat=null)}broadcastListenerUpdate(e,t,r){const i={type:"listener_update",agentId:e,browserId:t,listeners:r};for(const o of this.clients)o.agentId===e&&o.browserId===t&&this.sendJson(o.socket,i)}broadcastListenerTriggered(e,t,r){const i={type:"listener_triggered",agentId:e,browserId:t,...r};for(const o of this.clients)o.agentId===e&&o.browserId===t&&this.sendJson(o.socket,i)}}let u=null;async function O(g,e){return u||(u=new E(g,e),await u.start()),u}async function F(){u&&(await u.stop(),u=null)}export{E as BrowserWsServer,O as getBrowserWsServer,F as stopBrowserWsServer};
2
2
 
package/dist/config.d.ts CHANGED
@@ -64,6 +64,10 @@ export declare function getOpencodeConfigFile(runtimeHome: string): string;
64
64
 
65
65
  export declare function getAcodeDataHome(): string;
66
66
 
67
+ export declare function getAcodePluginDataHome(): string;
68
+
69
+ export declare function getAcodeSkillDataHome(): string;
70
+
67
71
  export declare function getAcodeConfigFile(): string;
68
72
 
69
73
  export declare function getCodexConfigFile(runtimeHome: string): string;
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- import u from"node:fs";import D from"node:net";import{homedir as L}from"node:os";import o from"node:path";import{fileURLToPath as f}from"node:url";import{logger as C}from"./utils/logger.js";function m(){return String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development"}let E;function P(){if(E!==void 0)return E;const e=o.dirname(f(import.meta.url)),t=o.resolve(e,".."),r=o.resolve(t,".."),n=u.existsSync(o.join(r,".git"))||u.existsSync(o.join(r,"package.json"));return E=o.join(n?r:t,".dev-home"),E}function T(){return String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||L()}function N(){return m()?String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||P():T()}const h=18081,H=28081,O=Number(process.env.AWS_RUNTIME_BRIDGE_PORT||(m()?H:h));let A;function M(){return A??O}function W(e){A=e}function z(){A=void 0}function I(e){return new Promise(t=>{const r=D.createServer();r.once("error",n=>{const s=n.code==="EADDRINUSE"||n.code==="EACCES"||n.code==="EPERM";t(!s)}),r.once("listening",()=>{r.close(()=>t(!0))}),r.listen(e)})}async function U(e){return await I({port:e})&&await I({port:e,host:"0.0.0.0"})?e:null}async function B(e,t=20){let r=Math.floor(e);for(let s=0;s<t;s+=1){if(r>=1&&r<=65535){const c=await U(r);if(c!==null)return c}r+=1}return await U(0)??e}async function J(e=O){const t=await B(e);return W(t),process.env.AWS_RUNTIME_BRIDGE_PORT=String(t),t!==e&&C.warn(`[runtime-bridge] \u9996\u9009\u7AEF\u53E3 ${e} \u5DF2\u88AB\u5360\u7528\uFF0C\u81EA\u52A8\u6539\u7528 ${t} \u542F\u52A8`),t}const S="http://localhost:8080";function R(e){return e==null?void 0:String(e).trim()||void 0}function _(e){const t=R(e);if(!t)return;const r=t.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1");try{const n=new URL(r);return n.protocol==="ws:"?n.protocol="http:":n.protocol==="wss:"?n.protocol="https:":n.protocol=n.protocol.toLowerCase(),n.hostname=n.hostname.toLowerCase(),n.origin}catch{return r.replace(/\/+$/,"")}}function w(){return o.join(N(),".aws-bridge","config.json")}function F(){return o.join(N(),".aws-bridge","bridge-runtime.properties")}function Y(){const e=F();u.mkdirSync(o.dirname(e),{recursive:!0});const t=[`port=${M()}`,`pid=${process.pid}`,`startedAt=${new Date().toISOString()}`];u.writeFileSync(e,`${t.join(`
1
+ import u from"node:fs";import L from"node:net";import{homedir as C}from"node:os";import n from"node:path";import{fileURLToPath as O}from"node:url";import{logger as P}from"./utils/logger.js";function E(){return String(process.env.AWS_RUNTIME_ENV||"").trim().toLowerCase()==="development"}let S;function R(){if(S!==void 0)return S;const e=n.dirname(O(import.meta.url)),t=n.resolve(e,".."),r=n.resolve(t,".."),o=u.existsSync(n.join(r,".git"))||u.existsSync(n.join(r,"package.json"));return S=n.join(o?r:t,".dev-home"),S}function N(){return String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||C()}function I(){return E()?String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim()||R():N()}const H=18081,M=28081,v=Number(process.env.AWS_RUNTIME_BRIDGE_PORT||(E()?M:H));let f;function h(){return f??v}function W(e){f=e}function z(){f=void 0}function U(e){return new Promise(t=>{const r=L.createServer();r.once("error",o=>{const i=o.code==="EADDRINUSE"||o.code==="EACCES"||o.code==="EPERM";t(!i)}),r.once("listening",()=>{r.close(()=>t(!0))}),r.listen(e)})}async function x(e){return await U({port:e})&&await U({port:e,host:"0.0.0.0"})?e:null}async function B(e,t=20){let r=Math.floor(e);for(let i=0;i<t;i+=1){if(r>=1&&r<=65535){const c=await x(r);if(c!==null)return c}r+=1}return await x(0)??e}async function J(e=v){const t=await B(e);return W(t),process.env.AWS_RUNTIME_BRIDGE_PORT=String(t),t!==e&&P.warn(`[runtime-bridge] \u9996\u9009\u7AEF\u53E3 ${e} \u5DF2\u88AB\u5360\u7528\uFF0C\u81EA\u52A8\u6539\u7528 ${t} \u542F\u52A8`),t}const g="http://localhost:8080";function m(e){return e==null?void 0:String(e).trim()||void 0}function _(e){const t=m(e);if(!t)return;const r=t.replace(/^((?:https?|wss?):\/\/(?:\[[^\]]+\]|[^/:?#]+):\d+):\d+(?=\/|$)/i,"$1");try{const o=new URL(r);return o.protocol==="ws:"?o.protocol="http:":o.protocol==="wss:"?o.protocol="https:":o.protocol=o.protocol.toLowerCase(),o.hostname=o.hostname.toLowerCase(),o.origin}catch{return r.replace(/\/+$/,"")}}function w(){return n.join(I(),".aws-bridge","config.json")}function F(){return n.join(I(),".aws-bridge","bridge-runtime.properties")}function Y(){const e=F();u.mkdirSync(n.dirname(e),{recursive:!0});const t=[`port=${h()}`,`pid=${process.pid}`,`startedAt=${new Date().toISOString()}`];u.writeFileSync(e,`${t.join(`
2
2
  `)}
3
- `,{encoding:"utf8",mode:384})}function v(){const e=w();try{if(!u.existsSync(e))return[];const t=JSON.parse(u.readFileSync(e,"utf-8")),r=i=>({serverUrl:_(i.serverUrl)||_(i.schedulerBaseUrl),instanceId:R(i.instanceId),instanceName:R(i.instanceName)}),s=(Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[]).filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))).map(r).filter(i=>!!i.serverUrl);if(s.length>0)return s;const c=r(t);return c.serverUrl?[c]:[]}catch{return[]}}function j(){const t=v().map(r=>r.serverUrl).filter(r=>!!r);return Array.from(new Set(t))}function q(){return k(void 0)}function k(e,t,r){const n=_(e);if(n)return{url:n,source:"request",ambiguousTargetUrls:[]};const s=typeof t=="string"?t.trim():"",c=typeof r=="string"?r.trim():"";if(s||c){const g=v();let a;if(s&&(a=g.find(p=>p.instanceId===s)),!a&&c&&(a=g.find(p=>p.instanceName===c)),!a&&s&&!c&&(a=g.find(p=>p.instanceName===s)),a?.serverUrl)return{url:a.serverUrl,source:"instance-id-match",ambiguousTargetUrls:[],instanceId:a.instanceId,instanceName:a.instanceName}}const i=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL);if(i)return{url:i,source:"env",ambiguousTargetUrls:[]};const l=j();return l.length===1?{url:l[0]||S,source:"single-auto-register-target",ambiguousTargetUrls:[]}:l.length>1?{url:S,source:"ambiguous-auto-register-targets",ambiguousTargetUrls:l}:{url:S,source:"default",ambiguousTargetUrls:[]}}const X=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL)||S,Q=process.env.NODE_ENV||"development",Z=process.env.AWS_ALLOW_HOST_FILE_BROWSER==="true",ee=String(process.env.AWS_RUNTIME_CORS_ORIGINS||"http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173").split(",").map(e=>e.trim()).filter(e=>e.length>0);function te(){}function re(e){return String(process.env.AWS_RUNTIME_CLAUDE_CONFIG_FILE||"").trim()||o.join(e,".claude","settings.json")}function ne(e){return String(process.env.AWS_RUNTIME_CLAUDE_MCP_CONFIG_FILE||"").trim()||o.join(e,".claude.json")}function oe(e){return String(process.env.AWS_RUNTIME_CLAUDE_SKILLS_DIR||"").trim()||o.join(e,".claude","skills")}function se(e){return String(process.env.AWS_RUNTIME_OPENCODE_CONFIG_FILE||"").trim()||o.join(e,".config","opencode","opencode.json")}function x(){return String(process.env.ACODE_HOME||"").trim()||o.join(T(),".acode")}function ie(){return String(process.env.AWS_RUNTIME_ACODE_CONFIG_FILE||"").trim()||o.join(x(),"config.json")}function ce(e){return String(process.env.AWS_RUNTIME_CODEX_CONFIG_FILE||"").trim()||o.join(e,".codex","config.toml")}function ae(e){return String(process.env.AWS_RUNTIME_CODEX_SKILLS_DIR||"").trim()||o.join(e,".codex","skills")}function ue(e){return String(process.env.AWS_RUNTIME_OPENCODE_SKILLS_DIR||"").trim()||o.join(e,".opencode","skills")}function le(){return String(process.env.AWS_RUNTIME_ACODE_SKILLS_DIR||"").trim()||o.join(x(),"skills")}const pe=Number(process.env.AWS_ORPHAN_SCAN_INTERVAL||3e4),_e=process.env.AWS_ORPHAN_AUTO_CLEAN_MODE||"alert",Ee=process.env.AWS_ORPHAN_SCAN_ENABLED!=="false",Se=Number(process.env.AWS_ORPHAN_UNRESPONSIVE_TIMEOUT||3e5),ge=Number(process.env.AWS_ORPHAN_CPU_THRESHOLD||100),Ae=Number(process.env.AWS_ORPHAN_MEMORY_THRESHOLD||2048),Re=process.env.AWS_AUTO_REGISTER==="true",de=process.env.AWS_TENANT_ID||"",fe=process.env.AWS_USER_KEY||"",me=process.env.AWS_INSTANCE_NAME||"",Te=process.env.AWS_PROJECT_NAME||"",Ne=process.env.AWS_ROLE_NAME||"",Oe=process.env.AWS_WORKSPACE_PATH||"",Ie=process.env.AWS_REGISTER_IP||process.env.AWS_VIRTUAL_IP||"";let d;function Ue(){if(d!==void 0)return d;let e="unknown";try{const t=o.dirname(f(import.meta.url)),r=o.resolve(t,"..","package.json");u.existsSync(r)&&(e=JSON.parse(u.readFileSync(r,"utf-8")).version||"unknown")}catch{}return d=e,e}export{Re as AUTO_REGISTER_ENABLED,me as AUTO_REGISTER_INSTANCE_NAME,Te as AUTO_REGISTER_PROJECT_NAME,Ne as AUTO_REGISTER_ROLE_NAME,de as AUTO_REGISTER_TENANT_ID,fe as AUTO_REGISTER_USER_KEY,Ie as AUTO_REGISTER_VIRTUAL_IP,Oe as AUTO_REGISTER_WORKSPACE_PATH,h as DEFAULT_BRIDGE_PORT,S as DEFAULT_SCHEDULER_BASE_URL,H as DEV_DEFAULT_BRIDGE_PORT,_e as ORPHAN_AUTO_CLEAN_MODE,ge as ORPHAN_CPU_THRESHOLD,Ae as ORPHAN_MEMORY_THRESHOLD,Ee as ORPHAN_SCAN_ENABLED,pe as ORPHAN_SCAN_INTERVAL,Se as ORPHAN_UNRESPONSIVE_TIMEOUT,Z as allowHostFileBrowser,ee as allowedCorsOrigins,B as findAvailableListenPort,ie as getAcodeConfigFile,x as getAcodeDataHome,le as getAcodeSkillsDir,M as getActiveBridgeHttpPort,w as getAutoRegisterConfigFilePath,F as getBridgeRuntimePropertiesFilePath,Ue as getBridgeVersion,re as getClaudeConfigFile,ne as getClaudeMcpConfigFile,oe as getClaudeSkillsDir,ce as getCodexConfigFile,ae as getCodexSkillsDir,se as getOpencodeConfigFile,ue as getOpencodeSkillsDir,N as getRuntimeHomeDir,T as getUserHomeDir,m as isDevMode,Q as nodeEnv,O as port,J as reserveBridgeListenPort,z as resetActiveBridgeHttpPort,q as resolveSchedulerBaseUrl,k as resolveSchedulerBaseUrlFrom,X as schedulerBaseUrl,W as setActiveBridgeHttpPort,te as validateProductionToken,Y as writeBridgeRuntimePropertiesFile};
3
+ `,{encoding:"utf8",mode:384})}function D(){const e=w();try{if(!u.existsSync(e))return[];const t=JSON.parse(u.readFileSync(e,"utf-8")),r=s=>({serverUrl:_(s.serverUrl)||_(s.schedulerBaseUrl),instanceId:m(s.instanceId),instanceName:m(s.instanceName)}),i=(Array.isArray(t.autoRegisterTargets)?t.autoRegisterTargets:[]).filter(s=>!!(s&&typeof s=="object"&&!Array.isArray(s))).map(r).filter(s=>!!s.serverUrl);if(i.length>0)return i;const c=r(t);return c.serverUrl?[c]:[]}catch{return[]}}function j(){const t=D().map(r=>r.serverUrl).filter(r=>!!r);return Array.from(new Set(t))}function q(){return k(void 0)}function k(e,t,r){const o=_(e);if(o)return{url:o,source:"request",ambiguousTargetUrls:[]};const i=typeof t=="string"?t.trim():"",c=typeof r=="string"?r.trim():"";if(i||c){const d=D();let a;if(i&&(a=d.find(l=>l.instanceId===i)),!a&&c&&(a=d.find(l=>l.instanceName===c)),!a&&i&&!c&&(a=d.find(l=>l.instanceName===i)),a?.serverUrl)return{url:a.serverUrl,source:"instance-id-match",ambiguousTargetUrls:[],instanceId:a.instanceId,instanceName:a.instanceName}}const s=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL);if(s)return{url:s,source:"env",ambiguousTargetUrls:[]};const p=j();return p.length===1?{url:p[0]||g,source:"single-auto-register-target",ambiguousTargetUrls:[]}:p.length>1?{url:g,source:"ambiguous-auto-register-targets",ambiguousTargetUrls:p}:{url:g,source:"default",ambiguousTargetUrls:[]}}const X=_(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL)||g,Q=process.env.NODE_ENV||"development",Z=process.env.AWS_ALLOW_HOST_FILE_BROWSER==="true",ee=String(process.env.AWS_RUNTIME_CORS_ORIGINS||"http://localhost:3000,http://127.0.0.1:3000,http://localhost:5173,http://127.0.0.1:5173").split(",").map(e=>e.trim()).filter(e=>e.length>0);function te(){}function re(e){return String(process.env.AWS_RUNTIME_CLAUDE_CONFIG_FILE||"").trim()||n.join(e,".claude","settings.json")}function ne(e){return String(process.env.AWS_RUNTIME_CLAUDE_MCP_CONFIG_FILE||"").trim()||n.join(e,".claude.json")}function oe(e){return String(process.env.AWS_RUNTIME_CLAUDE_SKILLS_DIR||"").trim()||n.join(e,".claude","skills")}function ie(e){return String(process.env.AWS_RUNTIME_OPENCODE_CONFIG_FILE||"").trim()||n.join(e,".config","opencode","opencode.json")}function A(){return String(process.env.ACODE_HOME||"").trim()||n.join(N(),".acode")}function se(){if(E()){const e=String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim();return n.join(e||R(),".acode")}return A()}function ce(){if(E()){const e=String(process.env.AWS_TEST_HOME||"").trim()||String(process.env.AWS_RUNTIME_HOME_DIR||"").trim();return n.join(e||R(),".acode")}return A()}function ae(){return String(process.env.AWS_RUNTIME_ACODE_CONFIG_FILE||"").trim()||n.join(A(),"config.json")}function ue(e){return String(process.env.AWS_RUNTIME_CODEX_CONFIG_FILE||"").trim()||n.join(e,".codex","config.toml")}function pe(e){return String(process.env.AWS_RUNTIME_CODEX_SKILLS_DIR||"").trim()||n.join(e,".codex","skills")}function le(e){return String(process.env.AWS_RUNTIME_OPENCODE_SKILLS_DIR||"").trim()||n.join(e,".opencode","skills")}function _e(){return String(process.env.AWS_RUNTIME_ACODE_SKILLS_DIR||"").trim()||n.join(A(),"skills")}const Ee=Number(process.env.AWS_ORPHAN_SCAN_INTERVAL||3e4),Se=process.env.AWS_ORPHAN_AUTO_CLEAN_MODE||"alert",ge=process.env.AWS_ORPHAN_SCAN_ENABLED!=="false",Ae=Number(process.env.AWS_ORPHAN_UNRESPONSIVE_TIMEOUT||3e5),de=Number(process.env.AWS_ORPHAN_CPU_THRESHOLD||100),Re=Number(process.env.AWS_ORPHAN_MEMORY_THRESHOLD||2048),fe=process.env.AWS_AUTO_REGISTER==="true",me=process.env.AWS_TENANT_ID||"",Te=process.env.AWS_USER_KEY||"",Oe=process.env.AWS_INSTANCE_NAME||"",Ne=process.env.AWS_PROJECT_NAME||"",Ie=process.env.AWS_ROLE_NAME||"",ve=process.env.AWS_WORKSPACE_PATH||"",Ue=process.env.AWS_REGISTER_IP||process.env.AWS_VIRTUAL_IP||"";let T;function xe(){if(T!==void 0)return T;let e="unknown";try{const t=n.dirname(O(import.meta.url)),r=n.resolve(t,"..","package.json");u.existsSync(r)&&(e=JSON.parse(u.readFileSync(r,"utf-8")).version||"unknown")}catch{}return T=e,e}export{fe as AUTO_REGISTER_ENABLED,Oe as AUTO_REGISTER_INSTANCE_NAME,Ne as AUTO_REGISTER_PROJECT_NAME,Ie as AUTO_REGISTER_ROLE_NAME,me as AUTO_REGISTER_TENANT_ID,Te as AUTO_REGISTER_USER_KEY,Ue as AUTO_REGISTER_VIRTUAL_IP,ve as AUTO_REGISTER_WORKSPACE_PATH,H as DEFAULT_BRIDGE_PORT,g as DEFAULT_SCHEDULER_BASE_URL,M as DEV_DEFAULT_BRIDGE_PORT,Se as ORPHAN_AUTO_CLEAN_MODE,de as ORPHAN_CPU_THRESHOLD,Re as ORPHAN_MEMORY_THRESHOLD,ge as ORPHAN_SCAN_ENABLED,Ee as ORPHAN_SCAN_INTERVAL,Ae as ORPHAN_UNRESPONSIVE_TIMEOUT,Z as allowHostFileBrowser,ee as allowedCorsOrigins,B as findAvailableListenPort,ae as getAcodeConfigFile,A as getAcodeDataHome,se as getAcodePluginDataHome,ce as getAcodeSkillDataHome,_e as getAcodeSkillsDir,h as getActiveBridgeHttpPort,w as getAutoRegisterConfigFilePath,F as getBridgeRuntimePropertiesFilePath,xe as getBridgeVersion,re as getClaudeConfigFile,ne as getClaudeMcpConfigFile,oe as getClaudeSkillsDir,ue as getCodexConfigFile,pe as getCodexSkillsDir,ie as getOpencodeConfigFile,le as getOpencodeSkillsDir,I as getRuntimeHomeDir,N as getUserHomeDir,E as isDevMode,Q as nodeEnv,v as port,J as reserveBridgeListenPort,z as resetActiveBridgeHttpPort,q as resolveSchedulerBaseUrl,k as resolveSchedulerBaseUrlFrom,X as schedulerBaseUrl,W as setActiveBridgeHttpPort,te as validateProductionToken,Y as writeBridgeRuntimePropertiesFile};
4
4
 
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{existsSync as E,readFileSync as T}from"node:fs";import B from"node:os";import R from"node:path";import M from"cors";import P from"express";import{adapterRegistry as O}from"./adapter/index.js";import{attachBrowserWebSocketServer as x}from"./browser/browser-ws-bridge.js";import{getActiveBridgeHttpPort as I,getAutoRegisterConfigFilePath as _,getBridgeRuntimePropertiesFilePath as F,getRuntimeHomeDir as G,reserveBridgeListenPort as K,validateProductionToken as L,writeBridgeRuntimePropertiesFile as j}from"./config.js";import{attachRemoteDesktopWebSocketServer as N}from"./remote-desktop/index.js";import{acodeTodosRouter as H}from"./routes/acode-todos.js";import{aiSourcesRouter as W}from"./routes/ai-sources.js";import{backgroundTasksRouter as U}from"./routes/background-tasks.js";import{browserListenersRouter as z}from"./routes/browser-listeners.js";import{browserSessionsRouter as J}from"./routes/browser-sessions.js";import{computerRouter as Y}from"./routes/computer.js";import{dashboardRouter as q}from"./routes/dashboard.js";import{eventsRouter as Z}from"./routes/events.js";import{fileBrowserRouter as Q}from"./routes/file-browser.js";import{fileChangeDiffRouter as V}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as X}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as ee}from"./routes/file-snapshot.js";import{gitRouter as re}from"./routes/git.js";import{instanceRouter as te,setGracefulShutdownFn as ie}from"./routes/instance.js";import{jdksRouter as oe}from"./routes/jdks.js";import{launchRouter as ne}from"./routes/launch.js";import{mcpRouter as se}from"./routes/mcp.js";import{processesRouter as ae}from"./routes/processes.js";import{propertiesRouter as me}from"./routes/properties.js";import{attachPtyWebSocketServer as ue,closeAllPtySessions as ce,ptyRouter as de,ptySessions as ge}from"./routes/pty.js";import{runtimeBindingRouter as pe,logRuntimeBindingStartupState as fe}from"./routes/runtime-binding.js";import{sessionsRouter as le}from"./routes/sessions.js";import{skillsRouter as be}from"./routes/skills.js";import{subAgentsRouter as we}from"./routes/sub-agents.js";import{systemMetricsRouter as he}from"./routes/system-metrics.js";import{taskContextRouter as Se}from"./routes/task-context.js";import{terminalRouter as Re,sdkSessions as h}from"./routes/terminal.js";import{ymlRouter as Pe}from"./routes/yml.js";import{ensureAcodePackageReleased as Ie}from"./services/acode-package.js";import{accessControlMiddleware as ye}from"./services/access-control.js";import{getAgentProcessManager as y}from"./services/agent-process-manager.js";import{autoRegister as $e,unregister as ke,bridgeRestartCleanup as Ce,cancelBackgroundRegisterRetries as ve}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Ae}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as De}from"./services/browser-session-manager.js";import{handleCliCommand as Ee}from"./services/cli-commands.js";import{disposeDesktopMcpManager as Te}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Be}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Me}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as Oe}from"./services/lifecycle-state.js";import{startOrphanMonitor as xe,stopOrphanMonitor as _e}from"./services/orphan-monitor.js";import{detectOrphanProcesses as Fe}from"./services/process-detector.js";import{buildGracefulShutdownPlan as Ge,shouldCleanupPersistedSessionsOnStartup as Ke}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Le}from"./services/startup-config-wizard.js";import{subAgentStore as je}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as $,savePersistedSessions as k}from"./services/terminal-persistence.js";import{stopTunnelClient as Ne}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const C=await Ee();C.handled&&process.exit(C.exitCode),await Le(),L(),Ae(),Ie(),Me(),fe(),await K(),j(),e.info(`[runtime-bridge] \u5DF2\u5199\u5165\u8FD0\u884C\u65F6\u914D\u7F6E ${F()}\uFF08port=${I()}\uFF09`),String(process.env.ACODE_HOME||"").trim()||(process.env.ACODE_HOME=R.join(G(),".acode")),e.info(`[runtime-bridge] ACode \u6570\u636E\u76EE\u5F55: ${process.env.ACODE_HOME}`);async function He(){try{if(await $e())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),s=o();!!s.userKey&&s.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${_()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}He().then(()=>We()).then(()=>Oe()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function We(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const s=await Ce();s.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${s.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${s.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function Ue(){try{const r=await $();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await y().rebuildRegistry(r.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}Ue().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function ze(){try{const r=await import("node:fs/promises"),o=await import("node:path"),s=await import("node:os"),f=o.join(s.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await $();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!Ke(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await y().rebuildRegistry(a.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await Fe(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:n}=await import("node:child_process");n(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(n){const c=n;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await k([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}ze().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),xe().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=P();i.use(ye),i.use(M()),i.use(P.json({limit:"1mb"})),i.use("/runtime",pe),i.use("/runtime",me),i.use("/runtime",Pe),i.use("/runtime",te),i.use("/runtime",be),i.use("/runtime",se),i.use("/runtime",Re),i.use("/runtime",le),i.use("/runtime",ae),i.use("/runtime",ne),i.use("/runtime",oe),i.use("/runtime",he),i.use("/runtime",Z),i.use("/runtime",re),i.use("/runtime",ee),i.use("/runtime",H),i.use("/runtime",U),i.use("/runtime",we),i.use("/runtime",J),i.use("/runtime",z),i.use("/runtime",W),i.use("/runtime",Se),i.use("/runtime",X),i.use("/runtime",V),i.use("/runtime/computer",Y),i.use("/pty",de),i.use("/",q),i.use("/api/file-browser",Q);function Je(){const r=I(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return ue(o),N(o),x(o),o.on("error",s=>{if(s.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",s),process.exitCode=1}),o}let v=!1;async function b(r,o,s=!1){if(v){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}v=!0,s||S()&&(s=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${s})`);const f=Date.now(),u=Ge(s);try{const a=h.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,n]of h.entries())try{const c=n.providerId||"claude-code",g=O.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),h.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),h.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=ge.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),ce("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:n}=await Be().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${n}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+require("path").join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(_e(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:n}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const D=await n(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${D.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const n=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",n.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await ke()}catch(t){const n=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(ve(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Ne()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await k([])}catch(t){const n=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await De(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Te(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}je.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const w=Je(),A=R.join(B.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function S(){try{if(E(A)){const r=T(A,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ie(async(r,o)=>{await b(r,w,o)}),process.on("SIGTERM",()=>{const r=S();b("SIGTERM",w,r)}),process.on("SIGINT",()=>{const r=S();b("SIGINT",w,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=S();b("SIGBREAK",w,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",w)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
2
+ import{existsSync as T,readFileSync as B}from"node:fs";import D from"node:os";import M from"node:path";import E from"cors";import S from"express";import{adapterRegistry as x}from"./adapter/index.js";import{attachBrowserWebSocketServer as F}from"./browser/browser-ws-bridge.js";import{getAcodeDataHome as G,getAcodePluginDataHome as O,getActiveBridgeHttpPort as P,getAutoRegisterConfigFilePath as _,getBridgeRuntimePropertiesFilePath as K,reserveBridgeListenPort as L,validateProductionToken as N,writeBridgeRuntimePropertiesFile as j}from"./config.js";import{attachRemoteDesktopWebSocketServer as W}from"./remote-desktop/index.js";import{acodeTodosRouter as H}from"./routes/acode-todos.js";import{aiSourcesRouter as U}from"./routes/ai-sources.js";import{backgroundTasksRouter as z}from"./routes/background-tasks.js";import{browserListenersRouter as J}from"./routes/browser-listeners.js";import{browserSessionsRouter as Y}from"./routes/browser-sessions.js";import{capabilitiesRouter as q}from"./routes/capabilities.js";import{computerRouter as Z}from"./routes/computer.js";import{dashboardRouter as Q}from"./routes/dashboard.js";import{eventsRouter as V}from"./routes/events.js";import{fileBrowserRouter as X}from"./routes/file-browser.js";import{fileChangeDiffRouter as ee}from"./routes/file-change-diff.js";import{fileDiffRollbackRouter as re}from"./routes/file-diff-rollback.js";import{fileSnapshotRouter as te}from"./routes/file-snapshot.js";import{gitRouter as ie}from"./routes/git.js";import{instanceRouter as oe,setGracefulShutdownFn as ne}from"./routes/instance.js";import{jdksRouter as se}from"./routes/jdks.js";import{launchRouter as ae}from"./routes/launch.js";import{mcpExtraRouter as me}from"./routes/mcp-extra.js";import{mcpRouter as ue}from"./routes/mcp.js";import{pluginsRouter as ce}from"./routes/plugins.js";import{processesRouter as de}from"./routes/processes.js";import{propertiesRouter as ge}from"./routes/properties.js";import{attachPtyWebSocketServer as pe,closeAllPtySessions as fe,ptyRouter as le,ptySessions as be}from"./routes/pty.js";import{runtimeBindingRouter as we,logRuntimeBindingStartupState as he}from"./routes/runtime-binding.js";import{sessionsRouter as Re}from"./routes/sessions.js";import{skillsRouter as Se}from"./routes/skills.js";import{subAgentsRouter as Pe}from"./routes/sub-agents.js";import{systemMetricsRouter as Ie}from"./routes/system-metrics.js";import{taskContextRouter as ye}from"./routes/task-context.js";import{terminalRouter as $e,sdkSessions as h}from"./routes/terminal.js";import{ymlRouter as ke}from"./routes/yml.js";import{accessControlMiddleware as Ce}from"./services/access-control.js";import{ensureAcodePackageReleased as Ae}from"./services/acode-package.js";import{getAgentProcessManager as I}from"./services/agent-process-manager.js";import{autoRegister as ve,unregister as Te,bridgeRestartCleanup as Be,cancelBackgroundRegisterRetries as De}from"./services/auto-register.js";import{ensureAwsClientAgentMcpReleased as Me}from"./services/aws-client-agent-mcp.js";import{disposeBrowserSessionManager as Ee}from"./services/browser-session-manager.js";import{handleCliCommand as xe}from"./services/cli-commands.js";import{disposeDesktopMcpManager as Fe}from"./services/desktop-mcp-manager.js";import{getLaunchManager as Ge}from"./services/launch-manager.js";import{migrateOldPathsOnStartup as Oe}from"./services/legacy-path-migration.js";import{deliverPendingBridgeLifecycleNotifications as _e}from"./services/lifecycle-state.js";import{startOrphanMonitor as Ke,stopOrphanMonitor as Le}from"./services/orphan-monitor.js";import{pluginManager as Ne}from"./services/plugin-manager.js";import{detectOrphanProcesses as je}from"./services/process-detector.js";import{buildGracefulShutdownPlan as We,shouldCleanupPersistedSessionsOnStartup as He}from"./services/runtime-lifecycle-policy.js";import{ensureStartupConfig as Ue}from"./services/startup-config-wizard.js";import{subAgentStore as ze}from"./services/sub-agent-manager-instance.js";import{loadPersistedSessions as y,savePersistedSessions as $}from"./services/terminal-persistence.js";import{stopTunnelClient as Je}from"./services/tunnel-client.js";import{logger as e}from"./utils/logger.js";const k=await xe();k.handled&&process.exit(k.exitCode),await Ue(),N(),Me(),Ae(),Oe(),he(),await L(),j(),e.info(`[runtime-bridge] \u5DF2\u5199\u5165\u8FD0\u884C\u65F6\u914D\u7F6E ${K()}\uFF08port=${P()}\uFF09`),e.info(`[runtime-bridge] ACode \u6570\u636E\u76EE\u5F55: ${G()}`),e.info(`[runtime-bridge] \u63D2\u4EF6\u6570\u636E\u76EE\u5F55: ${O()}`);async function Ye(){try{if(await ve())e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6210\u529F");else{const{loadConfig:o}=await import("./services/auto-register.js"),s=o();!!s.userKey&&s.enabled?e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6682\u65F6\u5931\u8D25\uFF0C\u5C06\u5728\u540E\u53F0\u6301\u7EED\u91CD\u8BD5\u76F4\u5230\u4E0E\u8C03\u5EA6\u4E2D\u5FC3\u5EFA\u7ACB\u8FDE\u63A5"):(e.info("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u672A\u914D\u7F6E\uFF0C\u7EE7\u7EED\u542F\u52A8\u670D\u52A1"),e.info(`[runtime-bridge] \u8981\u542F\u7528\u81EA\u52A8\u6CE8\u518C\uFF0C\u8BF7\u521B\u5EFA\u914D\u7F6E\u6587\u4EF6 ${_()}`))}}catch(r){const o=r;e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u51FA\u9519:",o.message)}}Ye().then(()=>qe()).then(()=>_e()).then(()=>{e.info("[runtime-bridge] Bridge \u751F\u547D\u5468\u671F\u901A\u77E5\u540C\u6B65\u5B8C\u6210")}).catch(r=>{e.warn("[runtime-bridge] \u81EA\u52A8\u6CE8\u518C\u6216\u6E05\u7406\u51FA\u9519:",r)}),import("./services/update-notifier.js").then(({startUpdateNotifier:r})=>r()).catch(r=>{e.warn("[runtime-bridge] \u7248\u672C\u68C0\u67E5\u670D\u52A1\u542F\u52A8\u5931\u8D25:",r.message)});async function qe(){try{if(process.env.AWS_BRIDGE_RESTART_CLEANUP!=="true"){e.info("[runtime-bridge] \u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406\uFF0C\u4FDD\u7559 Agent \u72B6\u6001\u4F9B\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D");return}const{getRegistrationState:r}=await import("./services/auto-register.js"),o=r();if(!o.registered||!o.instanceId){e.info("[runtime-bridge] \u5B9E\u4F8B\u672A\u6CE8\u518C\uFF0C\u8DF3\u8FC7 Bridge \u91CD\u542F\u6E05\u7406");return}e.info("[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5DF2\u663E\u5F0F\u542F\u7528\uFF0C\u6B63\u5728\u901A\u77E5\u8C03\u5EA6\u4E2D\u5FC3\u6E05\u7406 Agent \u72B6\u6001...");const s=await Be();s.success?e.info(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u6210\u529F\uFF0C\u6E05\u7406\u4E86 ${s.agentCount||0} \u4E2A Agent`):e.warn(`[runtime-bridge] \u2605 Bridge \u91CD\u542F\u6E05\u7406\u5931\u8D25: ${s.error}`)}catch(r){const o=r;e.warn("[runtime-bridge] Bridge \u91CD\u542F\u6E05\u7406\u51FA\u9519:",o.message)}}async function Ze(){try{const r=await y();if(r.length===0){e.info("[runtime-bridge] \u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u8DF3\u8FC7\u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA");return}await I().rebuildRegistry(r.map(s=>({agentId:s.agentId,sessionId:s.sessionId,pid:s.pid,workspacePath:s.workspacePath,command:s.command,mode:"sdk"}))),e.info(`[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5B8C\u6210: ${r.length} \u6761\u8BB0\u5F55`)}catch(r){const o=r;e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u5931\u8D25:",o.message)}}Ze().catch(r=>{e.warn("[runtime-bridge] \u8FDB\u7A0B\u6CE8\u518C\u8868\u91CD\u5EFA\u51FA\u9519:",r)});async function Qe(){try{const r=await import("node:fs/promises"),o=await import("node:path"),s=await import("node:os"),f=o.join(s.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");let u=!1;try{const t=await r.readFile(f,"utf-8");u=JSON.parse(t).preserveSessions===!0,await r.unlink(f),e.info(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230\u4FDD\u7559\u4F1A\u8BDD\u6807\u8BB0\uFF0CpreserveSessions=${u}`)}catch{}const a=await y();if(a.length===0){e.info("[runtime-bridge] \u542F\u52A8\u65F6\u65E0\u6301\u4E45\u5316\u4F1A\u8BDD\uFF0C\u65E0\u9700\u68C0\u6D4B\u5B64\u513F\u8FDB\u7A0B");return}if(!He(u)){e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u5E76\u91CD\u5EFA\u8FDB\u7A0B\u6CE8\u518C\u8868`),await I().rebuildRegistry(a.map(n=>({agentId:n.agentId,sessionId:n.sessionId,pid:n.pid,workspacePath:n.workspacePath,command:n.command,mode:"sdk"})));return}e.info(`[runtime-bridge] \u2605 \u5DF2\u663E\u5F0F\u542F\u7528\u542F\u52A8\u6E05\u7406\uFF0C\u68C0\u6D4B ${a.length} \u4E2A\u6301\u4E45\u5316\u4F1A\u8BDD\u7684\u5B64\u513F\u8FDB\u7A0B...`);const d=await je(a.map(t=>({agentId:t.agentId,pid:t.pid,workspacePath:t.workspacePath,command:t.command})));if(d.length>0){e.warn(`[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\u4ECD\u5728\u8FD0\u884C\uFF1A`);for(const t of d)e.warn(` - agentId=${t.agentId}, pid=${t.process.pid}, command=${t.process.command?.slice(0,50)}`);e.info("[runtime-bridge] \u6B63\u5728\u81EA\u52A8\u6E05\u7406\u6240\u6709\u5B64\u513F\u8FDB\u7A0B...");for(const t of d)try{if(t.process.pid)if(process.platform==="win32"){const{execSync:n}=await import("node:child_process");n(`taskkill /PID ${t.process.pid} /T /F`,{encoding:"utf8",timeout:3e3}),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}else process.kill(t.process.pid,"SIGKILL"),e.info(`[runtime-bridge] \u5DF2\u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B: agentId=${t.agentId}, PID=${t.process.pid}`)}catch(n){const c=n;e.warn(`[runtime-bridge] \u81EA\u52A8\u7EC8\u6B62\u5B64\u513F\u8FDB\u7A0B\u5931\u8D25: agentId=${t.agentId}, PID=${t.process.pid}, error=${c.message}`)}await new Promise(t=>setTimeout(t,1e3))}await $([]),e.info(`[runtime-bridge] \u2605 \u542F\u52A8\u6E05\u7406\u5B8C\u6210\uFF0C\u5DF2\u6E05\u7A7A\u6240\u6709\u6301\u4E45\u5316\u4F1A\u8BDD\uFF08\u6E05\u7406\u4E86 ${d.length} \u4E2A\u5B64\u513F\u8FDB\u7A0B\uFF09`)}catch(r){const o=r;e.warn("[runtime-bridge] \u542F\u52A8\u65F6\u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u5931\u8D25:",o.message)}}Qe().catch(r=>{e.warn("[runtime-bridge] \u5B64\u513F\u8FDB\u7A0B\u68C0\u6D4B\u51FA\u9519:",r)}),Ke().catch(r=>{e.warn("[runtime-bridge] \u542F\u52A8\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7\u5931\u8D25:",r)});const i=S();i.use(Ce),i.use(E()),i.use(S.json({limit:"1mb"})),i.use("/runtime",we),i.use("/runtime",ge),i.use("/runtime",ke),i.use("/runtime",oe),i.use("/runtime",Se),i.use("/runtime",ue),i.use("/runtime",q),i.use("/runtime",$e),i.use("/runtime",Re),i.use("/runtime",de),i.use("/runtime",ae),i.use("/runtime",se),i.use("/runtime",Ie),i.use("/runtime",V),i.use("/runtime",ie),i.use("/runtime",te),i.use("/runtime",H),i.use("/runtime",z),i.use("/runtime",Pe),i.use("/runtime",Y),i.use("/runtime",J),i.use("/runtime",ce),i.use("/runtime",me),i.use("/runtime",U),i.use("/runtime",ye),i.use("/runtime",re),i.use("/runtime",ee),i.use("/runtime/computer",Z),i.use("/pty",le),i.use("/",Q),i.use("/api/file-browser",X);function Ve(){const r=P(),o=i.listen(r,()=>{e.info(`[runtime-bridge] listening on ${r}`)});return pe(o),W(o),F(o),o.on("error",s=>{if(s.code==="EADDRINUSE"){e.error(`[runtime-bridge] port ${r} became unavailable after reservation (another process grabbed it concurrently). Set AWS_RUNTIME_BRIDGE_PORT to a free port and restart.`),process.exitCode=1;return}e.error("[runtime-bridge] failed to start server:",s),process.exitCode=1}),o}let C=!1;async function b(r,o,s=!1){if(C){e.info(`[runtime-bridge] \u5DF2\u5728\u5173\u95ED\u4E2D\uFF0C\u5FFD\u7565 ${r}`);return}C=!0,s||R()&&(s=!0,e.info("[runtime-bridge] \u2605 \u68C0\u6D4B\u5230 .preserve-sessions \u6807\u8BB0\u6587\u4EF6\uFF0C\u81EA\u52A8\u5347\u7EA7\u4E3A\u4FDD\u7559\u4F1A\u8BDD\u6A21\u5F0F")),e.info(`[runtime-bridge] \u6536\u5230 ${r} \u4FE1\u53F7\uFF0C\u5F00\u59CB\u4F18\u96C5\u5173\u95ED... (preserveSessions=${s})`);const f=Date.now(),u=We(s);try{const a=h.size;if(u.terminateSdkSessions){e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${a} \u4E2A SDK \u4F1A\u8BDD...`);for(const[t,n]of h.entries())try{const c=n.providerId||"claude-code",g=x.get(c);let p="";try{const m=g.getSessionPid?.(t);m&&(p=` (PID: ${m})`)}catch{}await g.terminateSession(t),e.info(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u5DF2\u7EC8\u6B62${p}`),h.delete(t)}catch(c){const g=c;e.error(`[runtime-bridge] SDK \u4F1A\u8BDD ${t} \u7EC8\u6B62\u5931\u8D25:`,g.message),h.delete(t)}}else e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${a} \u4E2A SDK \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u7EC8\u6B62 Agent \u8FDB\u7A0B`);const l=be.size;u.closePtySessions?(e.info(`[runtime-bridge] \u6B63\u5728\u505C\u6B62 ${l} \u4E2A PTY \u4F1A\u8BDD...`),fe("shutdown")):e.info(`[runtime-bridge] \u2605 \u4FDD\u7559 ${l} \u4E2A PTY \u4F1A\u8BDD\uFF0C\u4E0D\u5728\u91CD\u542F\u6062\u590D\u573A\u666F\u4E2D\u5173\u95ED\u7EC8\u7AEF\u8FDB\u7A0B`);try{const{running:t,stopped:n}=await Ge().stopAll();t>0&&e.info(`[runtime-bridge] \u542F\u52A8\u9879\u8FDB\u7A0B\u5DF2\u505C\u6B62: running=${t}, stopped=${n}`)}catch(t){e.warn("[runtime-bridge] \u505C\u6B62\u542F\u52A8\u9879\u8FDB\u7A0B\u5931\u8D25:",t.message)}e.info("[runtime-bridge] \u6B63\u5728\u505C\u6B62\u5B64\u513F\u8FDB\u7A0B\u76D1\u63A7...");try{const c=(await import("file://"+require("path").join(__dirname,"..","package","acode","dist","background-command-manager.js")).catch(()=>({backgroundCommandManager:null}))).backgroundCommandManager;c&&(e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7406\u540E\u53F0\u547D\u4EE4..."),await c.disposeAll())}catch(t){e.warn("[runtime-bridge] \u540E\u53F0\u547D\u4EE4\u6E05\u7406\u5931\u8D25: %s",t?.message)}if(Le(),u.terminateResidualProcesses&&(e.info("[runtime-bridge] \u7B49\u5F85\u8FDB\u7A0B\u5B8C\u5168\u7EC8\u6B62..."),await new Promise(t=>setTimeout(t,1e3))),u.terminateResidualProcesses)try{const{detectOrphanProcesses:t,terminateProcessTree:n}=await import("./services/process-detector.js"),{loadPersistedSessions:c}=await import("./services/terminal-persistence.js"),g=await c();if(g.length>0){const p=await t(g.map(m=>({agentId:m.agentId,pid:m.pid,workspacePath:m.workspacePath,command:m.command})));if(p.length>0){e.warn(`[runtime-bridge] \u68C0\u6D4B\u5230 ${p.length} \u4E2A\u6B8B\u7559\u8FDB\u7A0B\uFF0C\u6B63\u5728\u5F3A\u5236\u7EC8\u6B62...`);for(const m of p)if(m.process.pid){const v=await n(m.process.pid);e.info(`[runtime-bridge] \u5DF2\u5F3A\u5236\u7EC8\u6B62\u6B8B\u7559\u8FDB\u7A0B\u6811\uFF1AagentId=${m.agentId}, PID=${m.process.pid}, \u7EC8\u6B62\u4E86 ${v.terminated} \u4E2A\u8FDB\u7A0B`)}}}}catch(t){const n=t;e.warn("[runtime-bridge] \u6B8B\u7559\u8FDB\u7A0B\u68C0\u67E5\u5931\u8D25:",n.message)}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u6B8B\u7559\u8FDB\u7A0B\u5F3A\u5236\u7EC8\u6B62\uFF0C\u7B49\u5F85\u8C03\u5EA6\u4E2D\u5FC3\u6062\u590D\u4F1A\u8BDD");if(u.unregisterInstance){e.info("[runtime-bridge] \u6B63\u5728\u6CE8\u9500\u5B9E\u4F8B...");try{await Te()}catch(t){const n=t;e.error("[runtime-bridge] \u6CE8\u9500\u5B9E\u4F8B\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6A21\u5F0F\u8DF3\u8FC7\u5B9E\u4F8B\u6CE8\u9500\uFF0C\u907F\u514D\u8C03\u5EA6\u4E2D\u5FC3\u5C06 Agent \u6807\u8BB0\u4E3A stopped");if(De(),u.stopTunnelClient&&(e.info("[runtime-bridge] \u6B63\u5728\u5173\u95ED\u96A7\u9053\u5BA2\u6237\u7AEF..."),Je()),u.clearPersistedSessions){e.info("[runtime-bridge] \u6B63\u5728\u6E05\u7A7A\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001...");try{await $([])}catch(t){const n=t;e.error("[runtime-bridge] \u6E05\u7A7A\u6301\u4E45\u5316\u72B6\u6001\u5931\u8D25:",n.message)}}else e.info("[runtime-bridge] \u2605 \u4FDD\u7559\u6301\u4E45\u5316\u4F1A\u8BDD\u72B6\u6001\uFF08aws-mcp-server \u91CD\u542F\u6062\u590D\u573A\u666F\uFF09");try{await Ee(),e.info("[runtime-bridge] browser \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] browser \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Fe(),e.info("[runtime-bridge] desktop \u5DE5\u5177\u6808\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] desktop \u5DE5\u5177\u6808\u6E05\u7406\u5931\u8D25:",t.message)}try{await Ne.stopAll(),e.info("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u5DF2\u6E05\u7406")}catch(t){e.warn("[runtime-bridge] \u63D2\u4EF6\u76D1\u542C\u8FDB\u7A0B\u6E05\u7406\u5931\u8D25:",t.message)}const d=Date.now()-f;e.info(`[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u5B8C\u6210 (\u8017\u65F6 ${d}ms)\uFF0C\u505C\u6B62 ${a} SDK \u4F1A\u8BDD`),o.close(()=>{e.info("[runtime-bridge] HTTP \u670D\u52A1\u5668\u5DF2\u5173\u95ED"),process.exit(process.exitCode||0)}),setTimeout(()=>{e.warn("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8D85\u65F6\uFF0C\u5F3A\u5236\u9000\u51FA"),process.exit(1)},15e3)}catch(a){const l=a;e.error("[runtime-bridge] \u4F18\u96C5\u5173\u95ED\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:",l),process.exit(1)}}ze.reconcileZombies().then(r=>{r>0&&e.info(`[runtime-bridge] \u5DF2\u6E05\u7406 ${r} \u4E2A\u50F5\u5C38 sub-agent \u8BB0\u5F55`)}).catch(r=>{e.warn("[runtime-bridge] \u6E05\u7406\u50F5\u5C38 sub-agent \u8BB0\u5F55\u5931\u8D25:",r.message)});const w=Ve(),A=M.join(D.tmpdir(),"agentswork-runtime-bridge",".preserve-sessions");function R(){try{if(T(A)){const r=B(A,"utf-8");return JSON.parse(r).preserveSessions===!0}}catch{}return!1}ne(async(r,o)=>{await b(r,w,o)}),process.on("SIGTERM",()=>{const r=R();b("SIGTERM",w,r)}),process.on("SIGINT",()=>{const r=R();b("SIGINT",w,r)}),process.platform==="win32"&&process.on("SIGBREAK",()=>{const r=R();b("SIGBREAK",w,r)}),process.on("uncaughtException",r=>{e.error("[runtime-bridge] \u672A\u6355\u83B7\u5F02\u5E38:",r),b("uncaughtException",w)}),process.on("unhandledRejection",r=>{e.error("[runtime-bridge] \u672A\u5904\u7406\u7684 Promise \u62D2\u7EDD:",r)});
3
3
 
@@ -1,2 +1,2 @@
1
- import{hasRuntimeBinding as u,validateRuntimeBindingToken as c}from"../services/runtime-binding.js";import{getConfiguredConnectionKeys as f}from"../services/auto-register.js";import{validateSession as d}from"../services/panel-auth.js";function o(n){const t=n.header("X-Runtime-Token");return t?t.trim():(n.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||""}function m(n){return n?!!f().includes(n):!1}function s(n){const t=String(n||"").trim();return c(t)||m(t)}function l(n,t,e){const i=o(n);if(s(i)){e();return}if(!u()){t.status(401).json({error:"runtime_bridge_unpaired",message:"Runtime bridge is not paired. Add this instance from the panel first."});return}t.status(401).json({error:"unauthorized"})}function x(n,t,e){const i=n.ip||n.socket.remoteAddress||"";if(i==="127.0.0.1"||i==="::1"||i==="::ffff:127.0.0.1"){e();return}l(n,t,e)}const k="panel_sid";function p(n){const t={};if(!n)return t;for(const e of n.split(";")){const i=e.indexOf("=");if(i===-1)continue;const r=e.slice(0,i).trim(),a=e.slice(i+1).trim();r&&(t[r]=a)}return t}function h(n){return p(n.headers.cookie)[k]}function z(n,t,e){const i=o(n);if(s(i)){e();return}const r=h(n);if(r&&d(r)){e();return}t.status(401).json({error:"unauthorized"})}export{s as isRuntimeTokenValid,l as validateToken,x as validateTokenOrLoopback,z as validateTokenOrPanelSession};
1
+ import{getConfiguredConnectionKeys as u}from"../services/auto-register.js";import{validateSession as c}from"../services/panel-auth.js";import{hasRuntimeBinding as f,validateRuntimeBindingToken as d}from"../services/runtime-binding.js";function o(n){const t=n.header("X-Runtime-Token");return t?t.trim():(n.header("Authorization")||"").match(/^Bearer\s+(.+)$/i)?.[1]?.trim()||""}function m(n){return n?!!u().includes(n):!1}function s(n){const t=String(n||"").trim();return d(t)||m(t)}function l(n,t,e){const i=o(n);if(s(i)){e();return}if(!f()){t.status(401).json({error:"runtime_bridge_unpaired",message:"Runtime bridge is not paired. Add this instance from the panel first."});return}t.status(401).json({error:"unauthorized"})}function x(n,t,e){const i=n.ip||n.socket.remoteAddress||"";if(i==="127.0.0.1"||i==="::1"||i==="::ffff:127.0.0.1"){e();return}l(n,t,e)}const k="panel_sid";function p(n){const t={};if(!n)return t;for(const e of n.split(";")){const i=e.indexOf("=");if(i===-1)continue;const r=e.slice(0,i).trim(),a=e.slice(i+1).trim();r&&(t[r]=a)}return t}function h(n){return p(n.headers.cookie)[k]}function z(n,t,e){const i=o(n);if(s(i)){e();return}const r=h(n);if(r&&c(r)){e();return}t.status(401).json({error:"unauthorized"})}export{s as isRuntimeTokenValid,l as validateToken,x as validateTokenOrLoopback,z as validateTokenOrPanelSession};
2
2
 
@@ -1,5 +1,5 @@
1
- import type { ScreenCapture } from "./screen-capture.js";
2
1
  import type { InputBackend } from "./input-backends/interface.js";
2
+ import type { ScreenCapture } from "./screen-capture.js";
3
3
  import type { ScreenInfo, ScreenshotResult, AppInfo, UIElement } from "./types.js";
4
4
 
5
5
  export declare class ComputerControl {
@@ -1,6 +1,6 @@
1
1
  import type { Server } from "node:http";
2
- import { SessionManager } from "./session-manager.js";
3
2
  import { PermissionManager } from "./permission-manager.js";
3
+ import { SessionManager } from "./session-manager.js";
4
4
  declare const permissionManager: PermissionManager;
5
5
  declare const sessionManager: SessionManager;
6
6
  export declare function attachRemoteDesktopWebSocketServer(server: Server): void;
@@ -1,4 +1,4 @@
1
- import{WebSocketServer as C}from"ws";import{SessionManager as F}from"./session-manager.js";import{PermissionManager as A}from"./permission-manager.js";import{encodeFrame as D}from"./frame-encode.js";import{getSharpLoadStatus as M}from"./screen-capture.js";import{isRuntimeTokenValid as T}from"../middleware/auth.js";import{isUpgradeAllowed as v}from"../services/access-control.js";import{getFrameBufferLimit as I,shouldDropFrameForBackpressure as P}from"./frame-backpressure.js";const h=new A,i=new F(h);function W(n,o){const t=o.searchParams.get("token");if(t)return t;const e=n.headers["x-runtime-token"];if(typeof e=="string")return e;const s=n.headers.authorization;return typeof s=="string"&&s.startsWith("Bearer ")?s.slice(7):""}function l(n,o){n.readyState===n.OPEN&&n.send(JSON.stringify(o))}function x(n,o,t){switch(t.type){case"remote-desktop:input":{const e=t.data;i.handleInput(o,e).catch(s=>{l(n,{type:"remote-desktop:error",sessionId:o,data:{error:String(s)}})});break}case"remote-desktop:stop":{i.closeSession(o),n.close();break}case"remote-desktop:quality":{const e=i.getSession(o);e&&t.data&&e.screenCapture.setQuality(t.data.quality,t.data.fps);break}case"remote-desktop:control-mode":{const e=i.getSession(o);e&&t.data&&(t.data.enabled?e.enableControl().catch(s=>{console.warn("[remote-desktop] enableControl failed:",s)}):e.stopInputBackend());break}case"remote-desktop:switch-screen":{const e=i.getSession(o);e&&t.data&&e.switchScreen(t.data.screenId||null).catch(s=>{l(n,{type:"remote-desktop:error",sessionId:o,data:{error:String(s)}})});break}case"remote-desktop:ping":{l(n,{type:"remote-desktop:pong",sessionId:o,data:t.data});break}case"remote-desktop:resync":{const e=i.getSession(o);e&&e.screenCapture.requestFullFrame();break}}}function q(n){const o=new C({noServer:!0});n.on("upgrade",(t,e,s)=>{if(!v(t,e))return;const S=new URL(t.url||"/",`http://${t.headers.host}`);if(S.pathname!=="/remote-desktop")return;const k=W(t,S);if(!T(k)&&!h.validateToken(k)){e.write(`HTTP/1.1 401 Unauthorized\r
1
+ import{WebSocketServer as C}from"ws";import{isRuntimeTokenValid as F}from"../middleware/auth.js";import{isUpgradeAllowed as A}from"../services/access-control.js";import{getFrameBufferLimit as D,shouldDropFrameForBackpressure as M}from"./frame-backpressure.js";import{encodeFrame as T}from"./frame-encode.js";import{PermissionManager as v}from"./permission-manager.js";import{getSharpLoadStatus as I}from"./screen-capture.js";import{SessionManager as P}from"./session-manager.js";const h=new v,i=new P(h);function W(n,o){const t=o.searchParams.get("token");if(t)return t;const e=n.headers["x-runtime-token"];if(typeof e=="string")return e;const s=n.headers.authorization;return typeof s=="string"&&s.startsWith("Bearer ")?s.slice(7):""}function l(n,o){n.readyState===n.OPEN&&n.send(JSON.stringify(o))}function x(n,o,t){switch(t.type){case"remote-desktop:input":{const e=t.data;i.handleInput(o,e).catch(s=>{l(n,{type:"remote-desktop:error",sessionId:o,data:{error:String(s)}})});break}case"remote-desktop:stop":{i.closeSession(o),n.close();break}case"remote-desktop:quality":{const e=i.getSession(o);e&&t.data&&e.screenCapture.setQuality(t.data.quality,t.data.fps);break}case"remote-desktop:control-mode":{const e=i.getSession(o);e&&t.data&&(t.data.enabled?e.enableControl().catch(s=>{console.warn("[remote-desktop] enableControl failed:",s)}):e.stopInputBackend());break}case"remote-desktop:switch-screen":{const e=i.getSession(o);e&&t.data&&e.switchScreen(t.data.screenId||null).catch(s=>{l(n,{type:"remote-desktop:error",sessionId:o,data:{error:String(s)}})});break}case"remote-desktop:ping":{l(n,{type:"remote-desktop:pong",sessionId:o,data:t.data});break}case"remote-desktop:resync":{const e=i.getSession(o);e&&e.screenCapture.requestFullFrame();break}}}function q(n){const o=new C({noServer:!0});n.on("upgrade",(t,e,s)=>{if(!A(t,e))return;const S=new URL(t.url||"/",`http://${t.headers.host}`);if(S.pathname!=="/remote-desktop")return;const k=W(t,S);if(!F(k)&&!h.validateToken(k)){e.write(`HTTP/1.1 401 Unauthorized\r
2
2
  \r
3
- `),e.destroy();return}o.handleUpgrade(t,e,s,r=>{const b=S.searchParams.get("agentId")||"default";i.createSession(b,k).then(a=>{const c=i.getSession(a.sessionId);if(c?.attachWebSocket(r),l(r,{type:"remote-desktop:start-result",sessionId:a.sessionId,data:{screens:a.screens,permissions:a.permissions}}),c){let d=0,p=0,m=Date.now();const $=setInterval(()=>{const f=Date.now()-m,u=c.screenCapture.frameStats;console.log(`[remote-desktop] frames: sent=${d} dropped=${p} bufferedAmount=${r.bufferedAmount} silent=${f}ms quality=${c.screenCapture.getQuality()} sharp=${M()} full=${u.full} partial=${u.partial} null=${u.null} sharpFail=${u.sharpFail}`),d=0,p=0,c.screenCapture.resetFrameStats()},5e3);let g=0;c.startFrameLoop(y=>{if(r.readyState===r.OPEN&&!P(r.bufferedAmount,I(c.screenCapture.getQuality())))return r.send(D(y,g)),g=g+1>>>0,d++,m=Date.now(),!0;p++,c.screenCapture.notifyFrameDropped();const f=Date.now()-m;return f>3e3&&console.warn(`[remote-desktop] \u8FDE\u7EED ${f}ms \u65E0\u5E27\u53D1\u9001 bufferedAmount=${r.bufferedAmount} readyState=${r.readyState}`),!1}),r.on("close",()=>clearInterval($))}r.on("message",d=>{try{const p=d.toString();if(p.startsWith("{")){const m=JSON.parse(p);x(r,a.sessionId,m)}}catch{}}),r.on("close",()=>{i.closeSession(a.sessionId)}),r.on("error",()=>{i.closeSession(a.sessionId)})}).catch(a=>{console.error("[remote-desktop] createSession failed:",a),l(r,{type:"remote-desktop:error",sessionId:"",data:{error:String(a)}}),r.close(1011,String(a))})})})}export{q as attachRemoteDesktopWebSocketServer,h as permissionManager,i as sessionManager};
3
+ `),e.destroy();return}o.handleUpgrade(t,e,s,r=>{const b=S.searchParams.get("agentId")||"default";i.createSession(b,k).then(a=>{const c=i.getSession(a.sessionId);if(c?.attachWebSocket(r),l(r,{type:"remote-desktop:start-result",sessionId:a.sessionId,data:{screens:a.screens,permissions:a.permissions}}),c){let d=0,p=0,m=Date.now();const $=setInterval(()=>{const f=Date.now()-m,u=c.screenCapture.frameStats;console.warn(`[remote-desktop] frames: sent=${d} dropped=${p} bufferedAmount=${r.bufferedAmount} silent=${f}ms quality=${c.screenCapture.getQuality()} sharp=${I()} full=${u.full} partial=${u.partial} null=${u.null} sharpFail=${u.sharpFail}`),d=0,p=0,c.screenCapture.resetFrameStats()},5e3);let g=0;c.startFrameLoop(y=>{if(r.readyState===r.OPEN&&!M(r.bufferedAmount,D(c.screenCapture.getQuality())))return r.send(T(y,g)),g=g+1>>>0,d++,m=Date.now(),!0;p++,c.screenCapture.notifyFrameDropped();const f=Date.now()-m;return f>3e3&&console.warn(`[remote-desktop] \u8FDE\u7EED ${f}ms \u65E0\u5E27\u53D1\u9001 bufferedAmount=${r.bufferedAmount} readyState=${r.readyState}`),!1}),r.on("close",()=>clearInterval($))}r.on("message",d=>{try{const p=d.toString();if(p.startsWith("{")){const m=JSON.parse(p);x(r,a.sessionId,m)}}catch{}}),r.on("close",()=>{i.closeSession(a.sessionId)}),r.on("error",()=>{i.closeSession(a.sessionId)})}).catch(a=>{console.error("[remote-desktop] createSession failed:",a),l(r,{type:"remote-desktop:error",sessionId:"",data:{error:String(a)}}),r.close(1011,String(a))})})})}export{q as attachRemoteDesktopWebSocketServer,h as permissionManager,i as sessionManager};
4
4
 
@@ -1,8 +1,8 @@
1
1
  import type { WebSocket } from "ws";
2
- import { ScreenCapture } from "./screen-capture.js";
2
+ import { ComputerControl } from "./computer-control.js";
3
3
  import { InputDispatcher } from "./input-dispatcher.js";
4
4
  import { PermissionManager } from "./permission-manager.js";
5
- import { ComputerControl } from "./computer-control.js";
5
+ import { ScreenCapture } from "./screen-capture.js";
6
6
  import type { InputMessage, RemoteDesktopCapability, ScreenInfo, StartResult, CaptureFrame } from "./types.js";
7
7
  export declare class RemoteDesktopSession {
8
8