bloby-bot 0.17.2

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 (1128) hide show
  1. package/README.md +593 -0
  2. package/bin/cli.js +1788 -0
  3. package/cli/commands/daemon.ts +31 -0
  4. package/cli/commands/init.ts +40 -0
  5. package/cli/commands/start.ts +91 -0
  6. package/cli/commands/tunnel.ts +175 -0
  7. package/cli/commands/update.ts +170 -0
  8. package/cli/core/base-adapter.ts +99 -0
  9. package/cli/core/cloudflared.ts +71 -0
  10. package/cli/core/config.ts +58 -0
  11. package/cli/core/os-detector.ts +31 -0
  12. package/cli/core/server.ts +87 -0
  13. package/cli/core/types.ts +15 -0
  14. package/cli/index.ts +72 -0
  15. package/cli/platforms/darwin.ts +110 -0
  16. package/cli/platforms/index.ts +20 -0
  17. package/cli/platforms/linux.ts +116 -0
  18. package/cli/platforms/win32.ts +20 -0
  19. package/cli/utils/ui.ts +24 -0
  20. package/components.json +20 -0
  21. package/dist-bloby/assets/bloby-CMybOOCK.js +37 -0
  22. package/dist-bloby/assets/globals-CCAaaNDA.css +2 -0
  23. package/dist-bloby/assets/globals-Eq8C57hc.js +18 -0
  24. package/dist-bloby/assets/onboard-J0aqq4XH.js +1 -0
  25. package/dist-bloby/bloby.html +28 -0
  26. package/dist-bloby/onboard.html +14 -0
  27. package/package.json +103 -0
  28. package/postcss.config.js +5 -0
  29. package/scripts/install +316 -0
  30. package/scripts/install.ps1 +351 -0
  31. package/scripts/install.sh +322 -0
  32. package/scripts/postinstall.js +137 -0
  33. package/shared/ai.ts +141 -0
  34. package/shared/config.ts +68 -0
  35. package/shared/logger.ts +13 -0
  36. package/shared/paths.ts +20 -0
  37. package/shared/relay.ts +148 -0
  38. package/supervisor/app-ws.js +200 -0
  39. package/supervisor/backend.ts +143 -0
  40. package/supervisor/bloby-agent.ts +299 -0
  41. package/supervisor/channels/manager.ts +618 -0
  42. package/supervisor/channels/types.ts +59 -0
  43. package/supervisor/channels/whatsapp.ts +436 -0
  44. package/supervisor/chat/ARCHITECTURE.md +89 -0
  45. package/supervisor/chat/OnboardWizard.tsx +2353 -0
  46. package/supervisor/chat/bloby-main.tsx +567 -0
  47. package/supervisor/chat/bloby.html +26 -0
  48. package/supervisor/chat/onboard-main.tsx +19 -0
  49. package/supervisor/chat/onboard.html +12 -0
  50. package/supervisor/chat/src/components/Chat/AudioBubble.tsx +117 -0
  51. package/supervisor/chat/src/components/Chat/ChatView.tsx +25 -0
  52. package/supervisor/chat/src/components/Chat/ImageLightbox.tsx +86 -0
  53. package/supervisor/chat/src/components/Chat/InputBar.tsx +508 -0
  54. package/supervisor/chat/src/components/Chat/MessageBubble.tsx +226 -0
  55. package/supervisor/chat/src/components/Chat/MessageList.tsx +126 -0
  56. package/supervisor/chat/src/components/Chat/TypingIndicator.tsx +47 -0
  57. package/supervisor/chat/src/components/LoginScreen.tsx +280 -0
  58. package/supervisor/chat/src/hooks/useBlobyChat.ts +266 -0
  59. package/supervisor/chat/src/hooks/useChat.ts +237 -0
  60. package/supervisor/chat/src/hooks/useSpeechRecognition.ts +137 -0
  61. package/supervisor/chat/src/lib/auth.ts +38 -0
  62. package/supervisor/chat/src/lib/ws-client.ts +126 -0
  63. package/supervisor/chat/src/styles/globals.css +116 -0
  64. package/supervisor/file-saver.ts +50 -0
  65. package/supervisor/index.ts +1537 -0
  66. package/supervisor/scheduler.ts +309 -0
  67. package/supervisor/tunnel.ts +156 -0
  68. package/supervisor/vite-dev.ts +72 -0
  69. package/supervisor/widget.js +441 -0
  70. package/tsconfig.json +20 -0
  71. package/vite.bloby.config.ts +43 -0
  72. package/vite.config.ts +68 -0
  73. package/worker/claude-auth.ts +282 -0
  74. package/worker/codex-auth.ts +199 -0
  75. package/worker/db.ts +198 -0
  76. package/worker/index.ts +886 -0
  77. package/worker/prompts/bloby-system-prompt.txt +739 -0
  78. package/workspace/.backend.log +1 -0
  79. package/workspace/.env +3 -0
  80. package/workspace/CRONS.json +1 -0
  81. package/workspace/MEMORY.md +0 -0
  82. package/workspace/MYHUMAN.md +0 -0
  83. package/workspace/MYSELF.md +20 -0
  84. package/workspace/PULSE.json +8 -0
  85. package/workspace/app.db +0 -0
  86. package/workspace/backend/index.ts +52 -0
  87. package/workspace/client/index.html +75 -0
  88. package/workspace/client/public/.gitkeep +0 -0
  89. package/workspace/client/public/arrow.png +0 -0
  90. package/workspace/client/public/bloby-badge.png +0 -0
  91. package/workspace/client/public/bloby-icon-192.png +0 -0
  92. package/workspace/client/public/bloby-icon-512.png +0 -0
  93. package/workspace/client/public/bloby.png +0 -0
  94. package/workspace/client/public/bloby_frame1.png +0 -0
  95. package/workspace/client/public/bloby_happy.mov +0 -0
  96. package/workspace/client/public/bloby_happy.webm +0 -0
  97. package/workspace/client/public/bloby_happy_reappearing.mov +0 -0
  98. package/workspace/client/public/bloby_happy_reappearing.webm +0 -0
  99. package/workspace/client/public/bloby_say_hi.mov +0 -0
  100. package/workspace/client/public/bloby_say_hi.webm +0 -0
  101. package/workspace/client/public/bloby_tilts.webm +0 -0
  102. package/workspace/client/public/icons/claude.png +0 -0
  103. package/workspace/client/public/icons/codex.png +0 -0
  104. package/workspace/client/public/icons/openai.svg +15 -0
  105. package/workspace/client/public/manifest.json +23 -0
  106. package/workspace/client/public/spritesheet.webp +0 -0
  107. package/workspace/client/public/sw.js +136 -0
  108. package/workspace/client/src/App.tsx +191 -0
  109. package/workspace/client/src/components/Dashboard/DashboardPage.tsx +134 -0
  110. package/workspace/client/src/components/ErrorBoundary.tsx +23 -0
  111. package/workspace/client/src/components/Layout/DashboardLayout.tsx +56 -0
  112. package/workspace/client/src/components/Layout/Footer.tsx +14 -0
  113. package/workspace/client/src/components/Layout/MobileNav.tsx +30 -0
  114. package/workspace/client/src/components/Layout/Sidebar.tsx +110 -0
  115. package/workspace/client/src/components/deleteme_onboarding/WorkspaceTour.tsx +104 -0
  116. package/workspace/client/src/components/deleteme_onboarding/tour-theme.css +75 -0
  117. package/workspace/client/src/components/ui/avatar.tsx +109 -0
  118. package/workspace/client/src/components/ui/badge.tsx +48 -0
  119. package/workspace/client/src/components/ui/button.tsx +64 -0
  120. package/workspace/client/src/components/ui/card.tsx +92 -0
  121. package/workspace/client/src/components/ui/dialog.tsx +156 -0
  122. package/workspace/client/src/components/ui/dropdown-menu.tsx +257 -0
  123. package/workspace/client/src/components/ui/input.tsx +21 -0
  124. package/workspace/client/src/components/ui/scroll-area.tsx +58 -0
  125. package/workspace/client/src/components/ui/select.tsx +190 -0
  126. package/workspace/client/src/components/ui/separator.tsx +28 -0
  127. package/workspace/client/src/components/ui/sheet.tsx +142 -0
  128. package/workspace/client/src/components/ui/skeleton.tsx +13 -0
  129. package/workspace/client/src/components/ui/switch.tsx +33 -0
  130. package/workspace/client/src/components/ui/tabs.tsx +89 -0
  131. package/workspace/client/src/components/ui/textarea.tsx +18 -0
  132. package/workspace/client/src/components/ui/tooltip.tsx +55 -0
  133. package/workspace/client/src/lib/utils.ts +6 -0
  134. package/workspace/client/src/main.tsx +20 -0
  135. package/workspace/client/src/styles/globals.css +119 -0
  136. package/workspace/node_modules/.package-lock.json +1248 -0
  137. package/workspace/node_modules/.vite/deps/_metadata.json +116 -0
  138. package/workspace/node_modules/.vite/deps/clsx.js +18 -0
  139. package/workspace/node_modules/.vite/deps/clsx.js.map +1 -0
  140. package/workspace/node_modules/.vite/deps/driver__js.js +581 -0
  141. package/workspace/node_modules/.vite/deps/driver__js.js.map +1 -0
  142. package/workspace/node_modules/.vite/deps/framer-motion.js +13761 -0
  143. package/workspace/node_modules/.vite/deps/framer-motion.js.map +1 -0
  144. package/workspace/node_modules/.vite/deps/lucide-react.js +34357 -0
  145. package/workspace/node_modules/.vite/deps/lucide-react.js.map +1 -0
  146. package/workspace/node_modules/.vite/deps/package.json +3 -0
  147. package/workspace/node_modules/.vite/deps/radix-ui.js +13835 -0
  148. package/workspace/node_modules/.vite/deps/radix-ui.js.map +1 -0
  149. package/workspace/node_modules/.vite/deps/react-3_O8oni9.js +799 -0
  150. package/workspace/node_modules/.vite/deps/react-3_O8oni9.js.map +1 -0
  151. package/workspace/node_modules/.vite/deps/react-dom.js +185 -0
  152. package/workspace/node_modules/.vite/deps/react-dom.js.map +1 -0
  153. package/workspace/node_modules/.vite/deps/react-dom_client.js +14384 -0
  154. package/workspace/node_modules/.vite/deps/react-dom_client.js.map +1 -0
  155. package/workspace/node_modules/.vite/deps/react-router.js +9785 -0
  156. package/workspace/node_modules/.vite/deps/react-router.js.map +1 -0
  157. package/workspace/node_modules/.vite/deps/react.js +2 -0
  158. package/workspace/node_modules/.vite/deps/react_jsx-dev-runtime.js +204 -0
  159. package/workspace/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +1 -0
  160. package/workspace/node_modules/.vite/deps/react_jsx-runtime.js +209 -0
  161. package/workspace/node_modules/.vite/deps/react_jsx-runtime.js.map +1 -0
  162. package/workspace/node_modules/.vite/deps/recharts.js +34142 -0
  163. package/workspace/node_modules/.vite/deps/recharts.js.map +1 -0
  164. package/workspace/node_modules/.vite/deps/sonner.js +943 -0
  165. package/workspace/node_modules/.vite/deps/sonner.js.map +1 -0
  166. package/workspace/node_modules/.vite/deps/tailwind-merge.js +2025 -0
  167. package/workspace/node_modules/.vite/deps/tailwind-merge.js.map +1 -0
  168. package/workspace/node_modules/.vite/deps/use-sync-external-store.js +27 -0
  169. package/workspace/node_modules/.vite/deps/use-sync-external-store.js.map +1 -0
  170. package/workspace/node_modules/.vite/deps/use-sync-external-store_shim.js +75 -0
  171. package/workspace/node_modules/.vite/deps/use-sync-external-store_shim.js.map +1 -0
  172. package/workspace/node_modules/.vite/deps/zustand.js +49 -0
  173. package/workspace/node_modules/.vite/deps/zustand.js.map +1 -0
  174. package/workspace/node_modules/accepts/HISTORY.md +250 -0
  175. package/workspace/node_modules/accepts/LICENSE +23 -0
  176. package/workspace/node_modules/accepts/README.md +140 -0
  177. package/workspace/node_modules/accepts/index.js +238 -0
  178. package/workspace/node_modules/accepts/package.json +47 -0
  179. package/workspace/node_modules/base64-js/LICENSE +21 -0
  180. package/workspace/node_modules/base64-js/README.md +34 -0
  181. package/workspace/node_modules/base64-js/base64js.min.js +1 -0
  182. package/workspace/node_modules/base64-js/index.d.ts +3 -0
  183. package/workspace/node_modules/base64-js/index.js +150 -0
  184. package/workspace/node_modules/base64-js/package.json +47 -0
  185. package/workspace/node_modules/better-sqlite3/LICENSE +21 -0
  186. package/workspace/node_modules/better-sqlite3/README.md +99 -0
  187. package/workspace/node_modules/better-sqlite3/binding.gyp +38 -0
  188. package/workspace/node_modules/better-sqlite3/build/Release/better_sqlite3.node +0 -0
  189. package/workspace/node_modules/better-sqlite3/deps/common.gypi +68 -0
  190. package/workspace/node_modules/better-sqlite3/deps/copy.js +31 -0
  191. package/workspace/node_modules/better-sqlite3/deps/defines.gypi +41 -0
  192. package/workspace/node_modules/better-sqlite3/deps/download.sh +122 -0
  193. package/workspace/node_modules/better-sqlite3/deps/patches/1208.patch +15 -0
  194. package/workspace/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +265994 -0
  195. package/workspace/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +13968 -0
  196. package/workspace/node_modules/better-sqlite3/deps/sqlite3/sqlite3ext.h +730 -0
  197. package/workspace/node_modules/better-sqlite3/deps/sqlite3.gyp +80 -0
  198. package/workspace/node_modules/better-sqlite3/deps/test_extension.c +21 -0
  199. package/workspace/node_modules/better-sqlite3/lib/database.js +90 -0
  200. package/workspace/node_modules/better-sqlite3/lib/index.js +3 -0
  201. package/workspace/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
  202. package/workspace/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
  203. package/workspace/node_modules/better-sqlite3/lib/methods/function.js +31 -0
  204. package/workspace/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
  205. package/workspace/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
  206. package/workspace/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
  207. package/workspace/node_modules/better-sqlite3/lib/methods/table.js +189 -0
  208. package/workspace/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
  209. package/workspace/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
  210. package/workspace/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
  211. package/workspace/node_modules/better-sqlite3/lib/util.js +12 -0
  212. package/workspace/node_modules/better-sqlite3/package.json +59 -0
  213. package/workspace/node_modules/better-sqlite3/src/addon.cpp +47 -0
  214. package/workspace/node_modules/better-sqlite3/src/better_sqlite3.cpp +74 -0
  215. package/workspace/node_modules/better-sqlite3/src/objects/backup.cpp +120 -0
  216. package/workspace/node_modules/better-sqlite3/src/objects/backup.hpp +36 -0
  217. package/workspace/node_modules/better-sqlite3/src/objects/database.cpp +417 -0
  218. package/workspace/node_modules/better-sqlite3/src/objects/database.hpp +103 -0
  219. package/workspace/node_modules/better-sqlite3/src/objects/statement-iterator.cpp +113 -0
  220. package/workspace/node_modules/better-sqlite3/src/objects/statement-iterator.hpp +50 -0
  221. package/workspace/node_modules/better-sqlite3/src/objects/statement.cpp +383 -0
  222. package/workspace/node_modules/better-sqlite3/src/objects/statement.hpp +58 -0
  223. package/workspace/node_modules/better-sqlite3/src/util/bind-map.cpp +73 -0
  224. package/workspace/node_modules/better-sqlite3/src/util/binder.cpp +193 -0
  225. package/workspace/node_modules/better-sqlite3/src/util/constants.cpp +172 -0
  226. package/workspace/node_modules/better-sqlite3/src/util/custom-aggregate.cpp +121 -0
  227. package/workspace/node_modules/better-sqlite3/src/util/custom-function.cpp +59 -0
  228. package/workspace/node_modules/better-sqlite3/src/util/custom-table.cpp +409 -0
  229. package/workspace/node_modules/better-sqlite3/src/util/data-converter.cpp +17 -0
  230. package/workspace/node_modules/better-sqlite3/src/util/data.cpp +194 -0
  231. package/workspace/node_modules/better-sqlite3/src/util/helpers.cpp +109 -0
  232. package/workspace/node_modules/better-sqlite3/src/util/macros.cpp +83 -0
  233. package/workspace/node_modules/better-sqlite3/src/util/query-macros.cpp +71 -0
  234. package/workspace/node_modules/better-sqlite3/src/util/row-builder.cpp +49 -0
  235. package/workspace/node_modules/bindings/LICENSE.md +22 -0
  236. package/workspace/node_modules/bindings/README.md +98 -0
  237. package/workspace/node_modules/bindings/bindings.js +221 -0
  238. package/workspace/node_modules/bindings/package.json +28 -0
  239. package/workspace/node_modules/bl/.travis.yml +17 -0
  240. package/workspace/node_modules/bl/BufferList.js +396 -0
  241. package/workspace/node_modules/bl/LICENSE.md +13 -0
  242. package/workspace/node_modules/bl/README.md +247 -0
  243. package/workspace/node_modules/bl/bl.js +84 -0
  244. package/workspace/node_modules/bl/package.json +37 -0
  245. package/workspace/node_modules/bl/test/convert.js +21 -0
  246. package/workspace/node_modules/bl/test/indexOf.js +492 -0
  247. package/workspace/node_modules/bl/test/isBufferList.js +32 -0
  248. package/workspace/node_modules/bl/test/test.js +869 -0
  249. package/workspace/node_modules/body-parser/LICENSE +23 -0
  250. package/workspace/node_modules/body-parser/README.md +494 -0
  251. package/workspace/node_modules/body-parser/index.js +71 -0
  252. package/workspace/node_modules/body-parser/lib/read.js +247 -0
  253. package/workspace/node_modules/body-parser/lib/types/json.js +158 -0
  254. package/workspace/node_modules/body-parser/lib/types/raw.js +42 -0
  255. package/workspace/node_modules/body-parser/lib/types/text.js +36 -0
  256. package/workspace/node_modules/body-parser/lib/types/urlencoded.js +142 -0
  257. package/workspace/node_modules/body-parser/lib/utils.js +98 -0
  258. package/workspace/node_modules/body-parser/package.json +52 -0
  259. package/workspace/node_modules/buffer/AUTHORS.md +70 -0
  260. package/workspace/node_modules/buffer/LICENSE +21 -0
  261. package/workspace/node_modules/buffer/README.md +410 -0
  262. package/workspace/node_modules/buffer/index.d.ts +186 -0
  263. package/workspace/node_modules/buffer/index.js +1817 -0
  264. package/workspace/node_modules/buffer/package.json +96 -0
  265. package/workspace/node_modules/bytes/History.md +97 -0
  266. package/workspace/node_modules/bytes/LICENSE +23 -0
  267. package/workspace/node_modules/bytes/Readme.md +152 -0
  268. package/workspace/node_modules/bytes/index.js +170 -0
  269. package/workspace/node_modules/bytes/package.json +42 -0
  270. package/workspace/node_modules/call-bind-apply-helpers/.eslintrc +17 -0
  271. package/workspace/node_modules/call-bind-apply-helpers/.github/FUNDING.yml +12 -0
  272. package/workspace/node_modules/call-bind-apply-helpers/.nycrc +9 -0
  273. package/workspace/node_modules/call-bind-apply-helpers/CHANGELOG.md +30 -0
  274. package/workspace/node_modules/call-bind-apply-helpers/LICENSE +21 -0
  275. package/workspace/node_modules/call-bind-apply-helpers/README.md +62 -0
  276. package/workspace/node_modules/call-bind-apply-helpers/actualApply.d.ts +1 -0
  277. package/workspace/node_modules/call-bind-apply-helpers/actualApply.js +10 -0
  278. package/workspace/node_modules/call-bind-apply-helpers/applyBind.d.ts +19 -0
  279. package/workspace/node_modules/call-bind-apply-helpers/applyBind.js +10 -0
  280. package/workspace/node_modules/call-bind-apply-helpers/functionApply.d.ts +1 -0
  281. package/workspace/node_modules/call-bind-apply-helpers/functionApply.js +4 -0
  282. package/workspace/node_modules/call-bind-apply-helpers/functionCall.d.ts +1 -0
  283. package/workspace/node_modules/call-bind-apply-helpers/functionCall.js +4 -0
  284. package/workspace/node_modules/call-bind-apply-helpers/index.d.ts +64 -0
  285. package/workspace/node_modules/call-bind-apply-helpers/index.js +15 -0
  286. package/workspace/node_modules/call-bind-apply-helpers/package.json +85 -0
  287. package/workspace/node_modules/call-bind-apply-helpers/reflectApply.d.ts +3 -0
  288. package/workspace/node_modules/call-bind-apply-helpers/reflectApply.js +4 -0
  289. package/workspace/node_modules/call-bind-apply-helpers/test/index.js +63 -0
  290. package/workspace/node_modules/call-bind-apply-helpers/tsconfig.json +9 -0
  291. package/workspace/node_modules/call-bound/.eslintrc +13 -0
  292. package/workspace/node_modules/call-bound/.github/FUNDING.yml +12 -0
  293. package/workspace/node_modules/call-bound/.nycrc +9 -0
  294. package/workspace/node_modules/call-bound/CHANGELOG.md +42 -0
  295. package/workspace/node_modules/call-bound/LICENSE +21 -0
  296. package/workspace/node_modules/call-bound/README.md +53 -0
  297. package/workspace/node_modules/call-bound/index.d.ts +94 -0
  298. package/workspace/node_modules/call-bound/index.js +19 -0
  299. package/workspace/node_modules/call-bound/package.json +99 -0
  300. package/workspace/node_modules/call-bound/test/index.js +61 -0
  301. package/workspace/node_modules/call-bound/tsconfig.json +10 -0
  302. package/workspace/node_modules/chownr/LICENSE +15 -0
  303. package/workspace/node_modules/chownr/README.md +3 -0
  304. package/workspace/node_modules/chownr/chownr.js +167 -0
  305. package/workspace/node_modules/chownr/package.json +29 -0
  306. package/workspace/node_modules/content-disposition/HISTORY.md +72 -0
  307. package/workspace/node_modules/content-disposition/LICENSE +22 -0
  308. package/workspace/node_modules/content-disposition/README.md +142 -0
  309. package/workspace/node_modules/content-disposition/index.js +458 -0
  310. package/workspace/node_modules/content-disposition/package.json +43 -0
  311. package/workspace/node_modules/content-type/HISTORY.md +29 -0
  312. package/workspace/node_modules/content-type/LICENSE +22 -0
  313. package/workspace/node_modules/content-type/README.md +94 -0
  314. package/workspace/node_modules/content-type/index.js +225 -0
  315. package/workspace/node_modules/content-type/package.json +42 -0
  316. package/workspace/node_modules/cookie/LICENSE +24 -0
  317. package/workspace/node_modules/cookie/README.md +317 -0
  318. package/workspace/node_modules/cookie/SECURITY.md +25 -0
  319. package/workspace/node_modules/cookie/index.js +335 -0
  320. package/workspace/node_modules/cookie/package.json +44 -0
  321. package/workspace/node_modules/cookie-signature/History.md +70 -0
  322. package/workspace/node_modules/cookie-signature/LICENSE +22 -0
  323. package/workspace/node_modules/cookie-signature/Readme.md +23 -0
  324. package/workspace/node_modules/cookie-signature/index.js +47 -0
  325. package/workspace/node_modules/cookie-signature/package.json +24 -0
  326. package/workspace/node_modules/debug/LICENSE +20 -0
  327. package/workspace/node_modules/debug/README.md +481 -0
  328. package/workspace/node_modules/debug/package.json +64 -0
  329. package/workspace/node_modules/debug/src/browser.js +272 -0
  330. package/workspace/node_modules/debug/src/common.js +292 -0
  331. package/workspace/node_modules/debug/src/index.js +10 -0
  332. package/workspace/node_modules/debug/src/node.js +263 -0
  333. package/workspace/node_modules/decompress-response/index.d.ts +22 -0
  334. package/workspace/node_modules/decompress-response/index.js +58 -0
  335. package/workspace/node_modules/decompress-response/license +9 -0
  336. package/workspace/node_modules/decompress-response/package.json +56 -0
  337. package/workspace/node_modules/decompress-response/readme.md +48 -0
  338. package/workspace/node_modules/deep-extend/CHANGELOG.md +46 -0
  339. package/workspace/node_modules/deep-extend/LICENSE +20 -0
  340. package/workspace/node_modules/deep-extend/README.md +91 -0
  341. package/workspace/node_modules/deep-extend/index.js +1 -0
  342. package/workspace/node_modules/deep-extend/lib/deep-extend.js +150 -0
  343. package/workspace/node_modules/deep-extend/package.json +62 -0
  344. package/workspace/node_modules/depd/History.md +103 -0
  345. package/workspace/node_modules/depd/LICENSE +22 -0
  346. package/workspace/node_modules/depd/Readme.md +280 -0
  347. package/workspace/node_modules/depd/index.js +538 -0
  348. package/workspace/node_modules/depd/lib/browser/index.js +77 -0
  349. package/workspace/node_modules/depd/package.json +45 -0
  350. package/workspace/node_modules/detect-libc/LICENSE +201 -0
  351. package/workspace/node_modules/detect-libc/README.md +163 -0
  352. package/workspace/node_modules/detect-libc/index.d.ts +14 -0
  353. package/workspace/node_modules/detect-libc/lib/detect-libc.js +313 -0
  354. package/workspace/node_modules/detect-libc/lib/elf.js +39 -0
  355. package/workspace/node_modules/detect-libc/lib/filesystem.js +51 -0
  356. package/workspace/node_modules/detect-libc/lib/process.js +24 -0
  357. package/workspace/node_modules/detect-libc/package.json +44 -0
  358. package/workspace/node_modules/dunder-proto/.eslintrc +5 -0
  359. package/workspace/node_modules/dunder-proto/.github/FUNDING.yml +12 -0
  360. package/workspace/node_modules/dunder-proto/.nycrc +13 -0
  361. package/workspace/node_modules/dunder-proto/CHANGELOG.md +24 -0
  362. package/workspace/node_modules/dunder-proto/LICENSE +21 -0
  363. package/workspace/node_modules/dunder-proto/README.md +54 -0
  364. package/workspace/node_modules/dunder-proto/get.d.ts +5 -0
  365. package/workspace/node_modules/dunder-proto/get.js +30 -0
  366. package/workspace/node_modules/dunder-proto/package.json +76 -0
  367. package/workspace/node_modules/dunder-proto/set.d.ts +5 -0
  368. package/workspace/node_modules/dunder-proto/set.js +35 -0
  369. package/workspace/node_modules/dunder-proto/test/get.js +34 -0
  370. package/workspace/node_modules/dunder-proto/test/index.js +4 -0
  371. package/workspace/node_modules/dunder-proto/test/set.js +50 -0
  372. package/workspace/node_modules/dunder-proto/tsconfig.json +9 -0
  373. package/workspace/node_modules/ee-first/LICENSE +22 -0
  374. package/workspace/node_modules/ee-first/README.md +80 -0
  375. package/workspace/node_modules/ee-first/index.js +95 -0
  376. package/workspace/node_modules/ee-first/package.json +29 -0
  377. package/workspace/node_modules/encodeurl/LICENSE +22 -0
  378. package/workspace/node_modules/encodeurl/README.md +109 -0
  379. package/workspace/node_modules/encodeurl/index.js +60 -0
  380. package/workspace/node_modules/encodeurl/package.json +40 -0
  381. package/workspace/node_modules/end-of-stream/LICENSE +21 -0
  382. package/workspace/node_modules/end-of-stream/README.md +54 -0
  383. package/workspace/node_modules/end-of-stream/index.js +96 -0
  384. package/workspace/node_modules/end-of-stream/package.json +37 -0
  385. package/workspace/node_modules/es-define-property/.eslintrc +13 -0
  386. package/workspace/node_modules/es-define-property/.github/FUNDING.yml +12 -0
  387. package/workspace/node_modules/es-define-property/.nycrc +9 -0
  388. package/workspace/node_modules/es-define-property/CHANGELOG.md +29 -0
  389. package/workspace/node_modules/es-define-property/LICENSE +21 -0
  390. package/workspace/node_modules/es-define-property/README.md +49 -0
  391. package/workspace/node_modules/es-define-property/index.d.ts +3 -0
  392. package/workspace/node_modules/es-define-property/index.js +14 -0
  393. package/workspace/node_modules/es-define-property/package.json +81 -0
  394. package/workspace/node_modules/es-define-property/test/index.js +56 -0
  395. package/workspace/node_modules/es-define-property/tsconfig.json +10 -0
  396. package/workspace/node_modules/es-errors/.eslintrc +5 -0
  397. package/workspace/node_modules/es-errors/.github/FUNDING.yml +12 -0
  398. package/workspace/node_modules/es-errors/CHANGELOG.md +40 -0
  399. package/workspace/node_modules/es-errors/LICENSE +21 -0
  400. package/workspace/node_modules/es-errors/README.md +55 -0
  401. package/workspace/node_modules/es-errors/eval.d.ts +3 -0
  402. package/workspace/node_modules/es-errors/eval.js +4 -0
  403. package/workspace/node_modules/es-errors/index.d.ts +3 -0
  404. package/workspace/node_modules/es-errors/index.js +4 -0
  405. package/workspace/node_modules/es-errors/package.json +80 -0
  406. package/workspace/node_modules/es-errors/range.d.ts +3 -0
  407. package/workspace/node_modules/es-errors/range.js +4 -0
  408. package/workspace/node_modules/es-errors/ref.d.ts +3 -0
  409. package/workspace/node_modules/es-errors/ref.js +4 -0
  410. package/workspace/node_modules/es-errors/syntax.d.ts +3 -0
  411. package/workspace/node_modules/es-errors/syntax.js +4 -0
  412. package/workspace/node_modules/es-errors/test/index.js +19 -0
  413. package/workspace/node_modules/es-errors/tsconfig.json +49 -0
  414. package/workspace/node_modules/es-errors/type.d.ts +3 -0
  415. package/workspace/node_modules/es-errors/type.js +4 -0
  416. package/workspace/node_modules/es-errors/uri.d.ts +3 -0
  417. package/workspace/node_modules/es-errors/uri.js +4 -0
  418. package/workspace/node_modules/es-object-atoms/.eslintrc +16 -0
  419. package/workspace/node_modules/es-object-atoms/.github/FUNDING.yml +12 -0
  420. package/workspace/node_modules/es-object-atoms/CHANGELOG.md +37 -0
  421. package/workspace/node_modules/es-object-atoms/LICENSE +21 -0
  422. package/workspace/node_modules/es-object-atoms/README.md +63 -0
  423. package/workspace/node_modules/es-object-atoms/RequireObjectCoercible.d.ts +3 -0
  424. package/workspace/node_modules/es-object-atoms/RequireObjectCoercible.js +11 -0
  425. package/workspace/node_modules/es-object-atoms/ToObject.d.ts +7 -0
  426. package/workspace/node_modules/es-object-atoms/ToObject.js +10 -0
  427. package/workspace/node_modules/es-object-atoms/index.d.ts +3 -0
  428. package/workspace/node_modules/es-object-atoms/index.js +4 -0
  429. package/workspace/node_modules/es-object-atoms/isObject.d.ts +3 -0
  430. package/workspace/node_modules/es-object-atoms/isObject.js +6 -0
  431. package/workspace/node_modules/es-object-atoms/package.json +80 -0
  432. package/workspace/node_modules/es-object-atoms/test/index.js +38 -0
  433. package/workspace/node_modules/es-object-atoms/tsconfig.json +6 -0
  434. package/workspace/node_modules/escape-html/LICENSE +24 -0
  435. package/workspace/node_modules/escape-html/Readme.md +43 -0
  436. package/workspace/node_modules/escape-html/index.js +78 -0
  437. package/workspace/node_modules/escape-html/package.json +24 -0
  438. package/workspace/node_modules/etag/HISTORY.md +83 -0
  439. package/workspace/node_modules/etag/LICENSE +22 -0
  440. package/workspace/node_modules/etag/README.md +159 -0
  441. package/workspace/node_modules/etag/index.js +131 -0
  442. package/workspace/node_modules/etag/package.json +47 -0
  443. package/workspace/node_modules/expand-template/.travis.yml +6 -0
  444. package/workspace/node_modules/expand-template/LICENSE +21 -0
  445. package/workspace/node_modules/expand-template/README.md +43 -0
  446. package/workspace/node_modules/expand-template/index.js +26 -0
  447. package/workspace/node_modules/expand-template/package.json +29 -0
  448. package/workspace/node_modules/expand-template/test.js +67 -0
  449. package/workspace/node_modules/express/LICENSE +24 -0
  450. package/workspace/node_modules/express/Readme.md +276 -0
  451. package/workspace/node_modules/express/index.js +11 -0
  452. package/workspace/node_modules/express/lib/application.js +631 -0
  453. package/workspace/node_modules/express/lib/express.js +81 -0
  454. package/workspace/node_modules/express/lib/request.js +514 -0
  455. package/workspace/node_modules/express/lib/response.js +1053 -0
  456. package/workspace/node_modules/express/lib/utils.js +271 -0
  457. package/workspace/node_modules/express/lib/view.js +205 -0
  458. package/workspace/node_modules/express/package.json +99 -0
  459. package/workspace/node_modules/file-uri-to-path/.travis.yml +30 -0
  460. package/workspace/node_modules/file-uri-to-path/History.md +21 -0
  461. package/workspace/node_modules/file-uri-to-path/LICENSE +20 -0
  462. package/workspace/node_modules/file-uri-to-path/README.md +74 -0
  463. package/workspace/node_modules/file-uri-to-path/index.d.ts +2 -0
  464. package/workspace/node_modules/file-uri-to-path/index.js +66 -0
  465. package/workspace/node_modules/file-uri-to-path/package.json +32 -0
  466. package/workspace/node_modules/file-uri-to-path/test/test.js +24 -0
  467. package/workspace/node_modules/file-uri-to-path/test/tests.json +13 -0
  468. package/workspace/node_modules/finalhandler/HISTORY.md +239 -0
  469. package/workspace/node_modules/finalhandler/LICENSE +22 -0
  470. package/workspace/node_modules/finalhandler/README.md +150 -0
  471. package/workspace/node_modules/finalhandler/index.js +293 -0
  472. package/workspace/node_modules/finalhandler/package.json +47 -0
  473. package/workspace/node_modules/forwarded/HISTORY.md +21 -0
  474. package/workspace/node_modules/forwarded/LICENSE +22 -0
  475. package/workspace/node_modules/forwarded/README.md +57 -0
  476. package/workspace/node_modules/forwarded/index.js +90 -0
  477. package/workspace/node_modules/forwarded/package.json +45 -0
  478. package/workspace/node_modules/fresh/HISTORY.md +80 -0
  479. package/workspace/node_modules/fresh/LICENSE +23 -0
  480. package/workspace/node_modules/fresh/README.md +117 -0
  481. package/workspace/node_modules/fresh/index.js +136 -0
  482. package/workspace/node_modules/fresh/package.json +46 -0
  483. package/workspace/node_modules/fs-constants/LICENSE +21 -0
  484. package/workspace/node_modules/fs-constants/README.md +26 -0
  485. package/workspace/node_modules/fs-constants/browser.js +1 -0
  486. package/workspace/node_modules/fs-constants/index.js +1 -0
  487. package/workspace/node_modules/fs-constants/package.json +19 -0
  488. package/workspace/node_modules/function-bind/.eslintrc +21 -0
  489. package/workspace/node_modules/function-bind/.github/FUNDING.yml +12 -0
  490. package/workspace/node_modules/function-bind/.github/SECURITY.md +3 -0
  491. package/workspace/node_modules/function-bind/.nycrc +13 -0
  492. package/workspace/node_modules/function-bind/CHANGELOG.md +136 -0
  493. package/workspace/node_modules/function-bind/LICENSE +20 -0
  494. package/workspace/node_modules/function-bind/README.md +46 -0
  495. package/workspace/node_modules/function-bind/implementation.js +84 -0
  496. package/workspace/node_modules/function-bind/index.js +5 -0
  497. package/workspace/node_modules/function-bind/package.json +87 -0
  498. package/workspace/node_modules/function-bind/test/.eslintrc +9 -0
  499. package/workspace/node_modules/function-bind/test/index.js +252 -0
  500. package/workspace/node_modules/get-intrinsic/.eslintrc +42 -0
  501. package/workspace/node_modules/get-intrinsic/.github/FUNDING.yml +12 -0
  502. package/workspace/node_modules/get-intrinsic/.nycrc +9 -0
  503. package/workspace/node_modules/get-intrinsic/CHANGELOG.md +186 -0
  504. package/workspace/node_modules/get-intrinsic/LICENSE +21 -0
  505. package/workspace/node_modules/get-intrinsic/README.md +71 -0
  506. package/workspace/node_modules/get-intrinsic/index.js +378 -0
  507. package/workspace/node_modules/get-intrinsic/package.json +97 -0
  508. package/workspace/node_modules/get-intrinsic/test/GetIntrinsic.js +274 -0
  509. package/workspace/node_modules/get-proto/.eslintrc +10 -0
  510. package/workspace/node_modules/get-proto/.github/FUNDING.yml +12 -0
  511. package/workspace/node_modules/get-proto/.nycrc +9 -0
  512. package/workspace/node_modules/get-proto/CHANGELOG.md +21 -0
  513. package/workspace/node_modules/get-proto/LICENSE +21 -0
  514. package/workspace/node_modules/get-proto/Object.getPrototypeOf.d.ts +5 -0
  515. package/workspace/node_modules/get-proto/Object.getPrototypeOf.js +6 -0
  516. package/workspace/node_modules/get-proto/README.md +50 -0
  517. package/workspace/node_modules/get-proto/Reflect.getPrototypeOf.d.ts +3 -0
  518. package/workspace/node_modules/get-proto/Reflect.getPrototypeOf.js +4 -0
  519. package/workspace/node_modules/get-proto/index.d.ts +5 -0
  520. package/workspace/node_modules/get-proto/index.js +27 -0
  521. package/workspace/node_modules/get-proto/package.json +81 -0
  522. package/workspace/node_modules/get-proto/test/index.js +68 -0
  523. package/workspace/node_modules/get-proto/tsconfig.json +9 -0
  524. package/workspace/node_modules/github-from-package/.travis.yml +4 -0
  525. package/workspace/node_modules/github-from-package/LICENSE +18 -0
  526. package/workspace/node_modules/github-from-package/example/package.json +8 -0
  527. package/workspace/node_modules/github-from-package/example/url.js +3 -0
  528. package/workspace/node_modules/github-from-package/index.js +17 -0
  529. package/workspace/node_modules/github-from-package/package.json +30 -0
  530. package/workspace/node_modules/github-from-package/readme.markdown +53 -0
  531. package/workspace/node_modules/github-from-package/test/a.json +8 -0
  532. package/workspace/node_modules/github-from-package/test/b.json +5 -0
  533. package/workspace/node_modules/github-from-package/test/c.json +5 -0
  534. package/workspace/node_modules/github-from-package/test/d.json +7 -0
  535. package/workspace/node_modules/github-from-package/test/e.json +5 -0
  536. package/workspace/node_modules/github-from-package/test/url.js +19 -0
  537. package/workspace/node_modules/gopd/.eslintrc +16 -0
  538. package/workspace/node_modules/gopd/.github/FUNDING.yml +12 -0
  539. package/workspace/node_modules/gopd/CHANGELOG.md +45 -0
  540. package/workspace/node_modules/gopd/LICENSE +21 -0
  541. package/workspace/node_modules/gopd/README.md +40 -0
  542. package/workspace/node_modules/gopd/gOPD.d.ts +1 -0
  543. package/workspace/node_modules/gopd/gOPD.js +4 -0
  544. package/workspace/node_modules/gopd/index.d.ts +5 -0
  545. package/workspace/node_modules/gopd/index.js +15 -0
  546. package/workspace/node_modules/gopd/package.json +77 -0
  547. package/workspace/node_modules/gopd/test/index.js +36 -0
  548. package/workspace/node_modules/gopd/tsconfig.json +9 -0
  549. package/workspace/node_modules/has-symbols/.eslintrc +11 -0
  550. package/workspace/node_modules/has-symbols/.github/FUNDING.yml +12 -0
  551. package/workspace/node_modules/has-symbols/.nycrc +9 -0
  552. package/workspace/node_modules/has-symbols/CHANGELOG.md +91 -0
  553. package/workspace/node_modules/has-symbols/LICENSE +21 -0
  554. package/workspace/node_modules/has-symbols/README.md +46 -0
  555. package/workspace/node_modules/has-symbols/index.d.ts +3 -0
  556. package/workspace/node_modules/has-symbols/index.js +14 -0
  557. package/workspace/node_modules/has-symbols/package.json +111 -0
  558. package/workspace/node_modules/has-symbols/shams.d.ts +3 -0
  559. package/workspace/node_modules/has-symbols/shams.js +45 -0
  560. package/workspace/node_modules/has-symbols/test/index.js +22 -0
  561. package/workspace/node_modules/has-symbols/test/shams/core-js.js +29 -0
  562. package/workspace/node_modules/has-symbols/test/shams/get-own-property-symbols.js +29 -0
  563. package/workspace/node_modules/has-symbols/test/tests.js +58 -0
  564. package/workspace/node_modules/has-symbols/tsconfig.json +10 -0
  565. package/workspace/node_modules/hasown/.eslintrc +5 -0
  566. package/workspace/node_modules/hasown/.github/FUNDING.yml +12 -0
  567. package/workspace/node_modules/hasown/.nycrc +13 -0
  568. package/workspace/node_modules/hasown/CHANGELOG.md +40 -0
  569. package/workspace/node_modules/hasown/LICENSE +21 -0
  570. package/workspace/node_modules/hasown/README.md +40 -0
  571. package/workspace/node_modules/hasown/index.d.ts +3 -0
  572. package/workspace/node_modules/hasown/index.js +8 -0
  573. package/workspace/node_modules/hasown/package.json +92 -0
  574. package/workspace/node_modules/hasown/tsconfig.json +6 -0
  575. package/workspace/node_modules/http-errors/HISTORY.md +186 -0
  576. package/workspace/node_modules/http-errors/LICENSE +23 -0
  577. package/workspace/node_modules/http-errors/README.md +169 -0
  578. package/workspace/node_modules/http-errors/index.js +290 -0
  579. package/workspace/node_modules/http-errors/package.json +54 -0
  580. package/workspace/node_modules/iconv-lite/LICENSE +21 -0
  581. package/workspace/node_modules/iconv-lite/README.md +138 -0
  582. package/workspace/node_modules/iconv-lite/encodings/dbcs-codec.js +532 -0
  583. package/workspace/node_modules/iconv-lite/encodings/dbcs-data.js +185 -0
  584. package/workspace/node_modules/iconv-lite/encodings/index.js +23 -0
  585. package/workspace/node_modules/iconv-lite/encodings/internal.js +218 -0
  586. package/workspace/node_modules/iconv-lite/encodings/sbcs-codec.js +75 -0
  587. package/workspace/node_modules/iconv-lite/encodings/sbcs-data-generated.js +451 -0
  588. package/workspace/node_modules/iconv-lite/encodings/sbcs-data.js +178 -0
  589. package/workspace/node_modules/iconv-lite/encodings/tables/big5-added.json +122 -0
  590. package/workspace/node_modules/iconv-lite/encodings/tables/cp936.json +264 -0
  591. package/workspace/node_modules/iconv-lite/encodings/tables/cp949.json +273 -0
  592. package/workspace/node_modules/iconv-lite/encodings/tables/cp950.json +177 -0
  593. package/workspace/node_modules/iconv-lite/encodings/tables/eucjp.json +182 -0
  594. package/workspace/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +1 -0
  595. package/workspace/node_modules/iconv-lite/encodings/tables/gbk-added.json +56 -0
  596. package/workspace/node_modules/iconv-lite/encodings/tables/shiftjis.json +125 -0
  597. package/workspace/node_modules/iconv-lite/encodings/utf16.js +187 -0
  598. package/workspace/node_modules/iconv-lite/encodings/utf32.js +307 -0
  599. package/workspace/node_modules/iconv-lite/encodings/utf7.js +283 -0
  600. package/workspace/node_modules/iconv-lite/lib/bom-handling.js +48 -0
  601. package/workspace/node_modules/iconv-lite/lib/helpers/merge-exports.js +13 -0
  602. package/workspace/node_modules/iconv-lite/lib/index.d.ts +129 -0
  603. package/workspace/node_modules/iconv-lite/lib/index.js +182 -0
  604. package/workspace/node_modules/iconv-lite/lib/streams.js +105 -0
  605. package/workspace/node_modules/iconv-lite/package.json +70 -0
  606. package/workspace/node_modules/iconv-lite/types/encodings.d.ts +423 -0
  607. package/workspace/node_modules/ieee754/LICENSE +11 -0
  608. package/workspace/node_modules/ieee754/README.md +51 -0
  609. package/workspace/node_modules/ieee754/index.d.ts +10 -0
  610. package/workspace/node_modules/ieee754/index.js +85 -0
  611. package/workspace/node_modules/ieee754/package.json +52 -0
  612. package/workspace/node_modules/inherits/LICENSE +16 -0
  613. package/workspace/node_modules/inherits/README.md +42 -0
  614. package/workspace/node_modules/inherits/inherits.js +9 -0
  615. package/workspace/node_modules/inherits/inherits_browser.js +27 -0
  616. package/workspace/node_modules/inherits/package.json +29 -0
  617. package/workspace/node_modules/ini/LICENSE +15 -0
  618. package/workspace/node_modules/ini/README.md +102 -0
  619. package/workspace/node_modules/ini/ini.js +206 -0
  620. package/workspace/node_modules/ini/package.json +33 -0
  621. package/workspace/node_modules/ipaddr.js/LICENSE +19 -0
  622. package/workspace/node_modules/ipaddr.js/README.md +233 -0
  623. package/workspace/node_modules/ipaddr.js/ipaddr.min.js +1 -0
  624. package/workspace/node_modules/ipaddr.js/lib/ipaddr.js +673 -0
  625. package/workspace/node_modules/ipaddr.js/lib/ipaddr.js.d.ts +68 -0
  626. package/workspace/node_modules/ipaddr.js/package.json +35 -0
  627. package/workspace/node_modules/is-promise/LICENSE +19 -0
  628. package/workspace/node_modules/is-promise/index.d.ts +2 -0
  629. package/workspace/node_modules/is-promise/index.js +6 -0
  630. package/workspace/node_modules/is-promise/index.mjs +3 -0
  631. package/workspace/node_modules/is-promise/package.json +30 -0
  632. package/workspace/node_modules/is-promise/readme.md +33 -0
  633. package/workspace/node_modules/math-intrinsics/.eslintrc +16 -0
  634. package/workspace/node_modules/math-intrinsics/.github/FUNDING.yml +12 -0
  635. package/workspace/node_modules/math-intrinsics/CHANGELOG.md +24 -0
  636. package/workspace/node_modules/math-intrinsics/LICENSE +21 -0
  637. package/workspace/node_modules/math-intrinsics/README.md +50 -0
  638. package/workspace/node_modules/math-intrinsics/abs.d.ts +1 -0
  639. package/workspace/node_modules/math-intrinsics/abs.js +4 -0
  640. package/workspace/node_modules/math-intrinsics/constants/maxArrayLength.d.ts +3 -0
  641. package/workspace/node_modules/math-intrinsics/constants/maxArrayLength.js +4 -0
  642. package/workspace/node_modules/math-intrinsics/constants/maxSafeInteger.d.ts +3 -0
  643. package/workspace/node_modules/math-intrinsics/constants/maxSafeInteger.js +5 -0
  644. package/workspace/node_modules/math-intrinsics/constants/maxValue.d.ts +3 -0
  645. package/workspace/node_modules/math-intrinsics/constants/maxValue.js +5 -0
  646. package/workspace/node_modules/math-intrinsics/floor.d.ts +1 -0
  647. package/workspace/node_modules/math-intrinsics/floor.js +4 -0
  648. package/workspace/node_modules/math-intrinsics/isFinite.d.ts +3 -0
  649. package/workspace/node_modules/math-intrinsics/isFinite.js +12 -0
  650. package/workspace/node_modules/math-intrinsics/isInteger.d.ts +3 -0
  651. package/workspace/node_modules/math-intrinsics/isInteger.js +16 -0
  652. package/workspace/node_modules/math-intrinsics/isNaN.d.ts +1 -0
  653. package/workspace/node_modules/math-intrinsics/isNaN.js +6 -0
  654. package/workspace/node_modules/math-intrinsics/isNegativeZero.d.ts +3 -0
  655. package/workspace/node_modules/math-intrinsics/isNegativeZero.js +6 -0
  656. package/workspace/node_modules/math-intrinsics/max.d.ts +1 -0
  657. package/workspace/node_modules/math-intrinsics/max.js +4 -0
  658. package/workspace/node_modules/math-intrinsics/min.d.ts +1 -0
  659. package/workspace/node_modules/math-intrinsics/min.js +4 -0
  660. package/workspace/node_modules/math-intrinsics/mod.d.ts +3 -0
  661. package/workspace/node_modules/math-intrinsics/mod.js +9 -0
  662. package/workspace/node_modules/math-intrinsics/package.json +86 -0
  663. package/workspace/node_modules/math-intrinsics/pow.d.ts +1 -0
  664. package/workspace/node_modules/math-intrinsics/pow.js +4 -0
  665. package/workspace/node_modules/math-intrinsics/round.d.ts +1 -0
  666. package/workspace/node_modules/math-intrinsics/round.js +4 -0
  667. package/workspace/node_modules/math-intrinsics/sign.d.ts +3 -0
  668. package/workspace/node_modules/math-intrinsics/sign.js +11 -0
  669. package/workspace/node_modules/math-intrinsics/test/index.js +192 -0
  670. package/workspace/node_modules/math-intrinsics/tsconfig.json +3 -0
  671. package/workspace/node_modules/media-typer/HISTORY.md +50 -0
  672. package/workspace/node_modules/media-typer/LICENSE +22 -0
  673. package/workspace/node_modules/media-typer/README.md +93 -0
  674. package/workspace/node_modules/media-typer/index.js +143 -0
  675. package/workspace/node_modules/media-typer/package.json +33 -0
  676. package/workspace/node_modules/merge-descriptors/index.d.ts +11 -0
  677. package/workspace/node_modules/merge-descriptors/index.js +26 -0
  678. package/workspace/node_modules/merge-descriptors/license +11 -0
  679. package/workspace/node_modules/merge-descriptors/package.json +50 -0
  680. package/workspace/node_modules/merge-descriptors/readme.md +55 -0
  681. package/workspace/node_modules/mime-db/HISTORY.md +541 -0
  682. package/workspace/node_modules/mime-db/LICENSE +23 -0
  683. package/workspace/node_modules/mime-db/README.md +109 -0
  684. package/workspace/node_modules/mime-db/db.json +9342 -0
  685. package/workspace/node_modules/mime-db/index.js +12 -0
  686. package/workspace/node_modules/mime-db/package.json +56 -0
  687. package/workspace/node_modules/mime-types/HISTORY.md +428 -0
  688. package/workspace/node_modules/mime-types/LICENSE +23 -0
  689. package/workspace/node_modules/mime-types/README.md +126 -0
  690. package/workspace/node_modules/mime-types/index.js +211 -0
  691. package/workspace/node_modules/mime-types/mimeScore.js +57 -0
  692. package/workspace/node_modules/mime-types/package.json +49 -0
  693. package/workspace/node_modules/mimic-response/index.d.ts +17 -0
  694. package/workspace/node_modules/mimic-response/index.js +77 -0
  695. package/workspace/node_modules/mimic-response/license +9 -0
  696. package/workspace/node_modules/mimic-response/package.json +42 -0
  697. package/workspace/node_modules/mimic-response/readme.md +78 -0
  698. package/workspace/node_modules/minimist/.eslintrc +29 -0
  699. package/workspace/node_modules/minimist/.github/FUNDING.yml +12 -0
  700. package/workspace/node_modules/minimist/.nycrc +14 -0
  701. package/workspace/node_modules/minimist/CHANGELOG.md +298 -0
  702. package/workspace/node_modules/minimist/LICENSE +18 -0
  703. package/workspace/node_modules/minimist/README.md +121 -0
  704. package/workspace/node_modules/minimist/example/parse.js +4 -0
  705. package/workspace/node_modules/minimist/index.js +263 -0
  706. package/workspace/node_modules/minimist/package.json +75 -0
  707. package/workspace/node_modules/minimist/test/all_bool.js +34 -0
  708. package/workspace/node_modules/minimist/test/bool.js +177 -0
  709. package/workspace/node_modules/minimist/test/dash.js +43 -0
  710. package/workspace/node_modules/minimist/test/default_bool.js +37 -0
  711. package/workspace/node_modules/minimist/test/dotted.js +24 -0
  712. package/workspace/node_modules/minimist/test/kv_short.js +32 -0
  713. package/workspace/node_modules/minimist/test/long.js +33 -0
  714. package/workspace/node_modules/minimist/test/num.js +38 -0
  715. package/workspace/node_modules/minimist/test/parse.js +209 -0
  716. package/workspace/node_modules/minimist/test/parse_modified.js +11 -0
  717. package/workspace/node_modules/minimist/test/proto.js +64 -0
  718. package/workspace/node_modules/minimist/test/short.js +69 -0
  719. package/workspace/node_modules/minimist/test/stop_early.js +17 -0
  720. package/workspace/node_modules/minimist/test/unknown.js +104 -0
  721. package/workspace/node_modules/minimist/test/whitespace.js +10 -0
  722. package/workspace/node_modules/mkdirp-classic/LICENSE +21 -0
  723. package/workspace/node_modules/mkdirp-classic/README.md +18 -0
  724. package/workspace/node_modules/mkdirp-classic/index.js +98 -0
  725. package/workspace/node_modules/mkdirp-classic/package.json +18 -0
  726. package/workspace/node_modules/ms/index.js +162 -0
  727. package/workspace/node_modules/ms/license.md +21 -0
  728. package/workspace/node_modules/ms/package.json +38 -0
  729. package/workspace/node_modules/ms/readme.md +59 -0
  730. package/workspace/node_modules/napi-build-utils/.github/workflows/run-npm-tests.yml +31 -0
  731. package/workspace/node_modules/napi-build-utils/LICENSE +21 -0
  732. package/workspace/node_modules/napi-build-utils/README.md +52 -0
  733. package/workspace/node_modules/napi-build-utils/index.js +214 -0
  734. package/workspace/node_modules/napi-build-utils/index.md +0 -0
  735. package/workspace/node_modules/napi-build-utils/package.json +42 -0
  736. package/workspace/node_modules/negotiator/HISTORY.md +114 -0
  737. package/workspace/node_modules/negotiator/LICENSE +24 -0
  738. package/workspace/node_modules/negotiator/README.md +212 -0
  739. package/workspace/node_modules/negotiator/index.js +83 -0
  740. package/workspace/node_modules/negotiator/lib/charset.js +169 -0
  741. package/workspace/node_modules/negotiator/lib/encoding.js +205 -0
  742. package/workspace/node_modules/negotiator/lib/language.js +179 -0
  743. package/workspace/node_modules/negotiator/lib/mediaType.js +294 -0
  744. package/workspace/node_modules/negotiator/package.json +43 -0
  745. package/workspace/node_modules/node-abi/LICENSE +21 -0
  746. package/workspace/node_modules/node-abi/README.md +54 -0
  747. package/workspace/node_modules/node-abi/abi_registry.json +439 -0
  748. package/workspace/node_modules/node-abi/index.js +179 -0
  749. package/workspace/node_modules/node-abi/package.json +45 -0
  750. package/workspace/node_modules/object-inspect/.eslintrc +53 -0
  751. package/workspace/node_modules/object-inspect/.github/FUNDING.yml +12 -0
  752. package/workspace/node_modules/object-inspect/.nycrc +13 -0
  753. package/workspace/node_modules/object-inspect/CHANGELOG.md +424 -0
  754. package/workspace/node_modules/object-inspect/LICENSE +21 -0
  755. package/workspace/node_modules/object-inspect/example/all.js +23 -0
  756. package/workspace/node_modules/object-inspect/example/circular.js +6 -0
  757. package/workspace/node_modules/object-inspect/example/fn.js +5 -0
  758. package/workspace/node_modules/object-inspect/example/inspect.js +10 -0
  759. package/workspace/node_modules/object-inspect/index.js +544 -0
  760. package/workspace/node_modules/object-inspect/package-support.json +20 -0
  761. package/workspace/node_modules/object-inspect/package.json +105 -0
  762. package/workspace/node_modules/object-inspect/readme.markdown +84 -0
  763. package/workspace/node_modules/object-inspect/test/bigint.js +58 -0
  764. package/workspace/node_modules/object-inspect/test/browser/dom.js +15 -0
  765. package/workspace/node_modules/object-inspect/test/circular.js +16 -0
  766. package/workspace/node_modules/object-inspect/test/deep.js +12 -0
  767. package/workspace/node_modules/object-inspect/test/element.js +53 -0
  768. package/workspace/node_modules/object-inspect/test/err.js +48 -0
  769. package/workspace/node_modules/object-inspect/test/fakes.js +29 -0
  770. package/workspace/node_modules/object-inspect/test/fn.js +76 -0
  771. package/workspace/node_modules/object-inspect/test/global.js +17 -0
  772. package/workspace/node_modules/object-inspect/test/has.js +15 -0
  773. package/workspace/node_modules/object-inspect/test/holes.js +15 -0
  774. package/workspace/node_modules/object-inspect/test/indent-option.js +271 -0
  775. package/workspace/node_modules/object-inspect/test/inspect.js +139 -0
  776. package/workspace/node_modules/object-inspect/test/lowbyte.js +12 -0
  777. package/workspace/node_modules/object-inspect/test/number.js +58 -0
  778. package/workspace/node_modules/object-inspect/test/quoteStyle.js +26 -0
  779. package/workspace/node_modules/object-inspect/test/toStringTag.js +40 -0
  780. package/workspace/node_modules/object-inspect/test/undef.js +12 -0
  781. package/workspace/node_modules/object-inspect/test/values.js +261 -0
  782. package/workspace/node_modules/object-inspect/test-core-js.js +26 -0
  783. package/workspace/node_modules/object-inspect/util.inspect.js +1 -0
  784. package/workspace/node_modules/on-finished/HISTORY.md +98 -0
  785. package/workspace/node_modules/on-finished/LICENSE +23 -0
  786. package/workspace/node_modules/on-finished/README.md +162 -0
  787. package/workspace/node_modules/on-finished/index.js +234 -0
  788. package/workspace/node_modules/on-finished/package.json +39 -0
  789. package/workspace/node_modules/once/LICENSE +15 -0
  790. package/workspace/node_modules/once/README.md +79 -0
  791. package/workspace/node_modules/once/once.js +42 -0
  792. package/workspace/node_modules/once/package.json +33 -0
  793. package/workspace/node_modules/parseurl/HISTORY.md +58 -0
  794. package/workspace/node_modules/parseurl/LICENSE +24 -0
  795. package/workspace/node_modules/parseurl/README.md +133 -0
  796. package/workspace/node_modules/parseurl/index.js +158 -0
  797. package/workspace/node_modules/parseurl/package.json +40 -0
  798. package/workspace/node_modules/path-to-regexp/LICENSE +21 -0
  799. package/workspace/node_modules/path-to-regexp/Readme.md +224 -0
  800. package/workspace/node_modules/path-to-regexp/dist/index.d.ts +147 -0
  801. package/workspace/node_modules/path-to-regexp/dist/index.js +426 -0
  802. package/workspace/node_modules/path-to-regexp/dist/index.js.map +1 -0
  803. package/workspace/node_modules/path-to-regexp/package.json +64 -0
  804. package/workspace/node_modules/prebuild-install/CHANGELOG.md +131 -0
  805. package/workspace/node_modules/prebuild-install/CONTRIBUTING.md +6 -0
  806. package/workspace/node_modules/prebuild-install/LICENSE +21 -0
  807. package/workspace/node_modules/prebuild-install/README.md +163 -0
  808. package/workspace/node_modules/prebuild-install/asset.js +44 -0
  809. package/workspace/node_modules/prebuild-install/bin.js +78 -0
  810. package/workspace/node_modules/prebuild-install/download.js +142 -0
  811. package/workspace/node_modules/prebuild-install/error.js +14 -0
  812. package/workspace/node_modules/prebuild-install/help.txt +16 -0
  813. package/workspace/node_modules/prebuild-install/index.js +1 -0
  814. package/workspace/node_modules/prebuild-install/log.js +33 -0
  815. package/workspace/node_modules/prebuild-install/package.json +67 -0
  816. package/workspace/node_modules/prebuild-install/proxy.js +35 -0
  817. package/workspace/node_modules/prebuild-install/rc.js +64 -0
  818. package/workspace/node_modules/prebuild-install/util.js +143 -0
  819. package/workspace/node_modules/proxy-addr/HISTORY.md +161 -0
  820. package/workspace/node_modules/proxy-addr/LICENSE +22 -0
  821. package/workspace/node_modules/proxy-addr/README.md +139 -0
  822. package/workspace/node_modules/proxy-addr/index.js +327 -0
  823. package/workspace/node_modules/proxy-addr/package.json +47 -0
  824. package/workspace/node_modules/pump/.github/FUNDING.yml +2 -0
  825. package/workspace/node_modules/pump/.travis.yml +5 -0
  826. package/workspace/node_modules/pump/LICENSE +21 -0
  827. package/workspace/node_modules/pump/README.md +74 -0
  828. package/workspace/node_modules/pump/SECURITY.md +5 -0
  829. package/workspace/node_modules/pump/empty.js +1 -0
  830. package/workspace/node_modules/pump/index.js +86 -0
  831. package/workspace/node_modules/pump/package.json +30 -0
  832. package/workspace/node_modules/pump/test-browser.js +66 -0
  833. package/workspace/node_modules/pump/test-node.js +53 -0
  834. package/workspace/node_modules/qs/.editorconfig +46 -0
  835. package/workspace/node_modules/qs/.github/FUNDING.yml +12 -0
  836. package/workspace/node_modules/qs/.github/SECURITY.md +11 -0
  837. package/workspace/node_modules/qs/.github/THREAT_MODEL.md +78 -0
  838. package/workspace/node_modules/qs/.nycrc +13 -0
  839. package/workspace/node_modules/qs/CHANGELOG.md +806 -0
  840. package/workspace/node_modules/qs/LICENSE.md +29 -0
  841. package/workspace/node_modules/qs/README.md +758 -0
  842. package/workspace/node_modules/qs/dist/qs.js +141 -0
  843. package/workspace/node_modules/qs/eslint.config.mjs +56 -0
  844. package/workspace/node_modules/qs/lib/formats.js +23 -0
  845. package/workspace/node_modules/qs/lib/index.js +11 -0
  846. package/workspace/node_modules/qs/lib/parse.js +373 -0
  847. package/workspace/node_modules/qs/lib/stringify.js +356 -0
  848. package/workspace/node_modules/qs/lib/utils.js +342 -0
  849. package/workspace/node_modules/qs/package.json +94 -0
  850. package/workspace/node_modules/qs/test/empty-keys-cases.js +267 -0
  851. package/workspace/node_modules/qs/test/parse.js +1568 -0
  852. package/workspace/node_modules/qs/test/stringify.js +1310 -0
  853. package/workspace/node_modules/qs/test/utils.js +404 -0
  854. package/workspace/node_modules/range-parser/HISTORY.md +56 -0
  855. package/workspace/node_modules/range-parser/LICENSE +23 -0
  856. package/workspace/node_modules/range-parser/README.md +84 -0
  857. package/workspace/node_modules/range-parser/index.js +162 -0
  858. package/workspace/node_modules/range-parser/package.json +44 -0
  859. package/workspace/node_modules/raw-body/LICENSE +22 -0
  860. package/workspace/node_modules/raw-body/README.md +223 -0
  861. package/workspace/node_modules/raw-body/index.d.ts +85 -0
  862. package/workspace/node_modules/raw-body/index.js +336 -0
  863. package/workspace/node_modules/raw-body/package.json +46 -0
  864. package/workspace/node_modules/rc/LICENSE.APACHE2 +15 -0
  865. package/workspace/node_modules/rc/LICENSE.BSD +26 -0
  866. package/workspace/node_modules/rc/LICENSE.MIT +24 -0
  867. package/workspace/node_modules/rc/README.md +227 -0
  868. package/workspace/node_modules/rc/browser.js +7 -0
  869. package/workspace/node_modules/rc/cli.js +4 -0
  870. package/workspace/node_modules/rc/index.js +53 -0
  871. package/workspace/node_modules/rc/lib/utils.js +104 -0
  872. package/workspace/node_modules/rc/package.json +29 -0
  873. package/workspace/node_modules/rc/test/ini.js +16 -0
  874. package/workspace/node_modules/rc/test/nested-env-vars.js +50 -0
  875. package/workspace/node_modules/rc/test/test.js +59 -0
  876. package/workspace/node_modules/readable-stream/CONTRIBUTING.md +38 -0
  877. package/workspace/node_modules/readable-stream/GOVERNANCE.md +136 -0
  878. package/workspace/node_modules/readable-stream/LICENSE +47 -0
  879. package/workspace/node_modules/readable-stream/README.md +106 -0
  880. package/workspace/node_modules/readable-stream/errors-browser.js +127 -0
  881. package/workspace/node_modules/readable-stream/errors.js +116 -0
  882. package/workspace/node_modules/readable-stream/experimentalWarning.js +17 -0
  883. package/workspace/node_modules/readable-stream/lib/_stream_duplex.js +126 -0
  884. package/workspace/node_modules/readable-stream/lib/_stream_passthrough.js +37 -0
  885. package/workspace/node_modules/readable-stream/lib/_stream_readable.js +1027 -0
  886. package/workspace/node_modules/readable-stream/lib/_stream_transform.js +190 -0
  887. package/workspace/node_modules/readable-stream/lib/_stream_writable.js +641 -0
  888. package/workspace/node_modules/readable-stream/lib/internal/streams/async_iterator.js +180 -0
  889. package/workspace/node_modules/readable-stream/lib/internal/streams/buffer_list.js +183 -0
  890. package/workspace/node_modules/readable-stream/lib/internal/streams/destroy.js +96 -0
  891. package/workspace/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +86 -0
  892. package/workspace/node_modules/readable-stream/lib/internal/streams/from-browser.js +3 -0
  893. package/workspace/node_modules/readable-stream/lib/internal/streams/from.js +52 -0
  894. package/workspace/node_modules/readable-stream/lib/internal/streams/pipeline.js +86 -0
  895. package/workspace/node_modules/readable-stream/lib/internal/streams/state.js +22 -0
  896. package/workspace/node_modules/readable-stream/lib/internal/streams/stream-browser.js +1 -0
  897. package/workspace/node_modules/readable-stream/lib/internal/streams/stream.js +1 -0
  898. package/workspace/node_modules/readable-stream/package.json +68 -0
  899. package/workspace/node_modules/readable-stream/readable-browser.js +9 -0
  900. package/workspace/node_modules/readable-stream/readable.js +16 -0
  901. package/workspace/node_modules/router/HISTORY.md +228 -0
  902. package/workspace/node_modules/router/LICENSE +23 -0
  903. package/workspace/node_modules/router/README.md +416 -0
  904. package/workspace/node_modules/router/index.js +748 -0
  905. package/workspace/node_modules/router/lib/layer.js +247 -0
  906. package/workspace/node_modules/router/lib/route.js +242 -0
  907. package/workspace/node_modules/router/package.json +44 -0
  908. package/workspace/node_modules/safe-buffer/LICENSE +21 -0
  909. package/workspace/node_modules/safe-buffer/README.md +584 -0
  910. package/workspace/node_modules/safe-buffer/index.d.ts +187 -0
  911. package/workspace/node_modules/safe-buffer/index.js +65 -0
  912. package/workspace/node_modules/safe-buffer/package.json +51 -0
  913. package/workspace/node_modules/safer-buffer/LICENSE +21 -0
  914. package/workspace/node_modules/safer-buffer/Porting-Buffer.md +268 -0
  915. package/workspace/node_modules/safer-buffer/Readme.md +156 -0
  916. package/workspace/node_modules/safer-buffer/dangerous.js +58 -0
  917. package/workspace/node_modules/safer-buffer/package.json +34 -0
  918. package/workspace/node_modules/safer-buffer/safer.js +77 -0
  919. package/workspace/node_modules/safer-buffer/tests.js +406 -0
  920. package/workspace/node_modules/semver/LICENSE +15 -0
  921. package/workspace/node_modules/semver/README.md +665 -0
  922. package/workspace/node_modules/semver/bin/semver.js +191 -0
  923. package/workspace/node_modules/semver/classes/comparator.js +143 -0
  924. package/workspace/node_modules/semver/classes/index.js +7 -0
  925. package/workspace/node_modules/semver/classes/range.js +557 -0
  926. package/workspace/node_modules/semver/classes/semver.js +333 -0
  927. package/workspace/node_modules/semver/functions/clean.js +8 -0
  928. package/workspace/node_modules/semver/functions/cmp.js +54 -0
  929. package/workspace/node_modules/semver/functions/coerce.js +62 -0
  930. package/workspace/node_modules/semver/functions/compare-build.js +9 -0
  931. package/workspace/node_modules/semver/functions/compare-loose.js +5 -0
  932. package/workspace/node_modules/semver/functions/compare.js +7 -0
  933. package/workspace/node_modules/semver/functions/diff.js +60 -0
  934. package/workspace/node_modules/semver/functions/eq.js +5 -0
  935. package/workspace/node_modules/semver/functions/gt.js +5 -0
  936. package/workspace/node_modules/semver/functions/gte.js +5 -0
  937. package/workspace/node_modules/semver/functions/inc.js +21 -0
  938. package/workspace/node_modules/semver/functions/lt.js +5 -0
  939. package/workspace/node_modules/semver/functions/lte.js +5 -0
  940. package/workspace/node_modules/semver/functions/major.js +5 -0
  941. package/workspace/node_modules/semver/functions/minor.js +5 -0
  942. package/workspace/node_modules/semver/functions/neq.js +5 -0
  943. package/workspace/node_modules/semver/functions/parse.js +18 -0
  944. package/workspace/node_modules/semver/functions/patch.js +5 -0
  945. package/workspace/node_modules/semver/functions/prerelease.js +8 -0
  946. package/workspace/node_modules/semver/functions/rcompare.js +5 -0
  947. package/workspace/node_modules/semver/functions/rsort.js +5 -0
  948. package/workspace/node_modules/semver/functions/satisfies.js +12 -0
  949. package/workspace/node_modules/semver/functions/sort.js +5 -0
  950. package/workspace/node_modules/semver/functions/valid.js +8 -0
  951. package/workspace/node_modules/semver/index.js +91 -0
  952. package/workspace/node_modules/semver/internal/constants.js +37 -0
  953. package/workspace/node_modules/semver/internal/debug.js +11 -0
  954. package/workspace/node_modules/semver/internal/identifiers.js +29 -0
  955. package/workspace/node_modules/semver/internal/lrucache.js +42 -0
  956. package/workspace/node_modules/semver/internal/parse-options.js +17 -0
  957. package/workspace/node_modules/semver/internal/re.js +223 -0
  958. package/workspace/node_modules/semver/package.json +78 -0
  959. package/workspace/node_modules/semver/preload.js +4 -0
  960. package/workspace/node_modules/semver/range.bnf +16 -0
  961. package/workspace/node_modules/semver/ranges/gtr.js +6 -0
  962. package/workspace/node_modules/semver/ranges/intersects.js +9 -0
  963. package/workspace/node_modules/semver/ranges/ltr.js +6 -0
  964. package/workspace/node_modules/semver/ranges/max-satisfying.js +27 -0
  965. package/workspace/node_modules/semver/ranges/min-satisfying.js +26 -0
  966. package/workspace/node_modules/semver/ranges/min-version.js +63 -0
  967. package/workspace/node_modules/semver/ranges/outside.js +82 -0
  968. package/workspace/node_modules/semver/ranges/simplify.js +49 -0
  969. package/workspace/node_modules/semver/ranges/subset.js +249 -0
  970. package/workspace/node_modules/semver/ranges/to-comparators.js +10 -0
  971. package/workspace/node_modules/semver/ranges/valid.js +13 -0
  972. package/workspace/node_modules/send/LICENSE +23 -0
  973. package/workspace/node_modules/send/README.md +317 -0
  974. package/workspace/node_modules/send/index.js +997 -0
  975. package/workspace/node_modules/send/package.json +63 -0
  976. package/workspace/node_modules/serve-static/LICENSE +25 -0
  977. package/workspace/node_modules/serve-static/README.md +253 -0
  978. package/workspace/node_modules/serve-static/index.js +208 -0
  979. package/workspace/node_modules/serve-static/package.json +44 -0
  980. package/workspace/node_modules/setprototypeof/LICENSE +13 -0
  981. package/workspace/node_modules/setprototypeof/README.md +31 -0
  982. package/workspace/node_modules/setprototypeof/index.d.ts +2 -0
  983. package/workspace/node_modules/setprototypeof/index.js +17 -0
  984. package/workspace/node_modules/setprototypeof/package.json +38 -0
  985. package/workspace/node_modules/setprototypeof/test/index.js +24 -0
  986. package/workspace/node_modules/side-channel/.editorconfig +9 -0
  987. package/workspace/node_modules/side-channel/.eslintrc +12 -0
  988. package/workspace/node_modules/side-channel/.github/FUNDING.yml +12 -0
  989. package/workspace/node_modules/side-channel/.nycrc +13 -0
  990. package/workspace/node_modules/side-channel/CHANGELOG.md +110 -0
  991. package/workspace/node_modules/side-channel/LICENSE +21 -0
  992. package/workspace/node_modules/side-channel/README.md +61 -0
  993. package/workspace/node_modules/side-channel/index.d.ts +14 -0
  994. package/workspace/node_modules/side-channel/index.js +43 -0
  995. package/workspace/node_modules/side-channel/package.json +85 -0
  996. package/workspace/node_modules/side-channel/test/index.js +104 -0
  997. package/workspace/node_modules/side-channel/tsconfig.json +9 -0
  998. package/workspace/node_modules/side-channel-list/.editorconfig +9 -0
  999. package/workspace/node_modules/side-channel-list/.eslintrc +11 -0
  1000. package/workspace/node_modules/side-channel-list/.github/FUNDING.yml +12 -0
  1001. package/workspace/node_modules/side-channel-list/.nycrc +13 -0
  1002. package/workspace/node_modules/side-channel-list/CHANGELOG.md +15 -0
  1003. package/workspace/node_modules/side-channel-list/LICENSE +21 -0
  1004. package/workspace/node_modules/side-channel-list/README.md +62 -0
  1005. package/workspace/node_modules/side-channel-list/index.d.ts +13 -0
  1006. package/workspace/node_modules/side-channel-list/index.js +113 -0
  1007. package/workspace/node_modules/side-channel-list/list.d.ts +14 -0
  1008. package/workspace/node_modules/side-channel-list/package.json +77 -0
  1009. package/workspace/node_modules/side-channel-list/test/index.js +104 -0
  1010. package/workspace/node_modules/side-channel-list/tsconfig.json +9 -0
  1011. package/workspace/node_modules/side-channel-map/.editorconfig +9 -0
  1012. package/workspace/node_modules/side-channel-map/.eslintrc +11 -0
  1013. package/workspace/node_modules/side-channel-map/.github/FUNDING.yml +12 -0
  1014. package/workspace/node_modules/side-channel-map/.nycrc +13 -0
  1015. package/workspace/node_modules/side-channel-map/CHANGELOG.md +22 -0
  1016. package/workspace/node_modules/side-channel-map/LICENSE +21 -0
  1017. package/workspace/node_modules/side-channel-map/README.md +62 -0
  1018. package/workspace/node_modules/side-channel-map/index.d.ts +15 -0
  1019. package/workspace/node_modules/side-channel-map/index.js +68 -0
  1020. package/workspace/node_modules/side-channel-map/package.json +80 -0
  1021. package/workspace/node_modules/side-channel-map/test/index.js +114 -0
  1022. package/workspace/node_modules/side-channel-map/tsconfig.json +9 -0
  1023. package/workspace/node_modules/side-channel-weakmap/.editorconfig +9 -0
  1024. package/workspace/node_modules/side-channel-weakmap/.eslintrc +12 -0
  1025. package/workspace/node_modules/side-channel-weakmap/.github/FUNDING.yml +12 -0
  1026. package/workspace/node_modules/side-channel-weakmap/.nycrc +13 -0
  1027. package/workspace/node_modules/side-channel-weakmap/CHANGELOG.md +28 -0
  1028. package/workspace/node_modules/side-channel-weakmap/LICENSE +21 -0
  1029. package/workspace/node_modules/side-channel-weakmap/README.md +62 -0
  1030. package/workspace/node_modules/side-channel-weakmap/index.d.ts +15 -0
  1031. package/workspace/node_modules/side-channel-weakmap/index.js +84 -0
  1032. package/workspace/node_modules/side-channel-weakmap/package.json +87 -0
  1033. package/workspace/node_modules/side-channel-weakmap/test/index.js +114 -0
  1034. package/workspace/node_modules/side-channel-weakmap/tsconfig.json +9 -0
  1035. package/workspace/node_modules/simple-concat/.travis.yml +3 -0
  1036. package/workspace/node_modules/simple-concat/LICENSE +20 -0
  1037. package/workspace/node_modules/simple-concat/README.md +44 -0
  1038. package/workspace/node_modules/simple-concat/index.js +15 -0
  1039. package/workspace/node_modules/simple-concat/package.json +47 -0
  1040. package/workspace/node_modules/simple-concat/test/basic.js +41 -0
  1041. package/workspace/node_modules/simple-get/.github/dependabot.yml +15 -0
  1042. package/workspace/node_modules/simple-get/.github/workflows/ci.yml +23 -0
  1043. package/workspace/node_modules/simple-get/LICENSE +20 -0
  1044. package/workspace/node_modules/simple-get/README.md +333 -0
  1045. package/workspace/node_modules/simple-get/index.js +108 -0
  1046. package/workspace/node_modules/simple-get/package.json +67 -0
  1047. package/workspace/node_modules/statuses/HISTORY.md +87 -0
  1048. package/workspace/node_modules/statuses/LICENSE +23 -0
  1049. package/workspace/node_modules/statuses/README.md +139 -0
  1050. package/workspace/node_modules/statuses/codes.json +65 -0
  1051. package/workspace/node_modules/statuses/index.js +146 -0
  1052. package/workspace/node_modules/statuses/package.json +49 -0
  1053. package/workspace/node_modules/string_decoder/LICENSE +48 -0
  1054. package/workspace/node_modules/string_decoder/README.md +47 -0
  1055. package/workspace/node_modules/string_decoder/lib/string_decoder.js +296 -0
  1056. package/workspace/node_modules/string_decoder/package.json +34 -0
  1057. package/workspace/node_modules/strip-json-comments/index.js +70 -0
  1058. package/workspace/node_modules/strip-json-comments/license +21 -0
  1059. package/workspace/node_modules/strip-json-comments/package.json +42 -0
  1060. package/workspace/node_modules/strip-json-comments/readme.md +64 -0
  1061. package/workspace/node_modules/tar-fs/.travis.yml +6 -0
  1062. package/workspace/node_modules/tar-fs/LICENSE +21 -0
  1063. package/workspace/node_modules/tar-fs/README.md +165 -0
  1064. package/workspace/node_modules/tar-fs/index.js +363 -0
  1065. package/workspace/node_modules/tar-fs/package.json +41 -0
  1066. package/workspace/node_modules/tar-fs/test/fixtures/a/hello.txt +1 -0
  1067. package/workspace/node_modules/tar-fs/test/fixtures/b/a/test.txt +1 -0
  1068. package/workspace/node_modules/tar-fs/test/fixtures/d/file1 +0 -0
  1069. package/workspace/node_modules/tar-fs/test/fixtures/d/file2 +0 -0
  1070. package/workspace/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 +0 -0
  1071. package/workspace/node_modules/tar-fs/test/fixtures/d/sub-files/file3 +0 -0
  1072. package/workspace/node_modules/tar-fs/test/fixtures/d/sub-files/file4 +0 -0
  1073. package/workspace/node_modules/tar-fs/test/fixtures/e/directory/.ignore +0 -0
  1074. package/workspace/node_modules/tar-fs/test/fixtures/e/file +0 -0
  1075. package/workspace/node_modules/tar-fs/test/fixtures/invalid.tar +0 -0
  1076. package/workspace/node_modules/tar-fs/test/index.js +346 -0
  1077. package/workspace/node_modules/tar-stream/LICENSE +21 -0
  1078. package/workspace/node_modules/tar-stream/README.md +168 -0
  1079. package/workspace/node_modules/tar-stream/extract.js +257 -0
  1080. package/workspace/node_modules/tar-stream/headers.js +295 -0
  1081. package/workspace/node_modules/tar-stream/index.js +2 -0
  1082. package/workspace/node_modules/tar-stream/pack.js +255 -0
  1083. package/workspace/node_modules/tar-stream/package.json +58 -0
  1084. package/workspace/node_modules/tar-stream/sandbox.js +11 -0
  1085. package/workspace/node_modules/toidentifier/HISTORY.md +9 -0
  1086. package/workspace/node_modules/toidentifier/LICENSE +21 -0
  1087. package/workspace/node_modules/toidentifier/README.md +61 -0
  1088. package/workspace/node_modules/toidentifier/index.js +32 -0
  1089. package/workspace/node_modules/toidentifier/package.json +38 -0
  1090. package/workspace/node_modules/tunnel-agent/LICENSE +55 -0
  1091. package/workspace/node_modules/tunnel-agent/README.md +4 -0
  1092. package/workspace/node_modules/tunnel-agent/index.js +244 -0
  1093. package/workspace/node_modules/tunnel-agent/package.json +22 -0
  1094. package/workspace/node_modules/type-is/HISTORY.md +292 -0
  1095. package/workspace/node_modules/type-is/LICENSE +23 -0
  1096. package/workspace/node_modules/type-is/README.md +198 -0
  1097. package/workspace/node_modules/type-is/index.js +250 -0
  1098. package/workspace/node_modules/type-is/package.json +47 -0
  1099. package/workspace/node_modules/unpipe/HISTORY.md +4 -0
  1100. package/workspace/node_modules/unpipe/LICENSE +22 -0
  1101. package/workspace/node_modules/unpipe/README.md +43 -0
  1102. package/workspace/node_modules/unpipe/index.js +69 -0
  1103. package/workspace/node_modules/unpipe/package.json +27 -0
  1104. package/workspace/node_modules/util-deprecate/History.md +16 -0
  1105. package/workspace/node_modules/util-deprecate/LICENSE +24 -0
  1106. package/workspace/node_modules/util-deprecate/README.md +53 -0
  1107. package/workspace/node_modules/util-deprecate/browser.js +67 -0
  1108. package/workspace/node_modules/util-deprecate/node.js +6 -0
  1109. package/workspace/node_modules/util-deprecate/package.json +27 -0
  1110. package/workspace/node_modules/vary/HISTORY.md +39 -0
  1111. package/workspace/node_modules/vary/LICENSE +22 -0
  1112. package/workspace/node_modules/vary/README.md +101 -0
  1113. package/workspace/node_modules/vary/index.js +149 -0
  1114. package/workspace/node_modules/vary/package.json +43 -0
  1115. package/workspace/node_modules/wrappy/LICENSE +15 -0
  1116. package/workspace/node_modules/wrappy/README.md +36 -0
  1117. package/workspace/node_modules/wrappy/package.json +29 -0
  1118. package/workspace/node_modules/wrappy/wrappy.js +33 -0
  1119. package/workspace/package.json +9 -0
  1120. package/workspace/skills/backup skills/whatsapp/.claude-plugin/plugin.json +6 -0
  1121. package/workspace/skills/backup skills/whatsapp/SKILL.md +119 -0
  1122. package/workspace/skills/backup skills/whatsapp/skill.json +11 -0
  1123. package/workspace/skills/backup skills/whatsapp-clinic-secretary/.claude-plugin/plugin.json +6 -0
  1124. package/workspace/skills/backup skills/whatsapp-clinic-secretary/SCRIPT.md +154 -0
  1125. package/workspace/skills/backup skills/whatsapp-clinic-secretary/SKILL.md +132 -0
  1126. package/workspace/skills/backup skills/whatsapp-clinic-secretary/skill.json +12 -0
  1127. package/workspace/skills/backup skills/whatsapp-support/SCRIPT.md +172 -0
  1128. package/workspace/skills/backup skills/whatsapp-support/SKILL.md +21 -0
@@ -0,0 +1,1537 @@
1
+ import http from 'http';
2
+ import net from 'net';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import { WebSocketServer, WebSocket } from 'ws';
6
+ import { loadConfig, saveConfig } from '../shared/config.js';
7
+ import { createProvider, type AiProvider, type ChatMessage } from '../shared/ai.js';
8
+ import { paths } from '../shared/paths.js';
9
+ import { PKG_DIR, DATA_DIR, WORKSPACE_DIR } from '../shared/paths.js';
10
+ import { log } from '../shared/logger.js';
11
+ import { startTunnel, stopTunnel, isTunnelAlive, restartTunnel, startNamedTunnel, restartNamedTunnel } from './tunnel.js';
12
+ import { createWorkerApp } from '../worker/index.js';
13
+ import { closeDb, getSession, getSetting } from '../worker/db.js';
14
+ import { spawnBackend, stopBackend, getBackendPort, isBackendAlive, isBackendStopping, resetBackendRestarts } from './backend.js';
15
+ import { updateTunnelUrl, startHeartbeat, stopHeartbeat, disconnect } from '../shared/relay.js';
16
+ import { startBlobyAgentQuery, stopBlobyAgentQuery, type RecentMessage } from './bloby-agent.js';
17
+ import { ensureFileDirs, saveAttachment, type SavedFile } from './file-saver.js';
18
+ import { startViteDevServers, stopViteDevServers } from './vite-dev.js';
19
+ import { startScheduler, stopScheduler } from './scheduler.js';
20
+ import { execSync, spawn as cpSpawn } from 'child_process';
21
+ import crypto from 'crypto';
22
+ import { ChannelManager } from './channels/manager.js';
23
+
24
+ const DIST_BLOBY = path.join(PKG_DIR, 'dist-bloby');
25
+
26
+ // Ensure dist-bloby exists (postinstall may have failed silently)
27
+ if (!fs.existsSync(DIST_BLOBY)) {
28
+ log.info('Building bloby chat UI (first run)...');
29
+ try {
30
+ execSync('npx vite build --config vite.bloby.config.ts', {
31
+ cwd: PKG_DIR,
32
+ stdio: 'ignore',
33
+ });
34
+ log.ok('Bloby chat UI built');
35
+ } catch (err) {
36
+ log.warn(`Failed to build bloby chat UI: ${err instanceof Error ? err.message : err}`);
37
+ }
38
+ }
39
+
40
+ const MIME_TYPES: Record<string, string> = {
41
+ '.html': 'text/html',
42
+ '.js': 'application/javascript',
43
+ '.css': 'text/css',
44
+ '.png': 'image/png',
45
+ '.jpg': 'image/jpeg',
46
+ '.svg': 'image/svg+xml',
47
+ '.webm': 'video/webm',
48
+ '.mov': 'video/mp4',
49
+ '.mp4': 'video/mp4',
50
+ '.woff2': 'font/woff2',
51
+ '.json': 'application/json',
52
+ };
53
+
54
+ // Service worker content — embedded here so it ships with supervisor/ (always updated)
55
+ // Keep in sync with workspace/client/public/sw.js (prod builds)
56
+ const SW_JS = `// Service worker — app-shell caching + push notifications
57
+ // Caching strategy:
58
+ // Hashed assets (/assets/*-AbCd12.js) → cache-first (immutable)
59
+ // Navigation (HTML) → stale-while-revalidate (precached on install)
60
+ // Static assets (img/video/fonts) → stale-while-revalidate
61
+ // JS/CSS modules → stale-while-revalidate
62
+ // API, WebSocket, Vite internals → network-only (no cache)
63
+
64
+ var CACHE = 'bloby-v5';
65
+ var HASHED_RE = new RegExp('/assets/.+-[a-zA-Z0-9]{6,}[.](js|css)$');
66
+
67
+ // Precache the HTML shell on install so the cache is never empty.
68
+ // Without this, the first navigation isn't intercepted (SW wasn't
69
+ // controlling yet), so refresh would find an empty cache → white screen.
70
+ self.addEventListener('install', function(e) {
71
+ console.log('[SW] installing, cache:', CACHE);
72
+ e.waitUntil(
73
+ caches.open(CACHE)
74
+ .then(function(c) { return c.add('/'); })
75
+ .then(function() { console.log('[SW] precached / — calling skipWaiting'); return self.skipWaiting(); })
76
+ .catch(function(err) { console.error('[SW] install failed:', err); throw err; })
77
+ );
78
+ });
79
+
80
+ self.addEventListener('activate', function(e) {
81
+ console.log('[SW] activating, cache:', CACHE);
82
+ e.waitUntil(
83
+ caches.keys()
84
+ .then(function(keys) {
85
+ var old = keys.filter(function(k) { return k !== CACHE; });
86
+ if (old.length) console.log('[SW] deleting old caches:', old);
87
+ return Promise.all(old.map(function(k) { return caches.delete(k); }));
88
+ })
89
+ .then(function() { console.log('[SW] claiming clients'); return self.clients.claim(); })
90
+ );
91
+ });
92
+
93
+ self.addEventListener('message', function(e) {
94
+ if (e.data && e.data.type === 'SKIP_WAITING') self.skipWaiting();
95
+ });
96
+
97
+ self.addEventListener('fetch', function(event) {
98
+ var request = event.request;
99
+ var url = new URL(request.url);
100
+
101
+ // Network-only: never cache these
102
+ if (
103
+ request.method !== 'GET' ||
104
+ url.pathname.indexOf('/api/') === 0 ||
105
+ url.pathname.indexOf('/app/api/') === 0 ||
106
+ url.pathname.slice(-3) === '/ws' ||
107
+ url.pathname === '/sw.js' ||
108
+ url.pathname === '/bloby/sw.js' ||
109
+ url.pathname.indexOf('/@') === 0 ||
110
+ url.pathname.indexOf('/__') === 0
111
+ ) return;
112
+
113
+ // Hashed assets (immutable, content-addressed) → cache-first
114
+ if (HASHED_RE.test(url.pathname)) {
115
+ event.respondWith(caches.open(CACHE).then(function(c) {
116
+ return c.match(request).then(function(hit) {
117
+ return hit || fetch(request).then(function(r) { if (r.ok) c.put(request, r.clone()); return r; });
118
+ });
119
+ }));
120
+ return;
121
+ }
122
+
123
+ // Navigation: only stale-while-revalidate the dashboard root (/).
124
+ // /bloby/* is a separate app — let it go to network to avoid
125
+ // caching the wrong HTML under the / key.
126
+ if (request.mode === 'navigate') {
127
+ console.log('[SW] navigate →', url.pathname);
128
+ if (url.pathname === '/' || url.pathname === '/index.html') {
129
+ event.respondWith(caches.open(CACHE).then(function(c) {
130
+ return c.match('/').then(function(hit) {
131
+ console.log('[SW] cache hit for /:', !!hit);
132
+ var net = fetch(request)
133
+ .then(function(r) {
134
+ console.log('[SW] network response for /:', r.status);
135
+ if (r.ok) c.put('/', r.clone());
136
+ return r;
137
+ })
138
+ .catch(function(err) { console.warn('[SW] network failed, using cache:', err.message); return hit; });
139
+ return hit || net;
140
+ });
141
+ }));
142
+ return;
143
+ }
144
+ // Other navigations (/bloby/*, etc.) — network only
145
+ console.log('[SW] navigate (network-only) →', url.pathname);
146
+ return;
147
+ }
148
+
149
+ // Everything else → stale-while-revalidate
150
+ event.respondWith(caches.open(CACHE).then(function(c) {
151
+ return c.match(request).then(function(hit) {
152
+ var net = fetch(request)
153
+ .then(function(r) { if (r.ok) c.put(request, r.clone()); return r; })
154
+ .catch(function() { return hit; });
155
+ return hit || net;
156
+ });
157
+ }));
158
+ });
159
+
160
+ // Push notifications
161
+ self.addEventListener('push', function(event) {
162
+ var data = { title: 'Bloby', body: 'New message' };
163
+ try { data = event.data.json(); } catch(e) {}
164
+ event.waitUntil(
165
+ self.registration.showNotification(data.title || 'Bloby', {
166
+ body: data.body || '',
167
+ icon: '/bloby-icon-192.png',
168
+ badge: '/bloby-badge.png',
169
+ vibrate: [100, 50, 100],
170
+ tag: data.tag || 'bloby-default',
171
+ data: { url: data.url || '/' },
172
+ })
173
+ );
174
+ });
175
+
176
+ // Notification click — focus or open app
177
+ self.addEventListener('notificationclick', function(event) {
178
+ event.notification.close();
179
+ var url = (event.notification.data && event.notification.data.url) || '/';
180
+ event.waitUntil(
181
+ self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clients) {
182
+ for (var i = 0; i < clients.length; i++) {
183
+ if (clients[i].url.indexOf('/bloby') !== -1 && 'focus' in clients[i]) return clients[i].focus();
184
+ }
185
+ return self.clients.openWindow(url);
186
+ })
187
+ );
188
+ });
189
+ `;
190
+
191
+ const RECOVERING_HTML = `<!DOCTYPE html><html style="background:#222122"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Bloby</title>
192
+ <style>@keyframes _fs{to{transform:rotate(360deg)}}body{background:#222122;margin:0}</style></head>
193
+ <body><div style="background:#222122;color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100dvh;width:100vw;font-family:system-ui,-apple-system,sans-serif">
194
+ <img src="/bloby-icon-192.png" width="56" height="56" style="border-radius:14px;margin-bottom:20px" alt="" />
195
+ <div style="width:18px;height:18px;border:2px solid rgba(255,255,255,0.12);border-top-color:rgba(255,255,255,0.7);border-radius:50%;animation:_fs .6s linear infinite"></div>
196
+ </div><script>setTimeout(function(){location.reload()},3000)</script>
197
+ <script src="/bloby/widget.js"></script></body></html>`;
198
+
199
+ export async function startSupervisor() {
200
+ const config = loadConfig();
201
+ const backendPort = getBackendPort(config.port);
202
+ const internalSecret = crypto.randomBytes(16).toString('hex');
203
+
204
+ // Create HTTP server first (Vite needs it for HMR WebSocket)
205
+ // The request handler is set up later via server.on('request')
206
+ const server = http.createServer();
207
+
208
+ // Start Vite dev server — pass supervisor server so Vite attaches HMR WebSocket directly
209
+ console.log('[supervisor] Starting Vite dev server...');
210
+ const vitePorts = await startViteDevServers(config.port, server);
211
+ console.log(`[supervisor] Vite ready — dashboard :${vitePorts.dashboard}`);
212
+ console.log(`[supervisor] Upgrade listeners on server: ${server.listenerCount('upgrade')}`);
213
+
214
+ // Ensure file storage dirs exist
215
+ ensureFileDirs();
216
+
217
+ // Initialize worker routes in-process (no separate child process)
218
+ const workerApp = createWorkerApp();
219
+
220
+ // Bloby's AI brain
221
+ let ai: AiProvider | null = null;
222
+ if (config.ai.provider && (config.ai.apiKey || config.ai.provider === 'ollama')) {
223
+ ai = createProvider(config.ai.provider, config.ai.apiKey, config.ai.baseUrl);
224
+ }
225
+
226
+ // Bloby chat conversations (in-memory for now)
227
+ const conversations = new Map<WebSocket, ChatMessage[]>();
228
+
229
+ // Track active DB conversation per WS client
230
+ const clientConvs = new Map<WebSocket, string>();
231
+
232
+ // Track current stream state so reconnecting clients get caught up
233
+ let currentStreamConvId: string | null = null;
234
+ let currentStreamBuffer = '';
235
+
236
+ /** Call worker API endpoints (in-process via supervisor's own HTTP server) */
237
+ async function workerApi(apiPath: string, method = 'GET', body?: any) {
238
+ const opts: RequestInit = { method, headers: { 'Content-Type': 'application/json', 'x-internal': internalSecret } };
239
+ if (body) opts.body = JSON.stringify(body);
240
+ const res = await fetch(`http://127.0.0.1:${config.port}${apiPath}`, opts);
241
+ return res.json();
242
+ }
243
+
244
+ /** Broadcast to all bloby WS clients EXCEPT sender */
245
+ function broadcastBlobyExcept(sender: WebSocket, type: string, data: any) {
246
+ const msg = JSON.stringify({ type, data });
247
+ for (const client of blobyWss.clients) {
248
+ if (client !== sender && client.readyState === WebSocket.OPEN) client.send(msg);
249
+ }
250
+ }
251
+
252
+ // ── Auth middleware ──
253
+ const tokenCache = new Map<string, number>(); // token → expiry timestamp
254
+ const TOKEN_CACHE_TTL = 60_000; // 60s
255
+
256
+ async function validateToken(token: string): Promise<boolean> {
257
+ const cached = tokenCache.get(token);
258
+ if (cached && cached > Date.now()) return true;
259
+
260
+ try {
261
+ const session = getSession(token);
262
+ if (session) {
263
+ tokenCache.set(token, Date.now() + TOKEN_CACHE_TTL);
264
+ return true;
265
+ }
266
+ tokenCache.delete(token);
267
+ return false;
268
+ } catch {
269
+ return false;
270
+ }
271
+ }
272
+
273
+ let authRequiredCache: { value: boolean; expires: number } | null = null;
274
+
275
+ async function isAuthRequired(): Promise<boolean> {
276
+ if (authRequiredCache && authRequiredCache.expires > Date.now()) return authRequiredCache.value;
277
+ try {
278
+ const required = !!getSetting('portal_pass');
279
+ authRequiredCache = { value: required, expires: Date.now() + 30_000 };
280
+ return required;
281
+ } catch {
282
+ return false;
283
+ }
284
+ }
285
+
286
+ const AUTH_EXEMPT_ROUTES = [
287
+ 'POST /api/portal/login',
288
+ 'GET /api/portal/login',
289
+ 'POST /api/portal/validate-token',
290
+ 'GET /api/portal/validate-token',
291
+ 'GET /api/onboard/status',
292
+ 'GET /api/health',
293
+ 'POST /api/onboard',
294
+ 'GET /api/push/vapid-public-key',
295
+ 'GET /api/push/status',
296
+ 'POST /api/auth/claude/start',
297
+ 'POST /api/auth/claude/exchange',
298
+ 'GET /api/auth/claude/status',
299
+ 'POST /api/auth/codex/start',
300
+ 'POST /api/auth/codex/cancel',
301
+ 'GET /api/auth/codex/status',
302
+ 'POST /api/portal/totp/setup',
303
+ 'POST /api/portal/totp/verify-setup',
304
+ 'POST /api/portal/totp/disable',
305
+ 'GET /api/portal/totp/status',
306
+ 'GET /api/portal/login/totp',
307
+ 'POST /api/portal/devices/revoke',
308
+ 'GET /api/channels/status',
309
+ 'GET /api/channels/whatsapp/qr',
310
+ 'GET /api/channels/whatsapp/qr-page',
311
+ 'POST /api/channels/whatsapp/connect',
312
+ 'POST /api/channels/whatsapp/disconnect',
313
+ 'POST /api/channels/whatsapp/logout',
314
+ 'POST /api/channels/whatsapp/configure',
315
+ 'POST /api/channels/send',
316
+ ];
317
+
318
+ function isExemptRoute(method: string, url: string): boolean {
319
+ const path = url.split('?')[0];
320
+ return AUTH_EXEMPT_ROUTES.some((r) => {
321
+ const [m, p] = r.split(' ');
322
+ return method === m && path === p;
323
+ });
324
+ }
325
+
326
+ // HTTP request handler — proxies to Vite dev servers + worker API
327
+ server.on('request', async (req, res) => {
328
+ // Bloby widget — served directly (not part of Vite build)
329
+ if (req.url === '/bloby/widget.js') {
330
+ console.log('[supervisor] Serving /bloby/widget.js directly');
331
+ res.writeHead(200, { 'Content-Type': 'application/javascript', 'Cache-Control': 'no-cache' });
332
+ res.end(fs.readFileSync(paths.widgetJs));
333
+ return;
334
+ }
335
+
336
+ // App WS client — served directly (proxies /app/api calls through WebSocket)
337
+ if (req.url === '/bloby/app-ws.js') {
338
+ console.log('[supervisor] Serving /bloby/app-ws.js directly');
339
+ res.writeHead(200, { 'Content-Type': 'application/javascript', 'Cache-Control': 'no-cache' });
340
+ res.end(fs.readFileSync(path.join(PKG_DIR, 'supervisor', 'app-ws.js')));
341
+ return;
342
+ }
343
+
344
+ // Service worker — served from embedded constant (supervisor/ is always updated)
345
+ if (req.url === '/sw.js' || req.url === '/bloby/sw.js') {
346
+ res.writeHead(200, { 'Content-Type': 'application/javascript', 'Cache-Control': 'no-cache' });
347
+ res.end(SW_JS);
348
+ return;
349
+ }
350
+
351
+ // App API routes → proxy to user's backend server
352
+ if (req.url?.startsWith('/app/api')) {
353
+ const backendPath = req.url.replace(/^\/app/, '');
354
+ console.log(`[supervisor] → backend :${backendPort} | ${req.method} ${backendPath}`);
355
+ if (!isBackendAlive()) {
356
+ console.log('[supervisor] Backend down — returning 503');
357
+ res.writeHead(503, { 'Content-Type': 'application/json' });
358
+ res.end(JSON.stringify({ error: 'Backend is starting...' }));
359
+ return;
360
+ }
361
+
362
+ const proxy = http.request(
363
+ { host: '127.0.0.1', port: backendPort, path: backendPath, method: req.method, headers: req.headers },
364
+ (proxyRes) => {
365
+ res.writeHead(proxyRes.statusCode!, proxyRes.headers);
366
+ proxyRes.pipe(res);
367
+ },
368
+ );
369
+ proxy.on('error', (e) => {
370
+ console.error(`[supervisor] Backend proxy error: ${req.url}`, e.message);
371
+ res.writeHead(503, { 'Content-Type': 'application/json' });
372
+ res.end(JSON.stringify({ error: 'Backend unavailable' }));
373
+ });
374
+ req.pipe(proxy);
375
+ return;
376
+ }
377
+
378
+ // ── Channel API routes (handled by supervisor, not worker) ──
379
+ if (req.url?.startsWith('/api/channels')) {
380
+ const channelPath = req.url.split('?')[0];
381
+ res.setHeader('Content-Type', 'application/json');
382
+ res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
383
+
384
+ // GET /api/channels/status — all channel statuses
385
+ if (req.method === 'GET' && channelPath === '/api/channels/status') {
386
+ res.writeHead(200);
387
+ res.end(JSON.stringify(channelManager.getStatuses()));
388
+ return;
389
+ }
390
+
391
+ // GET /api/channels/whatsapp/qr — raw QR SVG data
392
+ if (req.method === 'GET' && channelPath === '/api/channels/whatsapp/qr') {
393
+ const qr = channelManager.getQrCode('whatsapp');
394
+ res.writeHead(200);
395
+ res.end(JSON.stringify({ qr }));
396
+ return;
397
+ }
398
+
399
+ // GET /api/channels/whatsapp/qr-page — standalone QR scanning page
400
+ if (req.method === 'GET' && channelPath === '/api/channels/whatsapp/qr-page') {
401
+ res.setHeader('Content-Type', 'text/html');
402
+ const qr = channelManager.getQrCode('whatsapp');
403
+ const status = channelManager.getStatus('whatsapp');
404
+ const connected = status?.connected || false;
405
+ res.writeHead(200);
406
+ const confettiHTML = Array.from({ length: 30 }, (_, i) => {
407
+ const colors = ['#04D1FE', '#AF27E3', '#FB4072', '#4ade80', '#facc15', '#818cf8'];
408
+ const color = colors[Math.floor(Math.random() * colors.length)];
409
+ const left = Math.random() * 100;
410
+ const delay = i * 0.04;
411
+ const drift = (Math.random() - 0.5) * 120;
412
+ const duration = 1.8 + Math.random() * 0.8;
413
+ return `<div class="confetti-dot" style="left:${left}%;background:${color};animation-delay:${delay}s;animation-duration:${duration}s;--drift:${drift}px"></div>`;
414
+ }).join('');
415
+
416
+ res.end(`<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
417
+ <title>WhatsApp QR</title>
418
+ <link rel="preconnect" href="https://fonts.googleapis.com">
419
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
420
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet">
421
+ <style>
422
+ *{margin:0;padding:0;box-sizing:border-box}
423
+ body{background:#212121;color:#f5f5f5;font-family:'Inter',system-ui,-apple-system,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;height:100dvh;margin:0;overflow:hidden}
424
+ .container{display:flex;flex-direction:column;align-items:center;max-width:360px;width:100%;padding:0 20px}
425
+
426
+ .qr-card{background:#2a2a2a;border:1px solid rgba(255,255,255,0.08);border-radius:20px;padding:28px;width:100%;box-shadow:0 0 0 1px rgba(175,39,227,0.1),0 0 20px -5px rgba(175,39,227,0.15);animation:fade-up .5s ease-out both}
427
+ .qr-inner{background:#fff;border-radius:12px;padding:16px}
428
+ .qr-inner svg{width:100%;height:auto;display:block}
429
+
430
+ .scan-hint{margin-top:20px;font-size:13px;color:#666;text-align:center;animation:fade-up .5s ease-out .2s both}
431
+
432
+ .confetti-wrap{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;overflow:hidden}
433
+ .confetti-dot{position:absolute;width:8px;height:8px;border-radius:50%;top:-10px;animation:confetti-fall 2s ease-out forwards}
434
+ @keyframes confetti-fall{0%{opacity:1;transform:translateY(0) translateX(0) rotate(0) scale(1)}100%{opacity:0;transform:translateY(100vh) translateX(var(--drift)) rotate(360deg) scale(.5)}}
435
+
436
+ .video-wrap{margin-bottom:8px;animation:pop-in .5s cubic-bezier(.34,1.56,.64,1) forwards}
437
+ .video-wrap video{width:200px;object-fit:contain}
438
+ @keyframes pop-in{0%{transform:scale(0);opacity:0}100%{transform:scale(1);opacity:1}}
439
+
440
+ .text-wrap{text-align:center;animation:fade-up .5s ease-out .3s both}
441
+ .title{font-family:'Space Grotesk',sans-serif;font-size:22px;font-weight:700;background:linear-gradient(135deg,#04D1FE,#AF27E3,#FB4072);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;margin-bottom:8px}
442
+ .subtitle{font-size:14px;color:#999;line-height:1.5}
443
+
444
+ .loading{font-size:14px;color:#999;animation:pulse 2s ease-in-out infinite}
445
+ @keyframes pulse{0%,100%{opacity:.5}50%{opacity:1}}
446
+ @keyframes fade-up{0%{opacity:0;transform:translateY(10px)}100%{opacity:1;transform:translateY(0)}}
447
+ </style></head><body>
448
+ <div class="container">
449
+ ${connected
450
+ ? `<div class="confetti-wrap">${confettiHTML}</div>
451
+ <div class="video-wrap"><video autoplay muted playsinline><source src="/bloby_happy_reappearing.mov" type='video/mp4; codecs="hvc1"'><source src="/bloby_happy_reappearing.webm" type="video/webm"></video></div>
452
+ <div class="text-wrap"><div class="title">Connected!</div><p class="subtitle">WhatsApp is linked. You can close this page.</p>
453
+ <button onclick="relink()" style="margin-top:20px;padding:10px 24px;background:#2a2a2a;border:1px solid rgba(255,255,255,0.15);border-radius:10px;color:#999;font-size:13px;cursor:pointer;font-family:inherit;transition:all .2s" onmouseover="this.style.borderColor='#AF27E3';this.style.color='#f5f5f5'" onmouseout="this.style.borderColor='rgba(255,255,255,0.15)';this.style.color='#999'">Relink to a different number</button>
454
+ </div>
455
+ <script>async function relink(){await fetch('/api/channels/whatsapp/logout',{method:'POST'});await fetch('/api/channels/whatsapp/connect',{method:'POST'});setTimeout(()=>location.reload(),2000)}</script>`
456
+ : qr
457
+ ? `<div class="qr-card"><div class="qr-inner">${qr}</div></div><p class="scan-hint">Scan with WhatsApp to link</p>`
458
+ : '<p class="loading">Starting WhatsApp... Refresh in a moment.</p>'}
459
+ </div>
460
+ ${!connected ? '<script>setTimeout(()=>location.reload(),4000)</script>' : ''}
461
+ </body></html>`);
462
+ return;
463
+ }
464
+
465
+ // POST /api/channels/whatsapp/connect — start WhatsApp connection (triggers QR)
466
+ if (req.method === 'POST' && channelPath === '/api/channels/whatsapp/connect') {
467
+ (async () => {
468
+ try {
469
+ // Enable WhatsApp in config
470
+ const cfg = loadConfig();
471
+ if (!cfg.channels) cfg.channels = {};
472
+ if (!cfg.channels.whatsapp) cfg.channels.whatsapp = { enabled: true, mode: 'channel' };
473
+ cfg.channels.whatsapp.enabled = true;
474
+ saveConfig(cfg);
475
+
476
+ await channelManager.connectWhatsApp();
477
+ res.writeHead(200);
478
+ res.end(JSON.stringify({ ok: true }));
479
+ } catch (err: any) {
480
+ res.writeHead(500);
481
+ res.end(JSON.stringify({ error: err.message }));
482
+ }
483
+ })();
484
+ return;
485
+ }
486
+
487
+ // POST /api/channels/whatsapp/disconnect — disconnect WhatsApp
488
+ if (req.method === 'POST' && channelPath === '/api/channels/whatsapp/disconnect') {
489
+ (async () => {
490
+ try {
491
+ await channelManager.disconnectChannel('whatsapp');
492
+ const cfg = loadConfig();
493
+ if (cfg.channels?.whatsapp) cfg.channels.whatsapp.enabled = false;
494
+ saveConfig(cfg);
495
+ res.writeHead(200);
496
+ res.end(JSON.stringify({ ok: true }));
497
+ } catch (err: any) {
498
+ res.writeHead(500);
499
+ res.end(JSON.stringify({ error: err.message }));
500
+ }
501
+ })();
502
+ return;
503
+ }
504
+
505
+ // POST /api/channels/whatsapp/logout — disconnect + delete credentials
506
+ if (req.method === 'POST' && channelPath === '/api/channels/whatsapp/logout') {
507
+ (async () => {
508
+ try {
509
+ await channelManager.logoutWhatsApp();
510
+ const cfg = loadConfig();
511
+ if (cfg.channels?.whatsapp) cfg.channels.whatsapp.enabled = false;
512
+ saveConfig(cfg);
513
+ res.writeHead(200);
514
+ res.end(JSON.stringify({ ok: true }));
515
+ } catch (err: any) {
516
+ res.writeHead(500);
517
+ res.end(JSON.stringify({ error: err.message }));
518
+ }
519
+ })();
520
+ return;
521
+ }
522
+
523
+ // POST /api/channels/whatsapp/configure — set mode + admins
524
+ if (req.method === 'POST' && channelPath === '/api/channels/whatsapp/configure') {
525
+ let body = '';
526
+ req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
527
+ req.on('end', () => {
528
+ try {
529
+ const data = JSON.parse(body);
530
+ const cfg = loadConfig();
531
+ if (!cfg.channels) cfg.channels = {};
532
+ if (!cfg.channels.whatsapp) cfg.channels.whatsapp = { enabled: true, mode: 'channel' };
533
+ if (data.mode) cfg.channels.whatsapp.mode = data.mode;
534
+ if (data.admins !== undefined) cfg.channels.whatsapp.admins = data.admins;
535
+ if (data.skill !== undefined) cfg.channels.whatsapp.skill = data.skill;
536
+ saveConfig(cfg);
537
+ res.writeHead(200);
538
+ res.end(JSON.stringify({ ok: true, config: cfg.channels.whatsapp }));
539
+ } catch (err: any) {
540
+ res.writeHead(400);
541
+ res.end(JSON.stringify({ error: err.message }));
542
+ }
543
+ });
544
+ return;
545
+ }
546
+
547
+ // POST /api/channels/send — send a message via any channel
548
+ if (req.method === 'POST' && channelPath === '/api/channels/send') {
549
+ let body = '';
550
+ req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
551
+ req.on('end', async () => {
552
+ try {
553
+ const { channel, to, text } = JSON.parse(body);
554
+ if (!channel || !to || !text) {
555
+ res.writeHead(400);
556
+ res.end(JSON.stringify({ error: 'Missing channel, to, or text' }));
557
+ return;
558
+ }
559
+ await channelManager.sendMessage(channel, to, text);
560
+ res.writeHead(200);
561
+ res.end(JSON.stringify({ ok: true }));
562
+ } catch (err: any) {
563
+ res.writeHead(500);
564
+ res.end(JSON.stringify({ error: err.message }));
565
+ }
566
+ });
567
+ return;
568
+ }
569
+
570
+ // Fallback for unknown channel routes
571
+ res.writeHead(404);
572
+ res.end(JSON.stringify({ error: 'Not found' }));
573
+ return;
574
+ }
575
+
576
+ // API routes → handled in-process by worker Express app
577
+ if (req.url?.startsWith('/api')) {
578
+ // Internal supervisor calls (workerApi) bypass auth — they carry a per-process secret
579
+ const isInternal = req.headers['x-internal'] === internalSecret;
580
+
581
+ if (!isInternal) {
582
+ // Auth check for mutation routes (POST/PUT/DELETE) — GET/HEAD are read-only, skip auth
583
+ const method = req.method || 'GET';
584
+ if (method !== 'GET' && method !== 'HEAD' && !isExemptRoute(method, req.url || '')) {
585
+ const needsAuth = await isAuthRequired();
586
+ if (needsAuth) {
587
+ const authHeader = req.headers['authorization'];
588
+ const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;
589
+ if (!token || !(await validateToken(token))) {
590
+ res.writeHead(401, { 'Content-Type': 'application/json' });
591
+ res.end(JSON.stringify({ error: 'Unauthorized' }));
592
+ return;
593
+ }
594
+ }
595
+ }
596
+ }
597
+
598
+ workerApp(req, res);
599
+ return;
600
+ }
601
+
602
+ // Bloby routes → serve pre-built static files from dist-bloby/
603
+ // Note: must check '/bloby/' (with slash) to avoid matching '/bloby_tilts.webm' etc.
604
+ if (req.url === '/bloby' || req.url?.startsWith('/bloby/')) {
605
+ // Strip /bloby prefix and resolve file path
606
+ let filePath = req.url!.replace(/^\/bloby\/?/, '') || 'bloby.html';
607
+ // Strip query strings (e.g. ?v=xxx)
608
+ filePath = filePath.split('?')[0];
609
+ const fullPath = path.join(DIST_BLOBY, filePath);
610
+
611
+ // Security: prevent directory traversal
612
+ if (!fullPath.startsWith(DIST_BLOBY)) {
613
+ res.writeHead(403);
614
+ res.end('Forbidden');
615
+ return;
616
+ }
617
+
618
+ try {
619
+ const stat = fs.statSync(fullPath);
620
+ if (stat.isFile()) {
621
+ const ext = path.extname(fullPath);
622
+ const mime = MIME_TYPES[ext] || 'application/octet-stream';
623
+ // HTML files: no-cache so rebuilds are picked up immediately
624
+ // Hashed assets (.js, .css): immutable caching
625
+ const cacheControl = ext === '.html' ? 'no-cache' : 'public, max-age=31536000, immutable';
626
+ res.writeHead(200, { 'Content-Type': mime, 'Cache-Control': cacheControl });
627
+ fs.createReadStream(fullPath).pipe(res);
628
+ } else {
629
+ res.writeHead(404);
630
+ res.end('Not found');
631
+ }
632
+ } catch {
633
+ res.writeHead(404);
634
+ res.end('Not found');
635
+ }
636
+ return;
637
+ }
638
+
639
+ // Everything else → proxy to dashboard Vite dev server
640
+ console.log(`[supervisor] → dashboard Vite :${vitePorts.dashboard} | ${req.method} ${req.url}`);
641
+ const proxy = http.request(
642
+ { host: '127.0.0.1', port: vitePorts.dashboard, path: req.url, method: req.method, headers: req.headers },
643
+ (proxyRes) => {
644
+ res.writeHead(proxyRes.statusCode!, proxyRes.headers);
645
+ proxyRes.pipe(res);
646
+ },
647
+ );
648
+ proxy.on('error', (e) => {
649
+ console.error(`[supervisor] Dashboard Vite proxy error: ${req.url}`, e.message);
650
+ res.writeHead(503, { 'Content-Type': 'text/html' });
651
+ res.end(RECOVERING_HTML);
652
+ });
653
+ req.pipe(proxy);
654
+ });
655
+
656
+ // WebSocket: Bloby chat + proxy worker WS
657
+ const blobyWss = new WebSocketServer({ noServer: true });
658
+
659
+ // WebSocket: App API proxy (routes /app/api calls through WS to avoid tunnel POST issues)
660
+ const appWss = new WebSocketServer({ noServer: true });
661
+
662
+ appWss.on('connection', (ws) => {
663
+ console.log('[supervisor] App API WS client connected');
664
+
665
+ ws.on('message', (raw) => {
666
+ const rawStr = raw.toString();
667
+
668
+ if (rawStr === 'ping') {
669
+ if (ws.readyState === WebSocket.OPEN) ws.send('pong');
670
+ return;
671
+ }
672
+
673
+ let msg: any;
674
+ try {
675
+ msg = JSON.parse(rawStr);
676
+ } catch {
677
+ return;
678
+ }
679
+
680
+ if (msg.type !== 'app:api' || !msg.data) return;
681
+
682
+ const { id, method, path: reqPath, headers: reqHeaders, body } = msg.data;
683
+ const backendPath = (reqPath || '').replace(/^\/app/, '');
684
+
685
+ console.log(`[supervisor] App WS → backend :${backendPort} | ${method} ${backendPath} (${id})`);
686
+
687
+ if (!isBackendAlive()) {
688
+ console.log('[supervisor] App WS: Backend down — returning 503');
689
+ if (ws.readyState === WebSocket.OPEN) {
690
+ ws.send(JSON.stringify({
691
+ type: 'app:api:response',
692
+ data: { id, status: 503, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ error: 'Backend is starting...' }) },
693
+ }));
694
+ }
695
+ return;
696
+ }
697
+
698
+ const proxyHeaders: Record<string, string> = { ...(reqHeaders || {}) };
699
+ if (body && !proxyHeaders['content-type']) {
700
+ proxyHeaders['content-type'] = 'application/json';
701
+ }
702
+
703
+ const proxyReq = http.request(
704
+ { host: '127.0.0.1', port: backendPort, path: backendPath, method, headers: proxyHeaders },
705
+ (proxyRes) => {
706
+ const chunks: Buffer[] = [];
707
+ proxyRes.on('data', (chunk: Buffer) => chunks.push(chunk));
708
+ proxyRes.on('end', () => {
709
+ const responseBody = Buffer.concat(chunks).toString('utf-8');
710
+ const resHeaders: Record<string, string> = {};
711
+ for (const [k, v] of Object.entries(proxyRes.headers)) {
712
+ if (typeof v === 'string') resHeaders[k] = v;
713
+ else if (Array.isArray(v)) resHeaders[k] = v.join(', ');
714
+ }
715
+
716
+ console.log(`[supervisor] App WS ← backend: ${proxyRes.statusCode} (${id})`);
717
+
718
+ if (ws.readyState === WebSocket.OPEN) {
719
+ ws.send(JSON.stringify({
720
+ type: 'app:api:response',
721
+ data: { id, status: proxyRes.statusCode, headers: resHeaders, body: responseBody },
722
+ }));
723
+ }
724
+ });
725
+ },
726
+ );
727
+
728
+ proxyReq.on('error', (e) => {
729
+ console.error(`[supervisor] App WS backend error: ${backendPath}`, e.message);
730
+ if (ws.readyState === WebSocket.OPEN) {
731
+ ws.send(JSON.stringify({
732
+ type: 'app:api:response',
733
+ data: { id, status: 503, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ error: 'Backend unavailable' }) },
734
+ }));
735
+ }
736
+ });
737
+
738
+ if (body) proxyReq.write(body);
739
+ proxyReq.end();
740
+ });
741
+
742
+ ws.on('close', () => {
743
+ console.log('[supervisor] App API WS client disconnected');
744
+ });
745
+ });
746
+
747
+ /** Send a message to all connected bloby WS clients */
748
+ function broadcastBloby(type: string, data: any = {}) {
749
+ const msg = JSON.stringify({ type, data });
750
+ for (const client of blobyWss.clients) {
751
+ if (client.readyState === WebSocket.OPEN) client.send(msg);
752
+ }
753
+ }
754
+
755
+ blobyWss.on('connection', (ws) => {
756
+ log.info('Bloby chat connected');
757
+ let convId = Math.random().toString(36).slice(2) + Date.now().toString(36);
758
+ conversations.set(ws, []);
759
+
760
+ // Send current streaming state so reconnecting clients can catch up
761
+ if (agentQueryActive && currentStreamConvId) {
762
+ ws.send(JSON.stringify({
763
+ type: 'chat:state',
764
+ data: {
765
+ streaming: true,
766
+ conversationId: currentStreamConvId,
767
+ buffer: currentStreamBuffer,
768
+ },
769
+ }));
770
+ }
771
+
772
+ ws.on('message', (raw) => {
773
+ const rawStr = raw.toString();
774
+
775
+ // Heartbeat
776
+ if (rawStr === 'ping') {
777
+ if (ws.readyState === WebSocket.OPEN) ws.send('pong');
778
+ return;
779
+ }
780
+
781
+ const msg = JSON.parse(rawStr);
782
+
783
+ // Whisper transcription via WebSocket (bypasses relay POST issues)
784
+ if (msg.type === 'whisper:transcribe') {
785
+ (async () => {
786
+ try {
787
+ const result = await workerApi('/api/whisper/transcribe', 'POST', { audio: msg.data.audio });
788
+ if (ws.readyState === WebSocket.OPEN) {
789
+ ws.send(JSON.stringify({ type: 'whisper:result', data: result }));
790
+ }
791
+ } catch (err: any) {
792
+ if (ws.readyState === WebSocket.OPEN) {
793
+ ws.send(JSON.stringify({ type: 'whisper:result', data: { error: err.message } }));
794
+ }
795
+ }
796
+ })();
797
+ return;
798
+ }
799
+
800
+ // Push subscribe via WebSocket (bypasses relay POST issues)
801
+ if (msg.type === 'push:subscribe') {
802
+ (async () => {
803
+ try {
804
+ const result = await workerApi('/api/push/subscribe', 'POST', msg.data);
805
+ if (ws.readyState === WebSocket.OPEN) {
806
+ ws.send(JSON.stringify({ type: 'push:subscribed', data: result }));
807
+ }
808
+ } catch (err: any) {
809
+ if (ws.readyState === WebSocket.OPEN) {
810
+ ws.send(JSON.stringify({ type: 'push:subscribe-error', data: { error: err.message } }));
811
+ }
812
+ }
813
+ })();
814
+ return;
815
+ }
816
+
817
+ // Push unsubscribe via WebSocket (bypasses relay POST issues)
818
+ if (msg.type === 'push:unsubscribe') {
819
+ (async () => {
820
+ try {
821
+ const result = await workerApi('/api/push/unsubscribe', 'DELETE', msg.data);
822
+ if (ws.readyState === WebSocket.OPEN) {
823
+ ws.send(JSON.stringify({ type: 'push:unsubscribed', data: result }));
824
+ }
825
+ } catch (err: any) {
826
+ if (ws.readyState === WebSocket.OPEN) {
827
+ ws.send(JSON.stringify({ type: 'push:unsubscribe-error', data: { error: err.message } }));
828
+ }
829
+ }
830
+ })();
831
+ return;
832
+ }
833
+
834
+ // Save settings via WebSocket (bypasses relay POST issues)
835
+ if (msg.type === 'settings:save') {
836
+ (async () => {
837
+ try {
838
+ const result = await workerApi('/api/onboard', 'POST', msg.data);
839
+ if (ws.readyState === WebSocket.OPEN) {
840
+ ws.send(JSON.stringify({ type: 'settings:saved', data: result }));
841
+ }
842
+ } catch (err: any) {
843
+ log.error(`[bloby] settings:save failed: ${err.message}`);
844
+ if (ws.readyState === WebSocket.OPEN) {
845
+ ws.send(JSON.stringify({ type: 'settings:save-error', data: { error: err.message } }));
846
+ }
847
+ }
848
+ })();
849
+ return;
850
+ }
851
+
852
+ // Switch tunnel mode at runtime (off ↔ quick)
853
+ if (msg.type === 'tunnel:switch') {
854
+ (async () => {
855
+ try {
856
+ const newMode = msg.data?.mode as 'off' | 'quick';
857
+ const cfg = loadConfig();
858
+
859
+ if (newMode === 'off') {
860
+ // Stop tunnel, heartbeat, relay, watchdog
861
+ stopHeartbeat();
862
+ if (cfg.relay?.token) {
863
+ try { await disconnect(cfg.relay.token); } catch {}
864
+ }
865
+ stopTunnel();
866
+ if (watchdogInterval) { clearInterval(watchdogInterval); watchdogInterval = null; }
867
+ tunnelUrl = null;
868
+ cfg.tunnel.mode = 'off';
869
+ delete cfg.tunnelUrl;
870
+ saveConfig(cfg);
871
+ log.ok('[tunnel:switch] Switched to off — tunnel stopped');
872
+ if (ws.readyState === WebSocket.OPEN) {
873
+ ws.send(JSON.stringify({ type: 'tunnel:switched', data: { mode: 'off' } }));
874
+ }
875
+ } else if (newMode === 'quick') {
876
+ // Start tunnel
877
+ const newUrl = await startTunnel(cfg.port);
878
+ tunnelUrl = newUrl;
879
+ cfg.tunnel.mode = 'quick';
880
+ cfg.tunnelUrl = newUrl;
881
+ saveConfig(cfg);
882
+ log.ok(`[tunnel:switch] Tunnel started: ${newUrl}`);
883
+
884
+ // Wait for local server readiness
885
+ for (let i = 0; i < 15; i++) {
886
+ try {
887
+ const res = await fetch(`http://127.0.0.1:${cfg.port}/api/health?_cb=${Date.now()}`, {
888
+ signal: AbortSignal.timeout(3000),
889
+ });
890
+ if (res.ok) break;
891
+ } catch {}
892
+ await new Promise(r => setTimeout(r, 1000));
893
+ }
894
+
895
+ // Reconnect relay if handle exists
896
+ if (cfg.relay?.token) {
897
+ try {
898
+ await updateTunnelUrl(cfg.relay.token, newUrl);
899
+ startHeartbeat(cfg.relay.token, newUrl);
900
+ log.ok('[tunnel:switch] Relay reconnected');
901
+ } catch (err) {
902
+ log.warn(`[tunnel:switch] Relay reconnect: ${err instanceof Error ? err.message : err}`);
903
+ }
904
+ }
905
+
906
+ // Re-create watchdog
907
+ if (watchdogInterval) clearInterval(watchdogInterval);
908
+ let lastTick = Date.now();
909
+ let healthCounter = 0;
910
+ watchdogInterval = setInterval(async () => {
911
+ const now = Date.now();
912
+ const wakeGap = now - lastTick > 60_000;
913
+ const periodicCheck = ++healthCounter % 10 === 0;
914
+ lastTick = now;
915
+ if (wakeGap || periodicCheck) {
916
+ const alive = await isTunnelAlive(tunnelUrl!, cfg.port);
917
+ if (!alive) {
918
+ log.warn('Tunnel dead, restarting...');
919
+ try {
920
+ const restartedUrl = await restartTunnel(cfg.port);
921
+ await new Promise(r => setTimeout(r, 3000));
922
+ tunnelUrl = restartedUrl;
923
+ const latestCfg = loadConfig();
924
+ latestCfg.tunnelUrl = restartedUrl;
925
+ saveConfig(latestCfg);
926
+ if (latestCfg.relay?.token) {
927
+ stopHeartbeat();
928
+ startHeartbeat(latestCfg.relay.token, restartedUrl);
929
+ await updateTunnelUrl(latestCfg.relay.token, restartedUrl);
930
+ }
931
+ log.ok(`Tunnel restored: ${restartedUrl}`);
932
+ } catch (err) {
933
+ log.error(`Tunnel restart failed: ${err instanceof Error ? err.message : err}`);
934
+ }
935
+ }
936
+ }
937
+ }, 30_000);
938
+
939
+ if (ws.readyState === WebSocket.OPEN) {
940
+ ws.send(JSON.stringify({ type: 'tunnel:switched', data: { mode: 'quick', tunnelUrl: newUrl } }));
941
+ }
942
+ }
943
+ } catch (err: any) {
944
+ log.error(`[tunnel:switch] Error: ${err.message}`);
945
+ if (ws.readyState === WebSocket.OPEN) {
946
+ ws.send(JSON.stringify({ type: 'tunnel:switch-error', data: { error: err.message } }));
947
+ }
948
+ }
949
+ })();
950
+ return;
951
+ }
952
+
953
+ // New protocol: { type: 'user:message', data: { content, conversationId? } }
954
+ if (msg.type === 'user:message') {
955
+ const data = msg.data || {};
956
+ const content = data.content;
957
+ if (!content) return;
958
+ if (data.conversationId) convId = data.conversationId;
959
+
960
+ // Re-read config on each message so post-onboard changes are picked up
961
+ const freshConfig = loadConfig();
962
+ const freshAi = (freshConfig.ai.provider && (freshConfig.ai.apiKey || freshConfig.ai.provider === 'ollama'))
963
+ ? createProvider(freshConfig.ai.provider, freshConfig.ai.apiKey, freshConfig.ai.baseUrl)
964
+ : null;
965
+
966
+ log.info(`[bloby] provider=${freshConfig.ai.provider}, model=${freshConfig.ai.model}`);
967
+
968
+ // Route Anthropic through Agent SDK (uses OAuth token, not API key)
969
+ if (freshConfig.ai.provider === 'anthropic') {
970
+ // Server-side persistence: create or reuse DB conversation, save user message
971
+ (async () => {
972
+ // Save attachments to disk (before try so it's accessible in startBlobyAgentQuery below)
973
+ let savedFiles: SavedFile[] = [];
974
+ if (data.attachments?.length) {
975
+ for (const att of data.attachments) {
976
+ try {
977
+ savedFiles.push(saveAttachment(att));
978
+ } catch (err: any) {
979
+ log.warn(`[bloby] File save error: ${err.message}`);
980
+ }
981
+ }
982
+ }
983
+
984
+ try {
985
+ // Check if we have an existing conversation for this client
986
+ let dbConvId = clientConvs.get(ws);
987
+ if (!dbConvId) {
988
+ // Check if there's a current conversation set in settings
989
+ const ctx = await workerApi('/api/context/current');
990
+ if (ctx.conversationId) {
991
+ dbConvId = ctx.conversationId;
992
+ } else {
993
+ // Create a new conversation
994
+ const conv = await workerApi('/api/conversations', 'POST', { title: content.slice(0, 80), model: freshConfig.ai.model });
995
+ dbConvId = conv.id;
996
+ await workerApi('/api/context/set', 'POST', { conversationId: dbConvId });
997
+ }
998
+ clientConvs.set(ws, dbConvId!);
999
+ // Notify client of the conversation ID
1000
+ if (ws.readyState === WebSocket.OPEN) {
1001
+ ws.send(JSON.stringify({ type: 'chat:conversation-created', data: { conversationId: dbConvId } }));
1002
+ }
1003
+ }
1004
+ convId = dbConvId!;
1005
+
1006
+ // Save user message to DB (include attachment metadata as JSON string)
1007
+ const meta: any = { model: freshConfig.ai.model };
1008
+ if (savedFiles.length) {
1009
+ meta.attachments = JSON.stringify(savedFiles.map((f) => ({
1010
+ type: f.type, name: f.name, mediaType: f.mediaType, filePath: f.relPath,
1011
+ })));
1012
+ }
1013
+ await workerApi(`/api/conversations/${convId}/messages`, 'POST', {
1014
+ role: 'user', content, meta,
1015
+ });
1016
+
1017
+ // Broadcast user message to other clients
1018
+ broadcastBlobyExcept(ws, 'chat:sync', {
1019
+ conversationId: convId,
1020
+ message: { role: 'user', content, timestamp: new Date().toISOString() },
1021
+ });
1022
+ } catch (err: any) {
1023
+ log.warn(`[bloby] DB persist error: ${err.message}`);
1024
+ }
1025
+
1026
+ // Fetch agent/user names and recent messages in parallel
1027
+ let botName = 'Bloby', humanName = 'Human';
1028
+ let recentMessages: RecentMessage[] = [];
1029
+ try {
1030
+ const [status, recentRaw] = await Promise.all([
1031
+ workerApi('/api/onboard/status') as Promise<any>,
1032
+ workerApi(`/api/conversations/${convId}/messages/recent?limit=20`) as Promise<any[]>,
1033
+ ]);
1034
+ botName = status.agentName || 'Bloby';
1035
+ humanName = status.userName || 'Human';
1036
+
1037
+ // Filter to user/assistant only, exclude the last entry (current message already sent as SDK prompt)
1038
+ if (Array.isArray(recentRaw)) {
1039
+ const filtered = recentRaw
1040
+ .filter((m: any) => m.role === 'user' || m.role === 'assistant');
1041
+ // Slice off the last entry — it's the current user message
1042
+ if (filtered.length > 0) {
1043
+ recentMessages = filtered.slice(0, -1).map((m: any) => ({
1044
+ role: m.role as 'user' | 'assistant',
1045
+ content: m.content,
1046
+ }));
1047
+ }
1048
+ }
1049
+ } catch {}
1050
+
1051
+ // Mirror chat responses to WhatsApp self-chat (if connected)
1052
+ const waStatus = channelManager.getStatus('whatsapp');
1053
+ const waMirrorJid = waStatus?.connected ? waStatus.info?.phoneNumber : null;
1054
+ let waChunkBuf = '';
1055
+
1056
+ // Start agent query
1057
+ agentQueryActive = true;
1058
+ currentStreamConvId = convId;
1059
+ currentStreamBuffer = '';
1060
+ startBlobyAgentQuery(convId, content, freshConfig.ai.model, (type, eventData) => {
1061
+ // Track stream buffer for reconnecting clients
1062
+ if (type === 'bot:token' && eventData.token) {
1063
+ currentStreamBuffer += eventData.token;
1064
+ if (waMirrorJid) waChunkBuf += eventData.token;
1065
+ }
1066
+
1067
+ // WhatsApp mirror: send intermediate chunk when agent pauses for tool use
1068
+ if (type === 'bot:tool' && waMirrorJid && waChunkBuf.trim()) {
1069
+ channelManager.sendMessage('whatsapp', `${waMirrorJid}@s.whatsapp.net`, waChunkBuf.trim()).catch(() => {});
1070
+ waChunkBuf = '';
1071
+ }
1072
+
1073
+ // Intercept bot:done — Vite HMR handles file changes automatically
1074
+ if (type === 'bot:done') {
1075
+ agentQueryActive = false;
1076
+ currentStreamConvId = null;
1077
+ currentStreamBuffer = '';
1078
+ // Restart if agent used file tools OR file watcher detected changes during the turn
1079
+ if (eventData.usedFileTools || pendingBackendRestart) {
1080
+ console.log('[supervisor] Agent turn ended — restarting backend');
1081
+ pendingBackendRestart = false;
1082
+ if (backendRestartTimer) { clearTimeout(backendRestartTimer); backendRestartTimer = null; }
1083
+ resetBackendRestarts();
1084
+ stopBackend().then(() => spawnBackend(backendPort));
1085
+ }
1086
+ // Run deferred update if agent requested one
1087
+ if (pendingUpdate) {
1088
+ pendingUpdate = false;
1089
+ runDeferredUpdate();
1090
+ }
1091
+ return; // don't forward bot:done to client
1092
+ }
1093
+
1094
+ // Save assistant response to DB + clear stream state
1095
+ if (type === 'bot:response') {
1096
+ currentStreamBuffer = '';
1097
+
1098
+ // WhatsApp mirror: send remaining chunk
1099
+ if (waMirrorJid && waChunkBuf.trim()) {
1100
+ channelManager.sendMessage('whatsapp', `${waMirrorJid}@s.whatsapp.net`, waChunkBuf.trim()).catch(() => {});
1101
+ waChunkBuf = '';
1102
+ }
1103
+
1104
+ (async () => {
1105
+ try {
1106
+ await workerApi(`/api/conversations/${convId}/messages`, 'POST', {
1107
+ role: 'assistant', content: eventData.content, meta: { model: freshConfig.ai.model },
1108
+ });
1109
+ } catch (err: any) {
1110
+ log.warn(`[bloby] DB persist bot response error: ${err.message}`);
1111
+ }
1112
+ })();
1113
+ }
1114
+
1115
+ // Stream all events to every connected client
1116
+ broadcastBloby(type, eventData);
1117
+ }, data.attachments, savedFiles, { botName, humanName }, recentMessages);
1118
+ })();
1119
+ return;
1120
+ }
1121
+
1122
+ // Other providers: use ai.chat() with conversation history
1123
+ const history = conversations.get(ws) || [];
1124
+ history.push({ role: 'user', content });
1125
+
1126
+ if (!freshAi) {
1127
+ if (ws.readyState === WebSocket.OPEN) {
1128
+ ws.send(JSON.stringify({ type: 'bot:error', data: { error: 'AI not configured. Set up your provider first.' } }));
1129
+ }
1130
+ return;
1131
+ }
1132
+
1133
+ if (ws.readyState === WebSocket.OPEN) {
1134
+ ws.send(JSON.stringify({ type: 'bot:typing', data: { conversationId: convId } }));
1135
+ }
1136
+
1137
+ freshAi.chat(
1138
+ [{ role: 'system', content: 'You are Bloby, a helpful AI assistant. You help users manage and customize their self-hosted bot.' }, ...history],
1139
+ freshConfig.ai.model,
1140
+ (token) => { if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'bot:token', data: { token, conversationId: convId } })); },
1141
+ (full) => {
1142
+ history.push({ role: 'assistant', content: full });
1143
+ if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'bot:response', data: { conversationId: convId, content: full } }));
1144
+ },
1145
+ (err) => { if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({ type: 'bot:error', data: { error: err.message } })); },
1146
+ );
1147
+ return;
1148
+ }
1149
+
1150
+ if (msg.type === 'user:stop') {
1151
+ stopBlobyAgentQuery(convId);
1152
+ return;
1153
+ }
1154
+
1155
+ if (msg.type === 'user:clear-context') {
1156
+ (async () => {
1157
+ try {
1158
+ clientConvs.delete(ws);
1159
+ await workerApi('/api/context/clear', 'POST');
1160
+ } catch (err: any) {
1161
+ log.warn(`[bloby] Clear context error: ${err.message}`);
1162
+ }
1163
+ // Broadcast clear to ALL clients
1164
+ broadcastBloby('chat:cleared');
1165
+ })();
1166
+ return;
1167
+ }
1168
+ });
1169
+
1170
+ ws.on('close', () => {
1171
+ conversations.delete(ws);
1172
+ clientConvs.delete(ws);
1173
+ });
1174
+ });
1175
+
1176
+ // Bloby chat WebSocket — Vite HMR is handled automatically (hmr.server = this server)
1177
+ server.on('upgrade', async (req, socket: net.Socket, head) => {
1178
+ console.log(`[supervisor] WebSocket upgrade: ${req.url} | protocol=${req.headers['sec-websocket-protocol'] || 'none'}`);
1179
+
1180
+ // App API WebSocket — no auth (backend handles its own auth)
1181
+ if (req.url?.startsWith('/app/ws')) {
1182
+ console.log('[supervisor] → App API WebSocket');
1183
+ appWss.handleUpgrade(req, socket, head, (ws) => appWss.emit('connection', ws, req));
1184
+ return;
1185
+ }
1186
+
1187
+ if (!req.url?.startsWith('/bloby/ws')) {
1188
+ console.log('[supervisor] → Letting Vite handle this upgrade');
1189
+ return;
1190
+ }
1191
+
1192
+ // Auth check for WebSocket
1193
+ const needsAuth = await isAuthRequired();
1194
+ if (needsAuth) {
1195
+ const urlObj = new URL(req.url, `http://${req.headers.host}`);
1196
+ const token = urlObj.searchParams.get('token');
1197
+ if (!token || !(await validateToken(token))) {
1198
+ console.log('[supervisor] WS auth failed — rejecting');
1199
+ socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
1200
+ socket.destroy();
1201
+ return;
1202
+ }
1203
+ }
1204
+
1205
+ console.log('[supervisor] → Bloby chat WebSocket');
1206
+ blobyWss.handleUpgrade(req, socket, head, (ws) => blobyWss.emit('connection', ws, req));
1207
+ });
1208
+
1209
+ // Start
1210
+ server.on('error', (err: NodeJS.ErrnoException) => {
1211
+ if (err.code === 'EADDRINUSE') {
1212
+ log.error(`Port ${config.port} is already in use. Stop the other process or change the port in ${paths.config}`);
1213
+ } else {
1214
+ log.error(`Server error: ${err.message}`);
1215
+ }
1216
+ process.exit(1);
1217
+ });
1218
+
1219
+ server.listen(config.port, () => {
1220
+ log.ok(`Supervisor on http://localhost:${config.port}`);
1221
+ log.ok(`Bloby chat at http://localhost:${config.port}/bloby`);
1222
+ if (config.tunnel.mode === 'off') {
1223
+ console.log('__READY__');
1224
+ }
1225
+ });
1226
+
1227
+ // Track whether an agent query is active — file watcher defers to bot:done during turns
1228
+ let agentQueryActive = false;
1229
+ let pendingBackendRestart = false; // Set when file watcher fires during agent turn
1230
+ let pendingUpdate = false; // Set when .update file is created during agent turn
1231
+
1232
+ // Run bloby update as a child process.
1233
+ // BLOBY_SELF_UPDATE=1 tells bin/cli.js to skip daemon stop/restart —
1234
+ // the supervisor exits after the update finishes, and systemd (Restart=on-failure)
1235
+ // or launchd (KeepAlive.SuccessfulExit=false) restarts us with the new code.
1236
+ function runDeferredUpdate() {
1237
+ const cliPath = path.join(PKG_DIR, 'bin', 'cli.js');
1238
+ const updateLog = path.join(DATA_DIR, 'update.log');
1239
+ log.info('Deferred update triggered — running bloby update...');
1240
+ try {
1241
+ const logFd = fs.openSync(updateLog, 'w');
1242
+ const child = cpSpawn(process.execPath, [cliPath, 'update'], {
1243
+ stdio: ['ignore', logFd, logFd],
1244
+ env: { ...process.env, BLOBY_SELF_UPDATE: '1' },
1245
+ });
1246
+ child.on('exit', (code) => {
1247
+ try { fs.closeSync(logFd); } catch {}
1248
+ if (code === 0) {
1249
+ log.ok('Update completed — restarting with new version...');
1250
+ process.exit(1); // non-zero triggers daemon manager to restart us
1251
+ } else {
1252
+ log.error(`Update process exited with code ${code} — see ${updateLog}`);
1253
+ }
1254
+ });
1255
+ } catch (err) {
1256
+ log.error(`Deferred update failed: ${err instanceof Error ? err.message : err}`);
1257
+ }
1258
+ }
1259
+
1260
+ // Spawn backend (worker runs in-process)
1261
+ spawnBackend(backendPort);
1262
+
1263
+ // Start pulse/cron scheduler
1264
+ startScheduler({
1265
+ broadcastBloby,
1266
+ workerApi,
1267
+ restartBackend: async () => {
1268
+ resetBackendRestarts();
1269
+ await stopBackend();
1270
+ spawnBackend(backendPort);
1271
+ },
1272
+ getModel: () => loadConfig().ai.model,
1273
+ });
1274
+
1275
+ // Initialize channel manager (WhatsApp, Telegram, etc.)
1276
+ const channelManager = new ChannelManager({
1277
+ broadcastBloby,
1278
+ workerApi,
1279
+ restartBackend: async () => {
1280
+ resetBackendRestarts();
1281
+ await stopBackend();
1282
+ spawnBackend(backendPort);
1283
+ },
1284
+ getModel: () => loadConfig().ai.model,
1285
+ });
1286
+
1287
+ // Broadcast channel status changes to all connected chat clients
1288
+ channelManager.onStatusChange((status) => {
1289
+ broadcastBloby('channel:status', status);
1290
+ // Also broadcast QR code updates
1291
+ if (status.info?.hasQr) {
1292
+ const qr = channelManager.getQrCode(status.channel);
1293
+ if (qr) broadcastBloby('channel:qr', { channel: status.channel, qr });
1294
+ }
1295
+ });
1296
+
1297
+ // Auto-init channels (will connect WhatsApp if previously configured)
1298
+ channelManager.init().catch((err) => {
1299
+ log.warn(`[channels] Init failed: ${err.message}`);
1300
+ });
1301
+
1302
+ // Watch workspace files for changes — auto-restart backend
1303
+ // Catches edits from VS Code, CLI, or any external tool.
1304
+ // During agent turns, defers to bot:done (avoids mid-turn restarts).
1305
+ const workspaceDir = WORKSPACE_DIR;
1306
+ const backendDir = path.join(workspaceDir, 'backend');
1307
+ let backendRestartTimer: ReturnType<typeof setTimeout> | null = null;
1308
+
1309
+ function scheduleBackendRestart(reason: string) {
1310
+ if (agentQueryActive) {
1311
+ // Agent is working — don't restart now, flag it for bot:done
1312
+ pendingBackendRestart = true;
1313
+ return;
1314
+ }
1315
+ // Skip if a stop/restart is already in progress (bot:done handler owns the restart)
1316
+ if (isBackendStopping()) return;
1317
+ if (backendRestartTimer) clearTimeout(backendRestartTimer);
1318
+ backendRestartTimer = setTimeout(async () => {
1319
+ if (isBackendStopping()) return; // re-check after delay
1320
+ log.info(`[watcher] ${reason} — restarting backend...`);
1321
+ resetBackendRestarts();
1322
+ await stopBackend();
1323
+ spawnBackend(backendPort);
1324
+ }, 1000);
1325
+ }
1326
+
1327
+ // Watch backend/ for code changes
1328
+ const backendWatcher = fs.watch(backendDir, { recursive: true }, (_event, filename) => {
1329
+ if (!filename || !filename.match(/\.(ts|js|json)$/)) return;
1330
+ scheduleBackendRestart(`Backend file changed: ${filename}`);
1331
+ });
1332
+
1333
+ // Watch workspace root for .env changes and .restart trigger
1334
+ const workspaceWatcher = fs.watch(workspaceDir, (_event, filename) => {
1335
+ if (!filename) return;
1336
+ if (filename === '.env') {
1337
+ scheduleBackendRestart('.env changed');
1338
+ }
1339
+ if (filename === '.restart') {
1340
+ // Consume the trigger file
1341
+ try { fs.unlinkSync(path.join(workspaceDir, '.restart')); } catch {}
1342
+ scheduleBackendRestart('.restart trigger');
1343
+ }
1344
+ if (filename === '.update') {
1345
+ // Consume the trigger file
1346
+ try { fs.unlinkSync(path.join(workspaceDir, '.update')); } catch {}
1347
+ if (agentQueryActive) {
1348
+ pendingUpdate = true;
1349
+ log.info('Update requested — deferring until agent turn ends');
1350
+ } else {
1351
+ runDeferredUpdate();
1352
+ }
1353
+ }
1354
+ });
1355
+
1356
+ // Tunnel
1357
+ let tunnelUrl: string | null = null;
1358
+
1359
+ if (config.tunnel.mode === 'quick') {
1360
+ try {
1361
+ tunnelUrl = await startTunnel(config.port);
1362
+ log.ok(`Tunnel: ${tunnelUrl}`);
1363
+ console.log(`__TUNNEL_URL__=${tunnelUrl}`);
1364
+
1365
+ // Persist tunnel URL so the worker can read it after handle registration
1366
+ config.tunnelUrl = tunnelUrl;
1367
+ saveConfig(config);
1368
+
1369
+ // Wait for local server to be reachable before telling the relay.
1370
+ // Probes localhost directly — avoids macOS issue where server can't
1371
+ // reach itself through the Cloudflare tunnel URL.
1372
+ let tunnelReady = false;
1373
+ log.info('Readiness probe: waiting for local server...');
1374
+ for (let i = 0; i < 30; i++) {
1375
+ try {
1376
+ const res = await fetch(`http://127.0.0.1:${config.port}/api/health?_cb=${Date.now()}`, {
1377
+ signal: AbortSignal.timeout(3000),
1378
+ });
1379
+ log.info(`Readiness probe #${i + 1}: ${res.status}`);
1380
+ if (res.ok) {
1381
+ tunnelReady = true;
1382
+ break;
1383
+ }
1384
+ } catch (err) {
1385
+ log.info(`Readiness probe #${i + 1}: ${err instanceof Error ? err.message : 'error'}`);
1386
+ }
1387
+ await new Promise(r => setTimeout(r, 1000));
1388
+ }
1389
+ if (!tunnelReady) {
1390
+ log.warn('Local server readiness probe timed out — updating relay anyway');
1391
+ }
1392
+
1393
+ // Now register tunnel URL with relay and start heartbeats
1394
+ if (config.relay?.token) {
1395
+ try {
1396
+ await updateTunnelUrl(config.relay.token, tunnelUrl);
1397
+ startHeartbeat(config.relay.token, tunnelUrl);
1398
+ if (config.relay.url) {
1399
+ log.ok(`Relay: ${config.relay.url}`);
1400
+ console.log(`__RELAY_URL__=${config.relay.url}`);
1401
+ }
1402
+ } catch (err) {
1403
+ log.warn(`Relay: ${err instanceof Error ? err.message : err}`);
1404
+ }
1405
+ }
1406
+ console.log('__READY__');
1407
+ } catch (err) {
1408
+ log.warn(`Tunnel: ${err instanceof Error ? err.message : err}`);
1409
+ console.log('__TUNNEL_FAILED__');
1410
+ }
1411
+ }
1412
+
1413
+ if (config.tunnel.mode === 'named') {
1414
+ try {
1415
+ await startNamedTunnel(config.tunnel.configPath!, config.tunnel.name!);
1416
+ tunnelUrl = `https://${config.tunnel.domain}`;
1417
+ log.ok(`Named tunnel: ${tunnelUrl}`);
1418
+ console.log(`__TUNNEL_URL__=${tunnelUrl}`);
1419
+
1420
+ config.tunnelUrl = tunnelUrl;
1421
+ saveConfig(config);
1422
+
1423
+ // Readiness probe — check local server (not tunnel URL, avoids macOS self-reach issue)
1424
+ let tunnelReady = false;
1425
+ log.info('Readiness probe: waiting for local server...');
1426
+ for (let i = 0; i < 30; i++) {
1427
+ try {
1428
+ const res = await fetch(`http://127.0.0.1:${config.port}/api/health?_cb=${Date.now()}`, {
1429
+ signal: AbortSignal.timeout(3000),
1430
+ });
1431
+ log.info(`Readiness probe #${i + 1}: ${res.status}`);
1432
+ if (res.ok) {
1433
+ tunnelReady = true;
1434
+ break;
1435
+ }
1436
+ } catch (err) {
1437
+ log.info(`Readiness probe #${i + 1}: ${err instanceof Error ? err.message : 'error'}`);
1438
+ }
1439
+ await new Promise(r => setTimeout(r, 1000));
1440
+ }
1441
+ if (!tunnelReady) {
1442
+ log.warn('Local server readiness probe timed out');
1443
+ }
1444
+
1445
+ console.log('__READY__');
1446
+ } catch (err) {
1447
+ log.warn(`Named tunnel: ${err instanceof Error ? err.message : err}`);
1448
+ console.log('__TUNNEL_FAILED__');
1449
+ }
1450
+ }
1451
+
1452
+ // Tunnel watchdog — detects sleep/wake + periodic health checks
1453
+ let watchdogInterval: ReturnType<typeof setInterval> | null = null;
1454
+ if (tunnelUrl) {
1455
+ let lastTick = Date.now();
1456
+ let healthCounter = 0;
1457
+
1458
+ watchdogInterval = setInterval(async () => {
1459
+ const now = Date.now();
1460
+ const wakeGap = now - lastTick > 60_000;
1461
+ const periodicCheck = ++healthCounter % 10 === 0;
1462
+ lastTick = now; // Update immediately so concurrent ticks don't see a stale gap
1463
+
1464
+ if (wakeGap || periodicCheck) {
1465
+ const alive = await isTunnelAlive(tunnelUrl!, config.port);
1466
+ if (!alive) {
1467
+ log.warn('Tunnel dead, restarting...');
1468
+ try {
1469
+ if (config.tunnel.mode === 'named') {
1470
+ // Named tunnel: restart process, URL doesn't change
1471
+ await restartNamedTunnel(config.tunnel.configPath!, config.tunnel.name!);
1472
+ log.ok(`Named tunnel restored: ${tunnelUrl}`);
1473
+ } else {
1474
+ // Quick tunnel: restart and get new URL
1475
+ const newUrl = await restartTunnel(config.port);
1476
+
1477
+ // Brief pause to let cloudflared establish the tunnel
1478
+ await new Promise(r => setTimeout(r, 3000));
1479
+
1480
+ tunnelUrl = newUrl;
1481
+
1482
+ // Re-read config from disk — relay token may have been added during onboarding
1483
+ const latestCfg = loadConfig();
1484
+ latestCfg.tunnelUrl = newUrl;
1485
+ saveConfig(latestCfg);
1486
+
1487
+ if (latestCfg.relay?.token) {
1488
+ stopHeartbeat();
1489
+ startHeartbeat(latestCfg.relay.token, newUrl);
1490
+ await updateTunnelUrl(latestCfg.relay.token, newUrl);
1491
+ log.ok(`Relay updated with new tunnel URL`);
1492
+ }
1493
+ log.ok(`Tunnel restored: ${newUrl}`);
1494
+ }
1495
+ } catch (err) {
1496
+ log.error(`Tunnel restart failed: ${err instanceof Error ? err.message : err}`);
1497
+ }
1498
+ }
1499
+ }
1500
+ }, 30_000);
1501
+ }
1502
+
1503
+ // Shutdown
1504
+ const shutdown = async () => {
1505
+ log.info('Shutting down...');
1506
+ await channelManager.disconnectAll();
1507
+ stopScheduler();
1508
+ backendWatcher.close();
1509
+ workspaceWatcher.close();
1510
+ if (backendRestartTimer) clearTimeout(backendRestartTimer);
1511
+ if (watchdogInterval) clearInterval(watchdogInterval);
1512
+ stopHeartbeat();
1513
+ const latestConfig = loadConfig();
1514
+ if (latestConfig.relay?.token) {
1515
+ await disconnect(latestConfig.relay.token);
1516
+ }
1517
+ // Clear persisted tunnel URL so stale values aren't reused
1518
+ delete latestConfig.tunnelUrl;
1519
+ saveConfig(latestConfig);
1520
+ closeDb();
1521
+ await stopBackend();
1522
+ stopTunnel();
1523
+ console.log('[supervisor] Stopping Vite dev servers...');
1524
+ await stopViteDevServers();
1525
+ server.close();
1526
+ process.exit(0);
1527
+ };
1528
+ process.on('SIGINT', () => shutdown());
1529
+ process.on('SIGTERM', () => shutdown());
1530
+
1531
+ return tunnelUrl;
1532
+ }
1533
+
1534
+ startSupervisor().catch((err) => {
1535
+ log.error('Fatal', err);
1536
+ process.exit(1);
1537
+ });