skybridge 0.0.0-dev.cb51733 → 0.0.0-dev.cb83b5b

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 (415) hide show
  1. package/README.md +17 -14
  2. package/dist/cli/build-helpers.d.ts +11 -0
  3. package/dist/cli/build-helpers.js +115 -0
  4. package/dist/cli/build-helpers.js.map +1 -0
  5. package/dist/cli/build-helpers.test.js +156 -0
  6. package/dist/cli/build-helpers.test.js.map +1 -0
  7. package/dist/cli/build-steps.d.ts +2 -0
  8. package/dist/cli/build-steps.js +84 -0
  9. package/dist/cli/build-steps.js.map +1 -0
  10. package/dist/cli/build-steps.test.js +72 -0
  11. package/dist/cli/build-steps.test.js.map +1 -0
  12. package/dist/cli/detect-port.d.ts +2 -2
  13. package/dist/cli/detect-port.js +8 -20
  14. package/dist/cli/detect-port.js.map +1 -1
  15. package/dist/cli/header.d.ts +1 -1
  16. package/dist/cli/resolve-skybridge-config.d.ts +6 -0
  17. package/dist/cli/resolve-skybridge-config.js +28 -0
  18. package/dist/cli/resolve-skybridge-config.js.map +1 -0
  19. package/dist/cli/run-plain.d.ts +18 -0
  20. package/dist/cli/run-plain.js +90 -0
  21. package/dist/cli/run-plain.js.map +1 -0
  22. package/dist/cli/telemetry.js +2 -0
  23. package/dist/cli/telemetry.js.map +1 -1
  24. package/dist/cli/use-execute-steps.d.ts +1 -1
  25. package/dist/cli/use-nodemon.d.ts +25 -1
  26. package/dist/cli/use-nodemon.js +96 -63
  27. package/dist/cli/use-nodemon.js.map +1 -1
  28. package/dist/cli/use-typescript-check.d.ts +8 -2
  29. package/dist/cli/use-typescript-check.js +72 -67
  30. package/dist/cli/use-typescript-check.js.map +1 -1
  31. package/dist/commands/build.d.ts +0 -8
  32. package/dist/commands/build.js +9 -138
  33. package/dist/commands/build.js.map +1 -1
  34. package/dist/commands/dev.d.ts +1 -0
  35. package/dist/commands/dev.js +51 -3
  36. package/dist/commands/dev.js.map +1 -1
  37. package/dist/commands/start.js +7 -5
  38. package/dist/commands/start.js.map +1 -1
  39. package/dist/context-warnings.d.ts +5 -0
  40. package/dist/context-warnings.js +31 -0
  41. package/dist/context-warnings.js.map +1 -0
  42. package/dist/context-warnings.test.js +28 -0
  43. package/dist/context-warnings.test.js.map +1 -0
  44. package/dist/server/app.d.ts +211 -0
  45. package/dist/server/app.js +277 -0
  46. package/dist/server/app.js.map +1 -0
  47. package/dist/server/app.test.js +178 -0
  48. package/dist/server/app.test.js.map +1 -0
  49. package/dist/server/auth/discovery.d.ts +33 -0
  50. package/dist/server/auth/discovery.js +56 -0
  51. package/dist/server/auth/discovery.js.map +1 -0
  52. package/dist/server/auth/discovery.test.js +93 -0
  53. package/dist/server/auth/discovery.test.js.map +1 -0
  54. package/dist/server/auth/index.d.ts +48 -0
  55. package/dist/server/auth/index.js +2 -0
  56. package/dist/server/auth/index.js.map +1 -0
  57. package/dist/server/auth/providers/auth0.d.ts +40 -0
  58. package/dist/server/auth/providers/auth0.js +36 -0
  59. package/dist/server/auth/providers/auth0.js.map +1 -0
  60. package/dist/server/auth/providers/auth0.test.d.ts +1 -0
  61. package/dist/server/auth/providers/auth0.test.js +50 -0
  62. package/dist/server/auth/providers/auth0.test.js.map +1 -0
  63. package/dist/server/auth/providers/authplane.d.ts +49 -0
  64. package/dist/server/auth/providers/authplane.js +57 -0
  65. package/dist/server/auth/providers/authplane.js.map +1 -0
  66. package/dist/server/auth/providers/authplane.test.d.ts +1 -0
  67. package/dist/server/auth/providers/authplane.test.js +143 -0
  68. package/dist/server/auth/providers/authplane.test.js.map +1 -0
  69. package/dist/server/auth/providers/clerk.d.ts +51 -0
  70. package/dist/server/auth/providers/clerk.js +19 -0
  71. package/dist/server/auth/providers/clerk.js.map +1 -0
  72. package/dist/server/auth/providers/clerk.test.d.ts +1 -0
  73. package/dist/server/auth/providers/clerk.test.js +30 -0
  74. package/dist/server/auth/providers/clerk.test.js.map +1 -0
  75. package/dist/server/auth/providers/custom.d.ts +42 -0
  76. package/dist/server/auth/providers/custom.js +59 -0
  77. package/dist/server/auth/providers/custom.js.map +1 -0
  78. package/dist/server/auth/providers/custom.test.d.ts +1 -0
  79. package/dist/server/auth/providers/custom.test.js +161 -0
  80. package/dist/server/auth/providers/custom.test.js.map +1 -0
  81. package/dist/server/auth/providers/descope.d.ts +44 -0
  82. package/dist/server/auth/providers/descope.js +44 -0
  83. package/dist/server/auth/providers/descope.js.map +1 -0
  84. package/dist/server/auth/providers/descope.test.d.ts +1 -0
  85. package/dist/server/auth/providers/descope.test.js +62 -0
  86. package/dist/server/auth/providers/descope.test.js.map +1 -0
  87. package/dist/server/auth/providers/shared.d.ts +2 -0
  88. package/dist/server/auth/providers/shared.js +6 -0
  89. package/dist/server/auth/providers/shared.js.map +1 -0
  90. package/dist/server/auth/providers/shared.test.d.ts +1 -0
  91. package/dist/server/auth/providers/shared.test.js +10 -0
  92. package/dist/server/auth/providers/shared.test.js.map +1 -0
  93. package/dist/server/auth/providers/stytch.d.ts +25 -0
  94. package/dist/server/auth/providers/stytch.js +16 -0
  95. package/dist/server/auth/providers/stytch.js.map +1 -0
  96. package/dist/server/auth/providers/verify-spy.d.ts +12 -0
  97. package/dist/server/auth/providers/verify-spy.js +21 -0
  98. package/dist/server/auth/providers/verify-spy.js.map +1 -0
  99. package/dist/server/auth/providers/workos.d.ts +34 -0
  100. package/dist/server/auth/providers/workos.js +16 -0
  101. package/dist/server/auth/providers/workos.js.map +1 -0
  102. package/dist/server/auth/security-schemes.d.ts +23 -0
  103. package/dist/server/auth/security-schemes.js +64 -0
  104. package/dist/server/auth/security-schemes.js.map +1 -0
  105. package/dist/server/auth/security-schemes.test.d.ts +1 -0
  106. package/dist/server/auth/security-schemes.test.js +99 -0
  107. package/dist/server/auth/security-schemes.test.js.map +1 -0
  108. package/dist/server/auth/setup.d.ts +6 -0
  109. package/dist/server/auth/setup.js +91 -0
  110. package/dist/server/auth/setup.js.map +1 -0
  111. package/dist/server/auth/setup.test.d.ts +1 -0
  112. package/dist/server/auth/setup.test.js +514 -0
  113. package/dist/server/auth/setup.test.js.map +1 -0
  114. package/dist/server/auth/verify.d.ts +48 -0
  115. package/dist/server/auth/verify.js +62 -0
  116. package/dist/server/auth/verify.js.map +1 -0
  117. package/dist/server/auth/verify.test.d.ts +1 -0
  118. package/dist/server/auth/verify.test.js +165 -0
  119. package/dist/server/auth/verify.test.js.map +1 -0
  120. package/dist/server/auth-extra.test-d.js +130 -0
  121. package/dist/server/auth-extra.test-d.js.map +1 -0
  122. package/dist/server/auth.d.ts +43 -6
  123. package/dist/server/auth.js +4 -5
  124. package/dist/server/auth.js.map +1 -1
  125. package/dist/server/build-manifest.test.d.ts +1 -0
  126. package/dist/server/build-manifest.test.js +28 -0
  127. package/dist/server/build-manifest.test.js.map +1 -0
  128. package/dist/server/content-helpers.d.ts +1 -1
  129. package/dist/server/content-helpers.js.map +1 -1
  130. package/dist/server/events.d.ts +113 -0
  131. package/dist/server/events.js +318 -0
  132. package/dist/server/events.js.map +1 -0
  133. package/dist/server/events.test.d.ts +1 -0
  134. package/dist/server/events.test.js +172 -0
  135. package/dist/server/events.test.js.map +1 -0
  136. package/dist/server/express.d.ts +24 -3
  137. package/dist/server/express.js +45 -35
  138. package/dist/server/express.js.map +1 -1
  139. package/dist/server/express.test.js +273 -108
  140. package/dist/server/express.test.js.map +1 -1
  141. package/dist/server/file-ref.d.ts +1 -1
  142. package/dist/server/file-ref.js +1 -1
  143. package/dist/server/file-ref.js.map +1 -1
  144. package/dist/server/form-input.d.ts +120 -0
  145. package/dist/server/form-input.js +89 -0
  146. package/dist/server/form-input.js.map +1 -0
  147. package/dist/server/host.d.ts +2 -0
  148. package/dist/server/host.js +11 -0
  149. package/dist/server/host.js.map +1 -0
  150. package/dist/server/host.test.d.ts +1 -0
  151. package/dist/server/host.test.js +13 -0
  152. package/dist/server/host.test.js.map +1 -0
  153. package/dist/server/index.d.ts +19 -3
  154. package/dist/server/index.js +16 -2
  155. package/dist/server/index.js.map +1 -1
  156. package/dist/server/mcp-errors.test.d.ts +1 -0
  157. package/dist/server/mcp-errors.test.js +229 -0
  158. package/dist/server/mcp-errors.test.js.map +1 -0
  159. package/dist/server/metric.d.ts +5 -3
  160. package/dist/server/metric.js +5 -5
  161. package/dist/server/metric.js.map +1 -1
  162. package/dist/server/middleware.d.ts +35 -10
  163. package/dist/server/middleware.js +33 -0
  164. package/dist/server/middleware.js.map +1 -1
  165. package/dist/server/middleware.test-d.js +1 -1
  166. package/dist/server/middleware.test-d.js.map +1 -1
  167. package/dist/server/middleware.test.js +242 -134
  168. package/dist/server/middleware.test.js.map +1 -1
  169. package/dist/server/register-tool.test.d.ts +1 -0
  170. package/dist/server/register-tool.test.js +230 -0
  171. package/dist/server/register-tool.test.js.map +1 -0
  172. package/dist/server/requestOrigin.d.ts +7 -0
  173. package/dist/server/requestOrigin.js +25 -0
  174. package/dist/server/requestOrigin.js.map +1 -0
  175. package/dist/server/server.d.ts +397 -132
  176. package/dist/server/server.js +584 -341
  177. package/dist/server/server.js.map +1 -1
  178. package/dist/server/skills-integration.test.d.ts +1 -0
  179. package/dist/server/skills-integration.test.js +86 -0
  180. package/dist/server/skills-integration.test.js.map +1 -0
  181. package/dist/server/skills.d.ts +27 -0
  182. package/dist/server/skills.js +188 -0
  183. package/dist/server/skills.js.map +1 -0
  184. package/dist/server/skills.test.d.ts +1 -0
  185. package/dist/server/skills.test.js +243 -0
  186. package/dist/server/skills.test.js.map +1 -0
  187. package/dist/server/templateHelper.d.ts +1 -3
  188. package/dist/server/templateHelper.js.map +1 -1
  189. package/dist/server/templates.generated.js +28 -18
  190. package/dist/server/templates.generated.js.map +1 -1
  191. package/dist/server/tool-extra.test.d.ts +1 -0
  192. package/dist/server/tool-extra.test.js +167 -0
  193. package/dist/server/tool-extra.test.js.map +1 -0
  194. package/dist/server/view-name.test-d.d.ts +1 -0
  195. package/dist/server/view-name.test-d.js +8 -0
  196. package/dist/server/view-name.test-d.js.map +1 -0
  197. package/dist/server/view-resource-resolution.test.d.ts +6 -0
  198. package/dist/server/view-resource-resolution.test.js +211 -0
  199. package/dist/server/view-resource-resolution.test.js.map +1 -0
  200. package/dist/server/viewsDevServer.js +4 -1
  201. package/dist/server/viewsDevServer.js.map +1 -1
  202. package/dist/test/utils.d.ts +9 -11
  203. package/dist/test/utils.js +220 -201
  204. package/dist/test/utils.js.map +1 -1
  205. package/dist/test/view.test.js +105 -133
  206. package/dist/test/view.test.js.map +1 -1
  207. package/dist/views/index.d.ts +10 -0
  208. package/dist/views/index.js +3 -0
  209. package/dist/views/index.js.map +1 -0
  210. package/dist/{web/plugin → views}/scan-views.js +1 -1
  211. package/dist/views/scan-views.js.map +1 -0
  212. package/dist/views/scan-views.test.d.ts +1 -0
  213. package/dist/views/scan-views.test.js.map +1 -0
  214. package/dist/views/validate-view.d.ts +1 -0
  215. package/dist/{web/plugin → views}/validate-view.js +2 -2
  216. package/dist/views/validate-view.js.map +1 -0
  217. package/dist/views/validate-view.test.d.ts +1 -0
  218. package/dist/views/validate-view.test.js.map +1 -0
  219. package/dist/web/bridges/adaptor.d.ts +62 -0
  220. package/dist/web/bridges/adaptor.js +477 -0
  221. package/dist/web/bridges/adaptor.js.map +1 -0
  222. package/dist/web/bridges/adaptor.test.d.ts +1 -0
  223. package/dist/web/bridges/adaptor.test.js +281 -0
  224. package/dist/web/bridges/adaptor.test.js.map +1 -0
  225. package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
  226. package/dist/web/bridges/apps-sdk/bridge.js +15 -4
  227. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
  228. package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
  229. package/dist/web/bridges/apps-sdk/index.js +0 -1
  230. package/dist/web/bridges/apps-sdk/index.js.map +1 -1
  231. package/dist/web/bridges/apps-sdk/types.d.ts +2 -3
  232. package/dist/web/bridges/apps-sdk/types.js.map +1 -1
  233. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +4 -4
  234. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +4 -4
  235. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
  236. package/dist/web/bridges/get-adaptor.d.ts +4 -4
  237. package/dist/web/bridges/get-adaptor.js +6 -11
  238. package/dist/web/bridges/get-adaptor.js.map +1 -1
  239. package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
  240. package/dist/web/bridges/get-adaptor.test.js +32 -0
  241. package/dist/web/bridges/get-adaptor.test.js.map +1 -0
  242. package/dist/web/bridges/mcp-app/bridge.d.ts +15 -3
  243. package/dist/web/bridges/mcp-app/bridge.js +80 -8
  244. package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
  245. package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
  246. package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
  247. package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
  248. package/dist/web/bridges/mcp-app/index.d.ts +0 -1
  249. package/dist/web/bridges/mcp-app/index.js +0 -1
  250. package/dist/web/bridges/mcp-app/index.js.map +1 -1
  251. package/dist/web/bridges/mcp-app/types.d.ts +19 -2
  252. package/dist/web/bridges/mcp-app/types.js.map +1 -1
  253. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +2 -2
  254. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
  255. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
  256. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
  257. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
  258. package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
  259. package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
  260. package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
  261. package/dist/web/bridges/types.d.ts +110 -9
  262. package/dist/web/bridges/types.js +14 -1
  263. package/dist/web/bridges/types.js.map +1 -1
  264. package/dist/web/bridges/types.test.d.ts +1 -0
  265. package/dist/web/bridges/types.test.js +19 -0
  266. package/dist/web/bridges/types.test.js.map +1 -0
  267. package/dist/web/components/modal-provider.d.ts +1 -1
  268. package/dist/web/components/modal-provider.js +4 -3
  269. package/dist/web/components/modal-provider.js.map +1 -1
  270. package/dist/web/create-store.test.js +10 -7
  271. package/dist/web/create-store.test.js.map +1 -1
  272. package/dist/web/data-llm.d.ts +1 -1
  273. package/dist/web/data-llm.js +3 -2
  274. package/dist/web/data-llm.js.map +1 -1
  275. package/dist/web/data-llm.test.js +26 -7
  276. package/dist/web/data-llm.test.js.map +1 -1
  277. package/dist/web/generate-helpers.d.ts +23 -19
  278. package/dist/web/generate-helpers.js +21 -17
  279. package/dist/web/generate-helpers.js.map +1 -1
  280. package/dist/web/generate-helpers.test-d.js +7 -5
  281. package/dist/web/generate-helpers.test-d.js.map +1 -1
  282. package/dist/web/generate-helpers.test.js +2 -2
  283. package/dist/web/generate-helpers.test.js.map +1 -1
  284. package/dist/web/hooks/index.d.ts +7 -1
  285. package/dist/web/hooks/index.js +7 -1
  286. package/dist/web/hooks/index.js.map +1 -1
  287. package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
  288. package/dist/web/hooks/openai-extensions.test.js +107 -0
  289. package/dist/web/hooks/openai-extensions.test.js.map +1 -0
  290. package/dist/web/hooks/test/utils.d.ts +2 -1
  291. package/dist/web/hooks/test/utils.js +1 -1
  292. package/dist/web/hooks/test/utils.js.map +1 -1
  293. package/dist/web/hooks/use-call-tool.d.ts +2 -2
  294. package/dist/web/hooks/use-call-tool.js +15 -10
  295. package/dist/web/hooks/use-call-tool.js.map +1 -1
  296. package/dist/web/hooks/use-call-tool.test.js +50 -25
  297. package/dist/web/hooks/use-call-tool.test.js.map +1 -1
  298. package/dist/web/hooks/use-deep-link.d.ts +22 -0
  299. package/dist/web/hooks/use-deep-link.js +34 -0
  300. package/dist/web/hooks/use-deep-link.js.map +1 -0
  301. package/dist/web/hooks/use-display-mode.d.ts +1 -1
  302. package/dist/web/hooks/use-display-mode.js +1 -1
  303. package/dist/web/hooks/use-display-mode.js.map +1 -1
  304. package/dist/web/hooks/use-display-mode.test.js +57 -21
  305. package/dist/web/hooks/use-display-mode.test.js.map +1 -1
  306. package/dist/web/hooks/use-download.d.ts +1 -3
  307. package/dist/web/hooks/use-download.js +1 -2
  308. package/dist/web/hooks/use-download.js.map +1 -1
  309. package/dist/web/hooks/use-download.test.js +18 -10
  310. package/dist/web/hooks/use-download.test.js.map +1 -1
  311. package/dist/web/hooks/use-file-resource.d.ts +37 -0
  312. package/dist/web/hooks/use-file-resource.js +98 -0
  313. package/dist/web/hooks/use-file-resource.js.map +1 -0
  314. package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
  315. package/dist/web/hooks/use-file-resource.test.js +65 -0
  316. package/dist/web/hooks/use-file-resource.test.js.map +1 -0
  317. package/dist/web/hooks/use-files.test.js +11 -3
  318. package/dist/web/hooks/use-files.test.js.map +1 -1
  319. package/dist/web/hooks/use-host.d.ts +44 -0
  320. package/dist/web/hooks/use-host.js +45 -0
  321. package/dist/web/hooks/use-host.js.map +1 -0
  322. package/dist/web/hooks/use-host.test.d.ts +1 -0
  323. package/dist/web/hooks/use-host.test.js +59 -0
  324. package/dist/web/hooks/use-host.test.js.map +1 -0
  325. package/dist/web/hooks/use-model-context.d.ts +44 -0
  326. package/dist/web/hooks/use-model-context.js +63 -0
  327. package/dist/web/hooks/use-model-context.js.map +1 -0
  328. package/dist/web/hooks/use-open-external.test.js +15 -5
  329. package/dist/web/hooks/use-open-external.test.js.map +1 -1
  330. package/dist/web/hooks/use-open-file.d.ts +20 -0
  331. package/dist/web/hooks/use-open-file.js +25 -0
  332. package/dist/web/hooks/use-open-file.js.map +1 -0
  333. package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
  334. package/dist/web/hooks/use-register-view-tool.js +50 -0
  335. package/dist/web/hooks/use-register-view-tool.js.map +1 -0
  336. package/dist/web/hooks/use-request-close.test.js +35 -40
  337. package/dist/web/hooks/use-request-close.test.js.map +1 -1
  338. package/dist/web/hooks/use-request-modal.test.js +11 -1
  339. package/dist/web/hooks/use-request-modal.test.js.map +1 -1
  340. package/dist/web/hooks/use-request-size.d.ts +1 -1
  341. package/dist/web/hooks/use-request-size.js +1 -1
  342. package/dist/web/hooks/use-request-size.js.map +1 -1
  343. package/dist/web/hooks/use-request-size.test.js +35 -53
  344. package/dist/web/hooks/use-request-size.test.js.map +1 -1
  345. package/dist/web/hooks/use-send-follow-up-message.d.ts +8 -2
  346. package/dist/web/hooks/use-send-follow-up-message.js +6 -0
  347. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
  348. package/dist/web/hooks/use-set-open-in-app-url.test.js +26 -12
  349. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
  350. package/dist/web/hooks/use-tool-info.d.ts +18 -19
  351. package/dist/web/hooks/use-tool-info.js +4 -8
  352. package/dist/web/hooks/use-tool-info.js.map +1 -1
  353. package/dist/web/hooks/use-tool-info.test-d.js +11 -34
  354. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
  355. package/dist/web/hooks/use-tool-info.test.js +42 -37
  356. package/dist/web/hooks/use-tool-info.test.js.map +1 -1
  357. package/dist/web/hooks/use-user.d.ts +3 -2
  358. package/dist/web/hooks/use-user.js +4 -3
  359. package/dist/web/hooks/use-user.js.map +1 -1
  360. package/dist/web/hooks/use-user.test.js +85 -37
  361. package/dist/web/hooks/use-user.test.js.map +1 -1
  362. package/dist/web/hooks/use-view-state.js +19 -9
  363. package/dist/web/hooks/use-view-state.js.map +1 -1
  364. package/dist/web/hooks/use-view-state.test.js +39 -4
  365. package/dist/web/hooks/use-view-state.test.js.map +1 -1
  366. package/dist/web/hooks/use-viewport.d.ts +20 -0
  367. package/dist/web/hooks/use-viewport.js +21 -0
  368. package/dist/web/hooks/use-viewport.js.map +1 -0
  369. package/dist/web/hooks/use-viewport.test.d.ts +1 -0
  370. package/dist/web/hooks/use-viewport.test.js +109 -0
  371. package/dist/web/hooks/use-viewport.test.js.map +1 -0
  372. package/dist/web/mount-view.d.ts +3 -2
  373. package/dist/web/mount-view.js +6 -11
  374. package/dist/web/mount-view.js.map +1 -1
  375. package/package.json +35 -27
  376. package/dist/commands/build-helpers.d.ts +0 -26
  377. package/dist/commands/build-helpers.js +0 -93
  378. package/dist/commands/build-helpers.js.map +0 -1
  379. package/dist/commands/build-helpers.test.js +0 -116
  380. package/dist/commands/build-helpers.test.js.map +0 -1
  381. package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -28
  382. package/dist/web/bridges/apps-sdk/adaptor.js +0 -113
  383. package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
  384. package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -52
  385. package/dist/web/bridges/mcp-app/adaptor.js +0 -280
  386. package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
  387. package/dist/web/hooks/use-layout.d.ts +0 -24
  388. package/dist/web/hooks/use-layout.js +0 -25
  389. package/dist/web/hooks/use-layout.js.map +0 -1
  390. package/dist/web/hooks/use-layout.test.js +0 -96
  391. package/dist/web/hooks/use-layout.test.js.map +0 -1
  392. package/dist/web/plugin/data-llm.test.js +0 -81
  393. package/dist/web/plugin/data-llm.test.js.map +0 -1
  394. package/dist/web/plugin/plugin.d.ts +0 -33
  395. package/dist/web/plugin/plugin.js +0 -189
  396. package/dist/web/plugin/plugin.js.map +0 -1
  397. package/dist/web/plugin/scan-views.js.map +0 -1
  398. package/dist/web/plugin/scan-views.test.js.map +0 -1
  399. package/dist/web/plugin/transform-data-llm.d.ts +0 -12
  400. package/dist/web/plugin/transform-data-llm.js +0 -96
  401. package/dist/web/plugin/transform-data-llm.js.map +0 -1
  402. package/dist/web/plugin/transform-data-llm.test.js +0 -81
  403. package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
  404. package/dist/web/plugin/validate-view.d.ts +0 -1
  405. package/dist/web/plugin/validate-view.js.map +0 -1
  406. package/dist/web/plugin/validate-view.test.js.map +0 -1
  407. /package/dist/{commands → cli}/build-helpers.test.d.ts +0 -0
  408. /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
  409. /package/dist/{web/plugin/data-llm.test.d.ts → context-warnings.test.d.ts} +0 -0
  410. /package/dist/{web/plugin/scan-views.test.d.ts → server/app.test.d.ts} +0 -0
  411. /package/dist/{web/plugin/validate-view.test.d.ts → server/auth/discovery.test.d.ts} +0 -0
  412. /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
  413. /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
  414. /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
  415. /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"use-nodemon.js","sourceRoot":"","sources":["../../src/cli/use-nodemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport nodemonOriginal from \"nodemon\";\nimport { useEffect } from \"react\";\nimport type { ExtendedNodemon } from \"./nodemon.d.ts\";\nimport type { PushMessage } from \"./use-messages.js\";\n\nconst nodemon = nodemonOriginal as ExtendedNodemon;\n\nconst SOURCEMAP_WARNING = /^Sourcemap for \".*\" points to missing source files$/;\n\nexport function useNodemon(\n env: NodeJS.ProcessEnv,\n pushMessage: PushMessage,\n): void {\n useEffect(() => {\n const configFile = resolve(process.cwd(), \"nodemon.json\");\n\n const config = existsSync(configFile)\n ? {\n configFile,\n }\n : {\n watch: [\"src\"],\n ext: \"ts,json\",\n exec: \"tsx src/server.ts\",\n };\n\n nodemon({ ...config, env, stdout: false });\n\n const handleStdoutData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (message) {\n pushMessage(message, \"log\");\n }\n };\n\n const handleStderrData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (!message) {\n return;\n }\n // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.\n const filtered = message\n .split(\"\\n\")\n .filter((line) => !SOURCEMAP_WARNING.test(line))\n .join(\"\\n\");\n if (filtered) {\n pushMessage(filtered, \"error\");\n }\n };\n\n const setupStdoutListener = () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n nodemon.stdout.on(\"data\", handleStdoutData);\n }\n };\n\n const setupStderrListener = () => {\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n nodemon.stderr.on(\"data\", handleStderrData);\n }\n };\n\n nodemon.on(\"readable\", () => {\n setupStdoutListener();\n setupStderrListener();\n });\n\n nodemon.on(\"restart\", (files: string[]) => {\n const restartMessage = `Server restarted due to file changes: ${files.join(\", \")}`;\n pushMessage(restartMessage, \"restart\");\n setupStdoutListener();\n setupStderrListener();\n });\n\n return () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n }\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n }\n nodemon.emit(\"quit\");\n };\n }, [env, pushMessage]);\n}\n"]}
1
+ {"version":3,"file":"use-nodemon.js","sourceRoot":"","sources":["../../src/cli/use-nodemon.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { useEffect, useState } from \"react\";\nimport type { ExtendedNodemon } from \"./nodemon.d.ts\";\nimport type { PushMessage } from \"./use-messages.js\";\n\nfunction loadNodemon(): ExtendedNodemon {\n try {\n return createRequire(import.meta.url)(\"nodemon\") as ExtendedNodemon;\n } catch {\n throw new Error(\n 'skybridge dev needs the \"nodemon\" peer dependency. Install it with `npm install -D nodemon`.',\n );\n }\n}\n\nexport const CRASH_MESSAGE =\n \"💥 Server crashed. Fix the error, then save a watched file to restart it.\";\n\nconst SOURCEMAP_WARNING = /^Sourcemap for \".*\" points to missing source files$/;\n\nexport interface NodemonHandlers {\n /** A raw chunk of server stdout, forwarded untouched. */\n onStdout: (chunk: Buffer) => void;\n /** A (filtered) chunk of server stderr. */\n onStderr: (message: string) => void;\n /** The server restarted because the listed files changed. */\n onRestart: (files: string[]) => void;\n /**\n * The server exited with a non-zero code. nodemon does not restart it on its\n * own: it waits for the next file change.\n */\n onCrash: () => void;\n}\n\n/**\n * Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a\n * cleanup function that detaches the listeners and quits nodemon. Shared by the\n * Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.\n */\nexport function startNodemon(\n env: NodeJS.ProcessEnv,\n handlers: NodemonHandlers,\n): () => void {\n const nodemon = loadNodemon();\n const configFile = resolve(process.cwd(), \"nodemon.json\");\n\n const config = existsSync(configFile)\n ? {\n configFile,\n }\n : {\n watch: [\"src\"],\n ext: \"ts,json,md\",\n exec: \"tsx src/index.ts\",\n };\n\n nodemon({ ...config, env, stdout: false });\n\n const handleStdoutData = (chunk: Buffer) => {\n handlers.onStdout(chunk);\n };\n\n const handleStderrData = (chunk: Buffer) => {\n const message = chunk.toString().trim();\n if (!message) {\n return;\n }\n // Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.\n const filtered = message\n .split(\"\\n\")\n .filter((line) => !SOURCEMAP_WARNING.test(line))\n .join(\"\\n\");\n if (filtered) {\n handlers.onStderr(filtered);\n }\n };\n\n const setupStdoutListener = () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n nodemon.stdout.on(\"data\", handleStdoutData);\n }\n };\n\n const setupStderrListener = () => {\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n nodemon.stderr.on(\"data\", handleStderrData);\n }\n };\n\n const reattachListeners = () => {\n setupStdoutListener();\n setupStderrListener();\n };\n\n nodemon.on(\"readable\", reattachListeners);\n\n nodemon.on(\"crash\", () => {\n handlers.onCrash();\n });\n\n nodemon.on(\"restart\", (files: string[]) => {\n handlers.onRestart(files);\n reattachListeners();\n });\n\n return () => {\n if (nodemon.stdout) {\n nodemon.stdout.off(\"data\", handleStdoutData);\n }\n if (nodemon.stderr) {\n nodemon.stderr.off(\"data\", handleStderrData);\n }\n nodemon.emit(\"quit\");\n };\n}\n\n/**\n * Boot nodemon for the Ink dev UI. Returns whether the server is currently\n * down after a crash, so the UI can stop advertising a URL nothing listens on.\n */\nexport function useNodemon(\n env: NodeJS.ProcessEnv,\n pushMessage: PushMessage,\n): boolean {\n const [crashed, setCrashed] = useState(false);\n\n useEffect(\n () =>\n startNodemon(env, {\n onStdout: (chunk) => {\n const message = chunk.toString().trim();\n if (message) {\n pushMessage(message, \"log\");\n }\n },\n onStderr: (message) => pushMessage(message, \"error\"),\n onRestart: (files) => {\n setCrashed(false);\n pushMessage(\n `Server restarted due to file changes: ${files.join(\", \")}`,\n \"restart\",\n );\n },\n onCrash: () => setCrashed(true),\n }),\n [env, pushMessage],\n );\n\n return crashed;\n}\n"]}
@@ -1,9 +1,15 @@
1
- type TsError = {
1
+ export type TsError = {
2
2
  file: string;
3
3
  line: number;
4
4
  col: number;
5
5
  code: string;
6
6
  message: string;
7
7
  };
8
+ /**
9
+ * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`
10
+ * (empty array when the check is clean). Returns a cleanup function that kills
11
+ * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})
12
+ * and the `--plain` runner.
13
+ */
14
+ export declare function startTypeScriptCheck(onErrors: (errors: Array<TsError>) => void): () => void;
8
15
  export declare function useTypeScriptCheck(): Array<TsError>;
9
- export {};
@@ -1,6 +1,6 @@
1
1
  import { isAbsolute, relative } from "node:path";
2
2
  import spawn from "cross-spawn";
3
- import { useEffect, useRef, useState } from "react";
3
+ import { useEffect, useState } from "react";
4
4
  // TypeScript nests from general to specific — the deepest line is the root cause.
5
5
  function extractBestMessage(message, continuationLines) {
6
6
  if (!continuationLines.length) {
@@ -19,76 +19,81 @@ function extractBestMessage(message, continuationLines) {
19
19
  .filter(Boolean)[0];
20
20
  return deepest ?? message;
21
21
  }
22
- export function useTypeScriptCheck() {
23
- const tsProcessRef = useRef(null);
24
- const [tsErrors, setTsErrors] = useState([]);
25
- useEffect(() => {
26
- const tsProcess = spawn("npx", ["tsc", "--noEmit", "--watch", "--pretty", "false"], {
27
- stdio: ["ignore", "pipe", "pipe"],
28
- shell: true,
29
- });
30
- tsProcessRef.current = tsProcess;
31
- let outputBuffer = "";
32
- let currentErrors = [];
33
- let pendingError = null;
34
- let continuationLines = [];
35
- const flushPending = () => {
36
- if (!pendingError) {
37
- return;
38
- }
39
- pendingError.message = extractBestMessage(pendingError.message, continuationLines);
40
- currentErrors.push(pendingError);
41
- pendingError = null;
42
- continuationLines = [];
43
- };
44
- const processOutput = (data) => {
45
- outputBuffer += data.toString();
46
- const lines = outputBuffer.split("\n");
47
- outputBuffer = lines.pop() || "";
48
- for (const line of lines) {
49
- const trimmed = line.trim();
50
- const errorMatch = trimmed.match(/^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+)?\s*:?\s*(.+)$/);
51
- if (errorMatch) {
52
- flushPending();
53
- const [, file, lineStr, colStr, code, message] = errorMatch;
54
- if (file && lineStr && colStr && message) {
55
- let cleanFile = file.trim();
56
- if (isAbsolute(cleanFile)) {
57
- cleanFile = relative(process.cwd(), cleanFile);
58
- }
59
- pendingError = {
60
- file: cleanFile,
61
- line: Number.parseInt(lineStr, 10),
62
- col: Number.parseInt(colStr, 10),
63
- code: code ?? "",
64
- message: message.trim(),
65
- };
22
+ /**
23
+ * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`
24
+ * (empty array when the check is clean). Returns a cleanup function that kills
25
+ * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})
26
+ * and the `--plain` runner.
27
+ */
28
+ export function startTypeScriptCheck(onErrors) {
29
+ const tsProcess = spawn("npx", ["tsc", "--noEmit", "--watch", "--pretty", "false"], {
30
+ stdio: ["ignore", "pipe", "pipe"],
31
+ });
32
+ let outputBuffer = "";
33
+ let currentErrors = [];
34
+ let pendingError = null;
35
+ let continuationLines = [];
36
+ const flushPending = () => {
37
+ if (!pendingError) {
38
+ return;
39
+ }
40
+ pendingError.message = extractBestMessage(pendingError.message, continuationLines);
41
+ currentErrors.push(pendingError);
42
+ pendingError = null;
43
+ continuationLines = [];
44
+ };
45
+ const processOutput = (data) => {
46
+ outputBuffer += data.toString();
47
+ const lines = outputBuffer.split("\n");
48
+ outputBuffer = lines.pop() || "";
49
+ for (const line of lines) {
50
+ const trimmed = line.trim();
51
+ const errorMatch = trimmed.match(/^(.+?)\((\d+),(\d+)\):\s+error\s+(TS\d+)?\s*:?\s*(.+)$/);
52
+ if (errorMatch) {
53
+ flushPending();
54
+ const [, file, lineStr, colStr, code, message] = errorMatch;
55
+ if (file && lineStr && colStr && message) {
56
+ let cleanFile = file.trim();
57
+ if (isAbsolute(cleanFile)) {
58
+ cleanFile = relative(process.cwd(), cleanFile);
66
59
  }
67
- continue;
68
- }
69
- if (pendingError && line.startsWith(" ")) {
70
- continuationLines.push(line);
71
- continue;
72
- }
73
- if (trimmed.includes("Found") && trimmed.includes("error")) {
74
- flushPending();
75
- setTsErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);
76
- currentErrors = [];
60
+ pendingError = {
61
+ file: cleanFile,
62
+ line: Number.parseInt(lineStr, 10),
63
+ col: Number.parseInt(colStr, 10),
64
+ code: code ?? "",
65
+ message: message.trim(),
66
+ };
77
67
  }
68
+ continue;
78
69
  }
79
- };
80
- if (tsProcess.stdout) {
81
- tsProcess.stdout.on("data", processOutput);
82
- }
83
- if (tsProcess.stderr) {
84
- tsProcess.stderr.on("data", processOutput);
85
- }
86
- return () => {
87
- if (tsProcessRef.current) {
88
- tsProcessRef.current.kill();
70
+ if (pendingError && line.startsWith(" ")) {
71
+ continuationLines.push(line);
72
+ continue;
89
73
  }
90
- };
91
- }, []);
74
+ if (trimmed.includes("Found") && trimmed.includes("error")) {
75
+ flushPending();
76
+ onErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);
77
+ currentErrors = [];
78
+ }
79
+ }
80
+ };
81
+ if (tsProcess.stdout) {
82
+ tsProcess.stdout.on("data", processOutput);
83
+ }
84
+ if (tsProcess.stderr) {
85
+ tsProcess.stderr.on("data", processOutput);
86
+ }
87
+ tsProcess.on("error", (err) => {
88
+ console.error(`TypeScript watcher failed to start: ${err.message}`);
89
+ });
90
+ return () => {
91
+ tsProcess.kill();
92
+ };
93
+ }
94
+ export function useTypeScriptCheck() {
95
+ const [tsErrors, setTsErrors] = useState([]);
96
+ useEffect(() => startTypeScriptCheck(setTsErrors), []);
92
97
  return tsErrors;
93
98
  }
94
99
  //# sourceMappingURL=use-typescript-check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-typescript-check.js","sourceRoot":"","sources":["../../src/cli/use-typescript-check.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative } from \"node:path\";\nimport spawn from \"cross-spawn\";\nimport { useEffect, useRef, useState } from \"react\";\n\ntype TsError = {\n file: string;\n line: number;\n col: number;\n code: string;\n message: string;\n};\n\n// TypeScript nests from general to specific — the deepest line is the root cause.\nfunction extractBestMessage(\n message: string,\n continuationLines: Array<string>,\n): string {\n if (!continuationLines.length) {\n return message;\n }\n let maxIndent = 0;\n for (const line of continuationLines) {\n const indent = line.length - line.trimStart().length;\n if (indent > maxIndent) {\n maxIndent = indent;\n }\n }\n const deepest = continuationLines\n .filter((l) => l.length - l.trimStart().length === maxIndent)\n .map((l) => l.trim())\n .filter(Boolean)[0];\n return deepest ?? message;\n}\n\nexport function useTypeScriptCheck(): Array<TsError> {\n const tsProcessRef = useRef<ReturnType<typeof spawn> | null>(null);\n const [tsErrors, setTsErrors] = useState<Array<TsError>>([]);\n\n useEffect(() => {\n const tsProcess = spawn(\n \"npx\",\n [\"tsc\", \"--noEmit\", \"--watch\", \"--pretty\", \"false\"],\n {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n shell: true,\n },\n );\n\n tsProcessRef.current = tsProcess;\n\n let outputBuffer = \"\";\n let currentErrors: Array<TsError> = [];\n let pendingError: TsError | null = null;\n let continuationLines: Array<string> = [];\n\n const flushPending = () => {\n if (!pendingError) {\n return;\n }\n pendingError.message = extractBestMessage(\n pendingError.message,\n continuationLines,\n );\n currentErrors.push(pendingError);\n pendingError = null;\n continuationLines = [];\n };\n\n const processOutput = (data: Buffer) => {\n outputBuffer += data.toString();\n const lines = outputBuffer.split(\"\\n\");\n outputBuffer = lines.pop() || \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n const errorMatch = trimmed.match(\n /^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+)?\\s*:?\\s*(.+)$/,\n );\n if (errorMatch) {\n flushPending();\n const [, file, lineStr, colStr, code, message] = errorMatch;\n if (file && lineStr && colStr && message) {\n let cleanFile = file.trim();\n if (isAbsolute(cleanFile)) {\n cleanFile = relative(process.cwd(), cleanFile);\n }\n pendingError = {\n file: cleanFile,\n line: Number.parseInt(lineStr, 10),\n col: Number.parseInt(colStr, 10),\n code: code ?? \"\",\n message: message.trim(),\n };\n }\n continue;\n }\n\n if (pendingError && line.startsWith(\" \")) {\n continuationLines.push(line);\n continue;\n }\n\n if (trimmed.includes(\"Found\") && trimmed.includes(\"error\")) {\n flushPending();\n setTsErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);\n currentErrors = [];\n }\n }\n };\n\n if (tsProcess.stdout) {\n tsProcess.stdout.on(\"data\", processOutput);\n }\n if (tsProcess.stderr) {\n tsProcess.stderr.on(\"data\", processOutput);\n }\n\n return () => {\n if (tsProcessRef.current) {\n tsProcessRef.current.kill();\n }\n };\n }, []);\n\n return tsErrors;\n}\n"]}
1
+ {"version":3,"file":"use-typescript-check.js","sourceRoot":"","sources":["../../src/cli/use-typescript-check.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative } from \"node:path\";\nimport spawn from \"cross-spawn\";\nimport { useEffect, useState } from \"react\";\n\nexport type TsError = {\n file: string;\n line: number;\n col: number;\n code: string;\n message: string;\n};\n\n// TypeScript nests from general to specific — the deepest line is the root cause.\nfunction extractBestMessage(\n message: string,\n continuationLines: Array<string>,\n): string {\n if (!continuationLines.length) {\n return message;\n }\n let maxIndent = 0;\n for (const line of continuationLines) {\n const indent = line.length - line.trimStart().length;\n if (indent > maxIndent) {\n maxIndent = indent;\n }\n }\n const deepest = continuationLines\n .filter((l) => l.length - l.trimStart().length === maxIndent)\n .map((l) => l.trim())\n .filter(Boolean)[0];\n return deepest ?? message;\n}\n\n/**\n * Spawn `tsc --noEmit --watch` and report each completed check via `onErrors`\n * (empty array when the check is clean). Returns a cleanup function that kills\n * the watcher. Shared by the Ink-based dev UI (via {@link useTypeScriptCheck})\n * and the `--plain` runner.\n */\nexport function startTypeScriptCheck(\n onErrors: (errors: Array<TsError>) => void,\n): () => void {\n const tsProcess = spawn(\n \"npx\",\n [\"tsc\", \"--noEmit\", \"--watch\", \"--pretty\", \"false\"],\n {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n },\n );\n\n let outputBuffer = \"\";\n let currentErrors: Array<TsError> = [];\n let pendingError: TsError | null = null;\n let continuationLines: Array<string> = [];\n\n const flushPending = () => {\n if (!pendingError) {\n return;\n }\n pendingError.message = extractBestMessage(\n pendingError.message,\n continuationLines,\n );\n currentErrors.push(pendingError);\n pendingError = null;\n continuationLines = [];\n };\n\n const processOutput = (data: Buffer) => {\n outputBuffer += data.toString();\n const lines = outputBuffer.split(\"\\n\");\n outputBuffer = lines.pop() || \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n const errorMatch = trimmed.match(\n /^(.+?)\\((\\d+),(\\d+)\\):\\s+error\\s+(TS\\d+)?\\s*:?\\s*(.+)$/,\n );\n if (errorMatch) {\n flushPending();\n const [, file, lineStr, colStr, code, message] = errorMatch;\n if (file && lineStr && colStr && message) {\n let cleanFile = file.trim();\n if (isAbsolute(cleanFile)) {\n cleanFile = relative(process.cwd(), cleanFile);\n }\n pendingError = {\n file: cleanFile,\n line: Number.parseInt(lineStr, 10),\n col: Number.parseInt(colStr, 10),\n code: code ?? \"\",\n message: message.trim(),\n };\n }\n continue;\n }\n\n if (pendingError && line.startsWith(\" \")) {\n continuationLines.push(line);\n continue;\n }\n\n if (trimmed.includes(\"Found\") && trimmed.includes(\"error\")) {\n flushPending();\n onErrors(trimmed.match(/Found 0 error/) ? [] : [...currentErrors]);\n currentErrors = [];\n }\n }\n };\n\n if (tsProcess.stdout) {\n tsProcess.stdout.on(\"data\", processOutput);\n }\n if (tsProcess.stderr) {\n tsProcess.stderr.on(\"data\", processOutput);\n }\n\n tsProcess.on(\"error\", (err: Error) => {\n console.error(`TypeScript watcher failed to start: ${err.message}`);\n });\n\n return () => {\n tsProcess.kill();\n };\n}\n\nexport function useTypeScriptCheck(): Array<TsError> {\n const [tsErrors, setTsErrors] = useState<Array<TsError>>([]);\n\n useEffect(() => startTypeScriptCheck(setTsErrors), []);\n\n return tsErrors;\n}\n"]}
@@ -1,14 +1,6 @@
1
1
  import { Command } from "@oclif/core";
2
- import { type CommandStep } from "../cli/use-execute-steps.js";
3
- export declare function buildSteps(target: "default" | "vercel", warnings: {
4
- current: string[];
5
- }): CommandStep[];
6
- export declare const commandSteps: CommandStep[];
7
2
  export default class Build extends Command {
8
3
  static description: string;
9
4
  static examples: string[];
10
- static flags: {
11
- target: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- };
13
5
  run(): Promise<void>;
14
6
  }
@@ -1,155 +1,26 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
- import path from "node:path";
4
- import { Command, Flags } from "@oclif/core";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Command } from "@oclif/core";
5
3
  import { Box, render, Text } from "ink";
6
- import { useEffect, useMemo, useRef } from "react";
4
+ import { useEffect } from "react";
5
+ import { getCommandSteps } from "../cli/build-steps.js";
7
6
  import { Header } from "../cli/header.js";
8
7
  import { useExecuteSteps } from "../cli/use-execute-steps.js";
9
- import { scanAndWriteViewsDts } from "../web/plugin/scan-views.js";
10
- import { emitManifestModule, emitVercelFunction, ensureVercelJson, } from "./build-helpers.js";
11
- async function resolveViewsDir(root) {
12
- const { loadConfigFromFile } = await import("vite");
13
- const loaded = await loadConfigFromFile({ command: "build", mode: "production" }, undefined, root);
14
- const isPluginCandidate = (value) => typeof value === "object" && value !== null;
15
- const plugins = [];
16
- const walk = (value) => {
17
- if (Array.isArray(value)) {
18
- value.forEach(walk);
19
- }
20
- else if (isPluginCandidate(value)) {
21
- plugins.push(value);
22
- }
23
- };
24
- walk(loaded?.config.plugins ?? []);
25
- return plugins.find((p) => p.name === "skybridge")?.api?.viewsDir;
26
- }
27
- export function buildSteps(target, warnings) {
28
- const scanViews = {
29
- label: "Scanning views",
30
- run: async () => {
31
- const root = process.cwd();
32
- const viewsDir = await resolveViewsDir(root);
33
- scanAndWriteViewsDts(root, viewsDir);
34
- },
35
- };
36
- const compileServer = {
37
- label: "Compiling server",
38
- run: () => rmSync("dist", { recursive: true, force: true }),
39
- command: "tsc -b --force",
40
- };
41
- const buildViews = {
42
- label: "Building views",
43
- command: "vite build",
44
- };
45
- if (target === "vercel") {
46
- return [
47
- scanViews,
48
- compileServer,
49
- buildViews,
50
- {
51
- label: "Relocating assets to public/",
52
- // Vite plugin's config() locks outDir to dist/assets; move post-build
53
- // to satisfy Vercel's CDN filesystem-precedence routing.
54
- run: () => {
55
- const root = process.cwd();
56
- const src = path.join(root, "dist", "assets");
57
- const dst = path.join(root, "public", "assets");
58
- rmSync(dst, { recursive: true, force: true });
59
- mkdirSync(path.join(root, "public"), { recursive: true });
60
- renameSync(src, dst);
61
- },
62
- },
63
- {
64
- label: "Emitting manifest module",
65
- run: () => {
66
- const root = process.cwd();
67
- emitManifestModule(path.join(root, "public", "assets", ".vite", "manifest.json"), path.join(root, "dist", "vite-manifest.js"));
68
- },
69
- },
70
- {
71
- label: "Emitting Vercel function",
72
- run: () => emitVercelFunction(process.cwd()),
73
- },
74
- {
75
- label: "Ensuring vercel.json",
76
- run: () => {
77
- const result = ensureVercelJson(process.cwd());
78
- warnings.current = result.warnings;
79
- },
80
- },
81
- ];
82
- }
83
- return [
84
- scanViews,
85
- compileServer,
86
- buildViews,
87
- {
88
- label: "Emitting manifest module",
89
- // Inline the Vite manifest as a JS module so the server can `import` it
90
- // instead of `readFileSync(process.cwd() + ...)` at runtime — required for
91
- // workerd, where neither cwd nor the assets directory is readable.
92
- run: () => {
93
- const root = process.cwd();
94
- emitManifestModule(path.join(root, "dist", "assets", ".vite", "manifest.json"), path.join(root, "dist", "vite-manifest.js"));
95
- },
96
- },
97
- {
98
- label: "Emitting Cloudflare redirects",
99
- // Cloudflare's `assets.directory` maps URL → file literally — no
100
- // mount-strip like `app.use("/assets", express.static(...))`. Rewrite
101
- // `/assets/assets/*` to `/assets/*` before lookup; status 200 =
102
- // server-side rewrite, not HTTP redirect.
103
- run: () => {
104
- const root = process.cwd();
105
- writeFileSync(path.join(root, "dist", "assets", "_redirects"), "/assets/assets/* /assets/:splat 200\n");
106
- },
107
- },
108
- {
109
- label: "Emitting Cloudflare headers",
110
- // Cloudflare's static asset handler bypasses the worker entirely, so
111
- // `app.use("/assets", cors())` never fires for asset requests. Attach
112
- // CORS at the edge so cross-origin view iframes can load JS/CSS.
113
- run: () => {
114
- const root = process.cwd();
115
- writeFileSync(path.join(root, "dist", "assets", "_headers"), "/assets/*\n Access-Control-Allow-Origin: *\n");
116
- },
117
- },
118
- ];
119
- }
120
- export const commandSteps = buildSteps("default", {
121
- current: [],
122
- });
123
8
  export default class Build extends Command {
124
9
  static description = "Build the views and MCP server";
125
- static examples = [
126
- "skybridge build",
127
- "skybridge build --target vercel",
128
- ];
129
- static flags = {
130
- target: Flags.string({
131
- description: "Deployment target. Omit for the default Cloudflare/Docker pipeline.",
132
- options: ["vercel"],
133
- }),
134
- };
10
+ static examples = ["skybridge build"];
135
11
  async run() {
136
- const { flags } = await this.parse(Build);
137
- const isVercel = flags.target === "vercel";
12
+ const commandSteps = await getCommandSteps().catch((e) => this.error(e instanceof Error ? e.message : String(e)));
138
13
  const App = () => {
139
- const warnings = useRef([]);
140
- // isVercel + warnings are captured from the enclosing closure and
141
- // never change identity across renders; empty deps are correct.
142
- const steps = useMemo(() => buildSteps(isVercel ? "vercel" : "default", warnings), []);
143
- const { currentStep, status, error, execute } = useExecuteSteps(steps);
14
+ const { currentStep, status, error, execute } = useExecuteSteps(commandSteps);
144
15
  useEffect(() => {
145
16
  execute();
146
17
  }, [execute]);
147
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Header, { version: this.config.version, children: _jsxs(Text, { color: "green", children: [" → building for production", isVercel ? " (vercel)" : "", "\u2026"] }) }), steps.map((step, index) => {
18
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Header, { version: this.config.version, children: _jsx(Text, { color: "green", children: " \u2192 building for production\u2026" }) }), commandSteps.map((step, index) => {
148
19
  const isCurrent = index === currentStep && status === "running";
149
20
  const isCompleted = index < currentStep || status === "success";
150
21
  const isError = status === "error" && index === currentStep;
151
22
  return (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: isError ? "red" : isCompleted ? "green" : "grey", children: [isError ? "✗" : isCompleted ? "✓" : isCurrent ? "⟳" : "○", " ", step.label] }) }, step.label));
152
- }), status === "success" && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "green", bold: true, children: "\u2713 Build completed successfully!" }), isVercel && warnings.current.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "yellow", bold: true, children: "\u26A0 vercel.json warnings:" }), warnings.current.map((line) => (_jsxs(Text, { color: "yellow", children: [" ", "\u2022 ", line] }, line)))] }))] })), status === "error" && error && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "red", bold: true, children: "\u2717 Build failed" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: error.split("\n").map((line) => (_jsx(Text, { color: "red", children: line }, line))) })] }))] }));
23
+ }), status === "success" && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "green", bold: true, children: "\u2713 Build completed successfully!" }) })), status === "error" && error && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "red", bold: true, children: "\u2717 Build failed" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: error.split("\n").map((line) => (_jsx(Text, { color: "red", children: line }, line))) })] }))] }));
153
24
  };
154
25
  render(_jsx(App, {}), {
155
26
  exitOnCtrlC: true,
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.tsx"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { Command, Flags } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { useEffect, useMemo, useRef } from \"react\";\nimport { Header } from \"../cli/header.js\";\nimport { type CommandStep, useExecuteSteps } from \"../cli/use-execute-steps.js\";\nimport { scanAndWriteViewsDts } from \"../web/plugin/scan-views.js\";\nimport {\n emitManifestModule,\n emitVercelFunction,\n ensureVercelJson,\n} from \"./build-helpers.js\";\n\nasync function resolveViewsDir(root: string): Promise<string | undefined> {\n const { loadConfigFromFile } = await import(\"vite\");\n const loaded = await loadConfigFromFile(\n { command: \"build\", mode: \"production\" },\n undefined,\n root,\n );\n\n const isPluginCandidate = (\n value: unknown,\n ): value is { name?: string; api?: { viewsDir?: string } } =>\n typeof value === \"object\" && value !== null;\n\n const plugins: Array<{ name?: string; api?: { viewsDir?: string } }> = [];\n const walk = (value: unknown) => {\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else if (isPluginCandidate(value)) {\n plugins.push(value);\n }\n };\n walk(loaded?.config.plugins ?? []);\n return plugins.find((p) => p.name === \"skybridge\")?.api?.viewsDir;\n}\n\nexport function buildSteps(\n target: \"default\" | \"vercel\",\n warnings: { current: string[] },\n): CommandStep[] {\n const scanViews: CommandStep = {\n label: \"Scanning views\",\n run: async () => {\n const root = process.cwd();\n const viewsDir = await resolveViewsDir(root);\n scanAndWriteViewsDts(root, viewsDir);\n },\n };\n const compileServer: CommandStep = {\n label: \"Compiling server\",\n run: () => rmSync(\"dist\", { recursive: true, force: true }),\n command: \"tsc -b --force\",\n };\n const buildViews: CommandStep = {\n label: \"Building views\",\n command: \"vite build\",\n };\n\n if (target === \"vercel\") {\n return [\n scanViews,\n compileServer,\n buildViews,\n {\n label: \"Relocating assets to public/\",\n // Vite plugin's config() locks outDir to dist/assets; move post-build\n // to satisfy Vercel's CDN filesystem-precedence routing.\n run: () => {\n const root = process.cwd();\n const src = path.join(root, \"dist\", \"assets\");\n const dst = path.join(root, \"public\", \"assets\");\n rmSync(dst, { recursive: true, force: true });\n mkdirSync(path.join(root, \"public\"), { recursive: true });\n renameSync(src, dst);\n },\n },\n {\n label: \"Emitting manifest module\",\n run: () => {\n const root = process.cwd();\n emitManifestModule(\n path.join(root, \"public\", \"assets\", \".vite\", \"manifest.json\"),\n path.join(root, \"dist\", \"vite-manifest.js\"),\n );\n },\n },\n {\n label: \"Emitting Vercel function\",\n run: () => emitVercelFunction(process.cwd()),\n },\n {\n label: \"Ensuring vercel.json\",\n run: () => {\n const result = ensureVercelJson(process.cwd());\n warnings.current = result.warnings;\n },\n },\n ];\n }\n\n return [\n scanViews,\n compileServer,\n buildViews,\n {\n label: \"Emitting manifest module\",\n // Inline the Vite manifest as a JS module so the server can `import` it\n // instead of `readFileSync(process.cwd() + ...)` at runtime — required for\n // workerd, where neither cwd nor the assets directory is readable.\n run: () => {\n const root = process.cwd();\n emitManifestModule(\n path.join(root, \"dist\", \"assets\", \".vite\", \"manifest.json\"),\n path.join(root, \"dist\", \"vite-manifest.js\"),\n );\n },\n },\n {\n label: \"Emitting Cloudflare redirects\",\n // Cloudflare's `assets.directory` maps URL → file literally — no\n // mount-strip like `app.use(\"/assets\", express.static(...))`. Rewrite\n // `/assets/assets/*` to `/assets/*` before lookup; status 200 =\n // server-side rewrite, not HTTP redirect.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_redirects\"),\n \"/assets/assets/* /assets/:splat 200\\n\",\n );\n },\n },\n {\n label: \"Emitting Cloudflare headers\",\n // Cloudflare's static asset handler bypasses the worker entirely, so\n // `app.use(\"/assets\", cors())` never fires for asset requests. Attach\n // CORS at the edge so cross-origin view iframes can load JS/CSS.\n run: () => {\n const root = process.cwd();\n writeFileSync(\n path.join(root, \"dist\", \"assets\", \"_headers\"),\n \"/assets/*\\n Access-Control-Allow-Origin: *\\n\",\n );\n },\n },\n ];\n}\n\nexport const commandSteps: CommandStep[] = buildSteps(\"default\", {\n current: [],\n});\n\nexport default class Build extends Command {\n static override description = \"Build the views and MCP server\";\n static override examples = [\n \"skybridge build\",\n \"skybridge build --target vercel\",\n ];\n static override flags = {\n target: Flags.string({\n description:\n \"Deployment target. Omit for the default Cloudflare/Docker pipeline.\",\n options: [\"vercel\"],\n }),\n };\n\n public async run(): Promise<void> {\n const { flags } = await this.parse(Build);\n const isVercel = flags.target === \"vercel\";\n\n const App = () => {\n const warnings = useRef<string[]>([]);\n // isVercel + warnings are captured from the enclosing closure and\n // never change identity across renders; empty deps are correct.\n const steps = useMemo(\n () => buildSteps(isVercel ? \"vercel\" : \"default\", warnings),\n [],\n );\n const { currentStep, status, error, execute } = useExecuteSteps(steps);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header version={this.config.version}>\n <Text color=\"green\">\n {\" → building for production\"}\n {isVercel ? \" (vercel)\" : \"\"}…\n </Text>\n </Header>\n\n {steps.map((step, index) => {\n const isCurrent = index === currentStep && status === \"running\";\n const isCompleted = index < currentStep || status === \"success\";\n const isError = status === \"error\" && index === currentStep;\n\n return (\n <Box key={step.label} marginBottom={0}>\n <Text color={isError ? \"red\" : isCompleted ? \"green\" : \"grey\"}>\n {isError ? \"✗\" : isCompleted ? \"✓\" : isCurrent ? \"⟳\" : \"○\"}{\" \"}\n {step.label}\n </Text>\n </Box>\n );\n })}\n\n {status === \"success\" && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"green\" bold>\n ✓ Build completed successfully!\n </Text>\n {isVercel && warnings.current.length > 0 && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"yellow\" bold>\n ⚠ vercel.json warnings:\n </Text>\n {warnings.current.map((line) => (\n <Text key={line} color=\"yellow\">\n {\" \"}\n • {line}\n </Text>\n ))}\n </Box>\n )}\n </Box>\n )}\n\n {status === \"error\" && error && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✗ Build failed\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n {error.split(\"\\n\").map((line) => (\n <Text key={line} color=\"red\">\n {line}\n </Text>\n ))}\n </Box>\n </Box>\n )}\n </Box>\n );\n };\n\n render(<App />, {\n exitOnCtrlC: true,\n patchConsole: false,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Command } from \"@oclif/core\";\nimport { Box, render, Text } from \"ink\";\nimport { useEffect } from \"react\";\nimport { getCommandSteps } from \"../cli/build-steps.js\";\nimport { Header } from \"../cli/header.js\";\nimport { useExecuteSteps } from \"../cli/use-execute-steps.js\";\n\nexport default class Build extends Command {\n static override description = \"Build the views and MCP server\";\n static override examples = [\"skybridge build\"];\n\n public async run(): Promise<void> {\n const commandSteps = await getCommandSteps().catch((e: unknown) =>\n this.error(e instanceof Error ? e.message : String(e)),\n );\n\n const App = () => {\n const { currentStep, status, error, execute } =\n useExecuteSteps(commandSteps);\n\n useEffect(() => {\n execute();\n }, [execute]);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header version={this.config.version}>\n <Text color=\"green\"> → building for production…</Text>\n </Header>\n\n {commandSteps.map((step, index) => {\n const isCurrent = index === currentStep && status === \"running\";\n const isCompleted = index < currentStep || status === \"success\";\n const isError = status === \"error\" && index === currentStep;\n\n return (\n <Box key={step.label} marginBottom={0}>\n <Text color={isError ? \"red\" : isCompleted ? \"green\" : \"grey\"}>\n {isError ? \"✗\" : isCompleted ? \"✓\" : isCurrent ? \"⟳\" : \"○\"}{\" \"}\n {step.label}\n </Text>\n </Box>\n );\n })}\n\n {status === \"success\" && (\n <Box marginTop={1}>\n <Text color=\"green\" bold>\n ✓ Build completed successfully!\n </Text>\n </Box>\n )}\n\n {status === \"error\" && error && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\" bold>\n ✗ Build failed\n </Text>\n <Box marginTop={1} flexDirection=\"column\">\n {error.split(\"\\n\").map((line) => (\n <Text key={line} color=\"red\">\n {line}\n </Text>\n ))}\n </Box>\n </Box>\n )}\n </Box>\n );\n };\n\n render(<App />, {\n exitOnCtrlC: true,\n patchConsole: false,\n });\n }\n}\n"]}
@@ -7,6 +7,7 @@ export default class Dev extends Command {
7
7
  tunnel: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  open: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
9
  verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ plain: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  };
11
12
  run(): Promise<void>;
12
13
  }
@@ -3,12 +3,15 @@ import { Command, Flags } from "@oclif/core";
3
3
  import { Box, render, Text } from "ink";
4
4
  import { resolvePort } from "../cli/detect-port.js";
5
5
  import { Header } from "../cli/header.js";
6
+ import { resolveSkybridgeConfig } from "../cli/resolve-skybridge-config.js";
7
+ import { runPlain } from "../cli/run-plain.js";
6
8
  import { startTunnelControlServer } from "../cli/tunnel-control-server.js";
7
9
  import { useMessages } from "../cli/use-messages.js";
8
- import { useNodemon } from "../cli/use-nodemon.js";
10
+ import { CRASH_MESSAGE, useNodemon } from "../cli/use-nodemon.js";
9
11
  import { useOpenBrowser } from "../cli/use-open-browser.js";
10
12
  import { useTunnel } from "../cli/use-tunnel.js";
11
13
  import { useTypeScriptCheck } from "../cli/use-typescript-check.js";
14
+ import { scanAndWriteViewsDts } from "../views/index.js";
12
15
  export default class Dev extends Command {
13
16
  static description = "Start development server";
14
17
  static examples = ["skybridge"];
@@ -32,9 +35,27 @@ export default class Dev extends Command {
32
35
  description: "Show tunnel logs",
33
36
  default: false,
34
37
  }),
38
+ plain: Flags.boolean({
39
+ description: "Disable the interactive UI and stream raw server logs to stdout, so you can pipe them through a formatter (e.g. `skybridge dev --plain | bunyan`).",
40
+ default: false,
41
+ }),
35
42
  };
36
43
  async run() {
37
44
  const { flags } = await this.parse(Dev);
45
+ // Generate .skybridge/views.d.ts before render() spawns `tsc --noEmit
46
+ // --watch`. Vite's plugin config hook writes the same file when nodemon
47
+ // boots the server, but tsc starts in parallel — if .skybridge/ doesn't
48
+ // exist at tsc startup, its watcher never picks up the late-created file
49
+ // and the dev UI reports phantom TS errors forever.
50
+ const root = process.cwd();
51
+ try {
52
+ scanAndWriteViewsDts(root, (await resolveSkybridgeConfig(root)).viewsDir);
53
+ }
54
+ catch {
55
+ // Best-effort: if the scan fails (e.g. broken vite config, duplicate
56
+ // view names) tsc may show phantom errors, but the dev server should
57
+ // still start so the developer can fix the underlying issue.
58
+ }
38
59
  const { port, fallback, envWarning } = await resolvePort(flags.port);
39
60
  if (envWarning) {
40
61
  this.warn(envWarning);
@@ -45,13 +66,40 @@ export default class Dev extends Command {
45
66
  __PORT: String(port),
46
67
  __TUNNEL_CONTROL_PORT: String(controlPort),
47
68
  };
69
+ if (flags.plain) {
70
+ const teardown = runPlain({
71
+ env,
72
+ port,
73
+ fallback,
74
+ version: this.config.version,
75
+ tunnel: flags.tunnel,
76
+ tunnelManager,
77
+ });
78
+ // Synchronous-first shutdown: kill the alpic subprocess up front so we
79
+ // can't leave it orphaned even if another SIGINT listener (e.g.
80
+ // nodemon's) exits the process before our async cleanup completes.
81
+ const shutdown = (code) => () => {
82
+ tunnelManager.stop();
83
+ teardown();
84
+ void closeTunnelControl()
85
+ .catch((err) => {
86
+ console.error("Failed to close tunnel control server", err);
87
+ })
88
+ .finally(() => {
89
+ process.exit(code);
90
+ });
91
+ };
92
+ process.once("SIGINT", shutdown(130));
93
+ process.once("SIGTERM", shutdown(143));
94
+ return;
95
+ }
48
96
  const App = () => {
49
97
  const tsErrors = useTypeScriptCheck();
50
98
  const [messages, pushMessage] = useMessages();
51
- useNodemon(env, pushMessage);
99
+ const crashed = useNodemon(env, pushMessage);
52
100
  useOpenBrowser(port, flags.open);
53
101
  const tunnelState = useTunnel(port, pushMessage, flags.verbose, flags.tunnel);
54
- return (_jsxs(Box, { flexDirection: "column", padding: 1, marginLeft: 1, children: [_jsx(Header, { version: this.config.version }), _jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDFE0", " "] }), fallback ? (_jsx(Text, { color: "yellow", children: "3000 in use, running on " })) : (_jsx(Text, { children: "Running on " })), _jsx(Text, { color: "green", children: `http://localhost:${port}/mcp` })] }), _jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsxs(Text, { color: "white", bold: true, children: ["Test locally with DevTools:", " "] }), _jsx(Text, { color: "green", children: `http://localhost:${port}/` })] }), tunnelState.status === "idle" && (_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { children: "Get a public URL and LLM Playground access with " }), _jsx(Text, { color: "cyan", bold: true, children: "--tunnel" }), _jsx(Text, { children: "." })] })), tunnelState.status === "starting" && (_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { color: "yellow", children: tunnelState.message })] })), tunnelState.status === "connected" && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { children: "Exposed on " }), _jsx(Text, { color: "green", children: `${tunnelState.url}/mcp` })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsxs(Text, { color: "white", bold: true, children: ["Test with an LLM on Playground:", " "] }), _jsx(Text, { color: "green", children: `${tunnelState.url}/try` })] })] })), tunnelState.status === "error" && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsxs(Text, { color: "red", children: ["Cannot open tunnel: ", tunnelState.message] })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsx(Text, { color: "red", children: `Try manually: npx alpic tunnel --port ${port}` })] })] })), _jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83D\uDEDF", " "] }), _jsx(Text, { children: "Need help? Reach us on " }), _jsx(Text, { color: "white", underline: true, children: "https://discord.alpic.ai" })] }), tsErrors.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "red", bold: true, children: "\u26A0\uFE0F TypeScript errors found:" }), tsErrors.map((error) => (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "white", children: error.file }), _jsxs(Text, { color: "grey", children: ["(", error.line, ",", error.col, "):", " "] })] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "red", children: error.message }) })] }, `${error.file}:${error.line}:${error.col}`)))] })), messages.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "white", bold: true, children: "Logs:" }), messages.map((message) => (_jsx(Box, { marginLeft: 2, children: message.type === "restart" ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "green", children: ["\u2713", " "] }), _jsx(Text, { color: "white", children: message.text })] })) : message.type === "error" ? (_jsx(Text, { color: "red", children: message.text })) : (_jsx(Text, { children: message.text })) }, message.id)))] }))] }));
102
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, marginLeft: 1, children: [_jsx(Header, { version: this.config.version }), crashed ? (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "red", children: CRASH_MESSAGE }) })) : (_jsxs(_Fragment, { children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDFE0", " "] }), fallback ? (_jsx(Text, { color: "yellow", children: "3000 in use, running on " })) : (_jsx(Text, { children: "Running on " })), _jsx(Text, { color: "green", children: `http://localhost:${port}/mcp` })] }), _jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsxs(Text, { color: "white", bold: true, children: ["Test locally with DevTools:", " "] }), _jsx(Text, { color: "green", children: `http://localhost:${port}/` })] })] })), tunnelState.status === "idle" && (_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { children: "Get a public URL and LLM Playground access with " }), _jsx(Text, { color: "cyan", bold: true, children: "--tunnel" }), _jsx(Text, { children: "." })] })), tunnelState.status === "starting" && (_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { color: "yellow", children: tunnelState.message })] })), tunnelState.status === "connected" && !crashed && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsx(Text, { children: "Exposed on " }), _jsx(Text, { color: "green", children: `${tunnelState.url}/mcp` })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsxs(Text, { color: "white", bold: true, children: ["Test with an LLM on Playground:", " "] }), _jsx(Text, { color: "green", children: `${tunnelState.url}/try` })] })] })), tunnelState.status === "error" && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83C\uDF0D", " "] }), _jsxs(Text, { color: "red", children: ["Cannot open tunnel: ", tunnelState.message] })] }), _jsxs(Box, { children: [_jsxs(Text, { color: "#20a832", children: ["\u2192", " "] }), _jsx(Text, { color: "red", children: `Try manually: npx alpic tunnel --port ${port}` })] })] })), _jsxs(Box, { children: [_jsxs(Text, { children: ["\uD83D\uDEDF", " "] }), _jsx(Text, { children: "Need help? Reach us on " }), _jsx(Text, { color: "white", underline: true, children: "https://discord.alpic.ai" })] }), tsErrors.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "red", bold: true, children: "\u26A0\uFE0F TypeScript errors found:" }), tsErrors.map((error) => (_jsxs(Box, { marginLeft: 2, flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: "white", children: error.file }), _jsxs(Text, { color: "grey", children: ["(", error.line, ",", error.col, "):", " "] })] }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { color: "red", children: error.message }) })] }, `${error.file}:${error.line}:${error.col}`)))] })), messages.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: "white", bold: true, children: "Logs:" }), messages.map((message) => (_jsx(Box, { marginLeft: 2, children: message.type === "restart" ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: "green", children: ["\u2713", " "] }), _jsx(Text, { color: "white", children: message.text })] })) : message.type === "error" ? (_jsx(Text, { color: "red", children: message.text })) : (_jsx(Text, { children: message.text })) }, message.id)))] }))] }));
55
103
  };
56
104
  // Note: `exitOnCtrlC: false` because we own SIGINT below to guarantee
57
105
  // alpic gets killed before we exit. If anything ever calls `useInput` or