@vibesdotdev/applets 0.0.0-stage → 1.0.0-rc.3

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 (421) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +43 -2
  3. package/dist/applet-gate.d.ts +47 -0
  4. package/dist/applet-gate.d.ts.map +1 -0
  5. package/dist/applet-gate.js +167 -0
  6. package/dist/applet-gate.js.map +1 -0
  7. package/dist/applet-root-surface.d.ts +135 -0
  8. package/dist/applet-root-surface.d.ts.map +1 -0
  9. package/dist/applet-root-surface.js +222 -0
  10. package/dist/applet-root-surface.js.map +1 -0
  11. package/dist/applet-value-bound.d.ts +24 -0
  12. package/dist/applet-value-bound.d.ts.map +1 -0
  13. package/dist/applet-value-bound.js +46 -0
  14. package/dist/applet-value-bound.js.map +1 -0
  15. package/dist/applets.cloud.plugin.d.ts +4 -0
  16. package/dist/applets.cloud.plugin.d.ts.map +1 -0
  17. package/dist/applets.cloud.plugin.js +11 -0
  18. package/dist/applets.cloud.plugin.js.map +1 -0
  19. package/dist/applets.consumer.plugin.d.ts +4 -0
  20. package/dist/applets.consumer.plugin.d.ts.map +1 -0
  21. package/dist/applets.consumer.plugin.js +11 -0
  22. package/dist/applets.consumer.plugin.js.map +1 -0
  23. package/dist/applets.plugin.d.ts +3 -0
  24. package/dist/applets.plugin.d.ts.map +1 -0
  25. package/dist/applets.plugin.js +30 -0
  26. package/dist/applets.plugin.js.map +1 -0
  27. package/dist/authorization.d.ts +87 -0
  28. package/dist/authorization.d.ts.map +1 -0
  29. package/dist/authorization.js +189 -0
  30. package/dist/authorization.js.map +1 -0
  31. package/dist/browser-runtime.d.ts +34 -0
  32. package/dist/browser-runtime.d.ts.map +1 -0
  33. package/dist/browser-runtime.js +5 -0
  34. package/dist/browser-runtime.js.map +1 -0
  35. package/dist/build-definition.d.ts +34 -0
  36. package/dist/build-definition.d.ts.map +1 -0
  37. package/dist/build-definition.js +44 -0
  38. package/dist/build-definition.js.map +1 -0
  39. package/dist/capabilities/capability.kind.d.ts +44 -0
  40. package/dist/capabilities/capability.kind.d.ts.map +1 -0
  41. package/dist/capabilities/capability.kind.js +17 -0
  42. package/dist/capabilities/capability.kind.js.map +1 -0
  43. package/dist/capabilities/runtime-dispatch.d.ts +9 -0
  44. package/dist/capabilities/runtime-dispatch.d.ts.map +1 -0
  45. package/dist/capabilities/runtime-dispatch.js +62 -0
  46. package/dist/capabilities/runtime-dispatch.js.map +1 -0
  47. package/dist/cli/applet-group.descriptor.d.ts +11 -0
  48. package/dist/cli/applet-group.descriptor.d.ts.map +1 -0
  49. package/dist/cli/applet-group.descriptor.js +19 -0
  50. package/dist/cli/applet-group.descriptor.js.map +1 -0
  51. package/dist/cli/applet-local-store.storage.descriptor.d.ts +66 -0
  52. package/dist/cli/applet-local-store.storage.descriptor.d.ts.map +1 -0
  53. package/dist/cli/applet-local-store.storage.descriptor.js +39 -0
  54. package/dist/cli/applet-local-store.storage.descriptor.js.map +1 -0
  55. package/dist/cli/applet-serve.process.descriptor.d.ts +37 -0
  56. package/dist/cli/applet-serve.process.descriptor.d.ts.map +1 -0
  57. package/dist/cli/applet-serve.process.descriptor.js +41 -0
  58. package/dist/cli/applet-serve.process.descriptor.js.map +1 -0
  59. package/dist/cli/commands/build.command.descriptor.d.ts +40 -0
  60. package/dist/cli/commands/build.command.descriptor.d.ts.map +1 -0
  61. package/dist/cli/commands/build.command.descriptor.js +52 -0
  62. package/dist/cli/commands/build.command.descriptor.js.map +1 -0
  63. package/dist/cli/commands/build.command.impl.d.ts +8 -0
  64. package/dist/cli/commands/build.command.impl.d.ts.map +1 -0
  65. package/dist/cli/commands/build.command.impl.js +116 -0
  66. package/dist/cli/commands/build.command.impl.js.map +1 -0
  67. package/dist/cli/commands/init.command.descriptor.d.ts +29 -0
  68. package/dist/cli/commands/init.command.descriptor.d.ts.map +1 -0
  69. package/dist/cli/commands/init.command.descriptor.js +23 -0
  70. package/dist/cli/commands/init.command.descriptor.js.map +1 -0
  71. package/dist/cli/commands/init.command.impl.d.ts +7 -0
  72. package/dist/cli/commands/init.command.impl.d.ts.map +1 -0
  73. package/dist/cli/commands/init.command.impl.js +64 -0
  74. package/dist/cli/commands/init.command.impl.js.map +1 -0
  75. package/dist/cli/commands/list.command.descriptor.d.ts +26 -0
  76. package/dist/cli/commands/list.command.descriptor.d.ts.map +1 -0
  77. package/dist/cli/commands/list.command.descriptor.js +22 -0
  78. package/dist/cli/commands/list.command.descriptor.js.map +1 -0
  79. package/dist/cli/commands/list.command.impl.d.ts +13 -0
  80. package/dist/cli/commands/list.command.impl.d.ts.map +1 -0
  81. package/dist/cli/commands/list.command.impl.js +47 -0
  82. package/dist/cli/commands/list.command.impl.js.map +1 -0
  83. package/dist/cli/commands/serve-stylesheet.d.ts +11 -0
  84. package/dist/cli/commands/serve-stylesheet.d.ts.map +1 -0
  85. package/dist/cli/commands/serve-stylesheet.js +50 -0
  86. package/dist/cli/commands/serve-stylesheet.js.map +1 -0
  87. package/dist/cli/commands/serve-surface.d.ts +36 -0
  88. package/dist/cli/commands/serve-surface.d.ts.map +1 -0
  89. package/dist/cli/commands/serve-surface.js +410 -0
  90. package/dist/cli/commands/serve-surface.js.map +1 -0
  91. package/dist/cli/commands/serve.command.descriptor.d.ts +42 -0
  92. package/dist/cli/commands/serve.command.descriptor.d.ts.map +1 -0
  93. package/dist/cli/commands/serve.command.descriptor.js +46 -0
  94. package/dist/cli/commands/serve.command.descriptor.js.map +1 -0
  95. package/dist/cli/commands/serve.command.impl.d.ts +110 -0
  96. package/dist/cli/commands/serve.command.impl.d.ts.map +1 -0
  97. package/dist/cli/commands/serve.command.impl.js +1105 -0
  98. package/dist/cli/commands/serve.command.impl.js.map +1 -0
  99. package/dist/cli/commands/serve.schemas.d.ts +127 -0
  100. package/dist/cli/commands/serve.schemas.d.ts.map +1 -0
  101. package/dist/cli/commands/serve.schemas.js +85 -0
  102. package/dist/cli/commands/serve.schemas.js.map +1 -0
  103. package/dist/cli/commands/served-applet-browser.d.ts +12 -0
  104. package/dist/cli/commands/served-applet-browser.d.ts.map +1 -0
  105. package/dist/cli/commands/served-applet-browser.js +48 -0
  106. package/dist/cli/commands/served-applet-browser.js.map +1 -0
  107. package/dist/cli/commands/served-applet-connection.d.ts +15 -0
  108. package/dist/cli/commands/served-applet-connection.d.ts.map +1 -0
  109. package/dist/cli/commands/served-applet-connection.js +25 -0
  110. package/dist/cli/commands/served-applet-connection.js.map +1 -0
  111. package/dist/cli/commands/served-applet-rpc.d.ts +16 -0
  112. package/dist/cli/commands/served-applet-rpc.d.ts.map +1 -0
  113. package/dist/cli/commands/served-applet-rpc.js +108 -0
  114. package/dist/cli/commands/served-applet-rpc.js.map +1 -0
  115. package/dist/cli/commands/served-applet-surface.d.ts +14 -0
  116. package/dist/cli/commands/served-applet-surface.d.ts.map +1 -0
  117. package/dist/cli/commands/served-applet-surface.js +99 -0
  118. package/dist/cli/commands/served-applet-surface.js.map +1 -0
  119. package/dist/cli/commands/templates.command.descriptor.d.ts +22 -0
  120. package/dist/cli/commands/templates.command.descriptor.d.ts.map +1 -0
  121. package/dist/cli/commands/templates.command.descriptor.js +21 -0
  122. package/dist/cli/commands/templates.command.descriptor.js.map +1 -0
  123. package/dist/cli/commands/templates.command.impl.d.ts +35 -0
  124. package/dist/cli/commands/templates.command.impl.d.ts.map +1 -0
  125. package/dist/cli/commands/templates.command.impl.js +59 -0
  126. package/dist/cli/commands/templates.command.impl.js.map +1 -0
  127. package/dist/cli/index.d.ts +7 -0
  128. package/dist/cli/index.d.ts.map +1 -0
  129. package/dist/cli/index.js +7 -0
  130. package/dist/cli/index.js.map +1 -0
  131. package/dist/cli/local-serve.authz-policy.descriptor.d.ts +22 -0
  132. package/dist/cli/local-serve.authz-policy.descriptor.d.ts.map +1 -0
  133. package/dist/cli/local-serve.authz-policy.descriptor.js +13 -0
  134. package/dist/cli/local-serve.authz-policy.descriptor.js.map +1 -0
  135. package/dist/cli/plugin.d.ts +19 -0
  136. package/dist/cli/plugin.d.ts.map +1 -0
  137. package/dist/cli/plugin.js +57 -0
  138. package/dist/cli/plugin.js.map +1 -0
  139. package/dist/cli/project-files.d.ts +48 -0
  140. package/dist/cli/project-files.d.ts.map +1 -0
  141. package/dist/cli/project-files.js +130 -0
  142. package/dist/cli/project-files.js.map +1 -0
  143. package/dist/client/contract.d.ts +113 -0
  144. package/dist/client/contract.d.ts.map +1 -0
  145. package/dist/client/contract.js +17 -0
  146. package/dist/client/contract.js.map +1 -0
  147. package/dist/client/index.d.ts +3 -0
  148. package/dist/client/index.d.ts.map +1 -0
  149. package/dist/client/index.js +3 -0
  150. package/dist/client/index.js.map +1 -0
  151. package/dist/client/repository.context.d.ts +113 -0
  152. package/dist/client/repository.context.d.ts.map +1 -0
  153. package/dist/client/repository.context.js +8 -0
  154. package/dist/client/repository.context.js.map +1 -0
  155. package/dist/client/runtime-client.d.ts +22 -0
  156. package/dist/client/runtime-client.d.ts.map +1 -0
  157. package/dist/client/runtime-client.js +200 -0
  158. package/dist/client/runtime-client.js.map +1 -0
  159. package/dist/companion-path.d.ts +25 -0
  160. package/dist/companion-path.d.ts.map +1 -0
  161. package/dist/companion-path.js +90 -0
  162. package/dist/companion-path.js.map +1 -0
  163. package/dist/component-ref.d.ts +12 -0
  164. package/dist/component-ref.d.ts.map +1 -0
  165. package/dist/component-ref.js +45 -0
  166. package/dist/component-ref.js.map +1 -0
  167. package/dist/composition-plan.d.ts +92 -0
  168. package/dist/composition-plan.d.ts.map +1 -0
  169. package/dist/composition-plan.js +44 -0
  170. package/dist/composition-plan.js.map +1 -0
  171. package/dist/composition.d.ts +97 -0
  172. package/dist/composition.d.ts.map +1 -0
  173. package/dist/composition.js +99 -0
  174. package/dist/composition.js.map +1 -0
  175. package/dist/config/applets.config.descriptor.d.ts +55 -0
  176. package/dist/config/applets.config.descriptor.d.ts.map +1 -0
  177. package/dist/config/applets.config.descriptor.js +37 -0
  178. package/dist/config/applets.config.descriptor.js.map +1 -0
  179. package/dist/config/load.d.ts +4 -0
  180. package/dist/config/load.d.ts.map +1 -0
  181. package/dist/config/load.js +12 -0
  182. package/dist/config/load.js.map +1 -0
  183. package/dist/content-path.d.ts +62 -0
  184. package/dist/content-path.d.ts.map +1 -0
  185. package/dist/content-path.js +121 -0
  186. package/dist/content-path.js.map +1 -0
  187. package/dist/contribution-registry.d.ts +270 -0
  188. package/dist/contribution-registry.d.ts.map +1 -0
  189. package/dist/contribution-registry.js +488 -0
  190. package/dist/contribution-registry.js.map +1 -0
  191. package/dist/docs/applets.docs.descriptor.d.ts +4 -0
  192. package/dist/docs/applets.docs.descriptor.d.ts.map +1 -0
  193. package/dist/docs/applets.docs.descriptor.js +74 -0
  194. package/dist/docs/applets.docs.descriptor.js.map +1 -0
  195. package/dist/host/local-host.contract.d.ts +7 -0
  196. package/dist/host/local-host.contract.d.ts.map +1 -0
  197. package/dist/host/local-host.contract.js +2 -0
  198. package/dist/host/local-host.contract.js.map +1 -0
  199. package/dist/host/local-host.impl.d.ts +9 -0
  200. package/dist/host/local-host.impl.d.ts.map +1 -0
  201. package/dist/host/local-host.impl.js +41 -0
  202. package/dist/host/local-host.impl.js.map +1 -0
  203. package/dist/host/local-host.plugin.d.ts +3 -0
  204. package/dist/host/local-host.plugin.d.ts.map +1 -0
  205. package/dist/host/local-host.plugin.js +16 -0
  206. package/dist/host/local-host.plugin.js.map +1 -0
  207. package/dist/index.d.ts +28 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +27 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/local-project.d.ts +106 -0
  212. package/dist/local-project.d.ts.map +1 -0
  213. package/dist/local-project.js +277 -0
  214. package/dist/local-project.js.map +1 -0
  215. package/dist/manifest-hash.d.ts +12 -0
  216. package/dist/manifest-hash.d.ts.map +1 -0
  217. package/dist/manifest-hash.js +76 -0
  218. package/dist/manifest-hash.js.map +1 -0
  219. package/dist/presentation.d.ts +43 -0
  220. package/dist/presentation.d.ts.map +1 -0
  221. package/dist/presentation.js +36 -0
  222. package/dist/presentation.js.map +1 -0
  223. package/dist/retention.d.ts +34 -0
  224. package/dist/retention.d.ts.map +1 -0
  225. package/dist/retention.js +51 -0
  226. package/dist/retention.js.map +1 -0
  227. package/dist/schemas/applet-messages.d.ts +97 -0
  228. package/dist/schemas/applet-messages.d.ts.map +1 -0
  229. package/dist/schemas/applet-messages.js +51 -0
  230. package/dist/schemas/applet-messages.js.map +1 -0
  231. package/dist/schemas/capabilities.d.ts +37 -0
  232. package/dist/schemas/capabilities.d.ts.map +1 -0
  233. package/dist/schemas/capabilities.js +28 -0
  234. package/dist/schemas/capabilities.js.map +1 -0
  235. package/dist/schemas/component-release-ref.d.ts +13 -0
  236. package/dist/schemas/component-release-ref.d.ts.map +1 -0
  237. package/dist/schemas/component-release-ref.js +21 -0
  238. package/dist/schemas/component-release-ref.js.map +1 -0
  239. package/dist/schemas/contributes.d.ts +306 -0
  240. package/dist/schemas/contributes.d.ts.map +1 -0
  241. package/dist/schemas/contributes.js +184 -0
  242. package/dist/schemas/contributes.js.map +1 -0
  243. package/dist/schemas/definition.d.ts +301 -0
  244. package/dist/schemas/definition.d.ts.map +1 -0
  245. package/dist/schemas/definition.js +457 -0
  246. package/dist/schemas/definition.js.map +1 -0
  247. package/dist/schemas/dispatch.d.ts +52 -0
  248. package/dist/schemas/dispatch.d.ts.map +1 -0
  249. package/dist/schemas/dispatch.js +32 -0
  250. package/dist/schemas/dispatch.js.map +1 -0
  251. package/dist/schemas/grants.d.ts +56 -0
  252. package/dist/schemas/grants.d.ts.map +1 -0
  253. package/dist/schemas/grants.js +64 -0
  254. package/dist/schemas/grants.js.map +1 -0
  255. package/dist/schemas/index.d.ts +16 -0
  256. package/dist/schemas/index.d.ts.map +1 -0
  257. package/dist/schemas/index.js +16 -0
  258. package/dist/schemas/index.js.map +1 -0
  259. package/dist/schemas/instance.d.ts +230 -0
  260. package/dist/schemas/instance.d.ts.map +1 -0
  261. package/dist/schemas/instance.js +44 -0
  262. package/dist/schemas/instance.js.map +1 -0
  263. package/dist/schemas/lineage.d.ts +60 -0
  264. package/dist/schemas/lineage.d.ts.map +1 -0
  265. package/dist/schemas/lineage.js +52 -0
  266. package/dist/schemas/lineage.js.map +1 -0
  267. package/dist/schemas/observation.d.ts +70 -0
  268. package/dist/schemas/observation.d.ts.map +1 -0
  269. package/dist/schemas/observation.js +49 -0
  270. package/dist/schemas/observation.js.map +1 -0
  271. package/dist/schemas/patterns.d.ts +24 -0
  272. package/dist/schemas/patterns.d.ts.map +1 -0
  273. package/dist/schemas/patterns.js +24 -0
  274. package/dist/schemas/patterns.js.map +1 -0
  275. package/dist/schemas/publishing.d.ts +27 -0
  276. package/dist/schemas/publishing.d.ts.map +1 -0
  277. package/dist/schemas/publishing.js +20 -0
  278. package/dist/schemas/publishing.js.map +1 -0
  279. package/dist/schemas/run.d.ts +35 -0
  280. package/dist/schemas/run.d.ts.map +1 -0
  281. package/dist/schemas/run.js +26 -0
  282. package/dist/schemas/run.js.map +1 -0
  283. package/dist/schemas/share-link.d.ts +61 -0
  284. package/dist/schemas/share-link.d.ts.map +1 -0
  285. package/dist/schemas/share-link.js +68 -0
  286. package/dist/schemas/share-link.js.map +1 -0
  287. package/dist/schemas/state-events.d.ts +66 -0
  288. package/dist/schemas/state-events.d.ts.map +1 -0
  289. package/dist/schemas/state-events.js +66 -0
  290. package/dist/schemas/state-events.js.map +1 -0
  291. package/dist/schemas/subscription.d.ts +47 -0
  292. package/dist/schemas/subscription.d.ts.map +1 -0
  293. package/dist/schemas/subscription.js +46 -0
  294. package/dist/schemas/subscription.js.map +1 -0
  295. package/dist/schemas/template-revision.d.ts +53 -0
  296. package/dist/schemas/template-revision.d.ts.map +1 -0
  297. package/dist/schemas/template-revision.js +30 -0
  298. package/dist/schemas/template-revision.js.map +1 -0
  299. package/dist/selection.d.ts +22 -0
  300. package/dist/selection.d.ts.map +1 -0
  301. package/dist/selection.js +21 -0
  302. package/dist/selection.js.map +1 -0
  303. package/dist/storage/index.d.ts +27 -0
  304. package/dist/storage/index.d.ts.map +1 -0
  305. package/dist/storage/index.js +27 -0
  306. package/dist/storage/index.js.map +1 -0
  307. package/dist/storage/records.d.ts +28 -0
  308. package/dist/storage/records.d.ts.map +1 -0
  309. package/dist/storage/records.js +272 -0
  310. package/dist/storage/records.js.map +1 -0
  311. package/dist/svelte/applets-svelte.plugin.d.ts +38 -0
  312. package/dist/svelte/applets-svelte.plugin.d.ts.map +1 -0
  313. package/dist/svelte/applets-svelte.plugin.js +25 -0
  314. package/dist/svelte/components/AppletCanvas.svelte +488 -0
  315. package/dist/svelte/components/AppletCanvas.svelte.d.ts +53 -0
  316. package/dist/svelte/components/AppletCanvas.svelte.d.ts.map +1 -0
  317. package/dist/svelte/components/AppletCatalog.svelte +42 -0
  318. package/dist/svelte/components/AppletCatalog.svelte.d.ts +8 -0
  319. package/dist/svelte/components/AppletCatalog.svelte.d.ts.map +1 -0
  320. package/dist/svelte/components/AppletComposition.svelte +128 -0
  321. package/dist/svelte/components/AppletComposition.svelte.d.ts +30 -0
  322. package/dist/svelte/components/AppletComposition.svelte.d.ts.map +1 -0
  323. package/dist/svelte/components/AppletConsent.svelte +143 -0
  324. package/dist/svelte/components/AppletConsent.svelte.d.ts +12 -0
  325. package/dist/svelte/components/AppletConsent.svelte.d.ts.map +1 -0
  326. package/dist/svelte/components/LocalAppletView.svelte +102 -0
  327. package/dist/svelte/components/LocalAppletView.svelte.d.ts +13 -0
  328. package/dist/svelte/components/LocalAppletView.svelte.d.ts.map +1 -0
  329. package/dist/svelte/components/RunnableTracker.svelte +51 -0
  330. package/dist/svelte/components/RunnableTracker.svelte.d.ts +18 -0
  331. package/dist/svelte/components/RunnableTracker.svelte.d.ts.map +1 -0
  332. package/dist/svelte/index.d.ts +11 -0
  333. package/dist/svelte/index.d.ts.map +1 -0
  334. package/dist/svelte/index.js +10 -0
  335. package/dist/svelte/lib/canvas-lifecycle.d.ts +68 -0
  336. package/dist/svelte/lib/canvas-lifecycle.d.ts.map +1 -0
  337. package/dist/svelte/lib/canvas-lifecycle.js +99 -0
  338. package/dist/svelte/lib/capability-review.d.ts +64 -0
  339. package/dist/svelte/lib/capability-review.d.ts.map +1 -0
  340. package/dist/svelte/lib/capability-review.js +77 -0
  341. package/dist/svelte/lib/message-protocol.d.ts +184 -0
  342. package/dist/svelte/lib/message-protocol.d.ts.map +1 -0
  343. package/dist/svelte/lib/message-protocol.js +251 -0
  344. package/dist/svelte/runnable-source.d.ts +5 -0
  345. package/dist/svelte/runnable-source.d.ts.map +1 -0
  346. package/dist/svelte/runnable-source.js +92 -0
  347. package/dist/svelte/serve-index.svelte +39 -0
  348. package/dist/svelte/serve-index.svelte.d.ts +10 -0
  349. package/dist/svelte/serve-index.svelte.d.ts.map +1 -0
  350. package/dist/svelte/state.svelte.d.ts +26 -0
  351. package/dist/svelte/state.svelte.d.ts.map +1 -0
  352. package/dist/svelte/state.svelte.js +74 -0
  353. package/dist/svelte/styles.css +4 -0
  354. package/dist/svelte/tool-widgets/AppletToolCard.svelte +148 -0
  355. package/dist/svelte/tool-widgets/AppletToolCard.svelte.d.ts +5 -0
  356. package/dist/svelte/tool-widgets/AppletToolCard.svelte.d.ts.map +1 -0
  357. package/dist/svelte/tool-widgets/applet-tool-card.d.ts +41 -0
  358. package/dist/svelte/tool-widgets/applet-tool-card.d.ts.map +1 -0
  359. package/dist/svelte/tool-widgets/applet-tool-card.js +167 -0
  360. package/dist/svelte/tool-widgets/index.d.ts +3 -0
  361. package/dist/svelte/tool-widgets/index.d.ts.map +1 -0
  362. package/dist/svelte/tool-widgets/index.js +2 -0
  363. package/dist/templates/index.d.ts +2 -0
  364. package/dist/templates/index.d.ts.map +1 -0
  365. package/dist/templates/index.js +2 -0
  366. package/dist/templates/index.js.map +1 -0
  367. package/dist/templates/template.kind.d.ts +39 -0
  368. package/dist/templates/template.kind.d.ts.map +1 -0
  369. package/dist/templates/template.kind.js +29 -0
  370. package/dist/templates/template.kind.js.map +1 -0
  371. package/dist/tools/applet.descriptor.d.ts +196 -0
  372. package/dist/tools/applet.descriptor.d.ts.map +1 -0
  373. package/dist/tools/applet.descriptor.js +81 -0
  374. package/dist/tools/applet.descriptor.js.map +1 -0
  375. package/dist/tools/applet.impl.d.ts +32 -0
  376. package/dist/tools/applet.impl.d.ts.map +1 -0
  377. package/dist/tools/applet.impl.js +485 -0
  378. package/dist/tools/applet.impl.js.map +1 -0
  379. package/dist/tools/applet.schemas.d.ts +198 -0
  380. package/dist/tools/applet.schemas.d.ts.map +1 -0
  381. package/dist/tools/applet.schemas.js +136 -0
  382. package/dist/tools/applet.schemas.js.map +1 -0
  383. package/dist/tools/index.d.ts +3 -0
  384. package/dist/tools/index.d.ts.map +1 -0
  385. package/dist/tools/index.js +3 -0
  386. package/dist/tools/index.js.map +1 -0
  387. package/dist/upgrade.d.ts +45 -0
  388. package/dist/upgrade.d.ts.map +1 -0
  389. package/dist/upgrade.js +179 -0
  390. package/dist/upgrade.js.map +1 -0
  391. package/dist/vite.d.ts +26 -0
  392. package/dist/vite.d.ts.map +1 -0
  393. package/dist/vite.js +28 -0
  394. package/dist/vite.js.map +1 -0
  395. package/package.json +264 -4
  396. package/templates/applet-tour/Applet.svelte +95 -0
  397. package/templates/applet-tour/applet.descriptor.ts +15 -0
  398. package/templates/assembly-field/Applet.svelte +242 -0
  399. package/templates/assembly-field/applet.descriptor.ts +7 -0
  400. package/templates/assembly-field/applet.storage.json +47 -0
  401. package/templates/assembly-field/schemas/settings.ts +14 -0
  402. package/templates/assembly-field/settings.ts +32 -0
  403. package/templates/benchmark-comparison/Applet.svelte +17 -0
  404. package/templates/benchmark-comparison/applet.descriptor.ts +7 -0
  405. package/templates/file-diff-viewer/Applet.svelte +91 -0
  406. package/templates/file-diff-viewer/applet.descriptor.ts +14 -0
  407. package/templates/file-diff-viewer/diff.ts +63 -0
  408. package/templates/file-viewer/Applet.svelte +80 -0
  409. package/templates/file-viewer/applet.descriptor.ts +14 -0
  410. package/templates/fleet-runs/Applet.svelte +14 -0
  411. package/templates/fleet-runs/applet.descriptor.ts +7 -0
  412. package/templates/graph-runbook-tracker/Applet.svelte +13 -0
  413. package/templates/graph-runbook-tracker/applet.descriptor.ts +7 -0
  414. package/templates/runbook-tracker/Applet.svelte +12 -0
  415. package/templates/runbook-tracker/applet.descriptor.ts +7 -0
  416. package/templates/runnable-tracker/Applet.svelte +16 -0
  417. package/templates/runnable-tracker/applet.descriptor.ts +10 -0
  418. package/templates/storage-viewer/Applet.svelte +90 -0
  419. package/templates/storage-viewer/applet.descriptor.ts +15 -0
  420. package/templates/workspace-graph-runbook-tracker/Applet.svelte +13 -0
  421. package/templates/workspace-graph-runbook-tracker/applet.descriptor.ts +7 -0
@@ -0,0 +1,1105 @@
1
+ /**
2
+ * `vibes applet serve` implementation — ONE local web server for every applet.
3
+ *
4
+ * Single-origin by design: one local port (applets config `serveHostname` /
5
+ * `servePort`, default 127.0.0.1:5190) serves an index at `/`, each
6
+ * applet host page at `/applet/{id}/`, compiled entries, transpiled project
7
+ * sources, the handed file set, and every module the applet reaches. A
8
+ * second invocation probes the health endpoint first and REUSES a running
9
+ * server instead of multiplying ports. Wire bodies are schema-validated
10
+ * (serve.schemas.ts) — schema-first, not stringly-typed.
11
+ *
12
+ * Module serving mirrors the filesystem: a resolved file is served at
13
+ * `/@fs/<absolute path>`, so relative imports inside any package resolve in
14
+ * the browser exactly as they do on disk. Bare specifiers are resolved with
15
+ * the module system (exports maps and conditions), never by regex on the
16
+ * package name; `.svelte` compiles and `.ts` transpiles at request time.
17
+ *
18
+ * Runtime-first: the workspace root resolves through the runtime, and every
19
+ * response is served from disk at request time — new or edited applet
20
+ * projects appear without restarting the server.
21
+ */
22
+ import { createCLIActionLifetime } from '@vibesdotdev/cli/providers';
23
+ import { writeStdoutLine } from '@vibesdotdev/cli/output';
24
+ import * as z from 'zod/v4';
25
+ import { requireRuntimeCwd, CaughtFailureSchema, isCapabilityError, CapabilityError } from '@vibesdotdev/kernel';
26
+ import { APPLET_SERVE_HOST_KIND } from '@vibesdotdev/kernel/kinds/applet-serve-host.kind';
27
+ import { getLogger } from '@vibesdotdev/logging';
28
+ import { statChecked } from '@vibesdotdev/filesystem';
29
+ import { getRuntimePath } from '@vibesdotdev/paths';
30
+ import { APPLET_SVELTE_RUNTIME_PROP, mediaTypeFor, readAppletLocalProject, resolveAppletCompanion } from '@vibesdotdev/applets';
31
+ import { appletProjectsDir, digestContents, listAppletProjectIds, readAppletProjectEntries, resolveAppletProjectHost, resolveAppletWorkspaceRoot } from "../project-files.js";
32
+ import { serveHealthSchema, servedAppletSchema, servedAppletFilesSchema } from "./serve.schemas.js";
33
+ import { collectServedStyleContents, compileServedStylesheet, prepareServedSvelte } from "./serve-stylesheet.js";
34
+ import { answerServedAppletSurface } from "./serve-surface.js";
35
+ import { createServedAppletRpc } from "./served-applet-rpc.js";
36
+ import { compile, compileModule } from 'svelte/compiler';
37
+ import { loadAppletsConfig } from "../../config/load.js";
38
+ const HEALTH_PATH = '/__vibes/applets/serve/health';
39
+ const FS_PREFIX = '/@fs';
40
+ const JSON_HEADERS = { 'content-type': 'application/json', 'cache-control': 'no-store' };
41
+ const JS_HEADERS = { 'content-type': 'text/javascript', 'cache-control': 'no-store' };
42
+ const CSS_HEADERS = { 'content-type': 'text/css', 'cache-control': 'no-store' };
43
+ const HTML_HEADERS = { 'content-type': 'text/html', 'cache-control': 'no-store' };
44
+ /** Both separators to one, so URL paths and containment checks are host-independent. */
45
+ function toPosix(path) {
46
+ return path.replaceAll('\\', '/');
47
+ }
48
+ /** The host-canonical path, or null when nothing is there. Existence is asked
49
+ * through the checked-stat outcome, not caught from a refusal, so only a
50
+ * confirmed absence answers null and every other failure surfaces. This is
51
+ * the HOST's own view: installed packages and this package's own sources
52
+ * routinely live outside the served workspace, which the workspace view
53
+ * refuses. Project content never uses this one. */
54
+ /** The nearest directory at or above `file` that holds a package.json, or null. */
55
+ async function packageRootOf(host, file) {
56
+ let dir = host.paths.dirname(file);
57
+ while (true) {
58
+ const manifest = await statChecked(host.hostFiles, host.paths.join(dir, 'package.json'));
59
+ if (manifest.found && manifest.stat.kind !== 'directory')
60
+ return dir;
61
+ const parent = host.paths.dirname(dir);
62
+ if (parent === dir)
63
+ return null;
64
+ dir = parent;
65
+ }
66
+ }
67
+ async function realpathOrNullHost(host, path) {
68
+ const checked = await statChecked(host.hostFiles, path);
69
+ if (!checked.found)
70
+ return null;
71
+ return (await host.hostFiles.realpath?.(path)) ?? path;
72
+ }
73
+ /** A host answer as text: an unencoded read is bytes; a text read passes through. */
74
+ function textOf(contents) {
75
+ return contents instanceof Uint8Array ? new TextDecoder().decode(contents) : contents;
76
+ }
77
+ /** A host read as a `Response` body: text passes through; bytes copy into an ArrayBuffer-backed view. */
78
+ function asBody(contents) {
79
+ if (!(contents instanceof Uint8Array))
80
+ return contents;
81
+ const copy = new Uint8Array(contents.length);
82
+ copy.set(contents);
83
+ return copy;
84
+ }
85
+ /** A file's bytes, or null when the path is absent or is not a regular file. */
86
+ async function readFileOrNull(host, path) {
87
+ const checked = await statChecked(host.files, path);
88
+ if (!checked.found || checked.stat.kind !== 'file')
89
+ return null;
90
+ return host.files.readFile(path);
91
+ }
92
+ /** `readFileOrNull` through the HOST's own view, for installed-package bytes.
93
+ * Project companions stay on the workspace view (`readFileOrNull`). */
94
+ async function readFileOrNullHost(host, path) {
95
+ const checked = await statChecked(host.hostFiles, path);
96
+ if (!checked.found || checked.stat.kind !== 'file')
97
+ return null;
98
+ return host.hostFiles.readFile(path);
99
+ }
100
+ /**
101
+ * Whether a `--root` is absolute without asking the path kind first: POSIX
102
+ * `/x`, or a Windows drive/UNC root. The capture-free order matters — a
103
+ * RELATIVE root must fail closed on a host with no captured cwd before any
104
+ * other kind is consulted.
105
+ */
106
+ function looksAbsolute(root) {
107
+ return root.startsWith('/') || root.startsWith('\\\\') || /^[A-Za-z]:[\\/]/.test(root);
108
+ }
109
+ /**
110
+ * An explicit `--root` wins (a managed process names its workspace; a relative
111
+ * one resolves against where the command ran). Otherwise the runtime's bound
112
+ * workspace answers, so an unbound host fails `workspace-unbound` before any
113
+ * filesystem kind is asked for.
114
+ */
115
+ async function resolveRootOption(runtime, root) {
116
+ const cwd = looksAbsolute(root) ? undefined : requireRuntimeCwd(runtime);
117
+ const paths = await getRuntimePath(runtime);
118
+ return cwd === undefined ? paths.resolve(root) : paths.resolve(cwd, root);
119
+ }
120
+ /** Modules a plain page cannot resolve, answered with the browser truth:
121
+ * `esm-env` selects its build by export condition, and the kit's `/svelte`
122
+ * barrel carries a few SvelteKit-bound components that import the `$app`
123
+ * and `$env` virtuals. Outside SvelteKit those are inert stand-ins. */
124
+ const shimSpecifierSchema = z.enum(['esm-env', '$app/state', '$app/navigation', '$env/dynamic/public', '$env/dynamic/private']);
125
+ const SHIMS = {
126
+ 'esm-env': 'export const BROWSER = true;\nexport const DEV = true;\nexport const NODE = false;\n',
127
+ '$app/state': [
128
+ 'export const page = { url: new URL(location.href), params: {}, route: { id: null }, status: 200, error: null, data: {}, form: null, state: {} };',
129
+ 'export const navigating = { from: null, to: null, type: null, willUnload: false, delta: null, complete: Promise.resolve() };',
130
+ 'export const updated = { current: false, check: async () => false };'
131
+ ].join('\n') + '\n',
132
+ '$app/navigation': [
133
+ 'export const goto = async (url) => { location.href = String(url); };',
134
+ 'export const invalidate = async () => {}; export const invalidateAll = async () => {};',
135
+ 'export const preloadData = async () => ({ type: "loaded", status: 200, data: {} }); export const preloadCode = async () => {};',
136
+ 'export const beforeNavigate = () => {}; export const afterNavigate = () => {}; export const onNavigate = () => {};',
137
+ 'export const pushState = () => {}; export const replaceState = () => {}; export const disableScrollHandling = () => {};'
138
+ ].join('\n') + '\n',
139
+ '$env/dynamic/public': 'export const env = {};\n',
140
+ '$env/dynamic/private': 'export const env = {};\n'
141
+ };
142
+ const SHIM_PREFIX = '/@shim/';
143
+ /**
144
+ * A stylesheet a module imports (`import 'pkg/style.css'`, `import './x.css'`): the page cannot load
145
+ * CSS as a module, so the import is rewritten to this prefix plus the sheet's own URL, which answers a
146
+ * module that adds the sheet once as a `<link>`.
147
+ */
148
+ const CSS_MODULE_PREFIX = '/@css-module';
149
+ /** A `?raw` import (Vite's convention, kept in built packages): the file's text as a module's default export. */
150
+ const RAW_MODULE_PREFIX = '/@raw-module';
151
+ /** A `?worker` import (Vite's convention, kept in built packages): a `Worker` constructor for the resolved module. */
152
+ const WORKER_MODULE_PREFIX = '/@worker-module';
153
+ function cssModule(sheetUrl) {
154
+ const href = JSON.stringify(sheetUrl);
155
+ return `if (!document.querySelector(\`link[data-applet-css=\${JSON.stringify(${href})}]\`)) {\n\tconst link = document.createElement('link');\n\tlink.rel = 'stylesheet';\n\tlink.href = ${href};\n\tlink.dataset.appletCss = ${href};\n\tdocument.head.appendChild(link);\n}\nexport {};\n`;
156
+ }
157
+ function workerModule(workerUrl) {
158
+ const href = JSON.stringify(workerUrl);
159
+ return `export default class ServedModuleWorker extends Worker {\n\tconstructor(options) {\n\t\tsuper(${href}, { type: 'module', name: options?.name, credentials: options?.credentials });\n\t}\n}\n`;
160
+ }
161
+ function shimUrl(specifier) {
162
+ return SHIM_PREFIX + encodeURIComponent(specifier) + '.js';
163
+ }
164
+ /** Export conditions a plain browser page satisfies, most specific first. */
165
+ const BROWSER_CONDITIONS = ['browser', 'svelte', 'import', 'module', 'default'];
166
+ const STYLESHEET_CONDITIONS = ['style', ...BROWSER_CONDITIONS];
167
+ const exportEntrySchema = z.union([
168
+ z.string(),
169
+ z.array(z.lazy(() => exportEntrySchema)),
170
+ z.record(z.string(), z.lazy(() => exportEntrySchema).optional())
171
+ ]);
172
+ const exportsMapSchema = z.record(z.string(), exportEntrySchema);
173
+ const packageJsonSchema = z.looseObject({
174
+ exports: z.unknown().optional(),
175
+ module: z.string().optional(),
176
+ browser: z.unknown().optional(),
177
+ main: z.string().optional()
178
+ });
179
+ function isExportString(entry) {
180
+ return typeof entry === 'string';
181
+ }
182
+ /**
183
+ * Walk an exports map entry to its relative files for the given conditions,
184
+ * most preferred first. A published package can name a condition target it
185
+ * does not ship (Kit's `style` points at `src/`, which only `dist/` publishes),
186
+ * so the caller takes the first candidate that exists rather than the first
187
+ * condition that matches.
188
+ */
189
+ function exportCandidates(entry, conditions = BROWSER_CONDITIONS) {
190
+ if (entry === undefined)
191
+ return [];
192
+ if (isExportString(entry))
193
+ return [entry];
194
+ if (Array.isArray(entry))
195
+ return entry.flatMap((item) => exportCandidates(item, conditions));
196
+ return conditions.flatMap((condition) => (condition in entry ? exportCandidates(entry[condition], conditions) : []));
197
+ }
198
+ function splitSpecifier(specifier) {
199
+ const parts = specifier.split('/');
200
+ const name = specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
201
+ const subpath = specifier.slice(name.length); // '' or '/x/y'
202
+ return { name, subpath };
203
+ }
204
+ async function findPackageRoot(host, name, fromDir) {
205
+ let dir = fromDir;
206
+ while (true) {
207
+ const candidate = host.paths.join(dir, 'node_modules', name);
208
+ // `node_modules/<name>` is host-owned and routinely sits outside the
209
+ // workspace, so this walk reads the host's own filesystem, not the
210
+ // workspace-rooted view, which would refuse the whole subtree.
211
+ if (await host.hostFiles.exists(host.paths.join(candidate, 'package.json')))
212
+ return candidate;
213
+ const parent = host.paths.dirname(dir);
214
+ if (parent === dir)
215
+ return null;
216
+ dir = parent;
217
+ }
218
+ }
219
+ const PackageNameSchema = z.looseObject({ name: z.string().optional() });
220
+ /**
221
+ * The package a directory sits in, when that package is `name` (a package importing its own name,
222
+ * as Node resolves a self-reference): the served kit checkout imports `@vibesdotdev/kit/...` with
223
+ * no `node_modules` link to itself, and must still resolve through its own exports map.
224
+ */
225
+ async function selfPackageRoot(host, name, fromDir) {
226
+ let dir = fromDir;
227
+ while (true) {
228
+ const manifest = host.paths.join(dir, 'package.json');
229
+ if (await host.hostFiles.exists(manifest)) {
230
+ const parsed = PackageNameSchema.safeParse(JSON.parse(textOf(await host.hostFiles.readFile(manifest, 'utf8'))));
231
+ return parsed.success && parsed.data.name === name ? dir : null;
232
+ }
233
+ const parent = host.paths.dirname(dir);
234
+ if (parent === dir)
235
+ return null;
236
+ dir = parent;
237
+ }
238
+ }
239
+ /**
240
+ * Resolve a bare specifier for a browser: the package's exports map under
241
+ * browser conditions first (so `svelte` yields the client build, not the
242
+ * server one), then the module system's own answer as the fallback.
243
+ */
244
+ async function resolveForBrowser(host, specifier, fromDir, fallback, conditions = BROWSER_CONDITIONS) {
245
+ const { name, subpath } = splitSpecifier(specifier);
246
+ const root = (await findPackageRoot(host, name, fromDir)) ?? (await selfPackageRoot(host, name, fromDir));
247
+ if (root) {
248
+ // `findPackageRoot` saw this package.json; a read or parse failure is a
249
+ // broken install and surfaces rather than resolving as if it had no exports.
250
+ const pkg = packageJsonSchema.parse(JSON.parse(textOf(await host.hostFiles.readFile(host.paths.join(root, 'package.json'), 'utf8'))));
251
+ const parsedMap = exportsMapSchema.safeParse(pkg.exports);
252
+ if (parsedMap.success) {
253
+ const map = parsedMap.data;
254
+ const key = '.' + subpath;
255
+ const candidates = exportCandidates(map[key], conditions);
256
+ if (candidates.length === 0) {
257
+ // One-level `*` patterns, e.g. "./components/*": "./dist/components/*"
258
+ for (const [pattern, target] of Object.entries(map)) {
259
+ const star = pattern.indexOf('*');
260
+ if (star < 0)
261
+ continue;
262
+ const head = pattern.slice(0, star), tail = pattern.slice(star + 1);
263
+ if (key.startsWith(head) && key.endsWith(tail) && key.length >= head.length + tail.length) {
264
+ const filled = key.slice(head.length, key.length - tail.length);
265
+ const picked = exportCandidates(target, conditions);
266
+ if (picked.length > 0) {
267
+ candidates.push(...picked.map((rel) => rel.replace('*', filled)));
268
+ break;
269
+ }
270
+ }
271
+ }
272
+ }
273
+ for (const rel of candidates) {
274
+ const abs = host.paths.resolve(root, rel);
275
+ if (await host.hostFiles.exists(abs))
276
+ return (await realpathOrNullHost(host, abs)) ?? abs;
277
+ }
278
+ }
279
+ else if (!subpath) {
280
+ const rel = z.string().safeParse(pkg.browser).data ?? pkg.module ?? pkg.main;
281
+ if (rel) {
282
+ const abs = host.paths.resolve(root, rel);
283
+ if (await host.hostFiles.exists(abs))
284
+ return (await realpathOrNullHost(host, abs)) ?? abs;
285
+ }
286
+ }
287
+ }
288
+ const fallen = fallback(specifier, fromDir);
289
+ if (!fallen)
290
+ return null;
291
+ // Real paths only: a symlinked package must resolve its own dependencies
292
+ // from where it actually lives, not from where it was linked.
293
+ if (!(await host.hostFiles.exists(fallen)))
294
+ return fallen;
295
+ return (await realpathOrNullHost(host, fallen)) ?? fallen;
296
+ }
297
+ /** A relative specifier a browser cannot follow (no extension, or a
298
+ * directory) is pinned to the file it means on disk. */
299
+ async function completeRelative(host, specifier, fromDir) {
300
+ const abs = host.paths.resolve(fromDir, specifier);
301
+ const exact = await statChecked(host.hostFiles, abs);
302
+ if (host.paths.extname(abs) && exact.found && exact.stat.kind !== 'directory')
303
+ return null; // already exact
304
+ // TypeScript sources import their siblings by the `.js` name they compile to (`./utils.js` for utils.ts).
305
+ if (abs.endsWith('.js') && !exact.found) {
306
+ const typed = await statChecked(host.hostFiles, abs.replace(/\.js$/, '.ts'));
307
+ if (typed.found && typed.stat.kind !== 'directory')
308
+ return specifier.replace(/\.js$/, '.ts');
309
+ }
310
+ const candidates = [
311
+ abs + '.js',
312
+ abs + '.ts',
313
+ abs + '.svelte',
314
+ host.paths.join(abs, 'index.js'),
315
+ host.paths.join(abs, 'index.ts')
316
+ ];
317
+ for (const candidate of candidates) {
318
+ const checked = await statChecked(host.hostFiles, candidate);
319
+ if (checked.found && checked.stat.kind !== 'directory') {
320
+ const rel = specifier.endsWith('/') ? specifier.slice(0, -1) : specifier;
321
+ return rel + toPosix(candidate.slice(abs.length));
322
+ }
323
+ }
324
+ return null;
325
+ }
326
+ function toFsUrl(absolutePath) {
327
+ return FS_PREFIX + absolutePath.split(/[\\/]/).map(encodeURIComponent).join('/');
328
+ }
329
+ function fromFsUrl(host, path) {
330
+ if (!path.startsWith(FS_PREFIX + '/'))
331
+ return null;
332
+ return host.paths.resolve(path.slice(FS_PREFIX.length).split('/').map(decodeURIComponent).join('/'));
333
+ }
334
+ function isRelative(specifier) {
335
+ return specifier.startsWith('./') || specifier.startsWith('../') || specifier.startsWith('/');
336
+ }
337
+ function replaceSpecifier(code, specifier, target) {
338
+ return code.split(`'${specifier}'`).join(`'${target}'`).split(`"${specifier}"`).join(`"${target}"`);
339
+ }
340
+ /**
341
+ * The URL one resolved companion is served at.
342
+ *
343
+ * Compiled modules get a `.js` suffix on their SOURCE path (so `x.svelte` is
344
+ * `x.svelte.js`, a rune `x.svelte.ts` is `x.svelte.ts.js`, a rune `x.svelte.js`
345
+ * is `x.svelte.js.js`), which keeps every source unambiguous under one route
346
+ * table. TypeScript is compiled to `x.js`, the convention the route already had.
347
+ * Everything else — css, md, images — is served at its own path as bytes.
348
+ */
349
+ function companionTarget(projectId, path) {
350
+ if (path.endsWith('.svelte.ts') || path.endsWith('.svelte.js') || path.endsWith('.svelte')) {
351
+ return `/applet/${projectId}/${path}.js`;
352
+ }
353
+ if (path.endsWith('.ts'))
354
+ return `/applet/${projectId}/${path.slice(0, -3)}.js`;
355
+ return `/applet/${projectId}/${path}`;
356
+ }
357
+ /** Rewrite every specifier in a served module to a URL this server answers. */
358
+ export async function rewriteModule(code, ctx) {
359
+ for (const specifier of ctx.tools.scan(code)) {
360
+ let target = null;
361
+ if (specifier.endsWith('?raw') && isRelative(specifier) && !ctx.project) {
362
+ // A vendor module's raw text import: the file beside it, served as a string module.
363
+ code = replaceSpecifier(code, specifier, RAW_MODULE_PREFIX + toFsUrl(ctx.host.paths.resolve(ctx.fromDirs[0], specifier.slice(0, -'?raw'.length))));
364
+ continue;
365
+ }
366
+ if (specifier.endsWith('?worker') && !ctx.project) {
367
+ // A vendor module's web-worker constructor import: resolve the underlying worker script and wrap it.
368
+ const bare = specifier.slice(0, -'?worker'.length);
369
+ let workerTarget = null;
370
+ if (isRelative(bare)) {
371
+ const completed = (await completeRelative(ctx.host, bare, ctx.fromDirs[0])) ?? bare;
372
+ workerTarget = toFsUrl(ctx.host.paths.resolve(ctx.fromDirs[0], completed));
373
+ }
374
+ else {
375
+ for (const dir of ctx.fromDirs) {
376
+ const abs = await resolveForBrowser(ctx.host, bare, dir, ctx.tools.resolve);
377
+ if (abs) {
378
+ await ctx.admitResolved?.(abs);
379
+ workerTarget = toFsUrl(abs);
380
+ break;
381
+ }
382
+ }
383
+ }
384
+ if (workerTarget) {
385
+ code = replaceSpecifier(code, specifier, WORKER_MODULE_PREFIX + workerTarget);
386
+ continue;
387
+ }
388
+ }
389
+ if (isRelative(specifier)) {
390
+ if (ctx.project) {
391
+ // A2b: companions resolve RELATIVE to the importing file, through the
392
+ // same pure resolver every host uses — extensionless names complete,
393
+ // nested `../` paths work, and binary media is served as bytes.
394
+ const resolved = resolveAppletCompanion({
395
+ importer: ctx.project.importer,
396
+ specifier,
397
+ files: ctx.project.files
398
+ });
399
+ if (!resolved.ok)
400
+ continue;
401
+ target = companionTarget(ctx.project.id, resolved.path);
402
+ }
403
+ else {
404
+ // Vendor modules: the URL mirrors the disk, so relative imports
405
+ // resolve as they do on disk — once they name an actual file.
406
+ target = await completeRelative(ctx.host, specifier, ctx.fromDirs[0]);
407
+ if (!target)
408
+ continue;
409
+ }
410
+ }
411
+ else if (shimSpecifierSchema.safeParse(specifier).success) {
412
+ target = shimUrl(specifier);
413
+ }
414
+ else if (specifier === '@vibesdotdev/applets/messages') {
415
+ target = '/applets/messages.js';
416
+ }
417
+ else {
418
+ for (const dir of ctx.fromDirs) {
419
+ const abs = await resolveForBrowser(ctx.host, specifier, dir, ctx.tools.resolve);
420
+ if (abs) {
421
+ await ctx.admitResolved?.(abs);
422
+ target = toFsUrl(abs);
423
+ break;
424
+ }
425
+ }
426
+ if (!target)
427
+ continue; // leave it; the browser reports the unresolved specifier by name
428
+ }
429
+ // A stylesheet import becomes the module that links it.
430
+ if (target.endsWith('.css'))
431
+ target = CSS_MODULE_PREFIX + target;
432
+ code = replaceSpecifier(code, specifier, target);
433
+ }
434
+ // The selected local host resolves browser build constants with its native compiler.
435
+ return ctx.tools.transpile(code);
436
+ }
437
+ function indexHostPage() {
438
+ return `<!doctype html>
439
+ <html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
440
+ <title>Local applets</title>
441
+ <link rel="stylesheet" href="/kit/styles.css"/>
442
+ <style>html,body{margin:0;height:100%;background:#0d1117;color:#e6edf3}</style>
443
+ </head><body><div id="app"></div>
444
+ <script type="module">
445
+ const health = await fetch('/__vibes/applets/serve/health').then(r => r.json());
446
+ const { mount } = await import('/serve/index.js');
447
+ mount(document.getElementById('app'), { applets: health.applets });
448
+ </script>
449
+ </body></html>`;
450
+ }
451
+ /**
452
+ * One applet's page. The applet mounts with its root surface as the `vibes`
453
+ * prop (the delivery contract in `browser-runtime.ts`); it used to mount with
454
+ * empty props, so a local applet had no runtime surface at all.
455
+ */
456
+ export function hostPage(id, surfaceClientUrl) {
457
+ return `<!doctype html>
458
+ <html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
459
+ <title>Applet — ${id}</title>
460
+ <link rel="stylesheet" href="/kit/styles.css?project=${id}"/><style>html,body{margin:0;height:100%;background:#0d1117}#app{height:100vh}</style>
461
+ </head><body><div id="runtime-status" role="status"></div><button id="runtime-reconnect" type="button" hidden>Reconnect runtime</button><p id="runtime-failure" role="alert" hidden></p><p id="runtime-cleanup-failure" role="alert" hidden></p><div id="app"></div>
462
+ <script type="module">
463
+ const status = document.getElementById('runtime-status');
464
+ const retry = document.getElementById('runtime-reconnect');
465
+ const failure = document.getElementById('runtime-failure');
466
+ const cleanupFailure = document.getElementById('runtime-cleanup-failure');
467
+ let connection;
468
+ let mounted;
469
+ let pending;
470
+ let releasing;
471
+ let disposed = false;
472
+ function report(error, target = failure) {
473
+ const message = error instanceof Error ? error.message : String(error);
474
+ const detail = target === cleanupFailure ? 'Previous runtime connection cleanup: ' + message : message;
475
+ target.textContent = [target.textContent, detail].filter(Boolean).join('\\n');
476
+ target.hidden = false;
477
+ }
478
+ function release() {
479
+ if (releasing) return releasing;
480
+ const previousMount = mounted;
481
+ const previousConnection = connection;
482
+ mounted = undefined;
483
+ connection = undefined;
484
+ releasing = Promise.allSettled([
485
+ (async () => { if (previousMount !== undefined) await unmount(previousMount); })(),
486
+ (async () => { await previousConnection?.close(); })()
487
+ ]).then(results => {
488
+ for (const result of results) if (result.status === 'rejected') report(result.reason, cleanupFailure);
489
+ }).finally(() => { releasing = undefined; });
490
+ return releasing;
491
+ }
492
+ async function connect() {
493
+ if (pending || disposed) return pending;
494
+ pending = Promise.resolve().then(async () => {
495
+ retry.disabled = true;
496
+ failure.hidden = true;
497
+ failure.textContent = '';
498
+ status.textContent = 'Connecting to the runtime.';
499
+ await release();
500
+ if (disposed) return;
501
+ const opened = await openServedApplet({ projectId: '${id}', origin: location.origin, fetch: (url, init) => fetch(url, init) });
502
+ if (disposed) { await opened.close(); return; }
503
+ connection = opened;
504
+ const props = readAppletLocation(AppletPresentationSchema.parse({ id: '${id}', title: '${id}' }), undefined, new URL(location.href));
505
+ mounted = mount(document.getElementById('app'), { ...props, ${APPLET_SVELTE_RUNTIME_PROP}: opened.surface });
506
+ status.textContent = '';
507
+ retry.hidden = true;
508
+ void opened.closed.then(() => {
509
+ if (connection !== opened || disposed) return;
510
+ const released = release();
511
+ status.textContent = 'Runtime connection closed. Reconnect to read the recorded work.';
512
+ retry.hidden = false;
513
+ return released;
514
+ }).catch(error => report(error, cleanupFailure));
515
+ window.dispatchEvent(new MessageEvent('message', { data: { type: 'files', files: files.files } }));
516
+ }).catch(async error => {
517
+ await release();
518
+ report(error);
519
+ status.textContent = 'Runtime connection unavailable.';
520
+ retry.hidden = false;
521
+ }).finally(() => { retry.disabled = false; pending = undefined; });
522
+ return pending;
523
+ }
524
+ window.addEventListener('pagehide', () => {
525
+ disposed = true;
526
+ void (async () => { await pending; await release(); })().catch(report);
527
+ }, { once: true });
528
+ const files = await fetch('/applet/${id}/files').then(r => r.json());
529
+ const { openServedApplet, readAppletLocation, AppletPresentationSchema } = await import('${surfaceClientUrl}');
530
+ const { mount, unmount } = await import('/applet/${id}/applet.js');
531
+ retry.addEventListener('click', connect);
532
+ await connect();
533
+ </script>
534
+ </body></html>`;
535
+ }
536
+ /** Svelte compiles a component to `export default function <Name>()`. Hosts
537
+ * need mount(element, props); expose Svelte's mount under that shape. */
538
+ function withMountAdapter(code, svelteUrl) {
539
+ const defaultExport = /export default function ([A-Za-z_$][\w$]*)/.exec(code);
540
+ if (!defaultExport)
541
+ return code;
542
+ return (code +
543
+ `\nimport { mount as __svelte_mount, unmount as __svelte_unmount } from '${svelteUrl}';\n` +
544
+ 'export function mount(target, props = {}) {\n' +
545
+ `\treturn __svelte_mount(${defaultExport[1]}, { target, props });\n` +
546
+ '}\n' +
547
+ 'export function unmount(instance) { return __svelte_unmount(instance); }\n');
548
+ }
549
+ /** Load one project from disk and compile its entry for the browser. */
550
+ export async function loadProject(workspaceRoot, id, ctx, svelteUrl) {
551
+ let entries;
552
+ const projectRead = await (async () => {
553
+ try {
554
+ return { ok: true, entries: await readAppletProjectEntries(workspaceRoot, id, ctx.host) };
555
+ }
556
+ catch (error) {
557
+ return { ok: false, error };
558
+ }
559
+ })();
560
+ if (!projectRead.ok) {
561
+ // No such project: 404 at the route layer. An unreadable one surfaces,
562
+ // and so does a failure no schema can read — the original, never a
563
+ // parse error about it.
564
+ const parsed = CaughtFailureSchema.safeParse(projectRead.error);
565
+ const failure = parsed.success ? parsed.data : null;
566
+ if (failure && isCapabilityError(failure) && failure.reason === 'applet-project-not-found')
567
+ return null;
568
+ throw projectRead.error;
569
+ }
570
+ entries = projectRead.entries;
571
+ const result = await readAppletLocalProject({ id, entries, digest: digestContents });
572
+ if (!result.ok)
573
+ return null;
574
+ const project = result.project;
575
+ const files = project.files.map((file) => file.path);
576
+ const filename = ctx.host.paths.join(appletProjectsDir(workspaceRoot, ctx.host), id, project.entry);
577
+ const prepared = await prepareServedSvelte(project.sources[project.entry], {
578
+ path: filename, base: ctx.host.paths.dirname(filename)
579
+ }, ctx.tools.compileStyle);
580
+ const compiled = compile(prepared, {
581
+ filename: project.entry,
582
+ generate: 'client',
583
+ css: 'injected'
584
+ });
585
+ const code = withMountAdapter(await rewriteModule(compiled.js.code, {
586
+ ...ctx,
587
+ project: { id, sources: project.sources, files, importer: project.entry }
588
+ }), svelteUrl);
589
+ return { id, entry: project.entry, sources: project.sources, files, compiledEntry: code };
590
+ }
591
+ /**
592
+ * One companion route for one loaded project — the body of the applet-scoped
593
+ * module and asset routes.
594
+ *
595
+ * A2b: companions resolve relative to the importing file. Compiled modules are
596
+ * addressed by their SOURCE path plus a `.js` suffix, so `x.svelte`, rune
597
+ * `x.svelte.ts` and rune `x.svelte.js` never collide under one route table.
598
+ * Everything else — css, md, svg, images — is served as BYTES with its declared
599
+ * media type. Returns null when no branch matches; the caller answers 404.
600
+ *
601
+ * Exported so a test can drive the REAL route pipeline without a socket.
602
+ */
603
+ export async function serveAppletCompanion(input) {
604
+ const { workspaceRoot, id, project, rest, tools, host, resolveDirs, admitResolved } = input;
605
+ const projectCtx = (importer) => ({
606
+ tools,
607
+ host,
608
+ fromDirs: resolveDirs,
609
+ admitResolved,
610
+ project: { id, sources: project.sources, files: project.files, importer }
611
+ });
612
+ if (rest.endsWith('.svelte.ts.js')) {
613
+ // A rune module written in TypeScript: transpile, then the module compiler.
614
+ const source = rest.slice(0, -3);
615
+ if (source in project.sources) {
616
+ const js = tools.transpile(project.sources[source]);
617
+ const compiled = compileModule(js, { filename: source, generate: 'client' });
618
+ return new Response(await rewriteModule(compiled.js.code, projectCtx(source)), { headers: JS_HEADERS });
619
+ }
620
+ }
621
+ else if (rest.endsWith('.svelte.js.js')) {
622
+ // A rune module already in JavaScript.
623
+ const source = rest.slice(0, -3);
624
+ if (source in project.sources) {
625
+ const compiled = compileModule(project.sources[source], { filename: source, generate: 'client' });
626
+ return new Response(await rewriteModule(compiled.js.code, projectCtx(source)), { headers: JS_HEADERS });
627
+ }
628
+ }
629
+ else if (rest.endsWith('.svelte.js')) {
630
+ // A companion component of the project, compiled for the browser.
631
+ const svelteFile = rest.slice(0, -3);
632
+ if (svelteFile in project.sources) {
633
+ const filename = host.paths.join(appletProjectsDir(workspaceRoot, host), id, svelteFile);
634
+ const prepared = await prepareServedSvelte(project.sources[svelteFile], {
635
+ path: filename, base: host.paths.dirname(filename)
636
+ }, tools.compileStyle);
637
+ const compiled = compile(prepared, {
638
+ filename: svelteFile,
639
+ generate: 'client',
640
+ css: 'injected'
641
+ });
642
+ return new Response(await rewriteModule(compiled.js.code, projectCtx(svelteFile)), { headers: JS_HEADERS });
643
+ }
644
+ }
645
+ else if (rest.endsWith('.js')) {
646
+ // A project TypeScript source, transpiled for the browser; else a project
647
+ // JavaScript source served through the same rewriter.
648
+ const srcPath = rest.replace(/\.js$/, '.ts');
649
+ if (srcPath in project.sources) {
650
+ return new Response(await rewriteModule(tools.transpile(project.sources[srcPath]), projectCtx(srcPath)), {
651
+ headers: JS_HEADERS
652
+ });
653
+ }
654
+ if (rest in project.sources) {
655
+ return new Response(await rewriteModule(project.sources[rest], projectCtx(rest)), { headers: JS_HEADERS });
656
+ }
657
+ }
658
+ else {
659
+ // A companion of any other type — css, md, svg, images: served as BYTES
660
+ // with its declared media type, straight from the project.
661
+ const mediaType = mediaTypeFor(rest);
662
+ if (mediaType !== undefined && project.files.includes(rest)) {
663
+ const full = host.paths.join(appletProjectsDir(workspaceRoot, host), id, ...rest.split('/'));
664
+ // A file removed since the listing is a confirmed absence (404); any other read failure is rethrown.
665
+ const read = await readFileOrNull(host, full);
666
+ if (read === null)
667
+ return new Response('Not found', { status: 404 });
668
+ return new Response(asBody(read), {
669
+ headers: { 'content-type': mediaType, 'cache-control': 'no-store' }
670
+ });
671
+ }
672
+ }
673
+ return null;
674
+ }
675
+ /**
676
+ * A package's installed root, walked through the HOST's own filesystem and
677
+ * path kinds — never `require.resolve`, whose answer belongs to whichever
678
+ * context (a compiled bundle, a linked checkout) happened to call it.
679
+ */
680
+ async function resolvePackageRoot(host, roots, name) {
681
+ for (const dir of roots) {
682
+ const found = await findPackageRoot(host, name, dir);
683
+ if (found)
684
+ return (await realpathOrNullHost(host, found)) ?? found;
685
+ }
686
+ throw new CapabilityError(`Package "${name}" is not installed in this workspace.`, 'UNAVAILABLE', {
687
+ reason: 'applet-package-unavailable',
688
+ details: { package: name },
689
+ retryable: false
690
+ });
691
+ }
692
+ /**
693
+ * Everything `run` must resolve before it can listen: the kit, the svelte
694
+ * runtime, the optional animation sheet, and this package's own served
695
+ * sources. Exported so a test can drive the REAL startup resolution without
696
+ * a socket.
697
+ */
698
+ export async function resolveServePackageRoots(input) {
699
+ const { host, runtime, tools, workspaceRoot, packageDir, packageSourcePath, surfaceClientPath } = input;
700
+ // The kit the workspace links (its source checkout, when present) wins over
701
+ // the copy pinned by this package: local serve exists to iterate on what
702
+ // is being built, and the pinned copy is the fallback for a plain install.
703
+ const kitPath = (await findPackageRoot(host, '@vibesdotdev/kit', workspaceRoot)) ??
704
+ (await resolvePackageRoot(host, [workspaceRoot, packageDir], '@vibesdotdev/kit'));
705
+ const kitRoot = (await realpathOrNullHost(host, kitPath)) ?? kitPath;
706
+ const resolveDirs = [kitRoot, packageDir, workspaceRoot];
707
+ const svelteEntry = await resolveForBrowser(host, 'svelte', kitRoot, tools.resolve);
708
+ if (!svelteEntry)
709
+ throw new CapabilityError('Svelte runtime not found in the workspace node_modules.', 'UNAVAILABLE', {
710
+ reason: 'applet-package-unavailable',
711
+ details: { package: 'svelte' },
712
+ retryable: false
713
+ });
714
+ const svelteUrl = toFsUrl(svelteEntry);
715
+ // The kit owns where its stylesheet builds to; its exports map names it.
716
+ const kitStylesheet = await resolveForBrowser(host, '@vibesdotdev/kit/styles.css', kitRoot, tools.resolve, STYLESHEET_CONDITIONS);
717
+ // Optional: without it the kit sheet drops the import. Absence is asked, not
718
+ // caught — findPackageRoot answers null when the package is not installed,
719
+ // so the one default below rests on a declared fact, not a swallowed refusal.
720
+ const twAnimatePath = (await findPackageRoot(host, 'tw-animate-css', workspaceRoot)) ??
721
+ (await findPackageRoot(host, 'tw-animate-css', packageDir));
722
+ const twAnimateRoot = twAnimatePath === null ? null : ((await realpathOrNullHost(host, twAnimatePath)) ?? twAnimatePath);
723
+ if (twAnimateRoot === null) {
724
+ getLogger('applets:serve', runtime).debug('optional package not installed; the kit sheet drops the import', {
725
+ package: 'tw-animate-css'
726
+ });
727
+ }
728
+ const packageSourceDir = (await realpathOrNullHost(host, packageSourcePath)) ?? packageSourcePath;
729
+ const surfaceClientUrl = toFsUrl((await realpathOrNullHost(host, surfaceClientPath)) ?? surfaceClientPath);
730
+ return { kitRoot, kitStylesheet, resolveDirs, svelteEntry, svelteUrl, twAnimateRoot, packageSourceDir, surfaceClientUrl };
731
+ }
732
+ export async function run(runtime, id, options = {}) {
733
+ const workspaceRoot = options.root
734
+ ? await resolveRootOption(runtime, options.root)
735
+ : await resolveAppletWorkspaceRoot(runtime);
736
+ const host = await resolveAppletProjectHost(runtime);
737
+ const appletsSettings = await loadAppletsConfig(runtime);
738
+ const hostname = appletsSettings.serveHostname;
739
+ const port = options.port ?? appletsSettings.servePort;
740
+ const base = `http://${hostname}:${port}`;
741
+ // Reuse probe: if our server already runs here, attach instead of multiply.
742
+ // Only an unreachable port means "not running"; a server that answers our
743
+ // health path with another shape is reported by the schema parse.
744
+ let probe = null;
745
+ const probeOutcome = await (async () => {
746
+ try {
747
+ return { ok: true, response: await fetch(base + HEALTH_PATH, { signal: AbortSignal.timeout(1500) }) };
748
+ }
749
+ catch (error) {
750
+ return { ok: false, error };
751
+ }
752
+ })();
753
+ if (probeOutcome.ok) {
754
+ probe = probeOutcome.response;
755
+ }
756
+ else {
757
+ // Refused or silent: nothing serves here yet. Any other failure surfaces.
758
+ const probeError = z.object({ code: z.string().optional(), name: z.string().optional() }).safeParse(probeOutcome.error);
759
+ const failure = probeError.success ? probeError.data : {};
760
+ if (failure.code !== 'ConnectionRefused' &&
761
+ failure.code !== 'ECONNREFUSED' &&
762
+ failure.name !== 'TimeoutError') {
763
+ throw probeOutcome.error;
764
+ }
765
+ getLogger('applets:serve', runtime).debug('no server on this port yet; starting one', { base });
766
+ }
767
+ if (probe?.ok) {
768
+ const health = serveHealthSchema.parse(await probe.json());
769
+ await writeStdoutLine(runtime, `Applet server already running at ${base} (${health.applets.length} applet(s)).`);
770
+ await writeStdoutLine(runtime, id ? `Open ${base}/applet/${id}/` : `Open ${base}/`);
771
+ return;
772
+ }
773
+ // The host bindings (serve + transpiler + resolver) resolve from the
774
+ // runtime's `applet/serve-host` kind: no implementation id and no Bun
775
+ // global at this call site. A host without the bindings fails typed
776
+ // (`NOT_FOUND` `not-registered`) instead of crashing on a missing global.
777
+ const serveHost = await runtime.query(APPLET_SERVE_HOST_KIND).enabled().firstOrThrow();
778
+ const tools = {
779
+ scan: serveHost.scanModuleSpecifiers,
780
+ resolve: (specifier, fromDir) => serveHost.resolveModuleSpecifier(specifier, fromDir, runtime),
781
+ transpile: serveHost.transpileTypeScriptSource,
782
+ compileStyle: entry => compileServedStylesheet(serveHost, { entry, sources: [], loadStylesheet })
783
+ };
784
+ // Files may only be served from the workspace or an installed package.
785
+ // This package's own sources are served too: the page imports the applet's
786
+ // surface client from here, wherever the CLI runs this package from.
787
+ const modulePath = host.paths.fileURLToPath(import.meta.url);
788
+ const hereDir = host.paths.dirname(modulePath);
789
+ const moduleExtension = host.paths.extname(modulePath);
790
+ const { kitRoot, kitStylesheet, resolveDirs, svelteUrl, twAnimateRoot, packageSourceDir, surfaceClientUrl } = await resolveServePackageRoots({
791
+ host,
792
+ runtime,
793
+ tools,
794
+ workspaceRoot,
795
+ packageDir: hereDir,
796
+ packageSourcePath: host.paths.fileURLToPath(new URL('../../', import.meta.url)),
797
+ surfaceClientPath: host.paths.fileURLToPath(new URL('./served-applet-browser' + moduleExtension, import.meta.url))
798
+ });
799
+ const workspacePosix = toPosix(workspaceRoot);
800
+ const appletRpc = createServedAppletRpc({ runtime, workspaceRoot });
801
+ const packagePosix = toPosix(packageSourceDir);
802
+ // Package roots a bare specifier resolved into, by real path. Installed
803
+ // packages already pass the `node_modules` check; workspace-linked ones
804
+ // resolve through their link to a real path that would otherwise refuse.
805
+ const admittedPackageRoots = new Set();
806
+ async function admitResolved(absolutePath) {
807
+ const root = await packageRootOf(host, (await realpathOrNullHost(host, absolutePath)) ?? absolutePath);
808
+ if (root)
809
+ admittedPackageRoots.add(toPosix(root));
810
+ }
811
+ const allowed = (absolutePath) => {
812
+ const candidate = toPosix(absolutePath);
813
+ return (candidate.startsWith(workspacePosix + '/') ||
814
+ candidate.startsWith(packagePosix + '/') ||
815
+ candidate.startsWith(toPosix(kitRoot) + '/') ||
816
+ candidate.includes('/node_modules/') ||
817
+ [...admittedPackageRoots].some(root => candidate.startsWith(root + '/')));
818
+ };
819
+ async function loadStylesheet(id, base) {
820
+ const resolved = isRelative(id)
821
+ ? host.paths.resolve(base, id)
822
+ : await resolveForBrowser(host, id, base, tools.resolve, STYLESHEET_CONDITIONS);
823
+ const path = resolved === null ? null : await realpathOrNullHost(host, resolved);
824
+ if (path === null) {
825
+ throw new CapabilityError('An imported applet stylesheet is unavailable.', 'UNAVAILABLE', {
826
+ reason: 'applet-stylesheet-import-unavailable', details: { id }
827
+ });
828
+ }
829
+ if (!allowed(path)) {
830
+ throw new CapabilityError('An imported stylesheet is outside the admitted module roots.', 'PERMISSION_DENIED', {
831
+ reason: 'applet-stylesheet-import-denied'
832
+ });
833
+ }
834
+ return { path, base: host.paths.dirname(path), content: textOf(await host.hostFiles.readFile(path, 'utf8')) };
835
+ }
836
+ // Actual text identity also catches edits that preserve size or timestamp granularity.
837
+ const moduleCache = new Map();
838
+ async function serveModule(requestedPath) {
839
+ const absolutePath = await realpathOrNullHost(host, requestedPath);
840
+ if (!absolutePath)
841
+ return new Response('Not found', { status: 404 });
842
+ const info = await statChecked(host.hostFiles, absolutePath);
843
+ if (!info.found || info.stat.kind !== 'file')
844
+ return new Response('Not found', { status: 404 });
845
+ const ext = host.paths.extname(absolutePath);
846
+ if (ext === '.css')
847
+ return new Response(asBody(await host.hostFiles.readFile(absolutePath)), { headers: CSS_HEADERS });
848
+ if (ext === '.json')
849
+ return new Response(asBody(await host.hostFiles.readFile(absolutePath)), { headers: JSON_HEADERS });
850
+ const original = textOf(await host.hostFiles.readFile(absolutePath, 'utf8'));
851
+ const source = ext === '.svelte'
852
+ ? await prepareServedSvelte(original, { path: absolutePath, base: host.paths.dirname(absolutePath) }, tools.compileStyle)
853
+ : original;
854
+ const cached = moduleCache.get(absolutePath);
855
+ if (cached && cached.source === source)
856
+ return new Response(cached.code, { headers: JS_HEADERS });
857
+ const ctx = { tools, host, fromDirs: [host.paths.dirname(absolutePath), ...resolveDirs], admitResolved };
858
+ let code;
859
+ const runeModule = /\.svelte\.(js|ts|mjs|mts)$/.test(absolutePath);
860
+ if (ext === '.svelte') {
861
+ code = await rewriteModule(compile(source, { filename: absolutePath, generate: 'client', css: 'injected' }).js.code, ctx);
862
+ }
863
+ else if (runeModule) {
864
+ // `.svelte.js` / `.svelte.ts` rune modules need the module compiler,
865
+ // not a plain transpile — `$state` outside a component is an error.
866
+ const js = ext === '.ts' || ext === '.mts' ? tools.transpile(source) : source;
867
+ code = await rewriteModule(compileModule(js, { filename: absolutePath, generate: 'client' }).js.code, ctx);
868
+ }
869
+ else if (ext === '.ts' || ext === '.mts') {
870
+ code = await rewriteModule(tools.transpile(source), ctx);
871
+ }
872
+ else if (ext === '.js' || ext === '.mjs') {
873
+ code = await rewriteModule(source, ctx);
874
+ }
875
+ else {
876
+ return new Response(asBody(await host.hostFiles.readFile(absolutePath)), { headers: { 'cache-control': 'no-store' } });
877
+ }
878
+ moduleCache.set(absolutePath, { source, code });
879
+ return new Response(code, { headers: JS_HEADERS });
880
+ }
881
+ async function serveStylesheet(projectId) {
882
+ const sheet = kitStylesheet === null ? null : await readFileOrNullHost(host, kitStylesheet);
883
+ if (sheet === null || kitStylesheet === null)
884
+ return new Response('Not found', { status: 404 });
885
+ const project = projectId === null ? null : await loadProject(workspaceRoot, projectId, { tools, host, fromDirs: resolveDirs, admitResolved }, svelteUrl);
886
+ if (projectId !== null && project === null)
887
+ return new Response('Not found', { status: 404 });
888
+ const entry = project === null ? '/serve/index.js' : `/applet/${project.id}/applet.js`;
889
+ const sources = await collectServedStyleContents({
890
+ entry,
891
+ scan: tools.scan,
892
+ async load(url) {
893
+ let response = null;
894
+ const diskPath = fromFsUrl(host, url);
895
+ if (diskPath) {
896
+ const real = await realpathOrNullHost(host, diskPath);
897
+ if (real === null || (!allowed(real) && !allowed(diskPath))) {
898
+ throw new CapabilityError('A stylesheet source is outside the admitted module graph.', 'PERMISSION_DENIED', { reason: 'applet-style-source-denied' });
899
+ }
900
+ if (real.endsWith('.css') || real.endsWith('.json'))
901
+ return null;
902
+ response = await serveModule(real);
903
+ }
904
+ else if (project && url === entry) {
905
+ return project.compiledEntry;
906
+ }
907
+ else if (project && url.startsWith(`/applet/${project.id}/`)) {
908
+ response = await serveAppletCompanion({ workspaceRoot, id: project.id, project, rest: url.slice(`/applet/${project.id}/`.length), tools, host, resolveDirs, admitResolved });
909
+ }
910
+ else if (url === '/serve/index.js') {
911
+ response = await serveModule(host.paths.fileURLToPath(new URL('../../svelte/serve-index.svelte', import.meta.url)));
912
+ }
913
+ else if (url === '/applets/messages.js') {
914
+ response = await serveModule(host.paths.fileURLToPath(new URL('../../schemas/applet-messages' + moduleExtension, import.meta.url)));
915
+ }
916
+ // Shims, raw resources and stylesheet-link modules contain no utility sources.
917
+ if (response === null)
918
+ return null;
919
+ if (!response.ok)
920
+ throw new CapabilityError('An admitted stylesheet module could not be read.', 'UNAVAILABLE', { reason: 'applet-style-source-unavailable', details: { url, status: response.status } });
921
+ if (response.headers.get('content-type')?.split(';')[0] !== JS_HEADERS['content-type'])
922
+ return null;
923
+ return response.text();
924
+ }
925
+ });
926
+ let content = textOf(sheet);
927
+ if (twAnimateRoot === null)
928
+ content = content.replace(/@import\s+['"]tw-animate-css['"];?/, '');
929
+ const css = await compileServedStylesheet(serveHost, {
930
+ entry: { path: kitStylesheet, base: host.paths.dirname(kitStylesheet), content: `@import 'tailwindcss';\n${content}` },
931
+ sources,
932
+ loadStylesheet
933
+ });
934
+ return new Response(css, { headers: CSS_HEADERS });
935
+ }
936
+ const server = serveHost.startAppletServeHost({
937
+ port,
938
+ hostname,
939
+ fetch: async (request) => {
940
+ const url = new URL(request.url);
941
+ const path = url.pathname;
942
+ // Health / registry — the reuse probe and the machine surface.
943
+ if (path === HEALTH_PATH) {
944
+ const ids = await listAppletProjectIds(workspaceRoot, host);
945
+ const applets = await Promise.all(ids.map(async (pid) => ({ id: pid, entry: 'Applet.svelte' })));
946
+ const health = { ok: true, root: workspaceRoot, applets };
947
+ return new Response(JSON.stringify(serveHealthSchema.parse(health)), { headers: JSON_HEADERS });
948
+ }
949
+ // ---- Modules: the filesystem mirror ----
950
+ if (path.startsWith(RAW_MODULE_PREFIX + '/')) {
951
+ const rawPath = fromFsUrl(host, path.slice(RAW_MODULE_PREFIX.length));
952
+ const real = rawPath ? await realpathOrNullHost(host, rawPath) : null;
953
+ if (!rawPath || !real)
954
+ return new Response('Not found', { status: 404 });
955
+ if (!allowed(real) && !allowed(rawPath))
956
+ return new Response('Forbidden', { status: 403 });
957
+ const text = textOf(await host.hostFiles.readFile(real, 'utf8'));
958
+ return new Response(`export default ${JSON.stringify(text)};\n`, { headers: JS_HEADERS });
959
+ }
960
+ if (path.startsWith(WORKER_MODULE_PREFIX + '/')) {
961
+ const workerPath = fromFsUrl(host, path.slice(WORKER_MODULE_PREFIX.length));
962
+ const real = workerPath ? await realpathOrNullHost(host, workerPath) : null;
963
+ if (!workerPath || !real)
964
+ return new Response('Not found', { status: 404 });
965
+ if (!allowed(real) && !allowed(workerPath))
966
+ return new Response('Forbidden', { status: 403 });
967
+ return new Response(workerModule(toFsUrl(real)), { headers: JS_HEADERS });
968
+ }
969
+ if (path.startsWith(CSS_MODULE_PREFIX + '/') && path.endsWith('.css')) {
970
+ return new Response(cssModule(path.slice(CSS_MODULE_PREFIX.length)), { headers: JS_HEADERS });
971
+ }
972
+ if (path.startsWith(SHIM_PREFIX) && path.endsWith('.js')) {
973
+ const specifier = shimSpecifierSchema.safeParse(decodeURIComponent(path.slice(SHIM_PREFIX.length, -3)));
974
+ if (specifier.success)
975
+ return new Response(SHIMS[specifier.data], { headers: JS_HEADERS });
976
+ return new Response('Not found', { status: 404 });
977
+ }
978
+ const fsPath = fromFsUrl(host, path);
979
+ if (fsPath) {
980
+ const real = await realpathOrNullHost(host, fsPath);
981
+ if (!real)
982
+ return new Response('Not found', { status: 404 });
983
+ if (!allowed(real) && !allowed(fsPath))
984
+ return new Response('Forbidden', { status: 403 });
985
+ return serveModule(real);
986
+ }
987
+ // ---- Kit stylesheet and the sheets it imports ----
988
+ if (path === '/kit/styles.css') {
989
+ const project = url.searchParams.get('project');
990
+ return serveStylesheet(project === null ? null : servedAppletSchema.shape.id.parse(project));
991
+ }
992
+ if (path.startsWith('/kit/styles/') && path.endsWith('.css')) {
993
+ const name = path.slice('/kit/styles/'.length);
994
+ if (name.includes('..'))
995
+ return new Response('Not found', { status: 404 });
996
+ // The sheets the kit stylesheet imports sit beside it (`./styles/<name>`).
997
+ const sheet = kitStylesheet === null ? null : await readFileOrNullHost(host, host.paths.join(host.paths.dirname(kitStylesheet), 'styles', name));
998
+ if (sheet === null)
999
+ return new Response('Not found', { status: 404 });
1000
+ return new Response(asBody(sheet), { headers: CSS_HEADERS });
1001
+ }
1002
+ // ---- Shared message schemas, compiled through the same pipeline ----
1003
+ if (path === '/applets/messages.js') {
1004
+ const abs = host.paths.fileURLToPath(new URL('../../schemas/applet-messages' + moduleExtension, import.meta.url));
1005
+ return serveModule(abs);
1006
+ }
1007
+ // Chrome: the kit-composed index, compiled through the same pipeline.
1008
+ if (path === '/serve/index.js') {
1009
+ const abs = host.paths.fileURLToPath(new URL('../../svelte/serve-index.svelte', import.meta.url));
1010
+ const response = await serveModule(abs);
1011
+ if (!response.ok)
1012
+ return response;
1013
+ return new Response(withMountAdapter(await response.text(), svelteUrl), { headers: JS_HEADERS });
1014
+ }
1015
+ // Index — kit-composed chrome, rescan per request.
1016
+ if (path === '/') {
1017
+ return new Response(indexHostPage(), { headers: HTML_HEADERS });
1018
+ }
1019
+ // Applet-scoped routes.
1020
+ const m = /^\/applet\/([a-z0-9-]+)(?:\/(.*))?$/.exec(path);
1021
+ if (m) {
1022
+ const id = m[1];
1023
+ const rest = m[2] ?? '';
1024
+ if (rest.startsWith('rpc/'))
1025
+ return appletRpc.handle(id, request);
1026
+ // The applet's root surface: answered from the project's manifest
1027
+ // alone, so it never compiles the entry.
1028
+ if (rest === 'surface') {
1029
+ return answerServedAppletSurface({ runtime, workspaceRoot, projectId: id, request });
1030
+ }
1031
+ const project = await loadProject(workspaceRoot, id, { tools, host, fromDirs: resolveDirs, admitResolved }, svelteUrl);
1032
+ if (!project) {
1033
+ return new Response(JSON.stringify({ error: `No applet "${id}"` }), { status: 404, headers: JSON_HEADERS });
1034
+ }
1035
+ if (rest === '') {
1036
+ return new Response(hostPage(id, surfaceClientUrl), { headers: HTML_HEADERS });
1037
+ }
1038
+ if (rest === 'applet.js') {
1039
+ return new Response(project.compiledEntry, { headers: JS_HEADERS });
1040
+ }
1041
+ if (rest === 'files') {
1042
+ const body = {
1043
+ id,
1044
+ entry: project.entry,
1045
+ files: Object.entries(project.sources).map(([p, contents]) => ({ path: p, contents }))
1046
+ };
1047
+ return new Response(JSON.stringify(servedAppletFilesSchema.parse(body)), { headers: JSON_HEADERS });
1048
+ }
1049
+ const companion = await serveAppletCompanion({
1050
+ workspaceRoot,
1051
+ id,
1052
+ project,
1053
+ rest,
1054
+ tools,
1055
+ host,
1056
+ resolveDirs,
1057
+ admitResolved
1058
+ });
1059
+ if (companion)
1060
+ return companion;
1061
+ return new Response(JSON.stringify({ error: 'Not found' }), { status: 404, headers: JSON_HEADERS });
1062
+ }
1063
+ return new Response('Not found', { status: 404 });
1064
+ }
1065
+ });
1066
+ const ids = await listAppletProjectIds(workspaceRoot, host);
1067
+ await writeStdoutLine(runtime, `Applet server serving ${ids.length} project(s) at ${base} (Ctrl+C to stop)`);
1068
+ if (id) {
1069
+ if (!ids.includes(id))
1070
+ await writeStdoutLine(runtime, `(no project "${id}" yet — it will appear once created under .vibes/applets)`);
1071
+ await writeStdoutLine(runtime, `Open ${base}/applet/${id}/`);
1072
+ }
1073
+ else {
1074
+ await writeStdoutLine(runtime, `Open ${base}/`);
1075
+ }
1076
+ // The command owns the server's lifetime: it stays pending until a signal
1077
+ // asks it to stop, so the CLI host never auto-exits underneath Bun.serve.
1078
+ const lifetime = await createCLIActionLifetime(runtime, async () => {
1079
+ await Promise.all([
1080
+ Promise.resolve().then(() => {
1081
+ try {
1082
+ server.stop();
1083
+ }
1084
+ finally {
1085
+ moduleCache.clear();
1086
+ }
1087
+ }),
1088
+ appletRpc.close()
1089
+ ]);
1090
+ });
1091
+ lifetime.bindProcessSignals();
1092
+ await lifetime.wait();
1093
+ }
1094
+ const serveArgsSchema = z.object({ id: z.string().min(1).optional() }).passthrough();
1095
+ const serveOptionsSchema = z.object({ port: z.number().optional(), root: z.string().min(1).optional() }).passthrough();
1096
+ export async function execute(args, options, context) {
1097
+ const parsedArgs = serveArgsSchema.safeParse(args);
1098
+ const parsedOptions = serveOptionsSchema.safeParse(options);
1099
+ const id = parsedArgs.success ? parsedArgs.data.id : undefined;
1100
+ const port = parsedOptions.success ? parsedOptions.data.port : undefined;
1101
+ const root = parsedOptions.success ? parsedOptions.data.root : undefined;
1102
+ await run(context.runtime, id, { port, root });
1103
+ }
1104
+ export default { execute };
1105
+ //# sourceMappingURL=serve.command.impl.js.map