whale-code 6.5.4 → 6.5.6

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 (853) hide show
  1. package/README.md +39 -31
  2. package/bin/{swagmanager-mcp.js → whale-code.js} +17 -2
  3. package/dist/cli/app.js +148 -72
  4. package/dist/cli/app.js.map +1 -0
  5. package/dist/cli/chat/AgentSelector.js +105 -10
  6. package/dist/cli/chat/AgentSelector.js.map +1 -0
  7. package/dist/cli/chat/ChatApp.d.ts +31 -0
  8. package/dist/cli/chat/ChatApp.js +539 -286
  9. package/dist/cli/chat/ChatApp.js.map +1 -0
  10. package/dist/cli/chat/ChatInput.js +1088 -770
  11. package/dist/cli/chat/ChatInput.js.map +1 -0
  12. package/dist/cli/chat/MarkdownText.js +39 -14
  13. package/dist/cli/chat/MarkdownText.js.map +1 -0
  14. package/dist/cli/chat/MemoryManager.js +181 -46
  15. package/dist/cli/chat/MemoryManager.js.map +1 -0
  16. package/dist/cli/chat/MessageList.d.ts +2 -3
  17. package/dist/cli/chat/MessageList.js +186 -45
  18. package/dist/cli/chat/MessageList.js.map +1 -0
  19. package/dist/cli/chat/ModelSelector.js +282 -63
  20. package/dist/cli/chat/ModelSelector.js.map +1 -0
  21. package/dist/cli/chat/NodeManager.js +165 -75
  22. package/dist/cli/chat/NodeManager.js.map +1 -0
  23. package/dist/cli/chat/NodeSelector.js +171 -30
  24. package/dist/cli/chat/NodeSelector.js.map +1 -0
  25. package/dist/cli/chat/PlanApproval.js +281 -57
  26. package/dist/cli/chat/PlanApproval.js.map +1 -0
  27. package/dist/cli/chat/RewindViewer.js +559 -144
  28. package/dist/cli/chat/RewindViewer.js.map +1 -0
  29. package/dist/cli/chat/SessionManager.js +137 -30
  30. package/dist/cli/chat/SessionManager.js.map +1 -0
  31. package/dist/cli/chat/SlashMenu.js +293 -164
  32. package/dist/cli/chat/SlashMenu.js.map +1 -0
  33. package/dist/cli/chat/StatusBar.js +172 -9
  34. package/dist/cli/chat/StatusBar.js.map +1 -0
  35. package/dist/cli/chat/StoreSelector.js +147 -18
  36. package/dist/cli/chat/StoreSelector.js.map +1 -0
  37. package/dist/cli/chat/StreamingText.d.ts +1 -5
  38. package/dist/cli/chat/StreamingText.js +22 -7
  39. package/dist/cli/chat/StreamingText.js.map +1 -0
  40. package/dist/cli/chat/SubagentPanel.d.ts +1 -2
  41. package/dist/cli/chat/SubagentPanel.js +612 -72
  42. package/dist/cli/chat/SubagentPanel.js.map +1 -0
  43. package/dist/cli/chat/TeamPanel.d.ts +1 -0
  44. package/dist/cli/chat/TeamPanel.js +230 -30
  45. package/dist/cli/chat/TeamPanel.js.map +1 -0
  46. package/dist/cli/chat/ThemeSelector.js +84 -24
  47. package/dist/cli/chat/ThemeSelector.js.map +1 -0
  48. package/dist/cli/chat/ToolIndicator.js +1476 -371
  49. package/dist/cli/chat/ToolIndicator.js.map +1 -0
  50. package/dist/cli/chat/hooks/useAgentLoop.d.ts +1 -0
  51. package/dist/cli/chat/hooks/useAgentLoop.js +481 -367
  52. package/dist/cli/chat/hooks/useAgentLoop.js.map +1 -0
  53. package/dist/cli/chat/hooks/useSlashCommands.d.ts +3 -14
  54. package/dist/cli/chat/hooks/useSlashCommands.js +744 -572
  55. package/dist/cli/chat/hooks/useSlashCommands.js.map +1 -0
  56. package/dist/cli/commands/config-cmd.js +56 -57
  57. package/dist/cli/commands/config-cmd.js.map +1 -0
  58. package/dist/cli/commands/db.js +184 -169
  59. package/dist/cli/commands/db.js.map +1 -0
  60. package/dist/cli/commands/doctor.js +212 -122
  61. package/dist/cli/commands/doctor.js.map +1 -0
  62. package/dist/cli/commands/init.js +211 -244
  63. package/dist/cli/commands/init.js.map +1 -0
  64. package/dist/cli/commands/mcp.js +127 -122
  65. package/dist/cli/commands/mcp.js.map +1 -0
  66. package/dist/cli/login/LoginApp.js +355 -141
  67. package/dist/cli/login/LoginApp.js.map +1 -0
  68. package/dist/cli/print-mode.js +196 -177
  69. package/dist/cli/print-mode.js.map +1 -0
  70. package/dist/cli/serve-mode.js +615 -530
  71. package/dist/cli/serve-mode.js.map +1 -0
  72. package/dist/cli/services/agent-config.d.ts +29 -0
  73. package/dist/cli/services/agent-config.js +91 -0
  74. package/dist/cli/services/agent-config.js.map +1 -0
  75. package/dist/cli/services/agent-definitions.d.ts +4 -1
  76. package/dist/cli/services/agent-definitions.js +97 -56
  77. package/dist/cli/services/agent-definitions.js.map +1 -0
  78. package/dist/cli/services/agent-events.js +225 -162
  79. package/dist/cli/services/agent-events.js.map +1 -0
  80. package/dist/cli/services/agent-loop.js +978 -669
  81. package/dist/cli/services/agent-loop.js.map +1 -0
  82. package/dist/cli/services/agent-worker-base.d.ts +35 -5
  83. package/dist/cli/services/agent-worker-base.js +337 -153
  84. package/dist/cli/services/agent-worker-base.js.map +1 -0
  85. package/dist/cli/services/api-retry.js +69 -64
  86. package/dist/cli/services/api-retry.js.map +1 -0
  87. package/dist/cli/services/auth-service.d.ts +3 -3
  88. package/dist/cli/services/auth-service.js +209 -132
  89. package/dist/cli/services/auth-service.js.map +1 -0
  90. package/dist/cli/services/background-processes.js +343 -267
  91. package/dist/cli/services/background-processes.js.map +1 -0
  92. package/dist/cli/services/browser-auth.d.ts +2 -2
  93. package/dist/cli/services/browser-auth.js +159 -118
  94. package/dist/cli/services/browser-auth.js.map +1 -0
  95. package/dist/cli/services/claude-md-loader.js +40 -36
  96. package/dist/cli/services/claude-md-loader.js.map +1 -0
  97. package/dist/cli/services/config-store.d.ts +9 -4
  98. package/dist/cli/services/config-store.js +164 -117
  99. package/dist/cli/services/config-store.js.map +1 -0
  100. package/dist/cli/services/debug-log.d.ts +1 -1
  101. package/dist/cli/services/debug-log.js +34 -35
  102. package/dist/cli/services/debug-log.js.map +1 -0
  103. package/dist/cli/services/env-detect.d.ts +7 -0
  104. package/dist/cli/services/env-detect.js +9 -0
  105. package/dist/cli/services/env-detect.js.map +1 -0
  106. package/dist/cli/services/error-logger.d.ts +2 -3
  107. package/dist/cli/services/error-logger.js +189 -180
  108. package/dist/cli/services/error-logger.js.map +1 -0
  109. package/dist/cli/services/file-history.d.ts +1 -1
  110. package/dist/cli/services/file-history.js +50 -54
  111. package/dist/cli/services/file-history.js.map +1 -0
  112. package/dist/cli/services/format-server-response.js +332 -372
  113. package/dist/cli/services/format-server-response.js.map +1 -0
  114. package/dist/cli/services/git-context.js +61 -45
  115. package/dist/cli/services/git-context.js.map +1 -0
  116. package/dist/cli/services/hooks.d.ts +2 -2
  117. package/dist/cli/services/hooks.js +195 -180
  118. package/dist/cli/services/hooks.js.map +1 -0
  119. package/dist/cli/services/ink-incremental.d.ts +19 -0
  120. package/dist/cli/services/ink-incremental.js +59 -0
  121. package/dist/cli/services/ink-incremental.js.map +1 -0
  122. package/dist/cli/services/ink-resize-fix.js +54 -44
  123. package/dist/cli/services/ink-resize-fix.js.map +1 -0
  124. package/dist/cli/services/ink-sync-output.d.ts +12 -0
  125. package/dist/cli/services/ink-sync-output.js +16 -0
  126. package/dist/cli/services/ink-sync-output.js.map +1 -0
  127. package/dist/cli/services/interactive-tools.js +268 -212
  128. package/dist/cli/services/interactive-tools.js.map +1 -0
  129. package/dist/cli/services/keybinding-manager.d.ts +11 -1
  130. package/dist/cli/services/keybinding-manager.js +126 -63
  131. package/dist/cli/services/keybinding-manager.js.map +1 -0
  132. package/dist/cli/services/local-tools.d.ts +1 -1
  133. package/dist/cli/services/local-tools.js +939 -656
  134. package/dist/cli/services/local-tools.js.map +1 -0
  135. package/dist/cli/services/lsp-manager.js +757 -594
  136. package/dist/cli/services/lsp-manager.js.map +1 -0
  137. package/dist/cli/services/mcp-client.d.ts +1 -1
  138. package/dist/cli/services/mcp-client.js +173 -134
  139. package/dist/cli/services/mcp-client.js.map +1 -0
  140. package/dist/cli/services/memory-manager.js +53 -40
  141. package/dist/cli/services/memory-manager.js.map +1 -0
  142. package/dist/cli/services/model-manager.js +55 -40
  143. package/dist/cli/services/model-manager.js.map +1 -0
  144. package/dist/cli/services/model-router.js +115 -85
  145. package/dist/cli/services/model-router.js.map +1 -0
  146. package/dist/cli/services/paths.d.ts +30 -0
  147. package/dist/cli/services/paths.js +81 -0
  148. package/dist/cli/services/paths.js.map +1 -0
  149. package/dist/cli/services/permission-modes.js +32 -25
  150. package/dist/cli/services/permission-modes.js.map +1 -0
  151. package/dist/cli/services/rewind.js +182 -168
  152. package/dist/cli/services/rewind.js.map +1 -0
  153. package/dist/cli/services/ripgrep.js +115 -115
  154. package/dist/cli/services/ripgrep.js.map +1 -0
  155. package/dist/cli/services/sandbox.d.ts +1 -1
  156. package/dist/cli/services/sandbox.js +58 -37
  157. package/dist/cli/services/sandbox.js.map +1 -0
  158. package/dist/cli/services/server-tools.js +738 -565
  159. package/dist/cli/services/server-tools.js.map +1 -0
  160. package/dist/cli/services/session-persistence.js +69 -74
  161. package/dist/cli/services/session-persistence.js.map +1 -0
  162. package/dist/cli/services/subagent-worker.js +42 -27
  163. package/dist/cli/services/subagent-worker.js.map +1 -0
  164. package/dist/cli/services/subagent.d.ts +2 -0
  165. package/dist/cli/services/subagent.js +606 -430
  166. package/dist/cli/services/subagent.js.map +1 -0
  167. package/dist/cli/services/system-prompt.js +86 -78
  168. package/dist/cli/services/system-prompt.js.map +1 -0
  169. package/dist/cli/services/task-decomposer.d.ts +1 -1
  170. package/dist/cli/services/task-decomposer.js +172 -139
  171. package/dist/cli/services/task-decomposer.js.map +1 -0
  172. package/dist/cli/services/team-lead.d.ts +2 -2
  173. package/dist/cli/services/team-lead.js +727 -529
  174. package/dist/cli/services/team-lead.js.map +1 -0
  175. package/dist/cli/services/team-state.js +319 -319
  176. package/dist/cli/services/team-state.js.map +1 -0
  177. package/dist/cli/services/teammate.d.ts +8 -2
  178. package/dist/cli/services/teammate.js +862 -560
  179. package/dist/cli/services/teammate.js.map +1 -0
  180. package/dist/cli/services/telemetry.d.ts +6 -1
  181. package/dist/cli/services/telemetry.js +180 -157
  182. package/dist/cli/services/telemetry.js.map +1 -0
  183. package/dist/cli/services/tools/agent-tools.d.ts +3 -3
  184. package/dist/cli/services/tools/agent-tools.js +480 -322
  185. package/dist/cli/services/tools/agent-tools.js.map +1 -0
  186. package/dist/cli/services/tools/file-ops.js +563 -450
  187. package/dist/cli/services/tools/file-ops.js.map +1 -0
  188. package/dist/cli/services/tools/search-tools.js +231 -162
  189. package/dist/cli/services/tools/search-tools.js.map +1 -0
  190. package/dist/cli/services/tools/shell-exec.js +197 -151
  191. package/dist/cli/services/tools/shell-exec.js.map +1 -0
  192. package/dist/cli/services/tools/task-manager.js +206 -173
  193. package/dist/cli/services/tools/task-manager.js.map +1 -0
  194. package/dist/cli/services/tools/web-tools.js +388 -341
  195. package/dist/cli/services/tools/web-tools.js.map +1 -0
  196. package/dist/cli/setup/SetupApp.d.ts +2 -2
  197. package/dist/cli/setup/SetupApp.js +608 -160
  198. package/dist/cli/setup/SetupApp.js.map +1 -0
  199. package/dist/cli/shared/ErrorBoundary.d.ts +22 -0
  200. package/dist/cli/shared/ErrorBoundary.js +73 -0
  201. package/dist/cli/shared/ErrorBoundary.js.map +1 -0
  202. package/dist/cli/shared/MatrixIntro.js +66 -69
  203. package/dist/cli/shared/MatrixIntro.js.map +1 -0
  204. package/dist/cli/shared/SpinnerSlot.d.ts +14 -0
  205. package/dist/cli/shared/SpinnerSlot.js +63 -0
  206. package/dist/cli/shared/SpinnerSlot.js.map +1 -0
  207. package/dist/cli/shared/Theme.d.ts +1 -1
  208. package/dist/cli/shared/Theme.js +136 -92
  209. package/dist/cli/shared/Theme.js.map +1 -0
  210. package/dist/cli/shared/WhaleBanner.js +99 -11
  211. package/dist/cli/shared/WhaleBanner.js.map +1 -0
  212. package/dist/cli/shared/markdown.d.ts +3 -1
  213. package/dist/cli/shared/markdown.js +736 -674
  214. package/dist/cli/shared/markdown.js.map +1 -0
  215. package/dist/cli/shared/marked-terminal.d.js +2 -0
  216. package/dist/cli/shared/marked-terminal.d.js.map +1 -0
  217. package/dist/cli/shared/theme-manager.js +99 -90
  218. package/dist/cli/shared/theme-manager.js.map +1 -0
  219. package/dist/cli/shared/theme-presets.js +256 -254
  220. package/dist/cli/shared/theme-presets.js.map +1 -0
  221. package/dist/cli/status/StatusApp.js +235 -86
  222. package/dist/cli/status/StatusApp.js.map +1 -0
  223. package/dist/cli/stores/StoreApp.js +275 -65
  224. package/dist/cli/stores/StoreApp.js.map +1 -0
  225. package/dist/index.d.ts +2 -2
  226. package/dist/index.js +509 -396
  227. package/dist/index.js.map +1 -0
  228. package/dist/local-agent/connection.d.ts +2 -2
  229. package/dist/local-agent/connection.js +352 -293
  230. package/dist/local-agent/connection.js.map +1 -0
  231. package/dist/local-agent/discovery.js +259 -122
  232. package/dist/local-agent/discovery.js.map +1 -0
  233. package/dist/local-agent/executor.js +216 -193
  234. package/dist/local-agent/executor.js.map +1 -0
  235. package/dist/local-agent/index.d.ts +2 -2
  236. package/dist/local-agent/index.js +156 -156
  237. package/dist/local-agent/index.js.map +1 -0
  238. package/dist/node/adapters/base.js +18 -8
  239. package/dist/node/adapters/base.js.map +1 -0
  240. package/dist/node/adapters/discord.js +286 -275
  241. package/dist/node/adapters/discord.js.map +1 -0
  242. package/dist/node/adapters/email.js +189 -202
  243. package/dist/node/adapters/email.js.map +1 -0
  244. package/dist/node/adapters/imessage.js +145 -142
  245. package/dist/node/adapters/imessage.js.map +1 -0
  246. package/dist/node/adapters/slack.js +237 -236
  247. package/dist/node/adapters/slack.js.map +1 -0
  248. package/dist/node/adapters/sms.js +149 -151
  249. package/dist/node/adapters/sms.js.map +1 -0
  250. package/dist/node/adapters/telegram.js +88 -92
  251. package/dist/node/adapters/telegram.js.map +1 -0
  252. package/dist/node/adapters/webchat.js +160 -136
  253. package/dist/node/adapters/webchat.js.map +1 -0
  254. package/dist/node/adapters/whatsapp.js +212 -215
  255. package/dist/node/adapters/whatsapp.js.map +1 -0
  256. package/dist/node/cli.js +884 -653
  257. package/dist/node/cli.js.map +1 -0
  258. package/dist/node/config.js +20 -18
  259. package/dist/node/config.js.map +1 -0
  260. package/dist/node/gateway-client.js +191 -181
  261. package/dist/node/gateway-client.js.map +1 -0
  262. package/dist/node/portal/clipboard.js +161 -130
  263. package/dist/node/portal/clipboard.js.map +1 -0
  264. package/dist/node/portal/discovery.js +51 -45
  265. package/dist/node/portal/discovery.js.map +1 -0
  266. package/dist/node/portal/forward.js +64 -58
  267. package/dist/node/portal/forward.js.map +1 -0
  268. package/dist/node/portal/index.js +246 -221
  269. package/dist/node/portal/index.js.map +1 -0
  270. package/dist/node/portal/multiplexer.js +192 -182
  271. package/dist/node/portal/multiplexer.js.map +1 -0
  272. package/dist/node/portal/permissions.js +102 -70
  273. package/dist/node/portal/permissions.js.map +1 -0
  274. package/dist/node/portal/protocol.js +153 -116
  275. package/dist/node/portal/protocol.js.map +1 -0
  276. package/dist/node/portal/screen.js +80 -69
  277. package/dist/node/portal/screen.js.map +1 -0
  278. package/dist/node/portal/session.js +124 -117
  279. package/dist/node/portal/session.js.map +1 -0
  280. package/dist/node/portal/shell.js +140 -113
  281. package/dist/node/portal/shell.js.map +1 -0
  282. package/dist/node/portal/stream.js +77 -75
  283. package/dist/node/portal/stream.js.map +1 -0
  284. package/dist/node/portal/transfer.js +190 -167
  285. package/dist/node/portal/transfer.js.map +1 -0
  286. package/dist/node/portal/ui.js +124 -99
  287. package/dist/node/portal/ui.js.map +1 -0
  288. package/dist/node/remote-desktop/compile-helper.js +50 -45
  289. package/dist/node/remote-desktop/compile-helper.js.map +1 -0
  290. package/dist/node/remote-desktop/index.js +215 -187
  291. package/dist/node/remote-desktop/index.js.map +1 -0
  292. package/dist/node/remote-desktop/protocol.js +45 -29
  293. package/dist/node/remote-desktop/protocol.js.map +1 -0
  294. package/dist/node/runtime.js +493 -410
  295. package/dist/node/runtime.js.map +1 -0
  296. package/dist/server/handlers/__test-utils__/test-db.js +39 -89
  297. package/dist/server/handlers/__test-utils__/test-db.js.map +1 -0
  298. package/dist/server/handlers/analytics.js +467 -261
  299. package/dist/server/handlers/analytics.js.map +1 -0
  300. package/dist/server/handlers/api-docs.d.ts +6 -0
  301. package/dist/server/handlers/api-docs.js +1613 -0
  302. package/dist/server/handlers/api-docs.js.map +1 -0
  303. package/dist/server/handlers/api-keys.js +295 -232
  304. package/dist/server/handlers/api-keys.js.map +1 -0
  305. package/dist/server/handlers/billing.js +330 -239
  306. package/dist/server/handlers/billing.js.map +1 -0
  307. package/dist/server/handlers/browser.js +468 -395
  308. package/dist/server/handlers/browser.js.map +1 -0
  309. package/dist/server/handlers/catalog.js +1377 -978
  310. package/dist/server/handlers/catalog.js.map +1 -0
  311. package/dist/server/handlers/clickhouse.js +157 -109
  312. package/dist/server/handlers/clickhouse.js.map +1 -0
  313. package/dist/server/handlers/comms.d.ts +0 -53
  314. package/dist/server/handlers/comms.js +1443 -970
  315. package/dist/server/handlers/comms.js.map +1 -0
  316. package/dist/server/handlers/creations.js +461 -394
  317. package/dist/server/handlers/creations.js.map +1 -0
  318. package/dist/server/handlers/crm.js +1082 -791
  319. package/dist/server/handlers/crm.js.map +1 -0
  320. package/dist/server/handlers/discovery.js +251 -232
  321. package/dist/server/handlers/discovery.js.map +1 -0
  322. package/dist/server/handlers/embeddings.js +241 -164
  323. package/dist/server/handlers/embeddings.js.map +1 -0
  324. package/dist/server/handlers/enrichment.js +887 -718
  325. package/dist/server/handlers/enrichment.js.map +1 -0
  326. package/dist/server/handlers/image-gen.js +467 -376
  327. package/dist/server/handlers/image-gen.js.map +1 -0
  328. package/dist/server/handlers/inventory.js +797 -424
  329. package/dist/server/handlers/inventory.js.map +1 -0
  330. package/dist/server/handlers/kali.js +272 -230
  331. package/dist/server/handlers/kali.js.map +1 -0
  332. package/dist/server/handlers/llm-providers.js +803 -580
  333. package/dist/server/handlers/llm-providers.js.map +1 -0
  334. package/dist/server/handlers/local-agent.js +133 -105
  335. package/dist/server/handlers/local-agent.js.map +1 -0
  336. package/dist/server/handlers/media.js +1179 -857
  337. package/dist/server/handlers/media.js.map +1 -0
  338. package/dist/server/handlers/meta-ads.js +2669 -2093
  339. package/dist/server/handlers/meta-ads.js.map +1 -0
  340. package/dist/server/handlers/nodes.js +1321 -913
  341. package/dist/server/handlers/nodes.js.map +1 -0
  342. package/dist/server/handlers/operations.js +183 -157
  343. package/dist/server/handlers/operations.js.map +1 -0
  344. package/dist/server/handlers/platform.js +346 -210
  345. package/dist/server/handlers/platform.js.map +1 -0
  346. package/dist/server/handlers/remove-bg.js +118 -86
  347. package/dist/server/handlers/remove-bg.js.map +1 -0
  348. package/dist/server/handlers/storefront.js +586 -446
  349. package/dist/server/handlers/storefront.js.map +1 -0
  350. package/dist/server/handlers/supply-chain.js +546 -326
  351. package/dist/server/handlers/supply-chain.js.map +1 -0
  352. package/dist/server/handlers/transcription.js +106 -97
  353. package/dist/server/handlers/transcription.js.map +1 -0
  354. package/dist/server/handlers/video-gen.js +593 -424
  355. package/dist/server/handlers/video-gen.js.map +1 -0
  356. package/dist/server/handlers/voice.js +1458 -1017
  357. package/dist/server/handlers/voice.js.map +1 -0
  358. package/dist/server/handlers/workflow-steps.js +2837 -2116
  359. package/dist/server/handlers/workflow-steps.js.map +1 -0
  360. package/dist/server/handlers/workflows.js +1630 -933
  361. package/dist/server/handlers/workflows.js.map +1 -0
  362. package/dist/server/index.js +3166 -2390
  363. package/dist/server/index.js.map +1 -0
  364. package/dist/server/lib/batch-client.js +471 -409
  365. package/dist/server/lib/batch-client.js.map +1 -0
  366. package/dist/server/lib/clickhouse-buffer.js +118 -104
  367. package/dist/server/lib/clickhouse-buffer.js.map +1 -0
  368. package/dist/server/lib/clickhouse-client.js +107 -107
  369. package/dist/server/lib/clickhouse-client.js.map +1 -0
  370. package/dist/server/lib/coa-renderer.js +1786 -356
  371. package/dist/server/lib/coa-renderer.js.map +1 -0
  372. package/dist/server/lib/code-worker-pool.js +227 -177
  373. package/dist/server/lib/code-worker-pool.js.map +1 -0
  374. package/dist/server/lib/code-worker.js +174 -164
  375. package/dist/server/lib/code-worker.js.map +1 -0
  376. package/dist/server/lib/compaction-service.d.ts +2 -12
  377. package/dist/server/lib/compaction-service.js +74 -184
  378. package/dist/server/lib/compaction-service.js.map +1 -0
  379. package/dist/server/lib/logger.js +36 -24
  380. package/dist/server/lib/logger.js.map +1 -0
  381. package/dist/server/lib/otel.js +101 -80
  382. package/dist/server/lib/otel.js.map +1 -0
  383. package/dist/server/lib/pdf-renderer.d.ts +1 -1
  384. package/dist/server/lib/pdf-renderer.js +954 -776
  385. package/dist/server/lib/pdf-renderer.js.map +1 -0
  386. package/dist/server/lib/prompt-sanitizer.js +188 -108
  387. package/dist/server/lib/prompt-sanitizer.js.map +1 -0
  388. package/dist/server/lib/provider-capabilities.js +136 -138
  389. package/dist/server/lib/provider-capabilities.js.map +1 -0
  390. package/dist/server/lib/provider-failover.js +190 -168
  391. package/dist/server/lib/provider-failover.js.map +1 -0
  392. package/dist/server/lib/rate-limiter.js +186 -117
  393. package/dist/server/lib/rate-limiter.js.map +1 -0
  394. package/dist/server/lib/react-pdf-layout.js +551 -382
  395. package/dist/server/lib/react-pdf-layout.js.map +1 -0
  396. package/dist/server/lib/server-agent-loop.d.ts +9 -0
  397. package/dist/server/lib/server-agent-loop.js +906 -624
  398. package/dist/server/lib/server-agent-loop.js.map +1 -0
  399. package/dist/server/lib/server-subagent.d.ts +2 -0
  400. package/dist/server/lib/server-subagent.js +260 -162
  401. package/dist/server/lib/server-subagent.js.map +1 -0
  402. package/dist/server/lib/session-checkpoint.js +105 -96
  403. package/dist/server/lib/session-checkpoint.js.map +1 -0
  404. package/dist/server/lib/ssrf-guard.js +193 -184
  405. package/dist/server/lib/ssrf-guard.js.map +1 -0
  406. package/dist/server/lib/supabase-client.js +94 -82
  407. package/dist/server/lib/supabase-client.js.map +1 -0
  408. package/dist/server/lib/template-resolver.js +154 -176
  409. package/dist/server/lib/template-resolver.js.map +1 -0
  410. package/dist/server/lib/utils.js +242 -133
  411. package/dist/server/lib/utils.js.map +1 -0
  412. package/dist/server/local-agent-gateway.d.ts +2 -2
  413. package/dist/server/local-agent-gateway.js +785 -627
  414. package/dist/server/local-agent-gateway.js.map +1 -0
  415. package/dist/server/providers/anthropic.js +254 -176
  416. package/dist/server/providers/anthropic.js.map +1 -0
  417. package/dist/server/providers/bedrock.js +221 -162
  418. package/dist/server/providers/bedrock.js.map +1 -0
  419. package/dist/server/providers/gemini.js +548 -418
  420. package/dist/server/providers/gemini.js.map +1 -0
  421. package/dist/server/providers/openai.js +571 -437
  422. package/dist/server/providers/openai.js.map +1 -0
  423. package/dist/server/providers/registry.js +23 -18
  424. package/dist/server/providers/registry.js.map +1 -0
  425. package/dist/server/providers/shared.js +123 -95
  426. package/dist/server/providers/shared.js.map +1 -0
  427. package/dist/server/providers/types.js +1 -11
  428. package/dist/server/providers/types.js.map +1 -0
  429. package/dist/server/proxy-handlers.js +209 -165
  430. package/dist/server/proxy-handlers.js.map +1 -0
  431. package/dist/server/tool-router.d.ts +13 -0
  432. package/dist/server/tool-router.js +960 -598
  433. package/dist/server/tool-router.js.map +1 -0
  434. package/dist/server/validation.js +248 -188
  435. package/dist/server/validation.js.map +1 -0
  436. package/dist/server/worker.js +202 -133
  437. package/dist/server/worker.js.map +1 -0
  438. package/dist/setup.d.ts +2 -2
  439. package/dist/setup.js +151 -147
  440. package/dist/setup.js.map +1 -0
  441. package/dist/shared/agent-core.d.ts +191 -24
  442. package/dist/shared/agent-core.js +971 -462
  443. package/dist/shared/agent-core.js.map +1 -0
  444. package/dist/shared/anthropic-types.js +1 -6
  445. package/dist/shared/anthropic-types.js.map +1 -0
  446. package/dist/shared/api-client.d.ts +17 -9
  447. package/dist/shared/api-client.js +419 -327
  448. package/dist/shared/api-client.js.map +1 -0
  449. package/dist/shared/compaction.d.ts +36 -0
  450. package/dist/shared/compaction.js +138 -0
  451. package/dist/shared/compaction.js.map +1 -0
  452. package/dist/shared/constants.js +67 -64
  453. package/dist/shared/constants.js.map +1 -0
  454. package/dist/shared/sse-parser.js +221 -219
  455. package/dist/shared/sse-parser.js.map +1 -0
  456. package/dist/shared/tool-dispatch.d.ts +4 -2
  457. package/dist/shared/tool-dispatch.js +226 -165
  458. package/dist/shared/tool-dispatch.js.map +1 -0
  459. package/dist/shared/types.js +1 -6
  460. package/dist/shared/types.js.map +1 -0
  461. package/dist/types/cli-highlight.d.js +2 -0
  462. package/dist/types/cli-highlight.d.js.map +1 -0
  463. package/dist/types/diff.d.js +2 -0
  464. package/dist/types/diff.d.js.map +1 -0
  465. package/dist/types/pdf-parse.d.js +2 -0
  466. package/dist/types/pdf-parse.d.js.map +1 -0
  467. package/dist/updater.d.ts +1 -1
  468. package/dist/updater.js +118 -92
  469. package/dist/updater.js.map +1 -0
  470. package/dist/webchat/widget.js +227 -380
  471. package/dist/webchat/widget.js.map +1 -0
  472. package/package.json +22 -10
  473. package/vendor/ink/build/ansi-tokenizer.d.ts +38 -0
  474. package/vendor/ink/build/ansi-tokenizer.js +316 -0
  475. package/vendor/ink/build/ansi-tokenizer.js.map +1 -0
  476. package/vendor/ink/build/apply-styles.js +175 -0
  477. package/vendor/ink/build/build-layout.js +77 -0
  478. package/vendor/ink/build/calculate-wrapped-text.js +53 -0
  479. package/vendor/ink/build/colorize.d.ts +3 -0
  480. package/vendor/ink/build/colorize.js +48 -0
  481. package/vendor/ink/build/colorize.js.map +1 -0
  482. package/vendor/ink/build/components/AccessibilityContext.d.ts +3 -0
  483. package/vendor/ink/build/components/AccessibilityContext.js +5 -0
  484. package/vendor/ink/build/components/AccessibilityContext.js.map +1 -0
  485. package/vendor/ink/build/components/App.d.ts +18 -0
  486. package/vendor/ink/build/components/App.js +351 -0
  487. package/vendor/ink/build/components/App.js.map +1 -0
  488. package/vendor/ink/build/components/AppContext.d.ts +15 -0
  489. package/vendor/ink/build/components/AppContext.js +11 -0
  490. package/vendor/ink/build/components/AppContext.js.map +1 -0
  491. package/vendor/ink/build/components/BackgroundContext.d.ts +4 -0
  492. package/vendor/ink/build/components/BackgroundContext.js +3 -0
  493. package/vendor/ink/build/components/BackgroundContext.js.map +1 -0
  494. package/vendor/ink/build/components/Box.d.ts +117 -0
  495. package/vendor/ink/build/components/Box.js +34 -0
  496. package/vendor/ink/build/components/Box.js.map +1 -0
  497. package/vendor/ink/build/components/Color.js +62 -0
  498. package/vendor/ink/build/components/Cursor.d.ts +83 -0
  499. package/vendor/ink/build/components/Cursor.js +53 -0
  500. package/vendor/ink/build/components/Cursor.js.map +1 -0
  501. package/vendor/ink/build/components/CursorContext.d.ts +11 -0
  502. package/vendor/ink/build/components/CursorContext.js +8 -0
  503. package/vendor/ink/build/components/CursorContext.js.map +1 -0
  504. package/vendor/ink/build/components/ErrorBoundary.d.ts +18 -0
  505. package/vendor/ink/build/components/ErrorBoundary.js +23 -0
  506. package/vendor/ink/build/components/ErrorBoundary.js.map +1 -0
  507. package/vendor/ink/build/components/ErrorOverview.d.ts +6 -0
  508. package/vendor/ink/build/components/ErrorOverview.js +84 -0
  509. package/vendor/ink/build/components/ErrorOverview.js.map +1 -0
  510. package/vendor/ink/build/components/FocusContext.d.ts +16 -0
  511. package/vendor/ink/build/components/FocusContext.js +17 -0
  512. package/vendor/ink/build/components/FocusContext.js.map +1 -0
  513. package/vendor/ink/build/components/Newline.d.ts +13 -0
  514. package/vendor/ink/build/components/Newline.js +8 -0
  515. package/vendor/ink/build/components/Newline.js.map +1 -0
  516. package/vendor/ink/build/components/Spacer.d.ts +7 -0
  517. package/vendor/ink/build/components/Spacer.js +11 -0
  518. package/vendor/ink/build/components/Spacer.js.map +1 -0
  519. package/vendor/ink/build/components/Static.d.ts +24 -0
  520. package/vendor/ink/build/components/Static.js +28 -0
  521. package/vendor/ink/build/components/Static.js.map +1 -0
  522. package/vendor/ink/build/components/StderrContext.d.ts +15 -0
  523. package/vendor/ink/build/components/StderrContext.js +13 -0
  524. package/vendor/ink/build/components/StderrContext.js.map +1 -0
  525. package/vendor/ink/build/components/StdinContext.d.ts +22 -0
  526. package/vendor/ink/build/components/StdinContext.js +19 -0
  527. package/vendor/ink/build/components/StdinContext.js.map +1 -0
  528. package/vendor/ink/build/components/StdoutContext.d.ts +15 -0
  529. package/vendor/ink/build/components/StdoutContext.js +13 -0
  530. package/vendor/ink/build/components/StdoutContext.js.map +1 -0
  531. package/vendor/ink/build/components/Text.d.ts +55 -0
  532. package/vendor/ink/build/components/Text.js +50 -0
  533. package/vendor/ink/build/components/Text.js.map +1 -0
  534. package/vendor/ink/build/components/Transform.d.ts +16 -0
  535. package/vendor/ink/build/components/Transform.js +15 -0
  536. package/vendor/ink/build/components/Transform.js.map +1 -0
  537. package/vendor/ink/build/cursor-helpers.d.ts +38 -0
  538. package/vendor/ink/build/cursor-helpers.js +56 -0
  539. package/vendor/ink/build/cursor-helpers.js.map +1 -0
  540. package/vendor/ink/build/devtools-window-polyfill.d.ts +1 -0
  541. package/vendor/ink/build/devtools-window-polyfill.js +65 -0
  542. package/vendor/ink/build/devtools-window-polyfill.js.map +1 -0
  543. package/vendor/ink/build/devtools.d.ts +1 -0
  544. package/vendor/ink/build/devtools.js +11 -0
  545. package/vendor/ink/build/devtools.js.map +1 -0
  546. package/vendor/ink/build/dom.d.ts +56 -0
  547. package/vendor/ink/build/dom.js +124 -0
  548. package/vendor/ink/build/dom.js.map +1 -0
  549. package/vendor/ink/build/experimental/apply-style.js +140 -0
  550. package/vendor/ink/build/experimental/dom.js +123 -0
  551. package/vendor/ink/build/experimental/output.js +91 -0
  552. package/vendor/ink/build/experimental/reconciler.js +141 -0
  553. package/vendor/ink/build/experimental/renderer.js +81 -0
  554. package/vendor/ink/build/get-max-width.d.ts +3 -0
  555. package/vendor/ink/build/get-max-width.js +10 -0
  556. package/vendor/ink/build/get-max-width.js.map +1 -0
  557. package/vendor/ink/build/hooks/use-app.d.ts +5 -0
  558. package/vendor/ink/build/hooks/use-app.js +8 -0
  559. package/vendor/ink/build/hooks/use-app.js.map +1 -0
  560. package/vendor/ink/build/hooks/use-cursor.d.ts +12 -0
  561. package/vendor/ink/build/hooks/use-cursor.js +29 -0
  562. package/vendor/ink/build/hooks/use-cursor.js.map +1 -0
  563. package/vendor/ink/build/hooks/use-focus-manager.d.ts +28 -0
  564. package/vendor/ink/build/hooks/use-focus-manager.js +17 -0
  565. package/vendor/ink/build/hooks/use-focus-manager.js.map +1 -0
  566. package/vendor/ink/build/hooks/use-focus.d.ts +29 -0
  567. package/vendor/ink/build/hooks/use-focus.js +42 -0
  568. package/vendor/ink/build/hooks/use-focus.js.map +1 -0
  569. package/vendor/ink/build/hooks/use-input.d.ts +131 -0
  570. package/vendor/ink/build/hooks/use-input.js +124 -0
  571. package/vendor/ink/build/hooks/use-input.js.map +1 -0
  572. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.d.ts +5 -0
  573. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js +11 -0
  574. package/vendor/ink/build/hooks/use-is-screen-reader-enabled.js.map +1 -0
  575. package/vendor/ink/build/hooks/use-stderr.d.ts +5 -0
  576. package/vendor/ink/build/hooks/use-stderr.js +8 -0
  577. package/vendor/ink/build/hooks/use-stderr.js.map +1 -0
  578. package/vendor/ink/build/hooks/use-stdin.d.ts +5 -0
  579. package/vendor/ink/build/hooks/use-stdin.js +8 -0
  580. package/vendor/ink/build/hooks/use-stdin.js.map +1 -0
  581. package/vendor/ink/build/hooks/use-stdout.d.ts +5 -0
  582. package/vendor/ink/build/hooks/use-stdout.js +8 -0
  583. package/vendor/ink/build/hooks/use-stdout.js.map +1 -0
  584. package/vendor/ink/build/hooks/useInput.js +38 -0
  585. package/vendor/ink/build/index.d.ts +34 -0
  586. package/vendor/ink/build/index.js +20 -0
  587. package/vendor/ink/build/index.js.map +1 -0
  588. package/vendor/ink/build/ink.d.ts +90 -0
  589. package/vendor/ink/build/ink.js +654 -0
  590. package/vendor/ink/build/ink.js.map +1 -0
  591. package/vendor/ink/build/input-parser.d.ts +7 -0
  592. package/vendor/ink/build/input-parser.js +154 -0
  593. package/vendor/ink/build/input-parser.js.map +1 -0
  594. package/vendor/ink/build/instance.js +205 -0
  595. package/vendor/ink/build/instances.d.ts +3 -0
  596. package/vendor/ink/build/instances.js +8 -0
  597. package/vendor/ink/build/instances.js.map +1 -0
  598. package/vendor/ink/build/kitty-keyboard.d.ts +23 -0
  599. package/vendor/ink/build/kitty-keyboard.js +32 -0
  600. package/vendor/ink/build/kitty-keyboard.js.map +1 -0
  601. package/vendor/ink/build/layout.d.ts +7 -0
  602. package/vendor/ink/build/layout.js +33 -0
  603. package/vendor/ink/build/layout.js.map +1 -0
  604. package/vendor/ink/build/log-update.d.ts +19 -0
  605. package/vendor/ink/build/log-update.js +243 -0
  606. package/vendor/ink/build/log-update.js.map +1 -0
  607. package/vendor/ink/build/measure-element.d.ts +16 -0
  608. package/vendor/ink/build/measure-element.js +9 -0
  609. package/vendor/ink/build/measure-element.js.map +1 -0
  610. package/vendor/ink/build/measure-text.d.ts +6 -0
  611. package/vendor/ink/build/measure-text.js +21 -0
  612. package/vendor/ink/build/measure-text.js.map +1 -0
  613. package/vendor/ink/build/options.d.ts +52 -0
  614. package/vendor/ink/build/options.js +2 -0
  615. package/vendor/ink/build/options.js.map +1 -0
  616. package/vendor/ink/build/output.d.ts +35 -0
  617. package/vendor/ink/build/output.js +183 -0
  618. package/vendor/ink/build/output.js.map +1 -0
  619. package/vendor/ink/build/parse-keypress.d.ts +22 -0
  620. package/vendor/ink/build/parse-keypress.js +493 -0
  621. package/vendor/ink/build/parse-keypress.js.map +1 -0
  622. package/vendor/ink/build/reconciler.d.ts +4 -0
  623. package/vendor/ink/build/reconciler.js +274 -0
  624. package/vendor/ink/build/reconciler.js.map +1 -0
  625. package/vendor/ink/build/render-background.d.ts +4 -0
  626. package/vendor/ink/build/render-background.js +25 -0
  627. package/vendor/ink/build/render-background.js.map +1 -0
  628. package/vendor/ink/build/render-border.d.ts +4 -0
  629. package/vendor/ink/build/render-border.js +73 -0
  630. package/vendor/ink/build/render-border.js.map +1 -0
  631. package/vendor/ink/build/render-node-to-output.d.ts +14 -0
  632. package/vendor/ink/build/render-node-to-output.js +147 -0
  633. package/vendor/ink/build/render-node-to-output.js.map +1 -0
  634. package/vendor/ink/build/render-to-string.d.ts +38 -0
  635. package/vendor/ink/build/render-to-string.js +115 -0
  636. package/vendor/ink/build/render-to-string.js.map +1 -0
  637. package/vendor/ink/build/render.d.ts +121 -0
  638. package/vendor/ink/build/render.js +55 -0
  639. package/vendor/ink/build/render.js.map +1 -0
  640. package/vendor/ink/build/renderer.d.ts +8 -0
  641. package/vendor/ink/build/renderer.js +55 -0
  642. package/vendor/ink/build/renderer.js.map +1 -0
  643. package/vendor/ink/build/sanitize-ansi.d.ts +2 -0
  644. package/vendor/ink/build/sanitize-ansi.js +27 -0
  645. package/vendor/ink/build/sanitize-ansi.js.map +1 -0
  646. package/vendor/ink/build/screen-reader-update.d.ts +13 -0
  647. package/vendor/ink/build/screen-reader-update.js +38 -0
  648. package/vendor/ink/build/screen-reader-update.js.map +1 -0
  649. package/vendor/ink/build/squash-text-nodes.d.ts +3 -0
  650. package/vendor/ink/build/squash-text-nodes.js +36 -0
  651. package/vendor/ink/build/squash-text-nodes.js.map +1 -0
  652. package/vendor/ink/build/styles.d.ts +240 -0
  653. package/vendor/ink/build/styles.js +232 -0
  654. package/vendor/ink/build/styles.js.map +1 -0
  655. package/vendor/ink/build/utils.d.ts +2 -0
  656. package/vendor/ink/build/utils.js +4 -0
  657. package/vendor/ink/build/utils.js.map +1 -0
  658. package/vendor/ink/build/wrap-text.d.ts +3 -0
  659. package/vendor/ink/build/wrap-text.js +31 -0
  660. package/vendor/ink/build/wrap-text.js.map +1 -0
  661. package/vendor/ink/build/write-synchronized.d.ts +4 -0
  662. package/vendor/ink/build/write-synchronized.js +7 -0
  663. package/vendor/ink/build/write-synchronized.js.map +1 -0
  664. package/vendor/ink/license +10 -0
  665. package/vendor/ink/node_modules/@types/node/LICENSE +21 -0
  666. package/vendor/ink/node_modules/@types/node/README.md +15 -0
  667. package/vendor/ink/node_modules/@types/node/assert/strict.d.ts +105 -0
  668. package/vendor/ink/node_modules/@types/node/assert.d.ts +955 -0
  669. package/vendor/ink/node_modules/@types/node/async_hooks.d.ts +623 -0
  670. package/vendor/ink/node_modules/@types/node/buffer.buffer.d.ts +466 -0
  671. package/vendor/ink/node_modules/@types/node/buffer.d.ts +1810 -0
  672. package/vendor/ink/node_modules/@types/node/child_process.d.ts +1428 -0
  673. package/vendor/ink/node_modules/@types/node/cluster.d.ts +486 -0
  674. package/vendor/ink/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
  675. package/vendor/ink/node_modules/@types/node/console.d.ts +151 -0
  676. package/vendor/ink/node_modules/@types/node/constants.d.ts +20 -0
  677. package/vendor/ink/node_modules/@types/node/crypto.d.ts +4065 -0
  678. package/vendor/ink/node_modules/@types/node/dgram.d.ts +564 -0
  679. package/vendor/ink/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  680. package/vendor/ink/node_modules/@types/node/dns/promises.d.ts +503 -0
  681. package/vendor/ink/node_modules/@types/node/dns.d.ts +922 -0
  682. package/vendor/ink/node_modules/@types/node/domain.d.ts +166 -0
  683. package/vendor/ink/node_modules/@types/node/events.d.ts +1054 -0
  684. package/vendor/ink/node_modules/@types/node/fs/promises.d.ts +1329 -0
  685. package/vendor/ink/node_modules/@types/node/fs.d.ts +4676 -0
  686. package/vendor/ink/node_modules/@types/node/globals.d.ts +150 -0
  687. package/vendor/ink/node_modules/@types/node/globals.typedarray.d.ts +101 -0
  688. package/vendor/ink/node_modules/@types/node/http.d.ts +2167 -0
  689. package/vendor/ink/node_modules/@types/node/http2.d.ts +2480 -0
  690. package/vendor/ink/node_modules/@types/node/https.d.ts +405 -0
  691. package/vendor/ink/node_modules/@types/node/index.d.ts +115 -0
  692. package/vendor/ink/node_modules/@types/node/inspector/promises.d.ts +41 -0
  693. package/vendor/ink/node_modules/@types/node/inspector.d.ts +224 -0
  694. package/vendor/ink/node_modules/@types/node/inspector.generated.d.ts +4226 -0
  695. package/vendor/ink/node_modules/@types/node/module.d.ts +819 -0
  696. package/vendor/ink/node_modules/@types/node/net.d.ts +933 -0
  697. package/vendor/ink/node_modules/@types/node/os.d.ts +507 -0
  698. package/vendor/ink/node_modules/@types/node/package.json +155 -0
  699. package/vendor/ink/node_modules/@types/node/path/posix.d.ts +8 -0
  700. package/vendor/ink/node_modules/@types/node/path/win32.d.ts +8 -0
  701. package/vendor/ink/node_modules/@types/node/path.d.ts +187 -0
  702. package/vendor/ink/node_modules/@types/node/perf_hooks.d.ts +643 -0
  703. package/vendor/ink/node_modules/@types/node/process.d.ts +2156 -0
  704. package/vendor/ink/node_modules/@types/node/punycode.d.ts +117 -0
  705. package/vendor/ink/node_modules/@types/node/querystring.d.ts +152 -0
  706. package/vendor/ink/node_modules/@types/node/quic.d.ts +910 -0
  707. package/vendor/ink/node_modules/@types/node/readline/promises.d.ts +161 -0
  708. package/vendor/ink/node_modules/@types/node/readline.d.ts +541 -0
  709. package/vendor/ink/node_modules/@types/node/repl.d.ts +415 -0
  710. package/vendor/ink/node_modules/@types/node/sea.d.ts +162 -0
  711. package/vendor/ink/node_modules/@types/node/sqlite.d.ts +955 -0
  712. package/vendor/ink/node_modules/@types/node/stream/consumers.d.ts +38 -0
  713. package/vendor/ink/node_modules/@types/node/stream/promises.d.ts +211 -0
  714. package/vendor/ink/node_modules/@types/node/stream/web.d.ts +296 -0
  715. package/vendor/ink/node_modules/@types/node/stream.d.ts +1760 -0
  716. package/vendor/ink/node_modules/@types/node/string_decoder.d.ts +67 -0
  717. package/vendor/ink/node_modules/@types/node/test/reporters.d.ts +96 -0
  718. package/vendor/ink/node_modules/@types/node/test.d.ts +2240 -0
  719. package/vendor/ink/node_modules/@types/node/timers/promises.d.ts +108 -0
  720. package/vendor/ink/node_modules/@types/node/timers.d.ts +159 -0
  721. package/vendor/ink/node_modules/@types/node/tls.d.ts +1198 -0
  722. package/vendor/ink/node_modules/@types/node/trace_events.d.ts +197 -0
  723. package/vendor/ink/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +462 -0
  724. package/vendor/ink/node_modules/@types/node/ts5.6/compatibility/float16array.d.ts +71 -0
  725. package/vendor/ink/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +36 -0
  726. package/vendor/ink/node_modules/@types/node/ts5.6/index.d.ts +117 -0
  727. package/vendor/ink/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts +72 -0
  728. package/vendor/ink/node_modules/@types/node/ts5.7/index.d.ts +117 -0
  729. package/vendor/ink/node_modules/@types/node/tty.d.ts +250 -0
  730. package/vendor/ink/node_modules/@types/node/url.d.ts +519 -0
  731. package/vendor/ink/node_modules/@types/node/util/types.d.ts +558 -0
  732. package/vendor/ink/node_modules/@types/node/util.d.ts +1662 -0
  733. package/vendor/ink/node_modules/@types/node/v8.d.ts +983 -0
  734. package/vendor/ink/node_modules/@types/node/vm.d.ts +1208 -0
  735. package/vendor/ink/node_modules/@types/node/wasi.d.ts +202 -0
  736. package/vendor/ink/node_modules/@types/node/web-globals/abortcontroller.d.ts +59 -0
  737. package/vendor/ink/node_modules/@types/node/web-globals/blob.d.ts +23 -0
  738. package/vendor/ink/node_modules/@types/node/web-globals/console.d.ts +9 -0
  739. package/vendor/ink/node_modules/@types/node/web-globals/crypto.d.ts +39 -0
  740. package/vendor/ink/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  741. package/vendor/ink/node_modules/@types/node/web-globals/encoding.d.ts +11 -0
  742. package/vendor/ink/node_modules/@types/node/web-globals/events.d.ts +106 -0
  743. package/vendor/ink/node_modules/@types/node/web-globals/fetch.d.ts +69 -0
  744. package/vendor/ink/node_modules/@types/node/web-globals/importmeta.d.ts +13 -0
  745. package/vendor/ink/node_modules/@types/node/web-globals/messaging.d.ts +23 -0
  746. package/vendor/ink/node_modules/@types/node/web-globals/navigator.d.ts +25 -0
  747. package/vendor/ink/node_modules/@types/node/web-globals/performance.d.ts +45 -0
  748. package/vendor/ink/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  749. package/vendor/ink/node_modules/@types/node/web-globals/streams.d.ts +115 -0
  750. package/vendor/ink/node_modules/@types/node/web-globals/timers.d.ts +44 -0
  751. package/vendor/ink/node_modules/@types/node/web-globals/url.d.ts +24 -0
  752. package/vendor/ink/node_modules/@types/node/worker_threads.d.ts +717 -0
  753. package/vendor/ink/node_modules/@types/node/zlib.d.ts +618 -0
  754. package/vendor/ink/node_modules/node-pty/LICENSE +69 -0
  755. package/vendor/ink/node_modules/node-pty/README.md +164 -0
  756. package/vendor/ink/node_modules/node-pty/binding.gyp +150 -0
  757. package/vendor/ink/node_modules/node-pty/lib/conpty_console_list_agent.js +25 -0
  758. package/vendor/ink/node_modules/node-pty/lib/eventEmitter2.js +47 -0
  759. package/vendor/ink/node_modules/node-pty/lib/index.js +52 -0
  760. package/vendor/ink/node_modules/node-pty/lib/interfaces.js +7 -0
  761. package/vendor/ink/node_modules/node-pty/lib/shared/conout.js +11 -0
  762. package/vendor/ink/node_modules/node-pty/lib/terminal.js +190 -0
  763. package/vendor/ink/node_modules/node-pty/lib/types.js +7 -0
  764. package/vendor/ink/node_modules/node-pty/lib/unixTerminal.js +349 -0
  765. package/vendor/ink/node_modules/node-pty/lib/utils.js +39 -0
  766. package/vendor/ink/node_modules/node-pty/lib/windowsConoutConnection.js +125 -0
  767. package/vendor/ink/node_modules/node-pty/lib/windowsPtyAgent.js +287 -0
  768. package/vendor/ink/node_modules/node-pty/lib/windowsTerminal.js +201 -0
  769. package/vendor/ink/node_modules/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  770. package/vendor/ink/node_modules/node-pty/package.json +65 -0
  771. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +0 -0
  772. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +0 -0
  773. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/pty.node +0 -0
  774. package/vendor/ink/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +0 -0
  775. package/vendor/ink/node_modules/node-pty/prebuilds/linux-arm64/pty.node +0 -0
  776. package/vendor/ink/node_modules/node-pty/prebuilds/linux-x64/pty.node +0 -0
  777. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  778. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  779. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  780. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty.pdb +0 -0
  781. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  782. package/vendor/ink/node_modules/node-pty/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  783. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  784. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  785. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  786. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty.pdb +0 -0
  787. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  788. package/vendor/ink/node_modules/node-pty/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  789. package/vendor/ink/node_modules/node-pty/scripts/post-install.js +76 -0
  790. package/vendor/ink/node_modules/node-pty/scripts/prebuild.js +34 -0
  791. package/vendor/ink/node_modules/node-pty/src/unix/pty.cc +875 -0
  792. package/vendor/ink/node_modules/node-pty/src/unix/spawn-helper.cc +23 -0
  793. package/vendor/ink/node_modules/node-pty/src/win/conpty.cc +582 -0
  794. package/vendor/ink/node_modules/node-pty/src/win/conpty.h +41 -0
  795. package/vendor/ink/node_modules/node-pty/src/win/conpty_console_list.cc +44 -0
  796. package/vendor/ink/node_modules/node-pty/src/win/path_util.cc +95 -0
  797. package/vendor/ink/node_modules/node-pty/src/win/path_util.h +26 -0
  798. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
  799. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
  800. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
  801. package/vendor/ink/node_modules/node-pty/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
  802. package/vendor/ink/node_modules/node-pty/typings/node-pty.d.ts +215 -0
  803. package/vendor/ink/node_modules/undici-types/LICENSE +21 -0
  804. package/vendor/ink/node_modules/undici-types/README.md +6 -0
  805. package/vendor/ink/node_modules/undici-types/agent.d.ts +32 -0
  806. package/vendor/ink/node_modules/undici-types/api.d.ts +43 -0
  807. package/vendor/ink/node_modules/undici-types/balanced-pool.d.ts +30 -0
  808. package/vendor/ink/node_modules/undici-types/cache-interceptor.d.ts +173 -0
  809. package/vendor/ink/node_modules/undici-types/cache.d.ts +36 -0
  810. package/vendor/ink/node_modules/undici-types/client-stats.d.ts +15 -0
  811. package/vendor/ink/node_modules/undici-types/client.d.ts +108 -0
  812. package/vendor/ink/node_modules/undici-types/connector.d.ts +34 -0
  813. package/vendor/ink/node_modules/undici-types/content-type.d.ts +21 -0
  814. package/vendor/ink/node_modules/undici-types/cookies.d.ts +30 -0
  815. package/vendor/ink/node_modules/undici-types/diagnostics-channel.d.ts +74 -0
  816. package/vendor/ink/node_modules/undici-types/dispatcher.d.ts +276 -0
  817. package/vendor/ink/node_modules/undici-types/env-http-proxy-agent.d.ts +22 -0
  818. package/vendor/ink/node_modules/undici-types/errors.d.ts +161 -0
  819. package/vendor/ink/node_modules/undici-types/eventsource.d.ts +66 -0
  820. package/vendor/ink/node_modules/undici-types/fetch.d.ts +211 -0
  821. package/vendor/ink/node_modules/undici-types/formdata.d.ts +108 -0
  822. package/vendor/ink/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  823. package/vendor/ink/node_modules/undici-types/global-origin.d.ts +7 -0
  824. package/vendor/ink/node_modules/undici-types/h2c-client.d.ts +73 -0
  825. package/vendor/ink/node_modules/undici-types/handlers.d.ts +15 -0
  826. package/vendor/ink/node_modules/undici-types/header.d.ts +160 -0
  827. package/vendor/ink/node_modules/undici-types/index.d.ts +88 -0
  828. package/vendor/ink/node_modules/undici-types/interceptors.d.ts +73 -0
  829. package/vendor/ink/node_modules/undici-types/mock-agent.d.ts +68 -0
  830. package/vendor/ink/node_modules/undici-types/mock-call-history.d.ts +111 -0
  831. package/vendor/ink/node_modules/undici-types/mock-client.d.ts +27 -0
  832. package/vendor/ink/node_modules/undici-types/mock-errors.d.ts +12 -0
  833. package/vendor/ink/node_modules/undici-types/mock-interceptor.d.ts +94 -0
  834. package/vendor/ink/node_modules/undici-types/mock-pool.d.ts +27 -0
  835. package/vendor/ink/node_modules/undici-types/package.json +55 -0
  836. package/vendor/ink/node_modules/undici-types/patch.d.ts +29 -0
  837. package/vendor/ink/node_modules/undici-types/pool-stats.d.ts +19 -0
  838. package/vendor/ink/node_modules/undici-types/pool.d.ts +41 -0
  839. package/vendor/ink/node_modules/undici-types/proxy-agent.d.ts +29 -0
  840. package/vendor/ink/node_modules/undici-types/readable.d.ts +68 -0
  841. package/vendor/ink/node_modules/undici-types/retry-agent.d.ts +8 -0
  842. package/vendor/ink/node_modules/undici-types/retry-handler.d.ts +125 -0
  843. package/vendor/ink/node_modules/undici-types/round-robin-pool.d.ts +41 -0
  844. package/vendor/ink/node_modules/undici-types/snapshot-agent.d.ts +109 -0
  845. package/vendor/ink/node_modules/undici-types/util.d.ts +18 -0
  846. package/vendor/ink/node_modules/undici-types/utility.d.ts +7 -0
  847. package/vendor/ink/node_modules/undici-types/webidl.d.ts +341 -0
  848. package/vendor/ink/node_modules/undici-types/websocket.d.ts +186 -0
  849. package/vendor/ink/package.json +201 -0
  850. package/vendor/ink/readme.md +2636 -0
  851. package/bin/swag-agent.js +0 -9
  852. package/dist/server/lib/pg-rate-limiter.d.ts +0 -21
  853. package/dist/server/lib/pg-rate-limiter.js +0 -86
@@ -1,28 +1,50 @@
1
1
  /**
2
2
  * Local Agent Gateway — WebSocket server for local agent connections.
3
3
  *
4
- * Accepts outbound WebSocket connections from user machines running swag-agent.
4
+ * Accepts outbound WebSocket connections from user machines running whale agent.
5
5
  * Authenticates per-store via API key, maintains connection pool, routes commands.
6
6
  *
7
7
  * Architecture:
8
8
  * Claude Code → MCP stdio → Fly.io server → local_agent handler
9
- * → this gateway → WebSocket → user's local swag-agent → execute locally
9
+ * → this gateway → WebSocket → user's local whale agent → execute locally
10
10
  *
11
11
  * Same pattern as kali.ts but routes through WebSocket instead of HTTP to Fly.io internal.
12
12
  */
13
+
13
14
  import { WebSocketServer, WebSocket } from "ws";
14
15
  import { randomUUID, createHash } from "node:crypto";
15
16
  import { createClient } from "@supabase/supabase-js";
16
17
  import { queueSpan, auditRowToSpan } from "./lib/clickhouse-buffer.js";
18
+
19
+ // ============================================================================
20
+ // TYPES
21
+ // ============================================================================
22
+
23
+ // Messages: server → agent
24
+
25
+ // Messages: agent → server
26
+
27
+ // ============================================================================
28
+ // REMOTE DESKTOP TYPES
29
+ // ============================================================================
30
+
17
31
  // ============================================================================
18
32
  // CONNECTION POOL
19
33
  // ============================================================================
34
+
20
35
  /** Map<storeId, LocalAgent[]> — multiple agents per store (e.g. multiple machines) */
21
36
  const agentPool = new Map();
37
+
22
38
  /** Map<requestId, pending request> */
23
39
  const pendingRequests = new Map();
40
+
24
41
  /** Map<sessionId, RemoteDesktopSession> — active remote desktop relay sessions */
25
42
  const rdSessions = new Map();
43
+
44
+ // ============================================================================
45
+ // PORTAL TYPES
46
+ // ============================================================================
47
+
26
48
  /** Map<sessionId, PortalRelaySession> — active portal sessions */
27
49
  const portalSessions = new Map();
28
50
  const PORTAL_MARKER = 0x01;
@@ -30,737 +52,873 @@ const MAX_AGENTS_PER_STORE = 25;
30
52
  const HEARTBEAT_INTERVAL_MS = 30_000;
31
53
  const PONG_TIMEOUT_MS = 45_000;
32
54
  const MAX_OUTPUT_CHARS = 500 * 1024; // 500KB safety cap — context_management handles limits
55
+
33
56
  // ============================================================================
34
57
  // GATEWAY
35
58
  // ============================================================================
59
+
36
60
  let wss = null;
37
61
  let heartbeatTimer = null;
38
62
  let supabaseClient = null;
39
63
  export function initLocalAgentGateway(server) {
40
- const SUPABASE_URL = process.env.SUPABASE_URL;
41
- const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
42
- supabaseClient = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
43
- wss = new WebSocketServer({ noServer: true });
44
- // Handle HTTP upgrade on /agent/ws path
45
- server.on("upgrade", (req, socket, head) => {
46
- const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
47
- if (url.pathname !== "/agent/ws") {
48
- socket.destroy();
49
- return;
50
- }
51
- wss.handleUpgrade(req, socket, head, (ws) => {
52
- wss.emit("connection", ws, req);
53
- });
64
+ const SUPABASE_URL = process.env.SUPABASE_URL;
65
+ const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
66
+ supabaseClient = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
67
+ wss = new WebSocketServer({
68
+ noServer: true
69
+ });
70
+
71
+ // Handle HTTP upgrade on /agent/ws path
72
+ server.on("upgrade", (req, socket, head) => {
73
+ const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
74
+ if (url.pathname !== "/agent/ws") {
75
+ socket.destroy();
76
+ return;
77
+ }
78
+ wss.handleUpgrade(req, socket, head, ws => {
79
+ wss.emit("connection", ws, req);
54
80
  });
55
- wss.on("connection", handleConnection);
56
- // Heartbeat — ping all agents, disconnect stale ones
57
- heartbeatTimer = setInterval(() => {
58
- const now = Date.now();
59
- for (const [storeId, agents] of agentPool) {
60
- for (let i = agents.length - 1; i >= 0; i--) {
61
- const agent = agents[i];
62
- if (now - agent.lastPong > PONG_TIMEOUT_MS) {
63
- console.log(`[local-agent] Disconnecting stale agent ${agent.agentId} (store=${storeId})`);
64
- agent.ws.terminate();
65
- agents.splice(i, 1);
66
- }
67
- else if (agent.ws.readyState === WebSocket.OPEN) {
68
- send(agent.ws, { type: "ping" });
69
- }
70
- }
71
- if (agents.length === 0)
72
- agentPool.delete(storeId);
81
+ });
82
+ wss.on("connection", handleConnection);
83
+
84
+ // Heartbeat ping all agents, disconnect stale ones
85
+ heartbeatTimer = setInterval(() => {
86
+ const now = Date.now();
87
+ for (const [storeId, agents] of agentPool) {
88
+ for (let i = agents.length - 1; i >= 0; i--) {
89
+ const agent = agents[i];
90
+ if (now - agent.lastPong > PONG_TIMEOUT_MS) {
91
+ console.log(`[local-agent] Disconnecting stale agent ${agent.agentId} (store=${storeId})`);
92
+ agent.ws.terminate();
93
+ agents.splice(i, 1);
94
+ } else if (agent.ws.readyState === WebSocket.OPEN) {
95
+ send(agent.ws, {
96
+ type: "ping"
97
+ });
73
98
  }
74
- }, HEARTBEAT_INTERVAL_MS);
75
- heartbeatTimer.unref();
76
- console.log("[local-agent] Gateway initialized on /agent/ws");
99
+ }
100
+ if (agents.length === 0) agentPool.delete(storeId);
101
+ }
102
+ }, HEARTBEAT_INTERVAL_MS);
103
+ heartbeatTimer.unref();
104
+ console.log("[local-agent] Gateway initialized on /agent/ws");
77
105
  }
78
106
  function handleConnection(ws, _req) {
79
- let authenticated = false;
80
- let agent = null;
81
- let viewerSession = null;
82
- // Auth timeout — must authenticate within 10 seconds
83
- const authTimer = setTimeout(() => {
84
- if (!authenticated) {
85
- send(ws, { type: "error", error: "Authentication timeout" });
86
- ws.close(4001, "Authentication timeout");
87
- }
88
- }, 10_000);
89
- ws.on("message", async (raw) => {
90
- // Handle binary messages — forward to paired viewer/agent in RD/portal sessions
91
- if (typeof raw !== "string" && !isJsonString(raw)) {
92
- const buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
93
- // Portal binary frames (marker 0x01) route by session UUID
94
- if (buf.length > 17 && buf[0] === PORTAL_MARKER) {
95
- const sessionUuid = buf.subarray(1, 17).toString("hex");
96
- const sessionId = `${sessionUuid.slice(0, 8)}-${sessionUuid.slice(8, 12)}-${sessionUuid.slice(12, 16)}-${sessionUuid.slice(16, 20)}-${sessionUuid.slice(20)}`;
97
- const portalSession = portalSessions.get(sessionId);
98
- if (portalSession && agent) {
99
- // Forward to the other side
100
- const targetAgentId = agent.agentId === portalSession.initiatorAgentId
101
- ? portalSession.targetAgentId
102
- : portalSession.initiatorAgentId;
103
- const target = pickAgentById(targetAgentId);
104
- if (target?.ws.readyState === WebSocket.OPEN) {
105
- target.ws.send(buf);
106
- portalSession.bytesRelayed += buf.length;
107
- }
108
- }
109
- return;
110
- }
111
- // Remote desktop binary frames (no marker or 0x00) — existing behavior
112
- if (agent) {
113
- for (const [, session] of rdSessions) {
114
- if (session.agentId === agent.agentId && session.viewerWs.readyState === WebSocket.OPEN) {
115
- session.viewerWs.send(buf);
116
- session.framesRelayed++;
117
- session.bytesRelayed += buf.length;
118
- }
119
- }
120
- }
121
- if (viewerSession) {
122
- const target = pickAgentById(viewerSession.agentId);
123
- if (target?.ws.readyState === WebSocket.OPEN) {
124
- target.ws.send(buf);
125
- }
126
- }
127
- return;
128
- }
129
- let msg;
130
- try {
131
- msg = JSON.parse(raw.toString());
132
- }
133
- catch {
134
- send(ws, { type: "error", error: "Invalid JSON" });
135
- return;
107
+ let authenticated = false;
108
+ let agent = null;
109
+ let viewerSession = null;
110
+
111
+ // Auth timeout must authenticate within 10 seconds
112
+ const authTimer = setTimeout(() => {
113
+ if (!authenticated) {
114
+ send(ws, {
115
+ type: "error",
116
+ error: "Authentication timeout"
117
+ });
118
+ ws.close(4001, "Authentication timeout");
119
+ }
120
+ }, 10_000);
121
+ ws.on("message", async raw => {
122
+ // Handle binary messages forward to paired viewer/agent in RD/portal sessions
123
+ if (typeof raw !== "string" && !isJsonString(raw)) {
124
+ const buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw);
125
+
126
+ // Portal binary frames (marker 0x01) — route by session UUID
127
+ if (buf.length > 17 && buf[0] === PORTAL_MARKER) {
128
+ const sessionUuid = buf.subarray(1, 17).toString("hex");
129
+ const sessionId = `${sessionUuid.slice(0, 8)}-${sessionUuid.slice(8, 12)}-${sessionUuid.slice(12, 16)}-${sessionUuid.slice(16, 20)}-${sessionUuid.slice(20)}`;
130
+ const portalSession = portalSessions.get(sessionId);
131
+ if (portalSession && agent) {
132
+ // Forward to the other side
133
+ const targetAgentId = agent.agentId === portalSession.initiatorAgentId ? portalSession.targetAgentId : portalSession.initiatorAgentId;
134
+ const target = pickAgentById(targetAgentId);
135
+ if (target?.ws.readyState === WebSocket.OPEN) {
136
+ target.ws.send(buf);
137
+ portalSession.bytesRelayed += buf.length;
138
+ }
136
139
  }
137
- // Handle viewer auth (remote desktop relay)
138
- if (msg.type === "auth" && msg.role === "viewer") {
139
- clearTimeout(authTimer);
140
- const viewerAuth = msg;
141
- const authResult = await authenticateViewer(viewerAuth);
142
- if (!authResult) {
143
- send(ws, { type: "error", error: "Invalid token or unauthorized" });
144
- ws.close(4003, "Authentication failed");
145
- return;
146
- }
147
- authenticated = true;
148
- // Find target agent with remote_desktop capability
149
- const targetAgent = pickAgent(authResult.storeId, undefined, viewerAuth.target_node_id);
150
- if (!targetAgent || !targetAgent.capabilities.includes("remote_desktop")) {
151
- send(ws, { type: "remote_desktop_response", success: false, error: "No remote desktop capable node online" });
152
- ws.close(4004, "No target node");
153
- return;
154
- }
155
- // Create relay session
156
- const sessionId = randomUUID();
157
- viewerSession = {
158
- sessionId,
159
- viewerWs: ws,
160
- agentId: targetAgent.agentId,
161
- storeId: authResult.storeId,
162
- userId: authResult.userId,
163
- startedAt: new Date(),
164
- framesRelayed: 0,
165
- bytesRelayed: 0,
166
- };
167
- rdSessions.set(sessionId, viewerSession);
168
- // Tell the agent to start a remote desktop session
169
- send(targetAgent.ws, {
170
- type: "remote_desktop",
171
- request_id: randomUUID(),
172
- type_inner: "remote_desktop_request",
173
- session_id: sessionId,
174
- viewer_user_id: authResult.userId,
175
- });
176
- send(ws, {
177
- type: "remote_desktop_response",
178
- success: true,
179
- session_id: sessionId,
180
- agent_hostname: targetAgent.hostname,
181
- });
182
- console.log(`[remote-desktop] Relay session ${sessionId}: viewer=${authResult.userId} → agent=${targetAgent.agentId}`);
183
- return;
140
+ return;
141
+ }
142
+
143
+ // Remote desktop binary frames (no marker or 0x00) — existing behavior
144
+ if (agent) {
145
+ for (const [, session] of rdSessions) {
146
+ if (session.agentId === agent.agentId && session.viewerWs.readyState === WebSocket.OPEN) {
147
+ session.viewerWs.send(buf);
148
+ session.framesRelayed++;
149
+ session.bytesRelayed += buf.length;
150
+ }
184
151
  }
185
- // Handle auth
186
- if (msg.type === "auth") {
187
- clearTimeout(authTimer);
188
- const authResult = await authenticateAgent(msg);
189
- if (!authResult) {
190
- send(ws, { type: "error", error: "Invalid API key" });
191
- ws.close(4003, "Authentication failed");
192
- return;
193
- }
194
- agent = {
195
- ws,
196
- storeId: authResult.storeId.toLowerCase(),
197
- userId: authResult.userId,
198
- nodeId: authResult.nodeId,
199
- capabilities: msg.capabilities || [],
200
- connectedAt: new Date(),
201
- lastPong: Date.now(),
202
- agentId: randomUUID(),
203
- platform: msg.platform || "unknown",
204
- hostname: msg.hostname || "unknown",
205
- };
206
- // Add to pool
207
- const existing = agentPool.get(agent.storeId) || [];
208
- if (existing.length >= MAX_AGENTS_PER_STORE) {
209
- // Disconnect oldest
210
- const oldest = existing.shift();
211
- send(oldest.ws, { type: "error", error: "Replaced by newer agent connection" });
212
- oldest.ws.close(4004, "Replaced by newer connection");
213
- }
214
- existing.push(agent);
215
- agentPool.set(agent.storeId, existing);
216
- authenticated = true;
217
- send(ws, {
218
- type: "authenticated",
219
- agent_id: agent.agentId,
220
- message: `Connected to SwagManager. ${agent.capabilities.length} local tools registered.`,
221
- });
222
- console.log(`[local-agent] Agent connected: store=${agent.storeId} platform=${agent.platform} hostname=${agent.hostname} tools=${agent.capabilities.length}`);
223
- // Telemetry → ClickHouse
224
- queueSpan(auditRowToSpan({
225
- action: "local_agent.connected",
226
- severity: "info",
227
- store_id: agent.storeId,
228
- resource_type: "local_agent",
229
- resource_id: agent.agentId,
230
- source: "local_agent",
231
- service_name: "agent-server",
232
- span_kind: "INTERNAL",
233
- status_code: "OK",
234
- start_time: new Date().toISOString(),
235
- end_time: new Date().toISOString(),
236
- details: {
237
- platform: agent.platform,
238
- hostname: agent.hostname,
239
- capabilities: agent.capabilities,
240
- },
241
- user_id: agent.userId,
242
- }));
243
- return;
152
+ }
153
+ if (viewerSession) {
154
+ const target = pickAgentById(viewerSession.agentId);
155
+ if (target?.ws.readyState === WebSocket.OPEN) {
156
+ target.ws.send(buf);
244
157
  }
245
- // Handle viewer input forwarding (after auth)
246
- if (authenticated && viewerSession && !agent) {
247
- // Forward input events from viewer to the target agent
248
- const target = pickAgentById(viewerSession.agentId);
249
- if (target?.ws.readyState === WebSocket.OPEN) {
250
- send(target.ws, { type: "remote_desktop", ...msg });
251
- }
252
- return;
158
+ }
159
+ return;
160
+ }
161
+ let msg;
162
+ try {
163
+ msg = JSON.parse(raw.toString());
164
+ } catch {
165
+ send(ws, {
166
+ type: "error",
167
+ error: "Invalid JSON"
168
+ });
169
+ return;
170
+ }
171
+
172
+ // Handle viewer auth (remote desktop relay)
173
+ if (msg.type === "auth" && msg.role === "viewer") {
174
+ clearTimeout(authTimer);
175
+ const viewerAuth = msg;
176
+ const authResult = await authenticateViewer(viewerAuth);
177
+ if (!authResult) {
178
+ send(ws, {
179
+ type: "error",
180
+ error: "Invalid token or unauthorized"
181
+ });
182
+ ws.close(4003, "Authentication failed");
183
+ return;
184
+ }
185
+ authenticated = true;
186
+
187
+ // Find target agent with remote_desktop capability
188
+ const targetAgent = pickAgent(authResult.storeId, undefined, viewerAuth.target_node_id);
189
+ if (!targetAgent || !targetAgent.capabilities.includes("remote_desktop")) {
190
+ send(ws, {
191
+ type: "remote_desktop_response",
192
+ success: false,
193
+ error: "No remote desktop capable node online"
194
+ });
195
+ ws.close(4004, "No target node");
196
+ return;
197
+ }
198
+
199
+ // Create relay session
200
+ const sessionId = randomUUID();
201
+ viewerSession = {
202
+ sessionId,
203
+ viewerWs: ws,
204
+ agentId: targetAgent.agentId,
205
+ storeId: authResult.storeId,
206
+ userId: authResult.userId,
207
+ startedAt: new Date(),
208
+ framesRelayed: 0,
209
+ bytesRelayed: 0
210
+ };
211
+ rdSessions.set(sessionId, viewerSession);
212
+
213
+ // Tell the agent to start a remote desktop session
214
+ send(targetAgent.ws, {
215
+ type: "remote_desktop",
216
+ request_id: randomUUID(),
217
+ type_inner: "remote_desktop_request",
218
+ session_id: sessionId,
219
+ viewer_user_id: authResult.userId
220
+ });
221
+ send(ws, {
222
+ type: "remote_desktop_response",
223
+ success: true,
224
+ session_id: sessionId,
225
+ agent_hostname: targetAgent.hostname
226
+ });
227
+ console.log(`[remote-desktop] Relay session ${sessionId}: viewer=${authResult.userId} → agent=${targetAgent.agentId}`);
228
+ return;
229
+ }
230
+
231
+ // Handle auth
232
+ if (msg.type === "auth") {
233
+ clearTimeout(authTimer);
234
+ const authResult = await authenticateAgent(msg);
235
+ if (!authResult) {
236
+ send(ws, {
237
+ type: "error",
238
+ error: "Invalid API key"
239
+ });
240
+ ws.close(4003, "Authentication failed");
241
+ return;
242
+ }
243
+ agent = {
244
+ ws,
245
+ storeId: authResult.storeId.toLowerCase(),
246
+ userId: authResult.userId,
247
+ nodeId: authResult.nodeId,
248
+ capabilities: msg.capabilities || [],
249
+ connectedAt: new Date(),
250
+ lastPong: Date.now(),
251
+ agentId: randomUUID(),
252
+ platform: msg.platform || "unknown",
253
+ hostname: msg.hostname || "unknown"
254
+ };
255
+
256
+ // Add to pool
257
+ const existing = agentPool.get(agent.storeId) || [];
258
+ if (existing.length >= MAX_AGENTS_PER_STORE) {
259
+ // Disconnect oldest
260
+ const oldest = existing.shift();
261
+ send(oldest.ws, {
262
+ type: "error",
263
+ error: "Replaced by newer agent connection"
264
+ });
265
+ oldest.ws.close(4004, "Replaced by newer connection");
266
+ }
267
+ existing.push(agent);
268
+ agentPool.set(agent.storeId, existing);
269
+ authenticated = true;
270
+ send(ws, {
271
+ type: "authenticated",
272
+ agent_id: agent.agentId,
273
+ message: `Connected to WhaleTools. ${agent.capabilities.length} local tools registered.`
274
+ });
275
+ console.log(`[local-agent] Agent connected: store=${agent.storeId} platform=${agent.platform} hostname=${agent.hostname} tools=${agent.capabilities.length}`);
276
+
277
+ // Telemetry → ClickHouse
278
+ queueSpan(auditRowToSpan({
279
+ action: "local_agent.connected",
280
+ severity: "info",
281
+ store_id: agent.storeId,
282
+ resource_type: "local_agent",
283
+ resource_id: agent.agentId,
284
+ source: "local_agent",
285
+ service_name: "agent-server",
286
+ span_kind: "INTERNAL",
287
+ status_code: "OK",
288
+ start_time: new Date().toISOString(),
289
+ end_time: new Date().toISOString(),
290
+ details: {
291
+ platform: agent.platform,
292
+ hostname: agent.hostname,
293
+ capabilities: agent.capabilities
294
+ },
295
+ user_id: agent.userId
296
+ }));
297
+ return;
298
+ }
299
+
300
+ // Handle viewer input forwarding (after auth)
301
+ if (authenticated && viewerSession && !agent) {
302
+ // Forward input events from viewer to the target agent
303
+ const target = pickAgentById(viewerSession.agentId);
304
+ if (target?.ws.readyState === WebSocket.OPEN) {
305
+ send(target.ws, {
306
+ type: "remote_desktop",
307
+ ...msg
308
+ });
309
+ }
310
+ return;
311
+ }
312
+ if (!authenticated || !agent) {
313
+ send(ws, {
314
+ type: "error",
315
+ error: "Not authenticated"
316
+ });
317
+ return;
318
+ }
319
+
320
+ // Handle pong
321
+ if (msg.type === "pong") {
322
+ agent.lastPong = Date.now();
323
+ return;
324
+ }
325
+
326
+ // Handle portal messages
327
+ if (msg.type === "portal_request" && agent) {
328
+ // Initiator wants to connect to a target node
329
+ const targetAgent = pickAgent(agent.storeId, undefined, msg.target_node_id);
330
+ if (!targetAgent) {
331
+ send(ws, {
332
+ type: "portal_reject",
333
+ session_id: msg.session_id,
334
+ reason: "Target node not online"
335
+ });
336
+ return;
337
+ }
338
+ // Forward request to target agent
339
+ send(targetAgent.ws, {
340
+ type: "portal_request",
341
+ session_id: msg.session_id,
342
+ capabilities: msg.capabilities,
343
+ requester_node_id: agent.nodeId,
344
+ requester_hostname: agent.hostname,
345
+ requester_role: msg.requester_role || "admin"
346
+ });
347
+ // Pre-register session so binary routing works once accepted
348
+ portalSessions.set(msg.session_id, {
349
+ sessionId: msg.session_id,
350
+ initiatorAgentId: agent.agentId,
351
+ targetAgentId: targetAgent.agentId,
352
+ storeId: agent.storeId,
353
+ capabilities: msg.capabilities || [],
354
+ startedAt: new Date(),
355
+ bytesRelayed: 0
356
+ });
357
+ console.log(`[portal] Session ${msg.session_id}: ${agent.hostname} → ${targetAgent.hostname}`);
358
+ return;
359
+ }
360
+ if (msg.type === "portal_accept" && agent) {
361
+ const session = portalSessions.get(msg.session_id);
362
+ if (session) {
363
+ const initiator = pickAgentById(session.initiatorAgentId);
364
+ if (initiator) {
365
+ send(initiator.ws, {
366
+ type: "portal_accept",
367
+ session_id: msg.session_id,
368
+ hostname: agent.hostname
369
+ });
253
370
  }
254
- if (!authenticated || !agent) {
255
- send(ws, { type: "error", error: "Not authenticated" });
256
- return;
371
+ }
372
+ return;
373
+ }
374
+ if (msg.type === "portal_reject" && agent) {
375
+ const session = portalSessions.get(msg.session_id);
376
+ if (session) {
377
+ const initiator = pickAgentById(session.initiatorAgentId);
378
+ if (initiator) {
379
+ send(initiator.ws, {
380
+ type: "portal_reject",
381
+ session_id: msg.session_id,
382
+ reason: msg.reason
383
+ });
257
384
  }
258
- // Handle pong
259
- if (msg.type === "pong") {
260
- agent.lastPong = Date.now();
261
- return;
385
+ portalSessions.delete(msg.session_id);
386
+ }
387
+ return;
388
+ }
389
+ if (msg.type === "portal_close" && agent) {
390
+ const session = portalSessions.get(msg.session_id);
391
+ if (session) {
392
+ // Notify the other side
393
+ const otherAgentId = agent.agentId === session.initiatorAgentId ? session.targetAgentId : session.initiatorAgentId;
394
+ const other = pickAgentById(otherAgentId);
395
+ if (other) {
396
+ send(other.ws, {
397
+ type: "portal_close",
398
+ session_id: msg.session_id
399
+ });
262
400
  }
263
- // Handle portal messages
264
- if (msg.type === "portal_request" && agent) {
265
- // Initiator wants to connect to a target node
266
- const targetAgent = pickAgent(agent.storeId, undefined, msg.target_node_id);
267
- if (!targetAgent) {
268
- send(ws, { type: "portal_reject", session_id: msg.session_id, reason: "Target node not online" });
269
- return;
270
- }
271
- // Forward request to target agent
272
- send(targetAgent.ws, {
273
- type: "portal_request",
274
- session_id: msg.session_id,
275
- capabilities: msg.capabilities,
276
- requester_node_id: agent.nodeId,
277
- requester_hostname: agent.hostname,
278
- requester_role: msg.requester_role || "admin",
279
- });
280
- // Pre-register session so binary routing works once accepted
281
- portalSessions.set(msg.session_id, {
282
- sessionId: msg.session_id,
283
- initiatorAgentId: agent.agentId,
284
- targetAgentId: targetAgent.agentId,
285
- storeId: agent.storeId,
286
- capabilities: msg.capabilities || [],
287
- startedAt: new Date(),
288
- bytesRelayed: 0,
401
+ portalSessions.delete(msg.session_id);
402
+ console.log(`[portal] Session ${msg.session_id} closed (${session.bytesRelayed} bytes relayed)`);
403
+ }
404
+ return;
405
+ }
406
+
407
+ // Handle tool discovery response
408
+ if (msg.type === "tools") {
409
+ agent.capabilities = msg.tools;
410
+ console.log(`[local-agent] Updated tools for ${agent.agentId}: ${msg.tools.join(", ")}`);
411
+ return;
412
+ }
413
+
414
+ // Handle command result
415
+ if (msg.type === "result") {
416
+ const pending = pendingRequests.get(msg.request_id);
417
+ if (!pending) return; // Already timed out or cancelled
418
+
419
+ clearTimeout(pending.timer);
420
+ pendingRequests.delete(msg.request_id);
421
+
422
+ // Truncate large outputs
423
+ const result = {
424
+ success: msg.success,
425
+ stdout: truncate(msg.stdout),
426
+ stderr: truncate(msg.stderr),
427
+ exit_code: msg.exit_code,
428
+ data: msg.data,
429
+ error: msg.error,
430
+ killed: msg.killed,
431
+ cwd: msg.cwd,
432
+ duration_ms: msg.duration_ms
433
+ };
434
+ pending.resolve(result);
435
+ }
436
+ });
437
+ ws.on("close", () => {
438
+ clearTimeout(authTimer);
439
+ if (agent) {
440
+ const agents = agentPool.get(agent.storeId);
441
+ if (agents) {
442
+ const idx = agents.findIndex(a => a.agentId === agent.agentId);
443
+ if (idx >= 0) agents.splice(idx, 1);
444
+ if (agents.length === 0) agentPool.delete(agent.storeId);
445
+ }
446
+ console.log(`[local-agent] Agent disconnected: ${agent.agentId} (store=${agent.storeId})`);
447
+
448
+ // Immediately fail all pending requests for this agent
449
+ failPendingRequestsForAgent(agent.agentId, `Agent disconnected (${agent.hostname})`);
450
+
451
+ // End any portal sessions through this agent
452
+ for (const [sessionId, session] of portalSessions) {
453
+ if (session.initiatorAgentId === agent.agentId || session.targetAgentId === agent.agentId) {
454
+ const otherAgentId = agent.agentId === session.initiatorAgentId ? session.targetAgentId : session.initiatorAgentId;
455
+ const other = pickAgentById(otherAgentId);
456
+ if (other) {
457
+ send(other.ws, {
458
+ type: "portal_close",
459
+ session_id: sessionId
289
460
  });
290
- console.log(`[portal] Session ${msg.session_id}: ${agent.hostname} → ${targetAgent.hostname}`);
291
- return;
292
- }
293
- if (msg.type === "portal_accept" && agent) {
294
- const session = portalSessions.get(msg.session_id);
295
- if (session) {
296
- const initiator = pickAgentById(session.initiatorAgentId);
297
- if (initiator) {
298
- send(initiator.ws, { type: "portal_accept", session_id: msg.session_id, hostname: agent.hostname });
299
- }
300
- }
301
- return;
302
- }
303
- if (msg.type === "portal_reject" && agent) {
304
- const session = portalSessions.get(msg.session_id);
305
- if (session) {
306
- const initiator = pickAgentById(session.initiatorAgentId);
307
- if (initiator) {
308
- send(initiator.ws, { type: "portal_reject", session_id: msg.session_id, reason: msg.reason });
309
- }
310
- portalSessions.delete(msg.session_id);
311
- }
312
- return;
313
- }
314
- if (msg.type === "portal_close" && agent) {
315
- const session = portalSessions.get(msg.session_id);
316
- if (session) {
317
- // Notify the other side
318
- const otherAgentId = agent.agentId === session.initiatorAgentId
319
- ? session.targetAgentId : session.initiatorAgentId;
320
- const other = pickAgentById(otherAgentId);
321
- if (other) {
322
- send(other.ws, { type: "portal_close", session_id: msg.session_id });
323
- }
324
- portalSessions.delete(msg.session_id);
325
- console.log(`[portal] Session ${msg.session_id} closed (${session.bytesRelayed} bytes relayed)`);
326
- }
327
- return;
328
- }
329
- // Handle tool discovery response
330
- if (msg.type === "tools") {
331
- agent.capabilities = msg.tools;
332
- console.log(`[local-agent] Updated tools for ${agent.agentId}: ${msg.tools.join(", ")}`);
333
- return;
334
- }
335
- // Handle command result
336
- if (msg.type === "result") {
337
- const pending = pendingRequests.get(msg.request_id);
338
- if (!pending)
339
- return; // Already timed out or cancelled
340
- clearTimeout(pending.timer);
341
- pendingRequests.delete(msg.request_id);
342
- // Truncate large outputs
343
- const result = {
344
- success: msg.success,
345
- stdout: truncate(msg.stdout),
346
- stderr: truncate(msg.stderr),
347
- exit_code: msg.exit_code,
348
- data: msg.data,
349
- error: msg.error,
350
- killed: msg.killed,
351
- cwd: msg.cwd,
352
- duration_ms: msg.duration_ms,
353
- };
354
- pending.resolve(result);
461
+ }
462
+ portalSessions.delete(sessionId);
463
+ console.log(`[portal] Session ${sessionId} ended (agent disconnected)`);
355
464
  }
356
- });
357
- ws.on("close", () => {
358
- clearTimeout(authTimer);
359
- if (agent) {
360
- const agents = agentPool.get(agent.storeId);
361
- if (agents) {
362
- const idx = agents.findIndex(a => a.agentId === agent.agentId);
363
- if (idx >= 0)
364
- agents.splice(idx, 1);
365
- if (agents.length === 0)
366
- agentPool.delete(agent.storeId);
367
- }
368
- console.log(`[local-agent] Agent disconnected: ${agent.agentId} (store=${agent.storeId})`);
369
- // Immediately fail all pending requests for this agent
370
- failPendingRequestsForAgent(agent.agentId, `Agent disconnected (${agent.hostname})`);
371
- // End any portal sessions through this agent
372
- for (const [sessionId, session] of portalSessions) {
373
- if (session.initiatorAgentId === agent.agentId || session.targetAgentId === agent.agentId) {
374
- const otherAgentId = agent.agentId === session.initiatorAgentId
375
- ? session.targetAgentId : session.initiatorAgentId;
376
- const other = pickAgentById(otherAgentId);
377
- if (other) {
378
- send(other.ws, { type: "portal_close", session_id: sessionId });
379
- }
380
- portalSessions.delete(sessionId);
381
- console.log(`[portal] Session ${sessionId} ended (agent disconnected)`);
382
- }
383
- }
384
- // End any remote desktop sessions through this agent
385
- for (const [sessionId, session] of rdSessions) {
386
- if (session.agentId === agent.agentId) {
387
- send(session.viewerWs, { type: "session_end", reason: "agent_disconnected" });
388
- session.viewerWs.close(1001, "Agent disconnected");
389
- rdSessions.delete(sessionId);
390
- console.log(`[remote-desktop] Session ${sessionId} ended (agent disconnected)`);
391
- }
392
- }
393
- }
394
- // Clean up viewer sessions
395
- if (viewerSession) {
396
- rdSessions.delete(viewerSession.sessionId);
397
- console.log(`[remote-desktop] Session ${viewerSession.sessionId} ended (viewer disconnected)`);
398
- viewerSession = null;
465
+ }
466
+
467
+ // End any remote desktop sessions through this agent
468
+ for (const [sessionId, session] of rdSessions) {
469
+ if (session.agentId === agent.agentId) {
470
+ send(session.viewerWs, {
471
+ type: "session_end",
472
+ reason: "agent_disconnected"
473
+ });
474
+ session.viewerWs.close(1001, "Agent disconnected");
475
+ rdSessions.delete(sessionId);
476
+ console.log(`[remote-desktop] Session ${sessionId} ended (agent disconnected)`);
399
477
  }
400
- });
401
- ws.on("error", (err) => {
402
- console.error("[local-agent] WebSocket error:", err.message);
403
- });
478
+ }
479
+ }
480
+
481
+ // Clean up viewer sessions
482
+ if (viewerSession) {
483
+ rdSessions.delete(viewerSession.sessionId);
484
+ console.log(`[remote-desktop] Session ${viewerSession.sessionId} ended (viewer disconnected)`);
485
+ viewerSession = null;
486
+ }
487
+ });
488
+ ws.on("error", err => {
489
+ console.error("[local-agent] WebSocket error:", err.message);
490
+ });
404
491
  }
492
+
405
493
  // ============================================================================
406
494
  // AUTHENTICATION
407
495
  // ============================================================================
496
+
408
497
  async function authenticateAgent(msg) {
409
- if (!supabaseClient || !msg.api_key)
410
- return null;
411
- const keyHash = createHash("sha256").update(msg.api_key).digest("hex");
412
- // 1. Try api_keys table first (standard API keys)
413
- const { data, error } = await supabaseClient
414
- .from("api_keys")
415
- .select("id, store_id, owner_user_id")
416
- .eq("key_hash", keyHash)
417
- .eq("is_active", true)
418
- .single();
419
- if (data && !error) {
420
- // Update last_used_at
421
- supabaseClient.from("api_keys")
422
- .update({ last_used_at: new Date().toISOString() })
423
- .eq("id", data.id)
424
- .then(() => { });
425
- return { storeId: data.store_id, userId: data.owner_user_id || null, nodeId: null };
426
- }
427
- // 2. Fall back to nodes table (node daemon API keys)
428
- const { data: nodeData, error: nodeErr } = await supabaseClient
429
- .from("nodes")
430
- .select("id, store_id")
431
- .eq("api_key_hash", keyHash)
432
- .single();
433
- if (nodeData && !nodeErr) {
434
- // Update node last_heartbeat on gateway connect
435
- supabaseClient.from("nodes")
436
- .update({ status: "online", last_heartbeat: new Date().toISOString() })
437
- .eq("id", nodeData.id)
438
- .then(() => { });
439
- return { storeId: nodeData.store_id, userId: null, nodeId: nodeData.id };
440
- }
441
- return null;
498
+ if (!supabaseClient || !msg.api_key) return null;
499
+ const keyHash = createHash("sha256").update(msg.api_key).digest("hex");
500
+
501
+ // 1. Try api_keys table first (standard API keys)
502
+ const {
503
+ data,
504
+ error
505
+ } = await supabaseClient.from("api_keys").select("id, store_id, owner_user_id").eq("key_hash", keyHash).eq("is_active", true).single();
506
+ if (data && !error) {
507
+ // Update last_used_at
508
+ supabaseClient.from("api_keys").update({
509
+ last_used_at: new Date().toISOString()
510
+ }).eq("id", data.id).then(() => {});
511
+ return {
512
+ storeId: data.store_id,
513
+ userId: data.owner_user_id || null,
514
+ nodeId: null
515
+ };
516
+ }
517
+
518
+ // 2. Fall back to nodes table (node daemon API keys)
519
+ const {
520
+ data: nodeData,
521
+ error: nodeErr
522
+ } = await supabaseClient.from("nodes").select("id, store_id").eq("api_key_hash", keyHash).single();
523
+ if (nodeData && !nodeErr) {
524
+ // Update node last_heartbeat on gateway connect
525
+ supabaseClient.from("nodes").update({
526
+ status: "online",
527
+ last_heartbeat: new Date().toISOString()
528
+ }).eq("id", nodeData.id).then(() => {});
529
+ return {
530
+ storeId: nodeData.store_id,
531
+ userId: null,
532
+ nodeId: nodeData.id
533
+ };
534
+ }
535
+ return null;
442
536
  }
537
+
443
538
  /**
444
539
  * Authenticate a viewer connection using Supabase JWT.
445
540
  */
446
541
  async function authenticateViewer(msg) {
447
- if (!supabaseClient || !msg.token)
448
- return null;
449
- try {
450
- // Verify JWT with Supabase auth
451
- const { data: { user }, error } = await supabaseClient.auth.getUser(msg.token);
452
- if (error || !user)
453
- return null;
454
- // Verify user has access to the requested store
455
- const { data: storeAccess } = await supabaseClient
456
- .from("store_users")
457
- .select("store_id")
458
- .eq("user_id", user.id)
459
- .eq("store_id", msg.store_id)
460
- .single();
461
- if (!storeAccess)
462
- return null;
463
- return { storeId: msg.store_id, userId: user.id };
464
- }
465
- catch {
466
- return null;
467
- }
542
+ if (!supabaseClient || !msg.token) return null;
543
+ try {
544
+ // Verify JWT with Supabase auth
545
+ const {
546
+ data: {
547
+ user
548
+ },
549
+ error
550
+ } = await supabaseClient.auth.getUser(msg.token);
551
+ if (error || !user) return null;
552
+
553
+ // Verify user has access to the requested store
554
+ const {
555
+ data: storeAccess
556
+ } = await supabaseClient.from("store_users").select("store_id").eq("user_id", user.id).eq("store_id", msg.store_id).single();
557
+ if (!storeAccess) return null;
558
+ return {
559
+ storeId: msg.store_id,
560
+ userId: user.id
561
+ };
562
+ } catch {
563
+ return null;
564
+ }
468
565
  }
566
+
469
567
  // ============================================================================
470
568
  // PUBLIC API — used by local-agent handler
471
569
  // ============================================================================
570
+
472
571
  /**
473
572
  * Check if a store has a connected local agent.
474
573
  */
475
574
  export function hasLocalAgent(storeId) {
476
- const agents = agentPool.get(storeId.toLowerCase());
477
- return !!agents?.some(a => a.ws.readyState === WebSocket.OPEN);
575
+ const agents = agentPool.get(storeId.toLowerCase());
576
+ return !!agents?.some(a => a.ws.readyState === WebSocket.OPEN);
478
577
  }
578
+
479
579
  /**
480
580
  * Get info about connected agents for a store.
481
581
  */
482
582
  export function getAgentInfo(storeId) {
483
- const agents = agentPool.get(storeId.toLowerCase()) || [];
484
- return agents
485
- .filter(a => a.ws.readyState === WebSocket.OPEN)
486
- .map(a => ({
487
- agent_id: a.agentId,
488
- platform: a.platform,
489
- hostname: a.hostname,
490
- capabilities: a.capabilities,
491
- connected_at: a.connectedAt.toISOString(),
492
- uptime_seconds: Math.floor((Date.now() - a.connectedAt.getTime()) / 1000),
493
- node_id: a.nodeId,
494
- }));
583
+ const agents = agentPool.get(storeId.toLowerCase()) || [];
584
+ return agents.filter(a => a.ws.readyState === WebSocket.OPEN).map(a => ({
585
+ agent_id: a.agentId,
586
+ platform: a.platform,
587
+ hostname: a.hostname,
588
+ capabilities: a.capabilities,
589
+ connected_at: a.connectedAt.toISOString(),
590
+ uptime_seconds: Math.floor((Date.now() - a.connectedAt.getTime()) / 1000),
591
+ node_id: a.nodeId
592
+ }));
495
593
  }
594
+
496
595
  /**
497
596
  * Execute a command on the user's local machine via their connected agent.
498
597
  */
499
598
  export async function executeOnLocalAgent(storeId, command, options = {}) {
500
- const agent = pickAgent(storeId, options.agent_id);
501
- if (!agent) {
502
- return {
503
- success: false,
504
- error: `No local agent connected for this store. Install and run: npx swagmanager-agent`,
505
- };
506
- }
507
- const requestId = randomUUID();
508
- const timeout = Math.min(options.timeout || 30000, 600000);
509
- const msg = {
510
- type: "exec",
511
- request_id: requestId,
512
- command,
513
- session_id: options.session_id,
514
- timeout,
599
+ const agent = pickAgent(storeId, options.agent_id);
600
+ if (!agent) {
601
+ return {
602
+ success: false,
603
+ error: `No local agent connected for this store. Install and run: whale agent start --key YOUR_API_KEY`
515
604
  };
516
- const sent = send(agent.ws, msg);
517
- if (!sent)
518
- return { success: false, error: "Agent connection closed" };
519
- return new Promise((resolve, reject) => {
520
- const timer = setTimeout(() => {
521
- pendingRequests.delete(requestId);
522
- resolve({
523
- success: false,
524
- error: `Local agent command timed out after ${timeout}ms`,
525
- });
526
- }, timeout + 5000); // 5s buffer over command timeout
527
- pendingRequests.set(requestId, { resolve, reject, timer, agentId: agent.agentId });
605
+ }
606
+ const requestId = randomUUID();
607
+ const timeout = Math.min(options.timeout || 30000, 600000);
608
+ const msg = {
609
+ type: "exec",
610
+ request_id: requestId,
611
+ command,
612
+ session_id: options.session_id,
613
+ timeout
614
+ };
615
+ const sent = send(agent.ws, msg);
616
+ if (!sent) return {
617
+ success: false,
618
+ error: "Agent connection closed"
619
+ };
620
+ return new Promise((resolve, reject) => {
621
+ const timer = setTimeout(() => {
622
+ pendingRequests.delete(requestId);
623
+ resolve({
624
+ success: false,
625
+ error: `Local agent command timed out after ${timeout}ms`
626
+ });
627
+ }, timeout + 5000); // 5s buffer over command timeout
628
+
629
+ pendingRequests.set(requestId, {
630
+ resolve,
631
+ reject,
632
+ timer,
633
+ agentId: agent.agentId
528
634
  });
635
+ });
529
636
  }
637
+
530
638
  /**
531
639
  * Execute a managed tool on the local agent (burp, zap, tshark, etc.)
532
640
  */
533
641
  export async function executeToolOnLocalAgent(storeId, tool, args, options = {}) {
534
- const agent = pickAgent(storeId, options.agent_id);
535
- if (!agent) {
536
- return {
537
- success: false,
538
- error: `No local agent connected. Install: npx swagmanager-agent`,
539
- };
540
- }
541
- // Check if agent has this tool
542
- if (!agent.capabilities.includes(tool)) {
543
- return {
544
- success: false,
545
- error: `Local agent does not have tool "${tool}" installed. Available: ${agent.capabilities.join(", ") || "none"}`,
546
- };
547
- }
548
- const requestId = randomUUID();
549
- const timeout = Math.min(options.timeout || 30000, 600000);
550
- const msg = {
551
- type: "tool_exec",
552
- request_id: requestId,
553
- tool,
554
- args,
555
- timeout,
642
+ const agent = pickAgent(storeId, options.agent_id);
643
+ if (!agent) {
644
+ return {
645
+ success: false,
646
+ error: `No local agent connected. Install: whale agent start --key YOUR_API_KEY`
556
647
  };
557
- const sent = send(agent.ws, msg);
558
- if (!sent)
559
- return { success: false, error: "Agent connection closed" };
560
- return new Promise((resolve, reject) => {
561
- const timer = setTimeout(() => {
562
- pendingRequests.delete(requestId);
563
- resolve({
564
- success: false,
565
- error: `Local tool "${tool}" timed out after ${timeout}ms`,
566
- });
567
- }, timeout + 5000);
568
- pendingRequests.set(requestId, { resolve, reject, timer, agentId: agent.agentId });
648
+ }
649
+
650
+ // Check if agent has this tool
651
+ if (!agent.capabilities.includes(tool)) {
652
+ return {
653
+ success: false,
654
+ error: `Local agent does not have tool "${tool}" installed. Available: ${agent.capabilities.join(", ") || "none"}`
655
+ };
656
+ }
657
+ const requestId = randomUUID();
658
+ const timeout = Math.min(options.timeout || 30000, 600000);
659
+ const msg = {
660
+ type: "tool_exec",
661
+ request_id: requestId,
662
+ tool,
663
+ args,
664
+ timeout
665
+ };
666
+ const sent = send(agent.ws, msg);
667
+ if (!sent) return {
668
+ success: false,
669
+ error: "Agent connection closed"
670
+ };
671
+ return new Promise((resolve, reject) => {
672
+ const timer = setTimeout(() => {
673
+ pendingRequests.delete(requestId);
674
+ resolve({
675
+ success: false,
676
+ error: `Local tool "${tool}" timed out after ${timeout}ms`
677
+ });
678
+ }, timeout + 5000);
679
+ pendingRequests.set(requestId, {
680
+ resolve,
681
+ reject,
682
+ timer,
683
+ agentId: agent.agentId
569
684
  });
685
+ });
570
686
  }
687
+
571
688
  /**
572
689
  * Request tool discovery from agent.
573
690
  */
574
691
  export async function discoverLocalTools(storeId) {
575
- const agent = pickAgent(storeId.toLowerCase());
576
- if (!agent) {
577
- return {
578
- success: false,
579
- error: `No local agent connected. Install: npx swagmanager-agent`,
580
- };
581
- }
582
- const requestId = randomUUID();
583
- const sent = send(agent.ws, { type: "discover", request_id: requestId });
584
- if (!sent)
585
- return { success: false, error: "Agent connection closed" };
586
- return new Promise((resolve) => {
587
- const timer = setTimeout(() => {
588
- pendingRequests.delete(requestId);
589
- resolve({ success: false, error: "Discovery timed out" });
590
- }, 15000);
591
- pendingRequests.set(requestId, {
592
- resolve,
593
- reject: () => resolve({ success: false, error: "Discovery failed" }),
594
- timer,
595
- agentId: agent.agentId,
596
- });
692
+ const agent = pickAgent(storeId.toLowerCase());
693
+ if (!agent) {
694
+ return {
695
+ success: false,
696
+ error: `No local agent connected. Install: whale agent start --key YOUR_API_KEY`
697
+ };
698
+ }
699
+ const requestId = randomUUID();
700
+ const sent = send(agent.ws, {
701
+ type: "discover",
702
+ request_id: requestId
703
+ });
704
+ if (!sent) return {
705
+ success: false,
706
+ error: "Agent connection closed"
707
+ };
708
+ return new Promise(resolve => {
709
+ const timer = setTimeout(() => {
710
+ pendingRequests.delete(requestId);
711
+ resolve({
712
+ success: false,
713
+ error: "Discovery timed out"
714
+ });
715
+ }, 15000);
716
+ pendingRequests.set(requestId, {
717
+ resolve,
718
+ reject: () => resolve({
719
+ success: false,
720
+ error: "Discovery failed"
721
+ }),
722
+ timer,
723
+ agentId: agent.agentId
597
724
  });
725
+ });
598
726
  }
727
+
599
728
  /**
600
729
  * Get gateway statistics.
601
730
  */
602
731
  export function getGatewayStats() {
603
- const agentsByStore = {};
604
- let totalAgents = 0;
605
- for (const [storeId, agents] of agentPool) {
606
- const active = agents.filter(a => a.ws.readyState === WebSocket.OPEN).length;
607
- if (active > 0) {
608
- agentsByStore[storeId] = active;
609
- totalAgents += active;
610
- }
732
+ const agentsByStore = {};
733
+ let totalAgents = 0;
734
+ for (const [storeId, agents] of agentPool) {
735
+ const active = agents.filter(a => a.ws.readyState === WebSocket.OPEN).length;
736
+ if (active > 0) {
737
+ agentsByStore[storeId] = active;
738
+ totalAgents += active;
611
739
  }
612
- return {
613
- total_agents: totalAgents,
614
- total_stores: Object.keys(agentsByStore).length,
615
- pending_requests: pendingRequests.size,
616
- agents_by_store: agentsByStore,
617
- };
740
+ }
741
+ return {
742
+ total_agents: totalAgents,
743
+ total_stores: Object.keys(agentsByStore).length,
744
+ pending_requests: pendingRequests.size,
745
+ agents_by_store: agentsByStore
746
+ };
618
747
  }
748
+
619
749
  /**
620
750
  * Get active remote desktop sessions.
621
751
  */
622
752
  export function getRemoteDesktopSessions() {
623
- return Array.from(rdSessions.values()).map(s => ({
624
- session_id: s.sessionId,
625
- store_id: s.storeId,
626
- user_id: s.userId,
627
- agent_id: s.agentId,
628
- started_at: s.startedAt.toISOString(),
629
- frames_relayed: s.framesRelayed,
630
- bytes_relayed: s.bytesRelayed,
631
- }));
753
+ return Array.from(rdSessions.values()).map(s => ({
754
+ session_id: s.sessionId,
755
+ store_id: s.storeId,
756
+ user_id: s.userId,
757
+ agent_id: s.agentId,
758
+ started_at: s.startedAt.toISOString(),
759
+ frames_relayed: s.framesRelayed,
760
+ bytes_relayed: s.bytesRelayed
761
+ }));
632
762
  }
763
+
633
764
  /**
634
765
  * Get active portal sessions.
635
766
  */
636
767
  export function getPortalSessions() {
637
- return Array.from(portalSessions.values()).map(s => ({
638
- session_id: s.sessionId,
639
- store_id: s.storeId,
640
- initiator_agent_id: s.initiatorAgentId,
641
- target_agent_id: s.targetAgentId,
642
- capabilities: s.capabilities,
643
- started_at: s.startedAt.toISOString(),
644
- bytes_relayed: s.bytesRelayed,
645
- }));
768
+ return Array.from(portalSessions.values()).map(s => ({
769
+ session_id: s.sessionId,
770
+ store_id: s.storeId,
771
+ initiator_agent_id: s.initiatorAgentId,
772
+ target_agent_id: s.targetAgentId,
773
+ capabilities: s.capabilities,
774
+ started_at: s.startedAt.toISOString(),
775
+ bytes_relayed: s.bytesRelayed
776
+ }));
646
777
  }
778
+
647
779
  // ============================================================================
648
780
  // INTERNALS
649
781
  // ============================================================================
782
+
650
783
  function pickAgent(storeId, agentId, nodeId) {
651
- const agents = agentPool.get(storeId.toLowerCase());
652
- if (!agents?.length)
653
- return null;
654
- // Filter to open connections
655
- const open = agents.filter(a => a.ws.readyState === WebSocket.OPEN);
656
- if (open.length === 0)
657
- return null;
658
- // Target specific agent if requested
659
- if (agentId) {
660
- return open.find(a => a.agentId === agentId) || null;
661
- }
662
- // Target specific node if requested
663
- if (nodeId) {
664
- return open.find(a => a.nodeId === nodeId) || null;
665
- }
666
- // Pick agent with most recent pong (most responsive)
667
- return open.reduce((best, a) => a.lastPong > best.lastPong ? a : best);
784
+ const agents = agentPool.get(storeId.toLowerCase());
785
+ if (!agents?.length) return null;
786
+
787
+ // Filter to open connections
788
+ const open = agents.filter(a => a.ws.readyState === WebSocket.OPEN);
789
+ if (open.length === 0) return null;
790
+
791
+ // Target specific agent if requested
792
+ if (agentId) {
793
+ return open.find(a => a.agentId === agentId) || null;
794
+ }
795
+
796
+ // Target specific node if requested
797
+ if (nodeId) {
798
+ return open.find(a => a.nodeId === nodeId) || null;
799
+ }
800
+
801
+ // Pick agent with most recent pong (most responsive)
802
+ return open.reduce((best, a) => a.lastPong > best.lastPong ? a : best);
668
803
  }
669
804
  function pickAgentById(agentId) {
670
- for (const [, agents] of agentPool) {
671
- const found = agents.find(a => a.agentId === agentId && a.ws.readyState === WebSocket.OPEN);
672
- if (found)
673
- return found;
674
- }
675
- return null;
805
+ for (const [, agents] of agentPool) {
806
+ const found = agents.find(a => a.agentId === agentId && a.ws.readyState === WebSocket.OPEN);
807
+ if (found) return found;
808
+ }
809
+ return null;
676
810
  }
677
811
  function isJsonString(data) {
678
- if (typeof data === "string")
679
- return true;
680
- if (Buffer.isBuffer(data)) {
681
- // Quick check: JSON starts with { or [
682
- return data.length > 0 && (data[0] === 0x7b || data[0] === 0x5b);
683
- }
684
- return false;
812
+ if (typeof data === "string") return true;
813
+ if (Buffer.isBuffer(data)) {
814
+ // Quick check: JSON starts with { or [
815
+ return data.length > 0 && (data[0] === 0x7b || data[0] === 0x5b);
816
+ }
817
+ return false;
685
818
  }
686
819
  function send(ws, data) {
687
- if (ws.readyState === WebSocket.OPEN) {
688
- ws.send(JSON.stringify(data));
689
- return true;
690
- }
691
- return false;
820
+ if (ws.readyState === WebSocket.OPEN) {
821
+ ws.send(JSON.stringify(data));
822
+ return true;
823
+ }
824
+ return false;
692
825
  }
693
826
  function failPendingRequestsForAgent(agentId, reason) {
694
- for (const [requestId, pending] of pendingRequests) {
695
- if (pending.agentId === agentId) {
696
- clearTimeout(pending.timer);
697
- pendingRequests.delete(requestId);
698
- pending.resolve({ success: false, error: reason });
699
- }
827
+ for (const [requestId, pending] of pendingRequests) {
828
+ if (pending.agentId === agentId) {
829
+ clearTimeout(pending.timer);
830
+ pendingRequests.delete(requestId);
831
+ pending.resolve({
832
+ success: false,
833
+ error: reason
834
+ });
700
835
  }
836
+ }
701
837
  }
702
838
  function truncate(text) {
703
- if (!text || text.length <= MAX_OUTPUT_CHARS)
704
- return text;
705
- return text.substring(0, MAX_OUTPUT_CHARS) + `\n...[truncated, ${text.length} total chars]`;
839
+ if (!text || text.length <= MAX_OUTPUT_CHARS) return text;
840
+ return text.substring(0, MAX_OUTPUT_CHARS) + `\n...[truncated, ${text.length} total chars]`;
706
841
  }
842
+
843
+ // ============================================================================
844
+ // CLUSTER COMMANDS — routes cluster operations to whale-node
845
+ // ============================================================================
846
+
707
847
  /**
708
848
  * Execute a cluster command on the connected whale-node.
709
849
  * Sends via WebSocket and waits for the result.
710
850
  */
711
851
  export async function executeClusterCommand(storeId, args, options = {}) {
712
- const agent = pickAgent(storeId, options.agent_id, options.node_id);
713
- if (!agent) {
714
- return {
715
- success: false,
716
- error: "No local agent connected for cluster commands.",
717
- };
718
- }
719
- const requestId = randomUUID();
720
- const timeout = Math.min(options.timeout || 60000, 600000);
721
- const sent = send(agent.ws, {
722
- type: "cluster_command",
723
- request_id: requestId,
724
- args,
725
- });
726
- if (!sent)
727
- return { success: false, error: "Agent connection closed" };
728
- return new Promise((resolve, reject) => {
729
- const timer = setTimeout(() => {
730
- pendingRequests.delete(requestId);
731
- resolve({
732
- success: false,
733
- error: `Cluster command timed out after ${timeout}ms`,
734
- });
735
- }, timeout + 5000);
736
- pendingRequests.set(requestId, { resolve, reject, timer, agentId: agent.agentId });
852
+ const agent = pickAgent(storeId, options.agent_id, options.node_id);
853
+ if (!agent) {
854
+ return {
855
+ success: false,
856
+ error: "No local agent connected for cluster commands."
857
+ };
858
+ }
859
+ const requestId = randomUUID();
860
+ const timeout = Math.min(options.timeout || 60000, 600000);
861
+ const sent = send(agent.ws, {
862
+ type: "cluster_command",
863
+ request_id: requestId,
864
+ args
865
+ });
866
+ if (!sent) return {
867
+ success: false,
868
+ error: "Agent connection closed"
869
+ };
870
+ return new Promise((resolve, reject) => {
871
+ const timer = setTimeout(() => {
872
+ pendingRequests.delete(requestId);
873
+ resolve({
874
+ success: false,
875
+ error: `Cluster command timed out after ${timeout}ms`
876
+ });
877
+ }, timeout + 5000);
878
+ pendingRequests.set(requestId, {
879
+ resolve,
880
+ reject,
881
+ timer,
882
+ agentId: agent.agentId
737
883
  });
884
+ });
738
885
  }
886
+
739
887
  // ============================================================================
740
888
  // SHUTDOWN
741
889
  // ============================================================================
890
+
742
891
  export function shutdownGateway() {
743
- if (heartbeatTimer) {
744
- clearInterval(heartbeatTimer);
745
- heartbeatTimer = null;
746
- }
747
- // Close all agent connections
748
- for (const [, agents] of agentPool) {
749
- for (const agent of agents) {
750
- send(agent.ws, { type: "shutdown", message: "Server shutting down" });
751
- agent.ws.close(1001, "Server shutdown");
752
- }
892
+ if (heartbeatTimer) {
893
+ clearInterval(heartbeatTimer);
894
+ heartbeatTimer = null;
895
+ }
896
+
897
+ // Close all agent connections
898
+ for (const [, agents] of agentPool) {
899
+ for (const agent of agents) {
900
+ send(agent.ws, {
901
+ type: "shutdown",
902
+ message: "Server shutting down"
903
+ });
904
+ agent.ws.close(1001, "Server shutdown");
753
905
  }
754
- agentPool.clear();
755
- // Reject all pending requests
756
- for (const [, pending] of pendingRequests) {
757
- clearTimeout(pending.timer);
758
- pending.resolve({ success: false, error: "Gateway shutting down" });
759
- }
760
- pendingRequests.clear();
761
- if (wss) {
762
- wss.close();
763
- wss = null;
764
- }
765
- console.log("[local-agent] Gateway shut down");
906
+ }
907
+ agentPool.clear();
908
+
909
+ // Reject all pending requests
910
+ for (const [, pending] of pendingRequests) {
911
+ clearTimeout(pending.timer);
912
+ pending.resolve({
913
+ success: false,
914
+ error: "Gateway shutting down"
915
+ });
916
+ }
917
+ pendingRequests.clear();
918
+ if (wss) {
919
+ wss.close();
920
+ wss = null;
921
+ }
922
+ console.log("[local-agent] Gateway shut down");
766
923
  }
924
+ //# sourceMappingURL=local-agent-gateway.js.map