skybridge 0.0.0-dev.ad2a0aa → 0.0.0-dev.ad54af7

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 (484) hide show
  1. package/README.md +123 -96
  2. package/bin/run.js +5 -0
  3. package/dist/cli/build-helpers.d.ts +5 -0
  4. package/dist/cli/build-helpers.js +44 -0
  5. package/dist/cli/build-helpers.js.map +1 -0
  6. package/dist/cli/build-helpers.test.js +34 -0
  7. package/dist/cli/build-helpers.test.js.map +1 -0
  8. package/dist/cli/detect-port.d.ts +18 -0
  9. package/dist/cli/detect-port.js +61 -0
  10. package/dist/cli/detect-port.js.map +1 -0
  11. package/dist/cli/header.d.ts +4 -0
  12. package/dist/cli/header.js +6 -0
  13. package/dist/cli/header.js.map +1 -0
  14. package/dist/cli/resolve-views-dir.d.ts +1 -0
  15. package/dist/cli/resolve-views-dir.js +17 -0
  16. package/dist/cli/resolve-views-dir.js.map +1 -0
  17. package/dist/cli/run-command.d.ts +2 -0
  18. package/dist/cli/run-command.js +43 -0
  19. package/dist/cli/run-command.js.map +1 -0
  20. package/dist/cli/telemetry.d.ts +7 -0
  21. package/dist/cli/telemetry.js +123 -0
  22. package/dist/cli/telemetry.js.map +1 -0
  23. package/dist/cli/tunnel-control-server.d.ts +9 -0
  24. package/dist/cli/tunnel-control-server.js +31 -0
  25. package/dist/cli/tunnel-control-server.js.map +1 -0
  26. package/dist/cli/tunnel-control-server.test.js +39 -0
  27. package/dist/cli/tunnel-control-server.test.js.map +1 -0
  28. package/dist/cli/tunnel-handler.d.ts +3 -0
  29. package/dist/cli/tunnel-handler.js +48 -0
  30. package/dist/cli/tunnel-handler.js.map +1 -0
  31. package/dist/cli/tunnel-handler.test.js +105 -0
  32. package/dist/cli/tunnel-handler.test.js.map +1 -0
  33. package/dist/cli/tunnel.d.ts +57 -0
  34. package/dist/cli/tunnel.js +154 -0
  35. package/dist/cli/tunnel.js.map +1 -0
  36. package/dist/cli/tunnel.test.js +190 -0
  37. package/dist/cli/tunnel.test.js.map +1 -0
  38. package/dist/cli/types.d.ts +5 -0
  39. package/dist/cli/types.js +2 -0
  40. package/dist/cli/types.js.map +1 -0
  41. package/dist/cli/use-execute-steps.d.ts +11 -0
  42. package/dist/cli/use-execute-steps.js +36 -0
  43. package/dist/cli/use-execute-steps.js.map +1 -0
  44. package/dist/cli/use-messages.d.ts +3 -0
  45. package/dist/cli/use-messages.js +11 -0
  46. package/dist/cli/use-messages.js.map +1 -0
  47. package/dist/cli/use-nodemon.d.ts +2 -0
  48. package/dist/cli/use-nodemon.js +73 -0
  49. package/dist/cli/use-nodemon.js.map +1 -0
  50. package/dist/cli/use-open-browser.d.ts +1 -0
  51. package/dist/cli/use-open-browser.js +44 -0
  52. package/dist/cli/use-open-browser.js.map +1 -0
  53. package/dist/cli/use-tunnel.d.ts +14 -0
  54. package/dist/cli/use-tunnel.js +131 -0
  55. package/dist/cli/use-tunnel.js.map +1 -0
  56. package/dist/cli/use-typescript-check.d.ts +9 -0
  57. package/dist/cli/use-typescript-check.js +94 -0
  58. package/dist/cli/use-typescript-check.js.map +1 -0
  59. package/dist/commands/build.d.ts +9 -0
  60. package/dist/commands/build.js +93 -0
  61. package/dist/commands/build.js.map +1 -0
  62. package/dist/commands/create.d.ts +9 -0
  63. package/dist/commands/create.js +30 -0
  64. package/dist/commands/create.js.map +1 -0
  65. package/dist/commands/dev.d.ts +12 -0
  66. package/dist/commands/dev.js +101 -0
  67. package/dist/commands/dev.js.map +1 -0
  68. package/dist/commands/start.d.ts +9 -0
  69. package/dist/commands/start.js +54 -0
  70. package/dist/commands/start.js.map +1 -0
  71. package/dist/commands/telemetry/disable.d.ts +5 -0
  72. package/dist/commands/telemetry/disable.js +14 -0
  73. package/dist/commands/telemetry/disable.js.map +1 -0
  74. package/dist/commands/telemetry/enable.d.ts +5 -0
  75. package/dist/commands/telemetry/enable.js +14 -0
  76. package/dist/commands/telemetry/enable.js.map +1 -0
  77. package/dist/commands/telemetry/status.d.ts +5 -0
  78. package/dist/commands/telemetry/status.js +14 -0
  79. package/dist/commands/telemetry/status.js.map +1 -0
  80. package/dist/server/asset-base-url-transform-plugin.d.ts +11 -0
  81. package/dist/server/asset-base-url-transform-plugin.js +48 -0
  82. package/dist/server/asset-base-url-transform-plugin.js.map +1 -0
  83. package/dist/server/asset-base-url-transform-plugin.test.js +134 -0
  84. package/dist/server/asset-base-url-transform-plugin.test.js.map +1 -0
  85. package/dist/server/auth.d.ts +20 -0
  86. package/dist/server/auth.js +28 -0
  87. package/dist/server/auth.js.map +1 -0
  88. package/dist/server/content-helpers.d.ts +67 -0
  89. package/dist/server/content-helpers.js +79 -0
  90. package/dist/server/content-helpers.js.map +1 -0
  91. package/dist/server/content-helpers.test.js +70 -0
  92. package/dist/server/content-helpers.test.js.map +1 -0
  93. package/dist/server/express.d.ts +11 -0
  94. package/dist/server/express.js +101 -0
  95. package/dist/server/express.js.map +1 -0
  96. package/dist/server/express.test.js +430 -0
  97. package/dist/server/express.test.js.map +1 -0
  98. package/dist/server/file-ref.d.ts +28 -0
  99. package/dist/server/file-ref.js +27 -0
  100. package/dist/server/file-ref.js.map +1 -0
  101. package/dist/server/index.d.ts +8 -0
  102. package/dist/server/index.js +6 -0
  103. package/dist/server/index.js.map +1 -0
  104. package/dist/{src/server → server}/inferUtilityTypes.d.ts +6 -6
  105. package/dist/server/inferUtilityTypes.js.map +1 -0
  106. package/dist/server/metric.d.ts +14 -0
  107. package/dist/server/metric.js +62 -0
  108. package/dist/server/metric.js.map +1 -0
  109. package/dist/server/middleware.d.ts +137 -0
  110. package/dist/server/middleware.js +93 -0
  111. package/dist/server/middleware.js.map +1 -0
  112. package/dist/server/middleware.test-d.js +75 -0
  113. package/dist/server/middleware.test-d.js.map +1 -0
  114. package/dist/server/middleware.test.js +493 -0
  115. package/dist/server/middleware.test.js.map +1 -0
  116. package/dist/server/server.d.ts +398 -0
  117. package/dist/server/server.js +561 -0
  118. package/dist/server/server.js.map +1 -0
  119. package/dist/{src/server → server}/templateHelper.d.ts +5 -7
  120. package/dist/server/templateHelper.js +11 -0
  121. package/dist/server/templateHelper.js.map +1 -0
  122. package/dist/server/templates.generated.d.ts +4 -0
  123. package/dist/server/templates.generated.js +47 -0
  124. package/dist/server/templates.generated.js.map +1 -0
  125. package/dist/server/tunnel-proxy-router.d.ts +7 -0
  126. package/dist/server/tunnel-proxy-router.js +110 -0
  127. package/dist/server/tunnel-proxy-router.js.map +1 -0
  128. package/dist/server/tunnel-proxy-router.test.js +229 -0
  129. package/dist/server/tunnel-proxy-router.test.js.map +1 -0
  130. package/dist/server/viewsDevServer.d.ts +14 -0
  131. package/dist/server/viewsDevServer.js +45 -0
  132. package/dist/server/viewsDevServer.js.map +1 -0
  133. package/dist/{src/test → test}/utils.d.ts +13 -21
  134. package/dist/{src/test → test}/utils.js +42 -37
  135. package/dist/test/utils.js.map +1 -0
  136. package/dist/test/view.test.js +568 -0
  137. package/dist/test/view.test.js.map +1 -0
  138. package/dist/version.d.ts +1 -0
  139. package/dist/version.js +3 -0
  140. package/dist/version.js.map +1 -0
  141. package/dist/web/bridges/apps-sdk/adaptor.d.ts +28 -0
  142. package/dist/web/bridges/apps-sdk/adaptor.js +113 -0
  143. package/dist/web/bridges/apps-sdk/adaptor.js.map +1 -0
  144. package/dist/web/bridges/apps-sdk/bridge.d.ts +11 -0
  145. package/dist/web/bridges/apps-sdk/bridge.js +47 -0
  146. package/dist/web/bridges/apps-sdk/bridge.js.map +1 -0
  147. package/dist/web/bridges/apps-sdk/index.d.ts +5 -0
  148. package/dist/web/bridges/apps-sdk/index.js +5 -0
  149. package/dist/web/bridges/apps-sdk/index.js.map +1 -0
  150. package/dist/web/bridges/apps-sdk/types.d.ts +133 -0
  151. package/dist/{src/web → web/bridges/apps-sdk}/types.js +0 -1
  152. package/dist/web/bridges/apps-sdk/types.js.map +1 -0
  153. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +13 -0
  154. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +18 -0
  155. package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -0
  156. package/dist/web/bridges/get-adaptor.d.ts +9 -0
  157. package/dist/web/bridges/get-adaptor.js +15 -0
  158. package/dist/web/bridges/get-adaptor.js.map +1 -0
  159. package/dist/web/bridges/index.d.ts +5 -0
  160. package/dist/web/bridges/index.js +6 -0
  161. package/dist/web/bridges/index.js.map +1 -0
  162. package/dist/web/bridges/mcp-app/adaptor.d.ts +52 -0
  163. package/dist/web/bridges/mcp-app/adaptor.js +280 -0
  164. package/dist/web/bridges/mcp-app/adaptor.js.map +1 -0
  165. package/dist/web/bridges/mcp-app/bridge.d.ts +27 -0
  166. package/dist/web/bridges/mcp-app/bridge.js +103 -0
  167. package/dist/web/bridges/mcp-app/bridge.js.map +1 -0
  168. package/dist/web/bridges/mcp-app/index.d.ts +4 -0
  169. package/dist/web/bridges/mcp-app/index.js +4 -0
  170. package/dist/web/bridges/mcp-app/index.js.map +1 -0
  171. package/dist/web/bridges/mcp-app/types.d.ts +8 -0
  172. package/dist/web/bridges/mcp-app/types.js +2 -0
  173. package/dist/web/bridges/mcp-app/types.js.map +1 -0
  174. package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +19 -0
  175. package/dist/web/bridges/mcp-app/use-mcp-app-context.js +19 -0
  176. package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -0
  177. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +26 -0
  178. package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -0
  179. package/dist/web/bridges/types.d.ts +171 -0
  180. package/dist/web/bridges/types.js +2 -0
  181. package/dist/web/bridges/types.js.map +1 -0
  182. package/dist/web/bridges/use-host-context.d.ts +7 -0
  183. package/dist/web/bridges/use-host-context.js +13 -0
  184. package/dist/web/bridges/use-host-context.js.map +1 -0
  185. package/dist/web/components/modal-provider.d.ts +4 -0
  186. package/dist/web/components/modal-provider.js +45 -0
  187. package/dist/web/components/modal-provider.js.map +1 -0
  188. package/dist/web/create-store.d.ts +29 -0
  189. package/dist/web/create-store.js +64 -0
  190. package/dist/web/create-store.js.map +1 -0
  191. package/dist/web/create-store.test.js +129 -0
  192. package/dist/web/create-store.test.js.map +1 -0
  193. package/dist/web/data-llm.d.ts +47 -0
  194. package/dist/{src/web → web}/data-llm.js +39 -7
  195. package/dist/web/data-llm.js.map +1 -0
  196. package/dist/web/data-llm.test.js +142 -0
  197. package/dist/web/data-llm.test.js.map +1 -0
  198. package/dist/{src/web → web}/generate-helpers.d.ts +24 -19
  199. package/dist/{src/web → web}/generate-helpers.js +22 -18
  200. package/dist/web/generate-helpers.js.map +1 -0
  201. package/dist/{src/web → web}/generate-helpers.test-d.js +30 -27
  202. package/dist/web/generate-helpers.test-d.js.map +1 -0
  203. package/dist/web/generate-helpers.test.js.map +1 -0
  204. package/dist/{src/web → web}/helpers/state.d.ts +2 -2
  205. package/dist/web/helpers/state.js +45 -0
  206. package/dist/web/helpers/state.js.map +1 -0
  207. package/dist/{src/web → web}/helpers/state.test.js +9 -9
  208. package/dist/web/helpers/state.test.js.map +1 -0
  209. package/dist/web/hooks/index.d.ts +14 -0
  210. package/dist/web/hooks/index.js +15 -0
  211. package/dist/web/hooks/index.js.map +1 -0
  212. package/dist/web/hooks/test/utils.d.ts +20 -0
  213. package/dist/web/hooks/test/utils.js +75 -0
  214. package/dist/web/hooks/test/utils.js.map +1 -0
  215. package/dist/{src/web → web}/hooks/use-call-tool.d.ts +47 -1
  216. package/dist/web/hooks/use-call-tool.js +96 -0
  217. package/dist/web/hooks/use-call-tool.js.map +1 -0
  218. package/dist/web/hooks/use-call-tool.test-d.js.map +1 -0
  219. package/dist/{src/web → web}/hooks/use-call-tool.test.js +50 -4
  220. package/dist/web/hooks/use-call-tool.test.js.map +1 -0
  221. package/dist/web/hooks/use-display-mode.d.ts +24 -0
  222. package/dist/web/hooks/use-display-mode.js +29 -0
  223. package/dist/web/hooks/use-display-mode.js.map +1 -0
  224. package/dist/web/hooks/use-display-mode.test-d.js +8 -0
  225. package/dist/web/hooks/use-display-mode.test-d.js.map +1 -0
  226. package/dist/{src/web → web}/hooks/use-display-mode.test.js +1 -1
  227. package/dist/web/hooks/use-display-mode.test.js.map +1 -0
  228. package/dist/web/hooks/use-download.d.ts +5 -0
  229. package/dist/web/hooks/use-download.js +8 -0
  230. package/dist/web/hooks/use-download.js.map +1 -0
  231. package/dist/web/hooks/use-download.test.d.ts +1 -0
  232. package/dist/web/hooks/use-download.test.js +95 -0
  233. package/dist/web/hooks/use-download.test.js.map +1 -0
  234. package/dist/web/hooks/use-files.d.ts +39 -0
  235. package/dist/web/hooks/use-files.js +42 -0
  236. package/dist/web/hooks/use-files.js.map +1 -0
  237. package/dist/web/hooks/use-files.test.d.ts +1 -0
  238. package/dist/web/hooks/use-files.test.js +54 -0
  239. package/dist/web/hooks/use-files.test.js.map +1 -0
  240. package/dist/web/hooks/use-layout.d.ts +24 -0
  241. package/dist/web/hooks/use-layout.js +25 -0
  242. package/dist/web/hooks/use-layout.js.map +1 -0
  243. package/dist/web/hooks/use-layout.test.d.ts +1 -0
  244. package/dist/web/hooks/use-layout.test.js +96 -0
  245. package/dist/web/hooks/use-layout.test.js.map +1 -0
  246. package/dist/web/hooks/use-open-external.d.ts +20 -0
  247. package/dist/web/hooks/use-open-external.js +24 -0
  248. package/dist/web/hooks/use-open-external.js.map +1 -0
  249. package/dist/web/hooks/use-open-external.test.d.ts +1 -0
  250. package/dist/web/hooks/use-open-external.test.js +65 -0
  251. package/dist/web/hooks/use-open-external.test.js.map +1 -0
  252. package/dist/web/hooks/use-request-close.d.ts +16 -0
  253. package/dist/web/hooks/use-request-close.js +21 -0
  254. package/dist/web/hooks/use-request-close.js.map +1 -0
  255. package/dist/web/hooks/use-request-close.test.d.ts +1 -0
  256. package/dist/web/hooks/use-request-close.test.js +52 -0
  257. package/dist/web/hooks/use-request-close.test.js.map +1 -0
  258. package/dist/web/hooks/use-request-modal.d.ts +24 -0
  259. package/dist/web/hooks/use-request-modal.js +31 -0
  260. package/dist/web/hooks/use-request-modal.js.map +1 -0
  261. package/dist/web/hooks/use-request-modal.test.d.ts +1 -0
  262. package/dist/web/hooks/use-request-modal.test.js +61 -0
  263. package/dist/web/hooks/use-request-modal.test.js.map +1 -0
  264. package/dist/web/hooks/use-request-size.d.ts +20 -0
  265. package/dist/web/hooks/use-request-size.js +24 -0
  266. package/dist/web/hooks/use-request-size.js.map +1 -0
  267. package/dist/web/hooks/use-request-size.test.d.ts +1 -0
  268. package/dist/web/hooks/use-request-size.test.js +65 -0
  269. package/dist/web/hooks/use-request-size.test.js.map +1 -0
  270. package/dist/web/hooks/use-send-follow-up-message.d.ts +19 -0
  271. package/dist/web/hooks/use-send-follow-up-message.js +25 -0
  272. package/dist/web/hooks/use-send-follow-up-message.js.map +1 -0
  273. package/dist/web/hooks/use-set-open-in-app-url.d.ts +18 -0
  274. package/dist/web/hooks/use-set-open-in-app-url.js +25 -0
  275. package/dist/web/hooks/use-set-open-in-app-url.js.map +1 -0
  276. package/dist/web/hooks/use-set-open-in-app-url.test.d.ts +1 -0
  277. package/dist/web/hooks/use-set-open-in-app-url.test.js +43 -0
  278. package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -0
  279. package/dist/web/hooks/use-tool-info.d.ts +69 -0
  280. package/dist/web/hooks/use-tool-info.js +52 -0
  281. package/dist/web/hooks/use-tool-info.js.map +1 -0
  282. package/dist/web/hooks/use-tool-info.test-d.d.ts +1 -0
  283. package/dist/{src/web → web}/hooks/use-tool-info.test-d.js +40 -4
  284. package/dist/web/hooks/use-tool-info.test-d.js.map +1 -0
  285. package/dist/web/hooks/use-tool-info.test.d.ts +1 -0
  286. package/dist/web/hooks/use-tool-info.test.js +130 -0
  287. package/dist/web/hooks/use-tool-info.test.js.map +1 -0
  288. package/dist/web/hooks/use-user.d.ts +20 -0
  289. package/dist/web/hooks/use-user.js +37 -0
  290. package/dist/web/hooks/use-user.js.map +1 -0
  291. package/dist/web/hooks/use-user.test.d.ts +1 -0
  292. package/dist/web/hooks/use-user.test.js +122 -0
  293. package/dist/web/hooks/use-user.test.js.map +1 -0
  294. package/dist/web/hooks/use-view-state.d.ts +25 -0
  295. package/dist/web/hooks/use-view-state.js +32 -0
  296. package/dist/web/hooks/use-view-state.js.map +1 -0
  297. package/dist/web/hooks/use-view-state.test.d.ts +1 -0
  298. package/dist/web/hooks/use-view-state.test.js +177 -0
  299. package/dist/web/hooks/use-view-state.test.js.map +1 -0
  300. package/dist/{src/web → web}/index.d.ts +1 -2
  301. package/dist/{src/web → web}/index.js +1 -2
  302. package/dist/web/index.js.map +1 -0
  303. package/dist/web/mount-view.d.ts +20 -0
  304. package/dist/web/mount-view.js +46 -0
  305. package/dist/web/mount-view.js.map +1 -0
  306. package/dist/web/plugin/data-llm.test.d.ts +1 -0
  307. package/dist/web/plugin/data-llm.test.js.map +1 -0
  308. package/dist/web/plugin/plugin.d.ts +33 -0
  309. package/dist/web/plugin/plugin.js +189 -0
  310. package/dist/web/plugin/plugin.js.map +1 -0
  311. package/dist/web/plugin/scan-views.d.ts +16 -0
  312. package/dist/web/plugin/scan-views.js +88 -0
  313. package/dist/web/plugin/scan-views.js.map +1 -0
  314. package/dist/web/plugin/scan-views.test.d.ts +1 -0
  315. package/dist/web/plugin/scan-views.test.js +99 -0
  316. package/dist/web/plugin/scan-views.test.js.map +1 -0
  317. package/dist/{src/web → web}/plugin/transform-data-llm.js +7 -4
  318. package/dist/web/plugin/transform-data-llm.js.map +1 -0
  319. package/dist/web/plugin/transform-data-llm.test.d.ts +1 -0
  320. package/dist/web/plugin/transform-data-llm.test.js.map +1 -0
  321. package/dist/web/plugin/validate-view.d.ts +1 -0
  322. package/dist/web/plugin/validate-view.js +9 -0
  323. package/dist/web/plugin/validate-view.js.map +1 -0
  324. package/dist/web/plugin/validate-view.test.d.ts +1 -0
  325. package/dist/web/plugin/validate-view.test.js +24 -0
  326. package/dist/web/plugin/validate-view.test.js.map +1 -0
  327. package/dist/{src/web → web}/proxy.js +0 -1
  328. package/dist/web/proxy.js.map +1 -0
  329. package/dist/web/types.d.ts +20 -0
  330. package/dist/web/types.js +2 -0
  331. package/dist/web/types.js.map +1 -0
  332. package/package.json +83 -43
  333. package/tsconfig.base.json +33 -0
  334. package/dist/src/server/devtoolsStaticServer.d.ts +0 -15
  335. package/dist/src/server/devtoolsStaticServer.js +0 -38
  336. package/dist/src/server/devtoolsStaticServer.js.map +0 -1
  337. package/dist/src/server/index.d.ts +0 -5
  338. package/dist/src/server/index.js +0 -4
  339. package/dist/src/server/index.js.map +0 -1
  340. package/dist/src/server/inferUtilityTypes.js.map +0 -1
  341. package/dist/src/server/server.d.ts +0 -74
  342. package/dist/src/server/server.js +0 -82
  343. package/dist/src/server/server.js.map +0 -1
  344. package/dist/src/server/templateHelper.js +0 -30
  345. package/dist/src/server/templateHelper.js.map +0 -1
  346. package/dist/src/server/templates/development.hbs +0 -13
  347. package/dist/src/server/templates/production.hbs +0 -7
  348. package/dist/src/server/widgetsDevServer.d.ts +0 -12
  349. package/dist/src/server/widgetsDevServer.js +0 -39
  350. package/dist/src/server/widgetsDevServer.js.map +0 -1
  351. package/dist/src/test/utils.js.map +0 -1
  352. package/dist/src/test/widget.test.js +0 -146
  353. package/dist/src/test/widget.test.js.map +0 -1
  354. package/dist/src/web/bridges/constants.d.ts +0 -2
  355. package/dist/src/web/bridges/constants.js +0 -3
  356. package/dist/src/web/bridges/constants.js.map +0 -1
  357. package/dist/src/web/bridges/index.d.ts +0 -2
  358. package/dist/src/web/bridges/index.js +0 -3
  359. package/dist/src/web/bridges/index.js.map +0 -1
  360. package/dist/src/web/bridges/use-apps-sdk-bridge.d.ts +0 -7
  361. package/dist/src/web/bridges/use-apps-sdk-bridge.js +0 -39
  362. package/dist/src/web/bridges/use-apps-sdk-bridge.js.map +0 -1
  363. package/dist/src/web/bridges/use-mcp-app-bridge.d.ts +0 -25
  364. package/dist/src/web/bridges/use-mcp-app-bridge.js +0 -128
  365. package/dist/src/web/bridges/use-mcp-app-bridge.js.map +0 -1
  366. package/dist/src/web/bridges/use-mcp-app-bridge.test.js +0 -65
  367. package/dist/src/web/bridges/use-mcp-app-bridge.test.js.map +0 -1
  368. package/dist/src/web/create-store.d.ts +0 -3
  369. package/dist/src/web/create-store.js +0 -25
  370. package/dist/src/web/create-store.js.map +0 -1
  371. package/dist/src/web/create-store.test.js +0 -70
  372. package/dist/src/web/create-store.test.js.map +0 -1
  373. package/dist/src/web/data-llm.d.ts +0 -14
  374. package/dist/src/web/data-llm.js.map +0 -1
  375. package/dist/src/web/data-llm.test.js +0 -76
  376. package/dist/src/web/data-llm.test.js.map +0 -1
  377. package/dist/src/web/generate-helpers.js.map +0 -1
  378. package/dist/src/web/generate-helpers.test-d.js.map +0 -1
  379. package/dist/src/web/generate-helpers.test.js.map +0 -1
  380. package/dist/src/web/helpers/state.js +0 -40
  381. package/dist/src/web/helpers/state.js.map +0 -1
  382. package/dist/src/web/helpers/state.test.js.map +0 -1
  383. package/dist/src/web/hooks/index.d.ts +0 -12
  384. package/dist/src/web/hooks/index.js +0 -13
  385. package/dist/src/web/hooks/index.js.map +0 -1
  386. package/dist/src/web/hooks/use-call-tool.js +0 -60
  387. package/dist/src/web/hooks/use-call-tool.js.map +0 -1
  388. package/dist/src/web/hooks/use-call-tool.test-d.js.map +0 -1
  389. package/dist/src/web/hooks/use-call-tool.test.js.map +0 -1
  390. package/dist/src/web/hooks/use-display-mode.d.ts +0 -4
  391. package/dist/src/web/hooks/use-display-mode.js +0 -10
  392. package/dist/src/web/hooks/use-display-mode.js.map +0 -1
  393. package/dist/src/web/hooks/use-display-mode.test.js.map +0 -1
  394. package/dist/src/web/hooks/use-files.d.ts +0 -10
  395. package/dist/src/web/hooks/use-files.js +0 -7
  396. package/dist/src/web/hooks/use-files.js.map +0 -1
  397. package/dist/src/web/hooks/use-files.test.js +0 -29
  398. package/dist/src/web/hooks/use-files.test.js.map +0 -1
  399. package/dist/src/web/hooks/use-locale.d.ts +0 -1
  400. package/dist/src/web/hooks/use-locale.js +0 -10
  401. package/dist/src/web/hooks/use-locale.js.map +0 -1
  402. package/dist/src/web/hooks/use-locale.test.js +0 -22
  403. package/dist/src/web/hooks/use-locale.test.js.map +0 -1
  404. package/dist/src/web/hooks/use-open-external.d.ts +0 -1
  405. package/dist/src/web/hooks/use-open-external.js +0 -6
  406. package/dist/src/web/hooks/use-open-external.js.map +0 -1
  407. package/dist/src/web/hooks/use-open-external.test.js +0 -24
  408. package/dist/src/web/hooks/use-open-external.test.js.map +0 -1
  409. package/dist/src/web/hooks/use-openai-global.d.ts +0 -3
  410. package/dist/src/web/hooks/use-openai-global.js +0 -6
  411. package/dist/src/web/hooks/use-openai-global.js.map +0 -1
  412. package/dist/src/web/hooks/use-request-modal.d.ts +0 -6
  413. package/dist/src/web/hooks/use-request-modal.js +0 -9
  414. package/dist/src/web/hooks/use-request-modal.js.map +0 -1
  415. package/dist/src/web/hooks/use-request-modal.test.js +0 -24
  416. package/dist/src/web/hooks/use-request-modal.test.js.map +0 -1
  417. package/dist/src/web/hooks/use-send-follow-up-message.d.ts +0 -1
  418. package/dist/src/web/hooks/use-send-follow-up-message.js +0 -11
  419. package/dist/src/web/hooks/use-send-follow-up-message.js.map +0 -1
  420. package/dist/src/web/hooks/use-theme.d.ts +0 -1
  421. package/dist/src/web/hooks/use-theme.js +0 -10
  422. package/dist/src/web/hooks/use-theme.js.map +0 -1
  423. package/dist/src/web/hooks/use-theme.test.js +0 -27
  424. package/dist/src/web/hooks/use-theme.test.js.map +0 -1
  425. package/dist/src/web/hooks/use-tool-info.d.ts +0 -25
  426. package/dist/src/web/hooks/use-tool-info.js +0 -20
  427. package/dist/src/web/hooks/use-tool-info.js.map +0 -1
  428. package/dist/src/web/hooks/use-tool-info.test-d.js.map +0 -1
  429. package/dist/src/web/hooks/use-tool-info.test.js +0 -60
  430. package/dist/src/web/hooks/use-tool-info.test.js.map +0 -1
  431. package/dist/src/web/hooks/use-user-agent.d.ts +0 -1
  432. package/dist/src/web/hooks/use-user-agent.js +0 -5
  433. package/dist/src/web/hooks/use-user-agent.js.map +0 -1
  434. package/dist/src/web/hooks/use-user-agent.test.js +0 -32
  435. package/dist/src/web/hooks/use-user-agent.test.js.map +0 -1
  436. package/dist/src/web/hooks/use-widget-state.d.ts +0 -4
  437. package/dist/src/web/hooks/use-widget-state.js +0 -32
  438. package/dist/src/web/hooks/use-widget-state.js.map +0 -1
  439. package/dist/src/web/hooks/use-widget-state.test.js +0 -61
  440. package/dist/src/web/hooks/use-widget-state.test.js.map +0 -1
  441. package/dist/src/web/index.js.map +0 -1
  442. package/dist/src/web/mount-widget.d.ts +0 -1
  443. package/dist/src/web/mount-widget.js +0 -19
  444. package/dist/src/web/mount-widget.js.map +0 -1
  445. package/dist/src/web/plugin/data-llm.test.js.map +0 -1
  446. package/dist/src/web/plugin/plugin.d.ts +0 -2
  447. package/dist/src/web/plugin/plugin.js +0 -39
  448. package/dist/src/web/plugin/plugin.js.map +0 -1
  449. package/dist/src/web/plugin/transform-data-llm.js.map +0 -1
  450. package/dist/src/web/plugin/transform-data-llm.test.js.map +0 -1
  451. package/dist/src/web/proxy.js.map +0 -1
  452. package/dist/src/web/types.d.ts +0 -138
  453. package/dist/src/web/types.js.map +0 -1
  454. package/dist/vitest.config.d.ts +0 -2
  455. package/dist/vitest.config.js +0 -8
  456. package/dist/vitest.config.js.map +0 -1
  457. /package/dist/{src/test/widget.test.d.ts → cli/build-helpers.test.d.ts} +0 -0
  458. /package/dist/{src/web/bridges/use-mcp-app-bridge.test.d.ts → cli/tunnel-control-server.test.d.ts} +0 -0
  459. /package/dist/{src/web/create-store.test.d.ts → cli/tunnel-handler.test.d.ts} +0 -0
  460. /package/dist/{src/web/data-llm.test.d.ts → cli/tunnel.test.d.ts} +0 -0
  461. /package/dist/{src/web/generate-helpers.test-d.d.ts → server/asset-base-url-transform-plugin.test.d.ts} +0 -0
  462. /package/dist/{src/web/generate-helpers.test.d.ts → server/content-helpers.test.d.ts} +0 -0
  463. /package/dist/{src/web/helpers/state.test.d.ts → server/express.test.d.ts} +0 -0
  464. /package/dist/{src/server → server}/inferUtilityTypes.js +0 -0
  465. /package/dist/{src/web/hooks/use-call-tool.test-d.d.ts → server/middleware.test-d.d.ts} +0 -0
  466. /package/dist/{src/web/hooks/use-call-tool.test.d.ts → server/middleware.test.d.ts} +0 -0
  467. /package/dist/{src/web/hooks/use-display-mode.test.d.ts → server/tunnel-proxy-router.test.d.ts} +0 -0
  468. /package/dist/{src/web/hooks/use-files.test.d.ts → test/view.test.d.ts} +0 -0
  469. /package/dist/{src/web/hooks/use-locale.test.d.ts → web/bridges/mcp-app/use-mcp-app-context.test.d.ts} +0 -0
  470. /package/dist/{src/web/hooks/use-open-external.test.d.ts → web/create-store.test.d.ts} +0 -0
  471. /package/dist/{src/web/plugin → web}/data-llm.test.d.ts +0 -0
  472. /package/dist/{src/web/hooks/use-request-modal.test.d.ts → web/generate-helpers.test-d.d.ts} +0 -0
  473. /package/dist/{src/web/hooks/use-theme.test.d.ts → web/generate-helpers.test.d.ts} +0 -0
  474. /package/dist/{src/web → web}/generate-helpers.test.js +0 -0
  475. /package/dist/{src/web/hooks/use-tool-info.test-d.d.ts → web/helpers/state.test.d.ts} +0 -0
  476. /package/dist/{src/web/hooks/use-tool-info.test.d.ts → web/hooks/use-call-tool.test-d.d.ts} +0 -0
  477. /package/dist/{src/web → web}/hooks/use-call-tool.test-d.js +0 -0
  478. /package/dist/{src/web/hooks/use-user-agent.test.d.ts → web/hooks/use-call-tool.test.d.ts} +0 -0
  479. /package/dist/{src/web/hooks/use-widget-state.test.d.ts → web/hooks/use-display-mode.test-d.d.ts} +0 -0
  480. /package/dist/{src/web/plugin/transform-data-llm.test.d.ts → web/hooks/use-display-mode.test.d.ts} +0 -0
  481. /package/dist/{src/web → web}/plugin/data-llm.test.js +0 -0
  482. /package/dist/{src/web → web}/plugin/transform-data-llm.d.ts +0 -0
  483. /package/dist/{src/web → web}/plugin/transform-data-llm.test.js +0 -0
  484. /package/dist/{src/web → web}/proxy.d.ts +0 -0
package/README.md CHANGED
@@ -1,125 +1,152 @@
1
- <div align="center">
2
-
3
- <img alt="Skybridge" src="docs/static/img/github-banner.png" width="100%">
4
-
5
- <br />
6
-
7
- # Skybridge
8
-
9
- **Build ChatGPT Apps. The Modern TypeScript Way.**
10
-
11
- The fullstack TypeScript framework for ChatGPT Apps.<br />
12
- **Type-safe. React-powered. Zero config.**
13
-
14
- <br />
15
-
16
- [![NPM Version](https://img.shields.io/npm/v/skybridge?color=e90060&style=for-the-badge)](https://www.npmjs.com/package/skybridge)
17
- [![NPM Downloads](https://img.shields.io/npm/dm/skybridge?color=e90060&style=for-the-badge)](https://www.npmjs.com/package/skybridge)
18
- [![GitHub License](https://img.shields.io/github/license/alpic-ai/skybridge?color=e90060&style=for-the-badge)](https://github.com/alpic-ai/skybridge/blob/main/LICENSE)
19
-
20
- <br />
21
-
22
- [Documentation](https://skybridge.tech) · [Quick Start](https://github.com/new?template_name=apps-sdk-template&template_owner=alpic-ai) · [Examples](https://github.com/alpic-ai/apps-sdk-template)
23
-
24
- </div>
25
-
26
- <br />
27
-
28
- ## ✨ Why Skybridge?
29
-
30
- ChatGPT Apps let you embed **rich, interactive UIs** directly in conversations. But the raw SDK is low-level—no hooks, no type safety, no dev tools, and no HMR.
31
-
32
- **Skybridge fixes that.**
33
-
34
- | | |
35
- |:--|:--|
36
- | 👨‍💻 **Full Dev Environment** — HMR, debug traces, and local devtools. No more refresh loops. | ✅ **End-to-End Type Safety** — tRPC-style inference from server to widget. Autocomplete everywhere. |
37
- | 🔄 **Widget-to-Model Sync** — Keep the model aware of UI state with `data-llm`. Dual surfaces, one source of truth. | ⚒️ **React Query-style Hooks** — `isPending`, `isError`, callbacks. State management you already know. |
38
-
39
- <br />
40
-
41
- ## 🚀 Get Started
42
-
43
- **Create a new ChatGPT app:**
44
-
1
+ # Skybridge - the MCP Apps framework
2
+
3
+ <p align="center">
4
+ <a href="https://docs.skybridge.tech">
5
+ <picture>
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/skybridge-readme-banner-dark.png" />
7
+ <img alt="Skybridge, the full-stack React framework for MCP apps and MCP servers" src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/skybridge-readme-banner-light.png" width="100%" />
8
+ </picture>
9
+ </a>
10
+ </p>
11
+
12
+ <p align="center">
13
+ <strong>The full-stack React framework for MCP Apps and MCP Servers.</strong>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://docs.skybridge.tech">Documentation</a> ·
18
+ <a href="https://docs.skybridge.tech/quickstart/create-new-app">Quickstart</a> ·
19
+ <a href="https://github.com/alpic-ai/skybridge/tree/main/examples">Examples</a>
20
+ </p>
21
+
22
+ <p align="center">
23
+ <a href="https://www.npmjs.com/package/skybridge"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/v/skybridge?color=77F5EE&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="npm version" src="https://img.shields.io/npm/v/skybridge?color=E3FAF7&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
24
+ <a href="https://www.npmjs.com/package/skybridge"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/dm/skybridge?color=D7FFC8&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="npm downloads" src="https://img.shields.io/npm/dm/skybridge?color=E8FBD9&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
25
+ <a href="https://discord.com/invite/gNAazGueab"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/badge/Discord-community-77F5EE?style=for-the-badge&amp;logo=discord&amp;logoColor=77F5EE&amp;labelColor=161B22"><img alt="Discord community" src="https://img.shields.io/badge/Discord-community-E3FAF7?style=for-the-badge&amp;logo=discord&amp;logoColor=5865F2&amp;labelColor=F6F8FA"></picture></a>
26
+ <a href="https://github.com/alpic-ai/skybridge/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/license/alpic-ai/skybridge?color=D7FFC8&amp;labelColor=161B22&amp;style=for-the-badge"><img alt="License: MIT" src="https://img.shields.io/github/license/alpic-ai/skybridge?color=E8FBD9&amp;labelColor=F6F8FA&amp;style=for-the-badge"></picture></a>
27
+ </p>
28
+
29
+ ## About Skybridge
30
+
31
+ Skybridge helps developers build type-safe MCP apps for Claude, ChatGPT and other UI-enabled MCP clients, with a complete set of tooling designed for both humans and agents.
32
+
33
+ Why? MCP apps extend the [Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro) with **rich, interactive UI views** rendered from MCP servers. Conversational apps need seamless interaction between the user, the UI, and the model. This means new UX patterns, developer tooling, and abstractions.
34
+ Plus, the raw SDKs are low-level: no hooks, type safety, HMR, etc.
35
+
36
+ That's why we built *Skybridge*.
37
+
38
+ Features include:
39
+
40
+ - **Delightful dev environment**: Skybridge provides a dev server with a local emulator, hot module reload, and a permanent tunnel to connect your local app to Claude and ChatGPT.
41
+ - **Write once, run everywhere**: the framework abstracts implementation differences between MCP clients, so your app runs seamlessly in Claude, ChatGPT, VSCode, and any other MCP apps compatible client.
42
+ - **Agent-ready**: powerful skills, CLI, and programmatic dev tool APIs, everything your coding agent needs to build MCP apps end-to-end.
43
+ - **Type-safe end-to-end**: tRPC-style inference from MCP server tool definition to React view for type safety from server to frontend.
44
+ - **React-first**: Intuitive React Query-style hooks, with advanced state management.
45
+ - **Example library**: get started quickly with ChatGPT- and Claude-ready app examples for ecommerce, travel, SaaS, and more.
46
+
47
+ They chose to build their MCP apps with Skybridge:
48
+
49
+ <p align="center">
50
+ <a href="https://www.datadoghq.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/datadog-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/datadog-light.svg" alt="Datadog" height="24"></picture></a>
51
+ &nbsp;&nbsp;
52
+ <a href="https://bitmovin.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/bitmovin-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/bitmovin-light.svg" alt="Bitmovin" height="22"></picture></a>
53
+ &nbsp;&nbsp;
54
+ <a href="https://www.evaneos.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/evaneos-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/evaneos-light.svg" alt="Evaneos" height="18"></picture></a>
55
+ &nbsp;&nbsp;
56
+ <a href="https://www.touchstream.media"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/touchstream-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/touchstream-light.svg" alt="Touchstream" height="24"></picture></a>
57
+ &nbsp;&nbsp;
58
+ <a href="https://www.cottages.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/cottages-dark.svg"><img src="https://raw.githubusercontent.com/alpic-ai/skybridge/main/docs/images/user-logos/cottages-light.svg" alt="Cottages.com" height="24"></picture></a>
59
+ </p>
60
+
61
+ ## Get started
62
+
63
+ **For agents**
64
+
65
+ Install our [skill](https://docs.skybridge.tech/devtools/skills) for building MCP apps and ChatGPT apps:
45
66
  ```bash
46
- gh repo create my-app --template alpic-ai/apps-sdk-template --clone
47
- cd my-app && pnpm install
67
+ npx skills add alpic-ai/skybridge -s skybridge
48
68
  ```
69
+ Once installed, ask your agent "What skills do you have?" to confirm, then try:
70
+
71
+ - _Create a new MCP app_
72
+ - _Migrate my MCP server to the Skybridge framework_
73
+ - _Add a new view to my MCP app_
49
74
 
50
- **Or add to an existing project:**
75
+ **For humans**
51
76
 
77
+ Bootstrap a new project with:
52
78
  ```bash
53
- npm i skybridge
54
- yarn add skybridge
55
- pnpm add skybridge
56
- bun add skybridge
57
- deno add skybridge
79
+ npm create skybridge@latest my-app
58
80
  ```
81
+ For full install instructions, read our [**Quickstart guide**](https://docs.skybridge.tech/quickstart/create-new-app).
59
82
 
60
- <div align="center">
83
+ ## Documentation
61
84
 
62
- **👉 [Read the Docs](https://skybridge.tech) 👈**
85
+ The [Skybridge documentation](https://docs.skybridge.tech) covers the full lifecycle of building MCP Apps:
63
86
 
64
- </div>
87
+ - [Fundamentals](https://docs.skybridge.tech/fundamentals): understand MCP Apps, ChatGPT Apps, and how Skybridge bridges both runtimes.
88
+ - [Core concepts](https://docs.skybridge.tech/concepts): learn about server <> model <> UI data flows, LLM context sync, type safety, and instant local iteration with our devtools.
89
+ - [Guides](https://docs.skybridge.tech/guides/fetching-data): build real app behavior with tools, views, state, and model communication.
90
+ - [API Reference](https://docs.skybridge.tech/api-reference): browse our MCP server APIs, React hooks, CLI commands, and runtime compatibility.
65
91
 
66
- <br />
92
+ ## Deploy
67
93
 
68
- ## 📦 The Stack
94
+ Deploy Skybridge apps instantly on [Alpic](https://alpic.ai) for scalable hosting, MCP-specific analytics, permanent tunneling, app store compliance auditing and submission help. You can also self-host on any Node.js-compatible platform.
69
95
 
70
- - **`skybridge/server`** — Drop-in MCP SDK replacement with widget registration and type inference.
71
- - **`skybridge/web`** — React hooks and components for ChatGPT's runtime.
96
+ See our [deployment guide](https://docs.skybridge.tech/quickstart/deploy) for the full production path.
72
97
 
73
- ### Server
98
+ ## Community & Contributing
74
99
 
75
- ```ts
76
- import { McpServer } from "skybridge/server";
100
+ We'd love your help improving Skybridge. Here are a few ways to get involved:
77
101
 
78
- server.registerWidget("flights", {}, {
79
- inputSchema: { destination: z.string() },
80
- }, async ({ destination }) => {
81
- const flights = await searchFlights(destination);
82
- return { structuredContent: { flights } };
83
- });
84
- ```
102
+ - **Bugs**: If you run into a bug or unexpected behavior, open a [GitHub Issue](https://github.com/alpic-ai/skybridge/issues) with a clear reproduction.
103
+ - **Questions and ideas**: Need help building with Skybridge or have ideas to improve the framework, docs, examples, or developer experience? [Open an issue](https://github.com/alpic-ai/skybridge/issues) or share them on our [Discord](https://discord.com/invite/gNAazGueab).
104
+ - **Pull requests**: For code or documentation changes, read the [Contributing Guide](https://github.com/alpic-ai/skybridge/blob/main/CONTRIBUTING.md) before opening a PR.
85
105
 
86
- ### Widget
106
+ Skybridge is released under the [MIT License](https://github.com/alpic-ai/skybridge/blob/main/LICENSE).
87
107
 
88
- ```tsx
89
- import { useToolInfo } from "skybridge/web";
108
+ ### Contributors
90
109
 
91
- function FlightsWidget() {
92
- const { output } = useToolInfo();
110
+ Built and maintained with ❤️ by [Harijoe](https://github.com/harijoe), [Fred Barthelet](https://github.com/fredericbarthelet), and the [Alpic](https://alpic.ai) team.
93
111
 
94
- return output.structuredContent.flights.map(f =>
95
- <FlightCard key={f.id} flight={f} />
96
- );
97
- }
98
- ```
112
+ <a href="https://github.com/alpic-ai/skybridge/graphs/contributors">
113
+ <img src="https://contrib.rocks/image?repo=alpic-ai/skybridge" alt="Skybridge contributors">
114
+ </a>
99
115
 
100
- <br />
116
+ ## Example templates
101
117
 
102
- ## 🎯 Features at a Glance
118
+ Explore all our example templates in the [Examples](https://docs.skybridge.tech/examples) section of the documentation.
103
119
 
104
- - **Live Reload** — Vite HMR. See changes instantly without reinstalling.
105
- - **Typed Hooks** — Full autocomplete for tools, inputs, outputs.
106
- - **Widget → Tool Calls** — Trigger server actions from UI.
107
- - **Dual Surface Sync** — Keep model aware of what users see with `data-llm`.
108
- - **React Query-style API** — `isPending`, `isError`, callbacks.
109
- - **MCP Compatible** — Extends the official SDK. Works with any MCP client.
120
+ ### Basic
110
121
 
111
- <br />
122
+ | Preview | App | Description | Demo | Code |
123
+ | --- | --- | --- | --- | --- |
124
+ | <img src="docs/images/showcase-example.png" alt="Everything" width="160" /> | Everything | Comprehensive playground app showcasing all Skybridge hooks and features. | [Try Demo](https://everything.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/everything) |
112
125
 
113
- <div align="center">
126
+ ### Use cases
114
127
 
115
- [![GitHub Discussions](https://img.shields.io/badge/Discussions-Ask%20Questions-blue?style=flat-square&logo=github)](https://github.com/alpic-ai/skybridge/discussions)
116
- [![GitHub Issues](https://img.shields.io/badge/Issues-Report%20Bugs-red?style=flat-square&logo=github)](https://github.com/alpic-ai/skybridge/issues)
117
- [![Discord](https://img.shields.io/badge/Discord-Chat-5865F2?style=flat-square&logo=discord&logoColor=white)](https://discord.com/invite/gNAazGueab)
128
+ | Preview | App | Description | Demo | Code |
129
+ | --- | --- | --- | --- | --- |
130
+ | <img src="docs/images/showcase-capitals.png" alt="Capitals Explorer" width="160" /> | Capitals Explorer | Interactive world map with geolocation, country information, and dynamic capital exploration. | [Try Demo](https://capitals.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/capitals) |
131
+ | <img src="docs/images/showcase-flight-booking.png" alt="Flight Booking" width="160" /> | Flight Booking | Flight search carousel with route details, pricing comparison, and external booking. | [Try Demo](https://flight-booking.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/flight-booking) |
132
+ | <img src="docs/images/showcase-ecommerce.png" alt="Ecommerce Carousel" width="160" /> | Ecommerce Carousel | Product carousel with persistent cart, localization, theme switching, and modal dialogs. | [Try Demo](https://ecommerce.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/ecom-carousel) |
133
+ | <img src="docs/images/showcase-investigation-game.png" alt="Investigation Game" width="160" /> | Investigation Game | Multi-screen mystery game with fullscreen mode, dynamic story progression and context asynchronicity demonstration | [Try Demo](https://investigation-game.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/investigation-game) |
134
+ | <img src="docs/images/showcase-productivity.png" alt="Productivity" width="160" /> | Productivity | Interactive analytics dashboard with charts, theme adaptation, localization, fullscreen mode, and bidirectional tool calls. | [Try Demo](https://productivity.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/productivity) |
135
+ | <img src="docs/images/showcase-times-up.png" alt="Time's Up" width="160" /> | Time's Up | Word-guessing party game where the user gives hints and the AI tries to guess. | [Try Demo](https://times-up.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/times-up) |
136
+ | <img src="docs/images/showcase-lumo.png" alt="Lumo Interactive AI Tutor" width="160" /> | Lumo — Interactive AI Tutor | Adaptive tutor with Mermaid diagrams, mind maps, quizzes, and fill-in-the-blank exercises. | [Try Demo](https://lumo-mcp-app-39519fdd.alpic.live/try) | [View code](https://github.com/connorads/lumo-mcp-app) |
118
137
 
119
- See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions
138
+ ### Auth
120
139
 
121
- <br />
140
+ | Preview | Provider | Description | Code |
141
+ | --- | --- | --- | --- |
142
+ | <img src="docs/images/showcase-clerk.png" alt="Auth Clerk" width="160" /> | Clerk | Full OAuth authentication with Clerk and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-clerk) |
143
+ | <img src="docs/images/showcase-workos.png" alt="Auth WorkOS AuthKit" width="160" /> | WorkOS AuthKit | Full OAuth authentication with WorkOS AuthKit and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-workos) |
144
+ | <img src="docs/images/showcase-stytch.png" alt="Auth Stytch" width="160" /> | Stytch | Full OAuth authentication with Stytch and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-stytch) |
145
+ | <img src="docs/images/showcase-auth0.png" alt="Auth Auth0" width="160" /> | Auth0 | Full OAuth authentication with Auth0 and personalized coffee shop search. | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/auth-auth0) |
122
146
 
123
- **[MIT License](LICENSE)** · Made with ❤️ by **[Alpic](https://alpic.ai)**
147
+ ### UI and component libraries
124
148
 
125
- </div>
149
+ | Preview | App | Description | Demo | Code |
150
+ | --- | --- | --- | --- | --- |
151
+ | <img src="docs/images/showcase-manifest-ui.png" alt="Manifest UI" width="160" /> | Manifest UI | Agentic component library example for rich AI-powered experiences. | [Try Demo](https://manifest-ui.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/manifest-ui) |
152
+ | <img src="docs/images/showcase-generative-ui.png" alt="Generative UI" width="160" /> | Generative UI | LLM-generated dynamic UIs with json-render and 36 pre-built shadcn/ui components. | [Try Demo](https://generative-ui.skybridge.tech/try) | [View code](https://github.com/alpic-ai/skybridge/tree/main/examples/generative-ui) |
package/bin/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execute } from "@oclif/core";
4
+
5
+ await execute({ dir: import.meta.url });
@@ -0,0 +1,5 @@
1
+ export declare const ENTRY_WRAPPER_CONTENT = "import manifest from \"./vite-manifest.js\";\nimport userExport from \"./server.js\";\n\nlet resolved;\nif (userExport && typeof userExport.setViteManifest === \"function\") {\n userExport.setViteManifest(manifest);\n resolved = await userExport.run();\n} else {\n resolved = userExport;\n}\n\nexport default resolved;\n";
2
+ export declare const DEV_ENTRY_CONTENT = "import userExport from \"../src/server.js\";\n\nif (userExport && typeof userExport.run === \"function\") {\n await userExport.run();\n}\n";
3
+ export declare function emitEntryWrapper(distDir: string): void;
4
+ export declare function emitDevEntry(projectRoot: string): void;
5
+ export declare function emitManifestModule(manifestPath: string, outPath: string): void;
@@ -0,0 +1,44 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ // Handles two `dist/server.js` shapes:
4
+ // - new: `export default server` — wrapper sets the manifest and awaits run().
5
+ // - legacy: `export default await server.run()` (pre-wrapper templates) —
6
+ // wrapper passes the value through so existing projects keep booting after
7
+ // a skybridge upgrade without rebuilding.
8
+ export const ENTRY_WRAPPER_CONTENT = `import manifest from "./vite-manifest.js";
9
+ import userExport from "./server.js";
10
+
11
+ let resolved;
12
+ if (userExport && typeof userExport.setViteManifest === "function") {
13
+ userExport.setViteManifest(manifest);
14
+ resolved = await userExport.run();
15
+ } else {
16
+ resolved = userExport;
17
+ }
18
+
19
+ export default resolved;
20
+ `;
21
+ // Dev counterpart to the prod entry wrapper. Skips setViteManifest (Vite
22
+ // middleware serves views in dev) and only calls run() when the user export
23
+ // is still an McpServer instance. Legacy templates that top-level-await
24
+ // run() themselves leave a resolved value here; the typeof guard makes this
25
+ // a no-op for them.
26
+ export const DEV_ENTRY_CONTENT = `import userExport from "../src/server.js";
27
+
28
+ if (userExport && typeof userExport.run === "function") {
29
+ await userExport.run();
30
+ }
31
+ `;
32
+ export function emitEntryWrapper(distDir) {
33
+ writeFileSync(path.join(distDir, "__entry.js"), ENTRY_WRAPPER_CONTENT);
34
+ }
35
+ export function emitDevEntry(projectRoot) {
36
+ const dir = path.join(projectRoot, ".skybridge");
37
+ mkdirSync(dir, { recursive: true });
38
+ writeFileSync(path.join(dir, "dev-entry.ts"), DEV_ENTRY_CONTENT);
39
+ }
40
+ export function emitManifestModule(manifestPath, outPath) {
41
+ const manifest = readFileSync(manifestPath, "utf-8");
42
+ writeFileSync(outPath, `export default ${manifest};\n`);
43
+ }
44
+ //# sourceMappingURL=build-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-helpers.js","sourceRoot":"","sources":["../../src/cli/build-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,uCAAuC;AACvC,+EAA+E;AAC/E,0EAA0E;AAC1E,6EAA6E;AAC7E,4CAA4C;AAC5C,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;CAYpC,CAAC;AAEF,yEAAyE;AACzE,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,oBAAoB;AACpB,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;CAKhC,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,qBAAqB,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACjD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,YAAoB,EACpB,OAAe;IAEf,MAAM,QAAQ,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACrD,aAAa,CAAC,OAAO,EAAE,kBAAkB,QAAQ,KAAK,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n// Handles two `dist/server.js` shapes:\n// - new: `export default server` — wrapper sets the manifest and awaits run().\n// - legacy: `export default await server.run()` (pre-wrapper templates) —\n// wrapper passes the value through so existing projects keep booting after\n// a skybridge upgrade without rebuilding.\nexport const ENTRY_WRAPPER_CONTENT = `import manifest from \"./vite-manifest.js\";\nimport userExport from \"./server.js\";\n\nlet resolved;\nif (userExport && typeof userExport.setViteManifest === \"function\") {\n userExport.setViteManifest(manifest);\n resolved = await userExport.run();\n} else {\n resolved = userExport;\n}\n\nexport default resolved;\n`;\n\n// Dev counterpart to the prod entry wrapper. Skips setViteManifest (Vite\n// middleware serves views in dev) and only calls run() when the user export\n// is still an McpServer instance. Legacy templates that top-level-await\n// run() themselves leave a resolved value here; the typeof guard makes this\n// a no-op for them.\nexport const DEV_ENTRY_CONTENT = `import userExport from \"../src/server.js\";\n\nif (userExport && typeof userExport.run === \"function\") {\n await userExport.run();\n}\n`;\n\nexport function emitEntryWrapper(distDir: string): void {\n writeFileSync(path.join(distDir, \"__entry.js\"), ENTRY_WRAPPER_CONTENT);\n}\n\nexport function emitDevEntry(projectRoot: string): void {\n const dir = path.join(projectRoot, \".skybridge\");\n mkdirSync(dir, { recursive: true });\n writeFileSync(path.join(dir, \"dev-entry.ts\"), DEV_ENTRY_CONTENT);\n}\n\nexport function emitManifestModule(\n manifestPath: string,\n outPath: string,\n): void {\n const manifest = readFileSync(manifestPath, \"utf-8\");\n writeFileSync(outPath, `export default ${manifest};\\n`);\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { mkdtempSync, readFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import path from "node:path";
4
+ import { describe, expect, it } from "vitest";
5
+ import { DEV_ENTRY_CONTENT, ENTRY_WRAPPER_CONTENT, emitDevEntry, emitEntryWrapper, } from "./build-helpers.js";
6
+ function mkTmp(prefix = "skybridge-build-helpers-") {
7
+ return mkdtempSync(path.join(tmpdir(), prefix));
8
+ }
9
+ describe("emitEntryWrapper", () => {
10
+ it("writes dist/__entry.js with backward-compatible manifest + run() wiring", () => {
11
+ const dir = mkTmp();
12
+ emitEntryWrapper(dir);
13
+ const out = readFileSync(path.join(dir, "__entry.js"), "utf-8");
14
+ expect(out).toBe(ENTRY_WRAPPER_CONTENT);
15
+ expect(out).toContain('import manifest from "./vite-manifest.js"');
16
+ expect(out).toContain('import userExport from "./server.js"');
17
+ expect(out).toContain('typeof userExport.setViteManifest === "function"');
18
+ expect(out).toContain("userExport.setViteManifest(manifest)");
19
+ expect(out).toContain("await userExport.run()");
20
+ expect(out).toContain("export default resolved");
21
+ });
22
+ });
23
+ describe("emitDevEntry", () => {
24
+ it("writes .skybridge/dev-entry.ts that conditionally awaits run()", () => {
25
+ const root = mkTmp();
26
+ emitDevEntry(root);
27
+ const out = readFileSync(path.join(root, ".skybridge", "dev-entry.ts"), "utf-8");
28
+ expect(out).toBe(DEV_ENTRY_CONTENT);
29
+ expect(out).toContain('import userExport from "../src/server.js"');
30
+ expect(out).toContain('typeof userExport.run === "function"');
31
+ expect(out).toContain("await userExport.run()");
32
+ });
33
+ });
34
+ //# sourceMappingURL=build-helpers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-helpers.test.js","sourceRoot":"","sources":["../../src/cli/build-helpers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,SAAS,KAAK,CAAC,MAAM,GAAG,0BAA0B;IAChD,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC;QACpB,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,2CAA2C,CAAC,CAAC;QACnE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,kDAAkD,CAAC,CAAC;QAC1E,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC;QACrB,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,GAAG,GAAG,YAAY,CACtB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC,EAC7C,OAAO,CACR,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,2CAA2C,CAAC,CAAC;QACnE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { mkdtempSync, readFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport {\n DEV_ENTRY_CONTENT,\n ENTRY_WRAPPER_CONTENT,\n emitDevEntry,\n emitEntryWrapper,\n} from \"./build-helpers.js\";\n\nfunction mkTmp(prefix = \"skybridge-build-helpers-\") {\n return mkdtempSync(path.join(tmpdir(), prefix));\n}\n\ndescribe(\"emitEntryWrapper\", () => {\n it(\"writes dist/__entry.js with backward-compatible manifest + run() wiring\", () => {\n const dir = mkTmp();\n emitEntryWrapper(dir);\n const out = readFileSync(path.join(dir, \"__entry.js\"), \"utf-8\");\n expect(out).toBe(ENTRY_WRAPPER_CONTENT);\n expect(out).toContain('import manifest from \"./vite-manifest.js\"');\n expect(out).toContain('import userExport from \"./server.js\"');\n expect(out).toContain('typeof userExport.setViteManifest === \"function\"');\n expect(out).toContain(\"userExport.setViteManifest(manifest)\");\n expect(out).toContain(\"await userExport.run()\");\n expect(out).toContain(\"export default resolved\");\n });\n});\n\ndescribe(\"emitDevEntry\", () => {\n it(\"writes .skybridge/dev-entry.ts that conditionally awaits run()\", () => {\n const root = mkTmp();\n emitDevEntry(root);\n const out = readFileSync(\n path.join(root, \".skybridge\", \"dev-entry.ts\"),\n \"utf-8\",\n );\n expect(out).toBe(DEV_ENTRY_CONTENT);\n expect(out).toContain('import userExport from \"../src/server.js\"');\n expect(out).toContain('typeof userExport.run === \"function\"');\n expect(out).toContain(\"await userExport.run()\");\n });\n});\n"]}
@@ -0,0 +1,18 @@
1
+ export declare function resolvePort(flagPort?: number): Promise<{
2
+ port: number;
3
+ fallback: boolean;
4
+ envWarning?: undefined;
5
+ } | {
6
+ port: number;
7
+ fallback: boolean;
8
+ envWarning: string;
9
+ }>;
10
+ /**
11
+ * Returns the given port if available, otherwise lets the OS
12
+ * pick a free port via `listen(0)`.
13
+ *
14
+ * @param host - Bind address for the check. Pass `"localhost"` for
15
+ * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
16
+ * services that bind to all interfaces (e.g. the HTTP server).
17
+ */
18
+ export declare function detectAvailablePort(startPort: number, host?: string): Promise<number>;
@@ -0,0 +1,61 @@
1
+ import net from "node:net";
2
+ const DEFAULT_PORT = 3000;
3
+ export async function resolvePort(flagPort) {
4
+ if (flagPort && flagPort > 1) {
5
+ return { port: flagPort, fallback: false };
6
+ }
7
+ const rawEnv = process.env.PORT;
8
+ if (rawEnv) {
9
+ const parsed = Number(rawEnv);
10
+ if (Number.isInteger(parsed) && parsed > 0) {
11
+ return { port: parsed, fallback: false };
12
+ }
13
+ return {
14
+ port: await detectAvailablePort(DEFAULT_PORT),
15
+ fallback: false,
16
+ envWarning: `Invalid PORT="${rawEnv}", ignoring and using default`,
17
+ };
18
+ }
19
+ const port = await detectAvailablePort(DEFAULT_PORT);
20
+ return { port, fallback: port !== DEFAULT_PORT };
21
+ }
22
+ /**
23
+ * Returns the given port if available, otherwise lets the OS
24
+ * pick a free port via `listen(0)`.
25
+ *
26
+ * @param host - Bind address for the check. Pass `"localhost"` for
27
+ * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
28
+ * services that bind to all interfaces (e.g. the HTTP server).
29
+ */
30
+ export async function detectAvailablePort(startPort, host) {
31
+ const available = await isPortAvailable(startPort, host);
32
+ if (available) {
33
+ return startPort;
34
+ }
35
+ return new Promise((resolve, reject) => {
36
+ const server = net.createServer();
37
+ server.once("error", reject);
38
+ server.once("listening", () => {
39
+ const addr = server.address();
40
+ if (addr && typeof addr === "object") {
41
+ const { port } = addr;
42
+ server.close(() => resolve(port));
43
+ }
44
+ else {
45
+ server.close(() => reject(new Error("Failed to detect available port")));
46
+ }
47
+ });
48
+ server.listen(0, host);
49
+ });
50
+ }
51
+ function isPortAvailable(port, host) {
52
+ return new Promise((resolve) => {
53
+ const server = net.createServer();
54
+ server.once("error", () => resolve(false));
55
+ server.once("listening", () => {
56
+ server.close(() => resolve(true));
57
+ });
58
+ server.listen(port, host);
59
+ });
60
+ }
61
+ //# sourceMappingURL=detect-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-port.js","sourceRoot":"","sources":["../../src/cli/detect-port.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAiB;IACjD,IAAI,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM,mBAAmB,CAAC,YAAY,CAAC;YAC7C,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,iBAAiB,MAAM,+BAA+B;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,IAAa;IAEb,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;gBACtB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAChB,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CACrD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,IAAa;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import net from \"node:net\";\n\nconst DEFAULT_PORT = 3000;\n\nexport async function resolvePort(flagPort?: number) {\n if (flagPort && flagPort > 1) {\n return { port: flagPort, fallback: false };\n }\n\n const rawEnv = process.env.PORT;\n if (rawEnv) {\n const parsed = Number(rawEnv);\n if (Number.isInteger(parsed) && parsed > 0) {\n return { port: parsed, fallback: false };\n }\n return {\n port: await detectAvailablePort(DEFAULT_PORT),\n fallback: false,\n envWarning: `Invalid PORT=\"${rawEnv}\", ignoring and using default`,\n };\n }\n\n const port = await detectAvailablePort(DEFAULT_PORT);\n return { port, fallback: port !== DEFAULT_PORT };\n}\n\n/**\n * Returns the given port if available, otherwise lets the OS\n * pick a free port via `listen(0)`.\n *\n * @param host - Bind address for the check. Pass `\"localhost\"` for\n * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for\n * services that bind to all interfaces (e.g. the HTTP server).\n */\nexport async function detectAvailablePort(\n startPort: number,\n host?: string,\n): Promise<number> {\n const available = await isPortAvailable(startPort, host);\n if (available) {\n return startPort;\n }\n\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n\n server.once(\"error\", reject);\n server.once(\"listening\", () => {\n const addr = server.address();\n if (addr && typeof addr === \"object\") {\n const { port } = addr;\n server.close(() => resolve(port));\n } else {\n server.close(() =>\n reject(new Error(\"Failed to detect available port\")),\n );\n }\n });\n\n server.listen(0, host);\n });\n}\n\nfunction isPortAvailable(port: number, host?: string): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n\n server.listen(port, host);\n });\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export declare const Header: ({ version, children, }: {
2
+ version: string;
3
+ children?: React.ReactNode;
4
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ export const Header = ({ version, children, }) => {
4
+ return (_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: "cyan", bold: true, children: ["\u26F0", " ", "Skybridge"] }), _jsxs(Text, { color: "cyan", children: [" v", version] }), children] }));
5
+ };
6
+ //# sourceMappingURL=header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/cli/header.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EACrB,OAAO,EACP,QAAQ,GAIT,EAAE,EAAE;IACH,OAAO,CACL,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,6BACnB,IAAI,iBACD,EACP,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,mBAAI,OAAO,IAAQ,EACpC,QAAQ,IACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { Box, Text } from \"ink\";\n\nexport const Header = ({\n version,\n children,\n}: {\n version: string;\n children?: React.ReactNode;\n}) => {\n return (\n <Box marginBottom={1}>\n <Text color=\"cyan\" bold>\n ⛰{\" \"}Skybridge\n </Text>\n <Text color=\"cyan\"> v{version}</Text>\n {children}\n </Box>\n );\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare function resolveViewsDir(root: string): Promise<string | undefined>;
@@ -0,0 +1,17 @@
1
+ export async function resolveViewsDir(root) {
2
+ const { loadConfigFromFile } = await import("vite");
3
+ const loaded = await loadConfigFromFile({ command: "build", mode: "production" }, undefined, root);
4
+ const isPluginCandidate = (value) => typeof value === "object" && value !== null;
5
+ const plugins = [];
6
+ const walk = (value) => {
7
+ if (Array.isArray(value)) {
8
+ value.forEach(walk);
9
+ }
10
+ else if (isPluginCandidate(value)) {
11
+ plugins.push(value);
12
+ }
13
+ };
14
+ walk(loaded?.config.plugins ?? []);
15
+ return plugins.find((p) => p.name === "skybridge")?.api?.viewsDir;
16
+ }
17
+ //# sourceMappingURL=resolve-views-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-views-dir.js","sourceRoot":"","sources":["../../src/cli/resolve-views-dir.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY;IAEZ,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EACxC,SAAS,EACT,IAAI,CACL,CAAC;IAEF,MAAM,iBAAiB,GAAG,CACxB,KAAc,EAC2C,EAAE,CAC3D,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;IAE9C,MAAM,OAAO,GAA0D,EAAE,CAAC;IAC1E,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;QAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC;AACpE,CAAC","sourcesContent":["export async function resolveViewsDir(\n root: string,\n): 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"]}
@@ -0,0 +1,2 @@
1
+ import { type SpawnOptions } from "node:child_process";
2
+ export declare function runCommand(command: string, options?: SpawnOptions): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import { spawn } from "node:child_process";
2
+ export function runCommand(command, options = {
3
+ stdio: ["ignore", "inherit", "inherit"],
4
+ }) {
5
+ return new Promise((resolve, reject) => {
6
+ const stdoutChunks = [];
7
+ const stderrChunks = [];
8
+ const proc = spawn(command, {
9
+ ...options,
10
+ shell: true,
11
+ });
12
+ if (proc.stdout) {
13
+ proc.stdout.on("data", (chunk) => {
14
+ stdoutChunks.push(chunk);
15
+ });
16
+ }
17
+ if (proc.stderr) {
18
+ proc.stderr.on("data", (chunk) => {
19
+ stderrChunks.push(chunk);
20
+ });
21
+ }
22
+ proc.on("close", (code) => {
23
+ if (code === 0) {
24
+ resolve();
25
+ }
26
+ else {
27
+ const stdoutOutput = Buffer.concat(stdoutChunks).toString();
28
+ const stderrOutput = Buffer.concat(stderrChunks).toString();
29
+ const allOutput = [stdoutOutput, stderrOutput]
30
+ .filter((output) => output.trim())
31
+ .join("\n");
32
+ const errorMessage = allOutput
33
+ ? `Command failed with exit code ${code}\n${allOutput}`
34
+ : `Command failed with exit code ${code}`;
35
+ reject(new Error(errorMessage));
36
+ }
37
+ });
38
+ proc.on("error", (error) => {
39
+ reject(error);
40
+ });
41
+ });
42
+ }
43
+ //# sourceMappingURL=run-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/cli/run-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE9D,MAAM,UAAU,UAAU,CACxB,OAAe,EACf,UAAwB;IACtB,KAAK,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC;CACxC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE;YAC1B,GAAG,OAAO;YACV,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC/B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC/B,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC5D,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAC5D,MAAM,SAAS,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC;qBAC3C,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;qBACjC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,MAAM,YAAY,GAAG,SAAS;oBAC5B,CAAC,CAAC,iCAAiC,IAAI,KAAK,SAAS,EAAE;oBACvD,CAAC,CAAC,iCAAiC,IAAI,EAAE,CAAC;gBAC5C,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACzB,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { type SpawnOptions, spawn } from \"node:child_process\";\n\nexport function runCommand(\n command: string,\n options: SpawnOptions = {\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n },\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const stdoutChunks: Buffer[] = [];\n const stderrChunks: Buffer[] = [];\n\n const proc = spawn(command, {\n ...options,\n shell: true,\n });\n\n if (proc.stdout) {\n proc.stdout.on(\"data\", (chunk) => {\n stdoutChunks.push(chunk);\n });\n }\n\n if (proc.stderr) {\n proc.stderr.on(\"data\", (chunk) => {\n stderrChunks.push(chunk);\n });\n }\n\n proc.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n const stdoutOutput = Buffer.concat(stdoutChunks).toString();\n const stderrOutput = Buffer.concat(stderrChunks).toString();\n const allOutput = [stdoutOutput, stderrOutput]\n .filter((output) => output.trim())\n .join(\"\\n\");\n const errorMessage = allOutput\n ? `Command failed with exit code ${code}\\n${allOutput}`\n : `Command failed with exit code ${code}`;\n reject(new Error(errorMessage));\n }\n });\n\n proc.on(\"error\", (error) => {\n reject(error);\n });\n });\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { Hook } from "@oclif/core";
2
+ export declare function isEnabled(): boolean;
3
+ export declare function isDebugMode(): boolean;
4
+ export declare function setEnabled(enabled: boolean): void;
5
+ export declare function getMachineId(): string;
6
+ declare const hook: Hook<"finally">;
7
+ export default hook;