gemi 0.109.0 → 0.111.0

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 (267) hide show
  1. package/dist/ai/Agent.d.ts +11 -0
  2. package/dist/ai/Agent.d.ts.map +1 -1
  3. package/dist/ai/AgentController.d.ts +7 -0
  4. package/dist/ai/AgentController.d.ts.map +1 -1
  5. package/dist/ai/index.js +11 -11
  6. package/dist/ai/index.js.map +4 -4
  7. package/dist/app/index.js +2 -2
  8. package/dist/app/index.js.map +1 -1
  9. package/dist/bin/gemi.js +485 -63
  10. package/dist/bin/gemi.js.map +12 -8
  11. package/dist/bun/plugin.js +2 -2
  12. package/dist/bun/plugin.js.map +1 -1
  13. package/dist/bun/preload.js +2 -2
  14. package/dist/bun/preload.js.map +1 -1
  15. package/dist/{chunk-hgz8sx40.js → chunk-09ypnhjv.js} +3 -3
  16. package/dist/{chunk-hgz8sx40.js.map → chunk-09ypnhjv.js.map} +1 -1
  17. package/dist/{chunk-qnq110tw.js → chunk-0d9qsmx2.js} +3 -3
  18. package/dist/{chunk-qnq110tw.js.map → chunk-0d9qsmx2.js.map} +1 -1
  19. package/dist/{chunk-m9609t1y.js → chunk-0sjh5v1n.js} +1 -1
  20. package/dist/{chunk-g5a3ptsa.js → chunk-11fsn5mr.js} +3 -3
  21. package/dist/{chunk-g5a3ptsa.js.map → chunk-11fsn5mr.js.map} +1 -1
  22. package/dist/chunk-1bkr5wnt.js +58 -0
  23. package/dist/chunk-1bkr5wnt.js.map +14 -0
  24. package/dist/{chunk-whe0x70j.js → chunk-1c1d0e60.js} +3 -3
  25. package/dist/{chunk-whe0x70j.js.map → chunk-1c1d0e60.js.map} +1 -1
  26. package/dist/{chunk-rgfzqwpg.js → chunk-1kr25rcg.js} +3 -3
  27. package/dist/{chunk-rgfzqwpg.js.map → chunk-1kr25rcg.js.map} +1 -1
  28. package/dist/{chunk-vee4j6ft.js → chunk-1pem26zc.js} +3 -3
  29. package/dist/{chunk-vee4j6ft.js.map → chunk-1pem26zc.js.map} +1 -1
  30. package/dist/{chunk-nxxx0m1a.js → chunk-1va15sfq.js} +2 -2
  31. package/dist/{chunk-nxxx0m1a.js.map → chunk-1va15sfq.js.map} +2 -2
  32. package/dist/{chunk-wvwee7dn.js → chunk-1yx2e0bh.js} +2 -2
  33. package/dist/{chunk-wvwee7dn.js.map → chunk-1yx2e0bh.js.map} +1 -1
  34. package/dist/{chunk-9r3znmqq.js → chunk-303mprnv.js} +2 -2
  35. package/dist/{chunk-9r3znmqq.js.map → chunk-303mprnv.js.map} +1 -1
  36. package/dist/{chunk-grs8dnkd.js → chunk-30xjcyzh.js} +2 -2
  37. package/dist/{chunk-grs8dnkd.js.map → chunk-30xjcyzh.js.map} +1 -1
  38. package/dist/{chunk-h15eae7g.js → chunk-358sdcx9.js} +3 -3
  39. package/dist/{chunk-h15eae7g.js.map → chunk-358sdcx9.js.map} +1 -1
  40. package/dist/{chunk-367kyrdx.js → chunk-3cg7y62b.js} +2 -2
  41. package/dist/{chunk-367kyrdx.js.map → chunk-3cg7y62b.js.map} +1 -1
  42. package/dist/{chunk-t26n9vzw.js → chunk-3y8q8x11.js} +2 -2
  43. package/dist/{chunk-t26n9vzw.js.map → chunk-3y8q8x11.js.map} +1 -1
  44. package/dist/chunk-4mfrgd5m.js +34 -0
  45. package/dist/chunk-4mfrgd5m.js.map +10 -0
  46. package/dist/chunk-5cygrbxv.js +4 -0
  47. package/dist/{chunk-9qw9fa6z.js.map → chunk-5cygrbxv.js.map} +2 -2
  48. package/dist/{chunk-tvy2fqza.js → chunk-5stgtwqw.js} +2 -2
  49. package/dist/{chunk-tvy2fqza.js.map → chunk-5stgtwqw.js.map} +1 -1
  50. package/dist/chunk-6chz1ktz.js +9 -0
  51. package/dist/chunk-6chz1ktz.js.map +13 -0
  52. package/dist/{chunk-wqsdjweb.js → chunk-6vr7f5fq.js} +4 -4
  53. package/dist/{chunk-wqsdjweb.js.map → chunk-6vr7f5fq.js.map} +1 -1
  54. package/dist/{chunk-g74qwhvf.js → chunk-7tx5y712.js} +2 -2
  55. package/dist/{chunk-g74qwhvf.js.map → chunk-7tx5y712.js.map} +1 -1
  56. package/dist/{chunk-g7fr2cy2.js → chunk-8afxrmdc.js} +3 -3
  57. package/dist/{chunk-g7fr2cy2.js.map → chunk-8afxrmdc.js.map} +1 -1
  58. package/dist/{chunk-vwkdfngg.js → chunk-8b2tw2yp.js} +1 -1
  59. package/dist/{chunk-t3qw9syt.js → chunk-9rchedr4.js} +2 -2
  60. package/dist/{chunk-t3qw9syt.js.map → chunk-9rchedr4.js.map} +1 -1
  61. package/dist/{chunk-jm4jn28j.js → chunk-9s851qz8.js} +2 -2
  62. package/dist/{chunk-jm4jn28j.js.map → chunk-9s851qz8.js.map} +1 -1
  63. package/dist/{chunk-jc4j61xb.js → chunk-a6453d9s.js} +3 -3
  64. package/dist/{chunk-jc4j61xb.js.map → chunk-a6453d9s.js.map} +1 -1
  65. package/dist/{chunk-9m18pknp.js → chunk-bn5yn731.js} +2 -2
  66. package/dist/{chunk-9m18pknp.js.map → chunk-bn5yn731.js.map} +1 -1
  67. package/dist/{chunk-t85rca2p.js → chunk-c098fzvk.js} +2 -2
  68. package/dist/{chunk-t85rca2p.js.map → chunk-c098fzvk.js.map} +1 -1
  69. package/dist/{chunk-mp5krm14.js → chunk-cttmy1jp.js} +4 -4
  70. package/dist/{chunk-mp5krm14.js.map → chunk-cttmy1jp.js.map} +2 -2
  71. package/dist/{chunk-eyg88bgv.js → chunk-cy5qp6mz.js} +3 -3
  72. package/dist/{chunk-eyg88bgv.js.map → chunk-cy5qp6mz.js.map} +1 -1
  73. package/dist/{chunk-zys7kecf.js → chunk-ddr4qvvt.js} +3 -3
  74. package/dist/{chunk-zys7kecf.js.map → chunk-ddr4qvvt.js.map} +1 -1
  75. package/dist/{chunk-r9gzbjc5.js → chunk-et4pv1b1.js} +1 -1
  76. package/dist/{chunk-a1g0bahx.js → chunk-frerzsxq.js} +2 -2
  77. package/dist/{chunk-a1g0bahx.js.map → chunk-frerzsxq.js.map} +1 -1
  78. package/dist/{chunk-qz9aaw5x.js → chunk-gb37722w.js} +3 -3
  79. package/dist/{chunk-qz9aaw5x.js.map → chunk-gb37722w.js.map} +1 -1
  80. package/dist/chunk-h3864a8z.js +17 -0
  81. package/dist/{chunk-s5aa4hty.js.map → chunk-h3864a8z.js.map} +13 -12
  82. package/dist/{chunk-zhm3qvrc.js → chunk-h4sw6nt3.js} +3 -3
  83. package/dist/{chunk-zhm3qvrc.js.map → chunk-h4sw6nt3.js.map} +1 -1
  84. package/dist/{chunk-5d6eaxab.js → chunk-he7z7y9j.js} +2 -2
  85. package/dist/{chunk-5d6eaxab.js.map → chunk-he7z7y9j.js.map} +1 -1
  86. package/dist/{chunk-d2tngs73.js → chunk-hf7a51s3.js} +2 -2
  87. package/dist/{chunk-d2tngs73.js.map → chunk-hf7a51s3.js.map} +1 -1
  88. package/dist/chunk-hn67spz6.js +5 -0
  89. package/dist/{chunk-z9x8x3wq.js.map → chunk-hn67spz6.js.map} +1 -1
  90. package/dist/{chunk-f7jhkg8x.js → chunk-jbrwt3cs.js} +4 -4
  91. package/dist/{chunk-f7jhkg8x.js.map → chunk-jbrwt3cs.js.map} +1 -1
  92. package/dist/{chunk-k1ezptt8.js → chunk-k1vw22t2.js} +2 -2
  93. package/dist/{chunk-k1ezptt8.js.map → chunk-k1vw22t2.js.map} +1 -1
  94. package/dist/chunk-k1xt2tw7.js +4 -0
  95. package/dist/{chunk-rjcsdazt.js.map → chunk-k1xt2tw7.js.map} +2 -2
  96. package/dist/{chunk-7mc5e61r.js → chunk-kf71mjxa.js} +3 -3
  97. package/dist/{chunk-7mc5e61r.js.map → chunk-kf71mjxa.js.map} +1 -1
  98. package/dist/{chunk-vna85rdq.js → chunk-m6ystvtk.js} +2 -2
  99. package/dist/{chunk-vna85rdq.js.map → chunk-m6ystvtk.js.map} +1 -1
  100. package/dist/{chunk-qyyxzy04.js → chunk-mb7q7s0a.js} +3 -3
  101. package/dist/{chunk-qyyxzy04.js.map → chunk-mb7q7s0a.js.map} +1 -1
  102. package/dist/{chunk-sp2v357a.js → chunk-mn5xw79b.js} +3 -3
  103. package/dist/{chunk-sp2v357a.js.map → chunk-mn5xw79b.js.map} +1 -1
  104. package/dist/{chunk-q8k7f11z.js → chunk-mwqg079k.js} +2 -2
  105. package/dist/{chunk-q8k7f11z.js.map → chunk-mwqg079k.js.map} +1 -1
  106. package/dist/{chunk-ga533cpz.js → chunk-nncz308h.js} +3 -3
  107. package/dist/{chunk-ga533cpz.js.map → chunk-nncz308h.js.map} +1 -1
  108. package/dist/{chunk-hf32yq23.js → chunk-nsvktvp4.js} +2 -2
  109. package/dist/{chunk-hf32yq23.js.map → chunk-nsvktvp4.js.map} +1 -1
  110. package/dist/{chunk-3x86bhfn.js → chunk-nvv9wej6.js} +3 -3
  111. package/dist/{chunk-3x86bhfn.js.map → chunk-nvv9wej6.js.map} +1 -1
  112. package/dist/chunk-p1aqq0ga.js +16 -0
  113. package/dist/{chunk-d5sbnzng.js.map → chunk-p1aqq0ga.js.map} +5 -9
  114. package/dist/chunk-p7r2w4qw.js +5 -0
  115. package/dist/{chunk-ehasw3qm.js.map → chunk-p7r2w4qw.js.map} +2 -2
  116. package/dist/{chunk-zz7h6tdr.js → chunk-pwmgqq7z.js} +2 -2
  117. package/dist/{chunk-zz7h6tdr.js.map → chunk-pwmgqq7z.js.map} +1 -1
  118. package/dist/chunk-pyj7cd9t.js +4 -0
  119. package/dist/{chunk-gdsby5jh.js.map → chunk-pyj7cd9t.js.map} +2 -2
  120. package/dist/{chunk-h6g9g8qc.js → chunk-q9s7kwgt.js} +3 -3
  121. package/dist/{chunk-h6g9g8qc.js.map → chunk-q9s7kwgt.js.map} +1 -1
  122. package/dist/{chunk-9hbwvcxn.js → chunk-qd2v93y4.js} +2 -2
  123. package/dist/{chunk-9hbwvcxn.js.map → chunk-qd2v93y4.js.map} +1 -1
  124. package/dist/{chunk-tr9mxdth.js → chunk-rfcygmf5.js} +3 -3
  125. package/dist/{chunk-tr9mxdth.js.map → chunk-rfcygmf5.js.map} +1 -1
  126. package/dist/{chunk-vsnmdtrs.js → chunk-s6jjy4y9.js} +2 -2
  127. package/dist/{chunk-vsnmdtrs.js.map → chunk-s6jjy4y9.js.map} +1 -1
  128. package/dist/{chunk-6zekebzt.js → chunk-sq2wkynk.js} +2 -2
  129. package/dist/{chunk-6zekebzt.js.map → chunk-sq2wkynk.js.map} +1 -1
  130. package/dist/{chunk-52vsdnny.js → chunk-td8tha3j.js} +3 -3
  131. package/dist/{chunk-52vsdnny.js.map → chunk-td8tha3j.js.map} +1 -1
  132. package/dist/chunk-tdsfke9q.js +6 -0
  133. package/dist/{chunk-fe1pcnw6.js.map → chunk-tdsfke9q.js.map} +5 -4
  134. package/dist/{chunk-t0bp8nrc.js → chunk-tk5q8hkv.js} +4 -4
  135. package/dist/{chunk-t0bp8nrc.js.map → chunk-tk5q8hkv.js.map} +2 -2
  136. package/dist/{chunk-dpy08xw4.js → chunk-tq85n8zh.js} +2 -2
  137. package/dist/{chunk-dpy08xw4.js.map → chunk-tq85n8zh.js.map} +1 -1
  138. package/dist/{chunk-wdpdqjr1.js → chunk-twnn7r66.js} +2 -2
  139. package/dist/{chunk-wdpdqjr1.js.map → chunk-twnn7r66.js.map} +1 -1
  140. package/dist/chunk-w7jsh3xd.js +5 -0
  141. package/dist/{chunk-1es50p4k.js.map → chunk-w7jsh3xd.js.map} +2 -2
  142. package/dist/chunk-wqvvjd5r.js +24 -0
  143. package/dist/{chunk-w3j53r0a.js.map → chunk-wqvvjd5r.js.map} +4 -4
  144. package/dist/{chunk-zh1t33nq.js → chunk-wsttx9rg.js} +2 -2
  145. package/dist/{chunk-zh1t33nq.js.map → chunk-wsttx9rg.js.map} +1 -1
  146. package/dist/{chunk-7ssjzp87.js → chunk-wvsv1jgg.js} +2 -2
  147. package/dist/{chunk-7ssjzp87.js.map → chunk-wvsv1jgg.js.map} +1 -1
  148. package/dist/chunk-x78jrs4y.js +4 -0
  149. package/dist/{chunk-y66ntxbg.js.map → chunk-x78jrs4y.js.map} +2 -2
  150. package/dist/chunk-xk930yaw.js +5 -0
  151. package/dist/{chunk-pa3khk46.js.map → chunk-xk930yaw.js.map} +2 -2
  152. package/dist/chunk-xkc7ftnq.js +9 -0
  153. package/dist/chunk-xkc7ftnq.js.map +10 -0
  154. package/dist/{chunk-564zfdd1.js → chunk-yer1r3t3.js} +2 -2
  155. package/dist/{chunk-564zfdd1.js.map → chunk-yer1r3t3.js.map} +1 -1
  156. package/dist/{chunk-c8dhvdrs.js → chunk-yqavgpwd.js} +3 -3
  157. package/dist/{chunk-c8dhvdrs.js.map → chunk-yqavgpwd.js.map} +1 -1
  158. package/dist/{chunk-hyfzw1fk.js → chunk-z10cas5r.js} +2 -2
  159. package/dist/{chunk-hyfzw1fk.js.map → chunk-z10cas5r.js.map} +1 -1
  160. package/dist/{chunk-jgtean4t.js → chunk-zhs1r1z0.js} +3 -3
  161. package/dist/{chunk-jgtean4t.js.map → chunk-zhs1r1z0.js.map} +1 -1
  162. package/dist/client/index.d.ts +1 -1
  163. package/dist/client/index.d.ts.map +1 -1
  164. package/dist/client/index.js +106 -52
  165. package/dist/client/index.js.map +1 -1
  166. package/dist/client/islands.d.ts +99 -56
  167. package/dist/client/islands.d.ts.map +1 -1
  168. package/dist/config/index.d.ts +8 -1
  169. package/dist/config/index.d.ts.map +1 -1
  170. package/dist/config/index.js +1 -1
  171. package/dist/config/index.js.map +2 -2
  172. package/dist/console/run.js +2 -2
  173. package/dist/console/run.js.map +1 -1
  174. package/dist/container/index.js +2 -2
  175. package/dist/container/index.js.map +1 -1
  176. package/dist/database/index.js +2 -2
  177. package/dist/database/index.js.map +1 -1
  178. package/dist/email/index.js +2 -2
  179. package/dist/email/index.js.map +1 -1
  180. package/dist/facades/Lang.d.ts +7 -1
  181. package/dist/facades/Lang.d.ts.map +1 -1
  182. package/dist/facades/index.js +2 -2
  183. package/dist/facades/index.js.map +1 -1
  184. package/dist/foundation/index.js +2 -2
  185. package/dist/foundation/index.js.map +1 -1
  186. package/dist/http/CorsMiddleware.d.ts +13 -0
  187. package/dist/http/CorsMiddleware.d.ts.map +1 -1
  188. package/dist/http/Middleware.d.ts +11 -0
  189. package/dist/http/Middleware.d.ts.map +1 -1
  190. package/dist/http/ViewRouter.d.ts +29 -0
  191. package/dist/http/ViewRouter.d.ts.map +1 -1
  192. package/dist/http/index.js +2 -2
  193. package/dist/http/index.js.map +1 -1
  194. package/dist/i18n/dictionaryRuntime.js +2 -2
  195. package/dist/i18n/dictionaryRuntime.js.map +1 -1
  196. package/dist/i18n/index.js +2 -2
  197. package/dist/i18n/index.js.map +1 -1
  198. package/dist/internal/islandRuntime.d.ts +45 -0
  199. package/dist/internal/islandRuntime.d.ts.map +1 -0
  200. package/dist/kernel/index.js +2 -2
  201. package/dist/kernel/index.js.map +1 -1
  202. package/dist/orm/context.d.ts +24 -0
  203. package/dist/orm/context.d.ts.map +1 -1
  204. package/dist/orm/index.d.ts +1 -1
  205. package/dist/orm/index.d.ts.map +1 -1
  206. package/dist/orm/index.js +3 -3
  207. package/dist/orm/index.js.map +2 -2
  208. package/dist/server/devFetch.d.ts.map +1 -1
  209. package/dist/server/httpDev.d.ts.map +1 -1
  210. package/dist/server/httpProd.d.ts.map +1 -1
  211. package/dist/server/idleTimeout.d.ts +24 -0
  212. package/dist/server/idleTimeout.d.ts.map +1 -0
  213. package/dist/server/index.js +2 -2
  214. package/dist/server/index.js.map +1 -1
  215. package/dist/server/modulePreloads.d.ts +7 -6
  216. package/dist/server/modulePreloads.d.ts.map +1 -1
  217. package/dist/services/index.js +2 -2
  218. package/dist/services/index.js.map +1 -1
  219. package/dist/services/middleware/MiddlewareRegistry.d.ts +13 -2
  220. package/dist/services/middleware/MiddlewareRegistry.d.ts.map +1 -1
  221. package/dist/services/queue/work.js +2 -2
  222. package/dist/services/queue/work.js.map +1 -1
  223. package/dist/services/router/DomainRouter.d.ts +10 -0
  224. package/dist/services/router/DomainRouter.d.ts.map +1 -1
  225. package/dist/services/router/ViewRouteDispatcher.d.ts +3 -1
  226. package/dist/services/router/ViewRouteDispatcher.d.ts.map +1 -1
  227. package/dist/services/router/staticCache.d.ts +23 -0
  228. package/dist/services/router/staticCache.d.ts.map +1 -0
  229. package/dist/services/router/staticDocument.d.ts +39 -17
  230. package/dist/services/router/staticDocument.d.ts.map +1 -1
  231. package/dist/stats/bundleStats.d.ts +104 -0
  232. package/dist/stats/bundleStats.d.ts.map +1 -0
  233. package/dist/stats/route-table.d.ts +2 -0
  234. package/dist/stats/route-table.d.ts.map +1 -0
  235. package/dist/stats/route-table.js +4 -0
  236. package/dist/stats/route-table.js.map +11 -0
  237. package/dist/stats/routeTable.d.ts +25 -0
  238. package/dist/stats/routeTable.d.ts.map +1 -0
  239. package/dist/stats/run.d.ts +43 -0
  240. package/dist/stats/run.d.ts.map +1 -0
  241. package/dist/support/index.js +2 -2
  242. package/dist/support/index.js.map +1 -1
  243. package/dist/vite/index.mjs +125 -23
  244. package/dist/vitest/index.d.ts +18 -0
  245. package/dist/vitest/index.d.ts.map +1 -1
  246. package/dist/vitest/index.js +2 -2
  247. package/dist/vitest/index.js.map +3 -3
  248. package/package.json +2 -1
  249. package/dist/chunk-1es50p4k.js +0 -5
  250. package/dist/chunk-9qw9fa6z.js +0 -4
  251. package/dist/chunk-d5sbnzng.js +0 -18
  252. package/dist/chunk-ehasw3qm.js +0 -5
  253. package/dist/chunk-fe1pcnw6.js +0 -6
  254. package/dist/chunk-fj6yftm7.js +0 -58
  255. package/dist/chunk-fj6yftm7.js.map +0 -14
  256. package/dist/chunk-gdsby5jh.js +0 -4
  257. package/dist/chunk-ngw4xzrt.js +0 -9
  258. package/dist/chunk-ngw4xzrt.js.map +0 -10
  259. package/dist/chunk-pa3khk46.js +0 -5
  260. package/dist/chunk-rjcsdazt.js +0 -4
  261. package/dist/chunk-s5aa4hty.js +0 -17
  262. package/dist/chunk-w3j53r0a.js +0 -24
  263. package/dist/chunk-y66ntxbg.js +0 -4
  264. package/dist/chunk-z9x8x3wq.js +0 -5
  265. /package/dist/{chunk-m9609t1y.js.map → chunk-0sjh5v1n.js.map} +0 -0
  266. /package/dist/{chunk-vwkdfngg.js.map → chunk-8b2tw2yp.js.map} +0 -0
  267. /package/dist/{chunk-r9gzbjc5.js.map → chunk-et4pv1b1.js.map} +0 -0
package/dist/bin/gemi.js CHANGED
@@ -35956,7 +35956,7 @@ function camelCase(text) {
35956
35956
 
35957
35957
  // bin/ai-client/extract.ts
35958
35958
  import { createRequire } from "module";
35959
- import path7 from "path";
35959
+ import path8 from "path";
35960
35960
  function parseAgentReference(reference) {
35961
35961
  const hash = reference.lastIndexOf("#");
35962
35962
  if (hash === -1)
@@ -35970,7 +35970,7 @@ function parseAgentReference(reference) {
35970
35970
  }
35971
35971
  async function loadTypeScript(cwd) {
35972
35972
  try {
35973
- return createRequire(path7.join(cwd, "package.json"))("typescript");
35973
+ return createRequire(path8.join(cwd, "package.json"))("typescript");
35974
35974
  } catch {
35975
35975
  try {
35976
35976
  return (await import("typescript")).default;
@@ -35980,7 +35980,7 @@ async function loadTypeScript(cwd) {
35980
35980
  }
35981
35981
  }
35982
35982
  function extractAgent(ts, reference, { cwd = process.cwd(), name } = {}) {
35983
- const file = path7.resolve(cwd, reference.file);
35983
+ const file = path8.resolve(cwd, reference.file);
35984
35984
  if (!ts.sys.fileExists(file)) {
35985
35985
  throw new GenerateClientError(`${reference.file} does not exist.`);
35986
35986
  }
@@ -35992,7 +35992,7 @@ function extractAgent(ts, reference, { cwd = process.cwd(), name } = {}) {
35992
35992
  if (agentType.getSymbol()?.getName() !== "Agent" || !agentFile) {
35993
35993
  throw new GenerateClientError(`${reference.file}#${reference.exportName} is not an Agent \u2014 it is ` + `\`${checker.typeToString(agentType)}\`. Point at the value \`Agent.create(...)\` returned.`);
35994
35994
  }
35995
- const probe = path7.join(path7.dirname(file), `__gemi_generate_client_${process.pid}.ts`);
35995
+ const probe = path8.join(path8.dirname(file), `__gemi_generate_client_${process.pid}.ts`);
35996
35996
  const source = [
35997
35997
  `import type { OutputOf, ToolShapesOf } from ${JSON.stringify(specifier(probe, agentFile))};`,
35998
35998
  `import type * as agentModule from ${JSON.stringify(specifier(probe, file))};`,
@@ -36013,7 +36013,7 @@ function extractAgent(ts, reference, { cwd = process.cwd(), name } = {}) {
36013
36013
  return second.getTypeChecker().getTypeAtLocation(declaration.name);
36014
36014
  };
36015
36015
  const mapper = new TypeMapper(ts, second.getTypeChecker());
36016
- const agentName = name ?? pascalCase(exported === "default" ? path7.parse(file).name : exported);
36016
+ const agentName = name ?? pascalCase(exported === "default" ? path8.parse(file).name : exported);
36017
36017
  const toolsType = alias("Tools");
36018
36018
  const tools = mapper.checker.getPropertiesOfType(toolsType).map((tool) => {
36019
36019
  const shape = mapper.checker.getTypeOfSymbol(tool);
@@ -36029,7 +36029,7 @@ function extractAgent(ts, reference, { cwd = process.cwd(), name } = {}) {
36029
36029
  const output = mapper.map(alias("Output"), "StructuredOutput", "the agent's output");
36030
36030
  return {
36031
36031
  name: agentName,
36032
- source: `${path7.relative(cwd, file).split(path7.sep).join("/")}#${reference.exportName}`,
36032
+ source: `${path8.relative(cwd, file).split(path8.sep).join("/")}#${reference.exportName}`,
36033
36033
  tools,
36034
36034
  output,
36035
36035
  types: mapper.types,
@@ -36037,7 +36037,7 @@ function extractAgent(ts, reference, { cwd = process.cwd(), name } = {}) {
36037
36037
  };
36038
36038
  }
36039
36039
  function compilerOptions(ts, file) {
36040
- const configPath = ts.findConfigFile(path7.dirname(file), ts.sys.fileExists);
36040
+ const configPath = ts.findConfigFile(path8.dirname(file), ts.sys.fileExists);
36041
36041
  let options = {
36042
36042
  target: ts.ScriptTarget.ESNext,
36043
36043
  module: ts.ModuleKind.ESNext,
@@ -36045,7 +36045,7 @@ function compilerOptions(ts, file) {
36045
36045
  };
36046
36046
  if (configPath) {
36047
36047
  const config = ts.readConfigFile(configPath, ts.sys.readFile);
36048
- options = ts.parseJsonConfigFileContent(config.config, ts.sys, path7.dirname(configPath)).options;
36048
+ options = ts.parseJsonConfigFileContent(config.config, ts.sys, path8.dirname(configPath)).options;
36049
36049
  }
36050
36050
  return {
36051
36051
  ...options,
@@ -36067,7 +36067,7 @@ function exportedType(ts, checker, sourceFile, reference) {
36067
36067
  return { type: checker.getTypeOfSymbolAtLocation(symbol, sourceFile), name: symbol.getName() };
36068
36068
  }
36069
36069
  function specifier(from, to) {
36070
- const relative5 = path7.relative(path7.dirname(from), to).split(path7.sep).join("/").replace(/(\.d)?\.(ts|tsx|mts|cts)$/, "");
36070
+ const relative5 = path8.relative(path8.dirname(from), to).split(path8.sep).join("/").replace(/(\.d)?\.(ts|tsx|mts|cts)$/, "");
36071
36071
  return relative5.startsWith(".") ? relative5 : `./${relative5}`;
36072
36072
  }
36073
36073
  function isFrameworkJsonValue(type) {
@@ -36687,8 +36687,8 @@ __export(exports_generate, {
36687
36687
  PLATFORMS: () => PLATFORMS,
36688
36688
  GenerateClientError: () => GenerateClientError
36689
36689
  });
36690
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
36691
- import path8 from "path";
36690
+ import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
36691
+ import path9 from "path";
36692
36692
  async function generateClient(options) {
36693
36693
  const cwd = options.cwd ?? process.cwd();
36694
36694
  const platform = parsePlatform(options.platform);
@@ -36701,10 +36701,10 @@ async function generateClient(options) {
36701
36701
  }
36702
36702
  const ts = await loadTypeScript(cwd);
36703
36703
  const model = extractAgent(ts, parseAgentReference(options.agent), { cwd, name: options.name });
36704
- const directory = path8.resolve(cwd, options.out);
36705
- const file = path8.join(directory, `${model.name}.${platform === "swift" ? "swift" : "kt"}`);
36704
+ const directory = path9.resolve(cwd, options.out);
36705
+ const file = path9.join(directory, `${model.name}.${platform === "swift" ? "swift" : "kt"}`);
36706
36706
  mkdirSync3(directory, { recursive: true });
36707
- writeFileSync3(file, platform === "swift" ? renderSwift(model) : renderKotlin(model, options.package));
36707
+ writeFileSync4(file, platform === "swift" ? renderSwift(model) : renderKotlin(model, options.package));
36708
36708
  const warnings = [...model.warnings];
36709
36709
  if (platform === "swift" && options.package) {
36710
36710
  warnings.push("--package is for Kotlin; a Swift file has no package, so it was ignored.");
@@ -36726,10 +36726,10 @@ var init_generate = __esm(() => {
36726
36726
  });
36727
36727
 
36728
36728
  // bin/gemi.ts
36729
- import path9 from "path";
36730
- import { existsSync as existsSync8 } from "fs";
36729
+ import path10 from "path";
36730
+ import { existsSync as existsSync10 } from "fs";
36731
36731
  import { mkdtemp, rm } from "fs/promises";
36732
- import { tmpdir } from "os";
36732
+ import { tmpdir as tmpdir2 } from "os";
36733
36733
 
36734
36734
  // bin/createRollupInput.ts
36735
36735
  var {Glob } = globalThis.Bun;
@@ -36748,16 +36748,8 @@ async function createRollupInput_default(appDir) {
36748
36748
  continue;
36749
36749
  if (/\.(test|spec)\.tsx$/.test(file))
36750
36750
  continue;
36751
- if (/\.island\.tsx$/.test(file))
36752
- continue;
36753
36751
  entries.add(`/app/views/${file}`);
36754
36752
  }
36755
- const islandGlob = new Glob("**/*.island.{ts,tsx,js,jsx,mts,mjs}");
36756
- for await (const file of islandGlob.scan({ cwd: appDir })) {
36757
- if (file.split("/").includes("node_modules"))
36758
- continue;
36759
- entries.add(`/app/${file}`);
36760
- }
36761
36753
  return Array.from(entries);
36762
36754
  }
36763
36755
 
@@ -40099,7 +40091,48 @@ function documentBase(base) {
40099
40091
  // vite/islandPlugin.ts
40100
40092
  import { realpathSync } from "fs";
40101
40093
  import { relative, sep } from "path";
40102
- var ISLAND_LOADER = /\(\s*\)\s*=>\s*import\(\s*(["'])([^"'\n]+?\.island(?:\.[cm]?[jt]sx?)?)\1\s*\)/g;
40094
+
40095
+ // internal/islandRuntime.ts
40096
+ var ISLAND_RUNTIME_ID = "virtual:gemi-island-runtime";
40097
+ var RESOLVED_ISLAND_RUNTIME_ID = `\x00${ISLAND_RUNTIME_ID}`;
40098
+ var ISLAND_ENTRY_QUERY = "?gemi-island";
40099
+ function islandEntrySource(file) {
40100
+ return `import * as m from ${JSON.stringify(file)};
40101
+ export { m };
40102
+ export { h } from ${JSON.stringify(ISLAND_RUNTIME_ID)};
40103
+ `;
40104
+ }
40105
+ var ISLAND_HYDRATE_SOURCE = `function h(marker, Component) {
40106
+ if (typeof Component !== "function" && (typeof Component !== "object" || Component === null)) {
40107
+ throw new Error("gemi: island module has no component export for " + marker.outerHTML.slice(0, 80));
40108
+ }
40109
+ const json = marker.getAttribute("data-props");
40110
+ const props = json ? JSON.parse(json) : {};
40111
+ let slot = null;
40112
+ for (const candidate of marker.querySelectorAll("gemi-slot")) {
40113
+ if (candidate.closest("gemi-island") === marker) {
40114
+ slot = candidate;
40115
+ break;
40116
+ }
40117
+ }
40118
+ const children = slot
40119
+ ? [createElement("gemi-slot", {
40120
+ style: { display: "contents" },
40121
+ suppressHydrationWarning: true,
40122
+ dangerouslySetInnerHTML: { __html: slot.innerHTML },
40123
+ })]
40124
+ : [];
40125
+ return hydrateRoot(marker, createElement(Component, props, ...children), {
40126
+ identifierPrefix: marker.getAttribute("data-uid") || undefined,
40127
+ });
40128
+ }`;
40129
+ var ISLAND_RUNTIME_SOURCE = `import { createElement } from "react";
40130
+ import { hydrateRoot } from "react-dom/client";
40131
+ export ${ISLAND_HYDRATE_SOURCE}
40132
+ `;
40133
+
40134
+ // vite/islandPlugin.ts
40135
+ var ISLAND_CALL = /\bisland\s*\(\s*(\(\s*\)\s*=>\s*import\(\s*(["'])([^"'\n]+)\2\s*\))/g;
40103
40136
  function realPath(path3) {
40104
40137
  try {
40105
40138
  return realpathSync(path3);
@@ -40109,24 +40142,43 @@ function realPath(path3) {
40109
40142
  }
40110
40143
  function gemiIslandPlugin() {
40111
40144
  let root = process.cwd();
40145
+ let clientBuild = false;
40146
+ const emitted = new Set;
40112
40147
  return {
40113
40148
  name: "gemi-plugin-islands",
40114
40149
  enforce: "pre",
40115
40150
  configResolved(config) {
40116
40151
  root = realPath(config.root);
40152
+ clientBuild = config.command === "build" && !config.build.ssr;
40117
40153
  },
40118
- async transform(code, id, options) {
40119
- if (id.includes("/node_modules/") || id.startsWith("\x00"))
40154
+ buildStart() {
40155
+ emitted.clear();
40156
+ },
40157
+ resolveId(id) {
40158
+ return id === ISLAND_RUNTIME_ID ? RESOLVED_ISLAND_RUNTIME_ID : null;
40159
+ },
40160
+ load(id) {
40161
+ if (id === RESOLVED_ISLAND_RUNTIME_ID)
40162
+ return ISLAND_RUNTIME_SOURCE;
40163
+ if (id.endsWith(ISLAND_ENTRY_QUERY)) {
40164
+ return islandEntrySource(id.slice(0, -ISLAND_ENTRY_QUERY.length));
40165
+ }
40166
+ return null;
40167
+ },
40168
+ async transform(code, id) {
40169
+ if (id.includes("/node_modules/") || id.startsWith("\x00") || id.endsWith(ISLAND_ENTRY_QUERY)) {
40120
40170
  return null;
40171
+ }
40121
40172
  if (!/\.[cm]?[jt]sx?$/.test(id.split("?")[0]))
40122
40173
  return null;
40123
- if (!code.includes(".island"))
40174
+ if (!code.includes("island"))
40124
40175
  return null;
40125
- const ssr = Boolean(options?.ssr) || this.environment?.config?.consumer === "server";
40176
+ const environmentConsumer = this.environment?.config?.consumer;
40177
+ const emitEntries = clientBuild && (environmentConsumer === undefined || environmentConsumer === "client");
40126
40178
  const s = new MagicString(code);
40127
- let changed = false;
40128
- for (const match of code.matchAll(ISLAND_LOADER)) {
40129
- const [whole, quote, specifier] = match;
40179
+ const imports = [];
40180
+ for (const match of code.matchAll(ISLAND_CALL)) {
40181
+ const [, loader, quote, specifier] = match;
40130
40182
  const resolved = await this.resolve(specifier, id);
40131
40183
  if (!resolved || resolved.external)
40132
40184
  continue;
@@ -40134,12 +40186,25 @@ function gemiIslandPlugin() {
40134
40186
  const key = relative(root, file).split(sep).join("/");
40135
40187
  if (key.startsWith(".."))
40136
40188
  continue;
40137
- const loader = ssr ? `() => Promise.reject(new Error("Island modules load in the browser."))` : `() => import(${quote}${specifier}${quote})`;
40138
- s.overwrite(match.index, match.index + whole.length, `Object.assign(${loader}, { gemiIsland: ${JSON.stringify(key)} })`);
40139
- changed = true;
40189
+ const name = `__gemi_island_${imports.length}`;
40190
+ imports.push(`import * as ${name} from ${quote}${specifier}${quote};`);
40191
+ const start = match.index + match[0].length - loader.length;
40192
+ s.overwrite(start, start + loader.length, `Object.assign(() => Promise.resolve(${name}), { gemiIsland: ${JSON.stringify(key)}, gemiModule: ${name} })`);
40193
+ const moduleId = resolved.id.split("?")[0];
40194
+ if (emitEntries && !emitted.has(moduleId)) {
40195
+ emitted.add(moduleId);
40196
+ this.emitFile({
40197
+ type: "chunk",
40198
+ id: `${moduleId}${ISLAND_ENTRY_QUERY}`,
40199
+ preserveSignature: "strict"
40200
+ });
40201
+ }
40140
40202
  }
40141
- if (!changed)
40203
+ if (imports.length === 0)
40142
40204
  return null;
40205
+ s.prepend(`${imports.join(`
40206
+ `)}
40207
+ `);
40143
40208
  return { code: s.toString(), map: s.generateMap({ hires: true }) };
40144
40209
  }
40145
40210
  };
@@ -40163,7 +40228,7 @@ var gemi = async () => {
40163
40228
  ssrEmitAssets: true,
40164
40229
  sourcemap: true,
40165
40230
  rollupOptions: {
40166
- input: Array.from(JSON.parse(process.env.GEMI_INPUT ?? "[]")).filter((entry) => !(env.isSsrBuild && /\.island\.[cm]?[jt]sx?$/.test(entry))),
40231
+ input: Array.from(JSON.parse(process.env.GEMI_INPUT ?? "[]")),
40167
40232
  preserveEntrySignatures: "strict",
40168
40233
  ...env.isSsrBuild ? { external: isGemiExternal } : {}
40169
40234
  }
@@ -41485,15 +41550,350 @@ function exitCodeOf(proc) {
41485
41550
  return signal ? 128 + signal : 1;
41486
41551
  }
41487
41552
 
41553
+ // stats/run.ts
41554
+ import path7 from "path";
41555
+ import { existsSync as existsSync9, mkdtempSync, readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
41556
+ import { tmpdir } from "os";
41557
+
41558
+ // stats/bundleStats.ts
41559
+ import { existsSync as existsSync8, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
41560
+ import { join as join8 } from "path";
41561
+ import { brotliCompressSync, constants as constants3, gzipSync } from "zlib";
41562
+
41563
+ // server/modulePreloads.ts
41564
+ var CLIENT_ENTRY_KEY = "app/client.tsx";
41565
+
41566
+ // stats/bundleStats.ts
41567
+ var VIEW_PREFIX = "app/views/";
41568
+ var VIEW_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js"];
41569
+ var ROOT_LAYOUT = "RootLayout";
41570
+ var ZERO = { raw: 0, gzip: 0, brotli: 0 };
41571
+ var add = (a, b) => ({
41572
+ raw: a.raw + b.raw,
41573
+ gzip: a.gzip + b.gzip,
41574
+ brotli: a.brotli + b.brotli
41575
+ });
41576
+ function chunkName(file) {
41577
+ return file.replace(/^.*\//, "").replace(/-[\w-]{8}(?=\.\w+$)/, "");
41578
+ }
41579
+ function routeKey(entry) {
41580
+ return entry.group ? `${entry.group}:${entry.path}` : entry.path;
41581
+ }
41582
+ function bundleStats(options) {
41583
+ const { clientDir } = options;
41584
+ const manifest = options.manifest ?? JSON.parse(readFileSync5(join8(clientDir, ".vite/manifest.json"), "utf8"));
41585
+ const sizes = new Map;
41586
+ const size = (file) => {
41587
+ let known = sizes.get(file);
41588
+ if (!known)
41589
+ sizes.set(file, known = measure(clientDir, file));
41590
+ return known;
41591
+ };
41592
+ const sum = (files) => [...files].map(size).reduce(add, ZERO);
41593
+ const closure = (key, seen = new Set) => {
41594
+ if (seen.has(key) || !manifest[key])
41595
+ return seen;
41596
+ seen.add(key);
41597
+ for (const imported of manifest[key].imports ?? [])
41598
+ closure(imported, seen);
41599
+ return seen;
41600
+ };
41601
+ const jsFiles = (keys) => [...new Set([...keys].map((key) => manifest[key].file))].filter(isJs).sort();
41602
+ const islandEntries = Object.keys(manifest).filter(isIslandEntry).sort();
41603
+ const shared = closure(CLIENT_ENTRY_KEY);
41604
+ for (const [key, chunk] of Object.entries(manifest)) {
41605
+ if (key.includes(ISLAND_RUNTIME_NAME) || chunk.name?.includes(ISLAND_RUNTIME_NAME))
41606
+ closure(key, shared);
41607
+ }
41608
+ const islandModules = new Map(islandEntries.map((entry) => [
41609
+ entry,
41610
+ (manifest[entry].imports ?? []).filter((imported) => !shared.has(imported))
41611
+ ]));
41612
+ const islandsBelow = (keys) => {
41613
+ const seen = new Set;
41614
+ const walk3 = (at) => {
41615
+ if (seen.has(at) || !manifest[at] || isIslandEntry(at))
41616
+ return;
41617
+ seen.add(at);
41618
+ for (const next of [...manifest[at].imports ?? [], ...manifest[at].dynamicImports ?? []])
41619
+ walk3(next);
41620
+ };
41621
+ for (const key of keys)
41622
+ walk3(key);
41623
+ return islandEntries.filter((entry) => islandModules.get(entry).some((module) => seen.has(module)));
41624
+ };
41625
+ const viewKey = (view) => VIEW_EXTENSIONS.map((ext) => `${VIEW_PREFIX}${view}${ext}`).find((key) => manifest[key]);
41626
+ const hydrated = (views) => {
41627
+ const keys = closure(CLIENT_ENTRY_KEY);
41628
+ for (const view of views) {
41629
+ const key = viewKey(view);
41630
+ if (key)
41631
+ closure(key, keys);
41632
+ }
41633
+ const files = jsFiles(keys);
41634
+ return { ...sum(files), views, chunks: files.map(chunkName) };
41635
+ };
41636
+ const staticRoute = (views, layout) => {
41637
+ const roots = [layout ?? ROOT_LAYOUT, ...views].map(viewKey).filter((key) => Boolean(key));
41638
+ const islands2 = islandsBelow(roots);
41639
+ const keys = new Set;
41640
+ for (const island of islands2)
41641
+ closure(island, keys);
41642
+ const files = jsFiles(keys);
41643
+ return { ...sum(files), views, static: true, islands: islands2, chunks: files.map(chunkName) };
41644
+ };
41645
+ const routes = {};
41646
+ if (options.routes) {
41647
+ for (const entry of options.routes) {
41648
+ routes[routeKey(entry)] = entry.static ? staticRoute(entry.views, entry.static.layout) : hydrated(entry.views);
41649
+ }
41650
+ } else {
41651
+ for (const [key, chunk] of Object.entries(manifest)) {
41652
+ if (!chunk.isEntry || !key.startsWith(VIEW_PREFIX) || isIslandEntry(key))
41653
+ continue;
41654
+ const view = key.slice(VIEW_PREFIX.length).replace(/\.[jt]sx?$/, "");
41655
+ routes[view] = hydrated([view]);
41656
+ }
41657
+ }
41658
+ const islands = {};
41659
+ for (const key of islandEntries) {
41660
+ const files = jsFiles(closure(key));
41661
+ islands[key] = { ...sum(files), chunks: files.map(chunkName) };
41662
+ }
41663
+ const chunks = {};
41664
+ const allFiles = [...new Set(Object.values(manifest).map((chunk) => chunk.file))];
41665
+ for (const file of allFiles.filter(isJs).sort()) {
41666
+ const name = chunkName(file);
41667
+ let unique = name;
41668
+ for (let n2 = 2;chunks[unique]; n2++)
41669
+ unique = `${name}~${n2}`;
41670
+ chunks[unique] = size(file);
41671
+ }
41672
+ const css = new Set(Object.values(manifest).flatMap((chunk) => chunk.css ?? []));
41673
+ return {
41674
+ version: 1,
41675
+ by: options.routes ? "routes" : "views",
41676
+ routes,
41677
+ islands,
41678
+ chunks,
41679
+ css: sum(css)
41680
+ };
41681
+ }
41682
+ var ISLAND_RUNTIME_NAME = "gemi-island-runtime";
41683
+ function isIslandEntry(key) {
41684
+ return key.endsWith(ISLAND_ENTRY_QUERY);
41685
+ }
41686
+ function isJs(file) {
41687
+ return /\.m?js$/.test(file);
41688
+ }
41689
+ function measure(clientDir, file) {
41690
+ const path7 = join8(clientDir, file);
41691
+ const sibling = (ext) => existsSync8(path7 + ext) ? statSync3(path7 + ext).size : null;
41692
+ let buffer;
41693
+ const read = () => buffer ??= readFileSync5(path7);
41694
+ return {
41695
+ raw: statSync3(path7).size,
41696
+ gzip: sibling(".gz") ?? gzipSync(read(), { level: 9 }).length,
41697
+ brotli: sibling(".br") ?? brotliCompressSync(read(), {
41698
+ params: { [constants3.BROTLI_PARAM_QUALITY]: 11 }
41699
+ }).length
41700
+ };
41701
+ }
41702
+ var kb = (bytes) => bytes / 1024;
41703
+ var format = (bytes) => kb(bytes).toFixed(1);
41704
+ var signed = (bytes) => `${bytes > 0 ? "+" : ""}${format(bytes)}`;
41705
+ function budgetFor(key, route, budgets) {
41706
+ if (!budgets)
41707
+ return;
41708
+ const page = route.views.at(-1);
41709
+ return budgets.routes?.[key] ?? (page ? budgets.routes?.[page] : undefined) ?? budgets.default;
41710
+ }
41711
+ function overBudget(stats, budgets) {
41712
+ if (!budgets)
41713
+ return [];
41714
+ const unit = budgets.unit ?? "gzip";
41715
+ return Object.entries(stats.routes).flatMap(([key, route]) => {
41716
+ const budget = budgetFor(key, route, budgets);
41717
+ return budget !== undefined && kb(route[unit]) > budget ? [`${key}: ${format(route[unit])} KB ${unit} is over its budget of ${budget} KB`] : [];
41718
+ });
41719
+ }
41720
+ function unusedBudgets(stats, budgets) {
41721
+ const keys = Object.keys(budgets?.routes ?? {});
41722
+ const known = new Set(Object.keys(stats.routes));
41723
+ for (const route of Object.values(stats.routes)) {
41724
+ const page = route.views.at(-1);
41725
+ if (page)
41726
+ known.add(page);
41727
+ }
41728
+ return keys.filter((key) => !known.has(key));
41729
+ }
41730
+ var NOISE_KB = 2;
41731
+ var byGzip = (stats) => Object.keys(stats.routes).sort((a, b) => stats.routes[b].gzip - stats.routes[a].gzip);
41732
+ function markdownReport(stats, base, budgets) {
41733
+ const unit = budgets?.unit ?? "gzip";
41734
+ const lines = [
41735
+ `| Route | ${unit} KB | \u0394 gzip | \u0394 raw | \u0394 brotli | budget |`,
41736
+ "|---|---:|---:|---:|---:|---:|"
41737
+ ];
41738
+ for (const key of byGzip(stats)) {
41739
+ const now = stats.routes[key];
41740
+ const before = base?.routes[key];
41741
+ const delta = (size) => before ? signed(now[size] - before[size]) : base ? "new" : "\u2013";
41742
+ const budget = budgetFor(key, now, budgets);
41743
+ const flag = budget !== undefined && kb(now[unit]) > budget ? " \u274C" : before && kb(now.gzip - before.gzip) > NOISE_KB ? " \u26A0\uFE0F" : "";
41744
+ const kind = now.static ? " (static)" : "";
41745
+ lines.push(`| \`${key}\`${kind}${flag} | ${format(now[unit])} | ${delta("gzip")} | ${delta("raw")} | ${delta("brotli")} | ${budget ?? ""} |`);
41746
+ }
41747
+ if (base) {
41748
+ const removedRoutes = Object.keys(base.routes).filter((key) => !stats.routes[key]);
41749
+ if (removedRoutes.length) {
41750
+ lines.push("", `**Removed routes:** ${removedRoutes.map((key) => `\`${key}\``).join(", ")}`);
41751
+ }
41752
+ const added = Object.keys(stats.chunks).filter((name) => !base.chunks[name]);
41753
+ const removed = Object.keys(base.chunks).filter((name) => !stats.chunks[name]);
41754
+ const changed = Object.keys(stats.chunks).filter((name) => base.chunks[name] && kb(Math.abs(stats.chunks[name].gzip - base.chunks[name].gzip)) > 0.5);
41755
+ const list = (names, describe) => names.length ? names.map((name) => `\`${name}\` ${describe(name)}`).join(", ") : "none";
41756
+ lines.push("", `**New chunks:** ${list(added, (name) => `(${format(stats.chunks[name].gzip)} KB gzip)`)}`, `**Removed chunks:** ${list(removed, (name) => `(${format(base.chunks[name].gzip)} KB gzip)`)}`, `**Changed chunks (> 0.5 KB gzip):** ${list(changed, (name) => `(${signed(stats.chunks[name].gzip - base.chunks[name].gzip)} KB gzip)`)}`, `**CSS:** ${format(stats.css.gzip)} KB gzip (${signed(stats.css.gzip - base.css.gzip)})`);
41757
+ }
41758
+ return lines.join(`
41759
+ `);
41760
+ }
41761
+ function textReport(stats, budgets) {
41762
+ const unit = budgets?.unit ?? "gzip";
41763
+ const rows = byGzip(stats).map((key) => {
41764
+ const route = stats.routes[key];
41765
+ const budget = budgetFor(key, route, budgets);
41766
+ const over = budget !== undefined && kb(route[unit]) > budget;
41767
+ return [
41768
+ key,
41769
+ route.static ? "static" : "hydrated",
41770
+ format(route.raw),
41771
+ format(route.gzip),
41772
+ format(route.brotli),
41773
+ String(route.chunks.length),
41774
+ budget === undefined ? "" : `${budget}${over ? " OVER" : ""}`
41775
+ ];
41776
+ });
41777
+ const header = [
41778
+ stats.by === "routes" ? "Route" : "View",
41779
+ "Kind",
41780
+ "raw KB",
41781
+ "gzip KB",
41782
+ "br KB",
41783
+ "files",
41784
+ `budget (${unit})`
41785
+ ];
41786
+ const table = [header, ...rows];
41787
+ const widths = header.map((_, i) => Math.max(...table.map((row) => row[i].length)));
41788
+ const line = (row) => row.map((cell, i) => i < 2 ? cell.padEnd(widths[i]) : cell.padStart(widths[i])).join(" ").trimEnd();
41789
+ const islands = Object.entries(stats.islands);
41790
+ return [
41791
+ "Initial JavaScript per " + (stats.by === "routes" ? "route" : "view") + ":",
41792
+ "",
41793
+ ...table.map(line),
41794
+ ...islands.length ? [
41795
+ "",
41796
+ "Islands (each with its imports):",
41797
+ ...islands.map(([key, island]) => ` ${key} ${format(island.gzip)} KB gzip, ${island.chunks.length} file(s)`)
41798
+ ] : [],
41799
+ "",
41800
+ `CSS: ${format(stats.css.raw)} KB raw, ${format(stats.css.gzip)} KB gzip`
41801
+ ].join(`
41802
+ `);
41803
+ }
41804
+
41805
+ // stats/run.ts
41806
+ async function runStats(options) {
41807
+ const log = options.log ?? console.log;
41808
+ const error = options.error ?? console.error;
41809
+ const clientDir = path7.join(options.rootDir, "dist", "client");
41810
+ if (!existsSync9(path7.join(clientDir, ".vite/manifest.json"))) {
41811
+ error(`No client build in ${clientDir}. Run \`gemi build\` first.`);
41812
+ return 1;
41813
+ }
41814
+ let routes = null;
41815
+ if (options.routes !== false) {
41816
+ const table = await loadRouteTable(options.rootDir, options.preloadArgs ?? []);
41817
+ if ("routes" in table)
41818
+ routes = table.routes;
41819
+ else
41820
+ error(`Could not read the route table, so this reports per view and can't tell static ` + `views apart (pass --no-routes to skip it):
41821
+ ${table.message}`);
41822
+ }
41823
+ const stats = bundleStats({ clientDir, routes });
41824
+ const budgets = options.config?.budgets;
41825
+ log(textReport(stats, budgets));
41826
+ if (options.json) {
41827
+ writeFileSync3(options.json, `${JSON.stringify(stats, null, 2)}
41828
+ `);
41829
+ }
41830
+ if (options.markdown) {
41831
+ const base = options.base && existsSync9(options.base) ? JSON.parse(readFileSync6(options.base, "utf8")) : null;
41832
+ writeFileSync3(options.markdown, `${markdownReport(stats, base, budgets)}
41833
+ `);
41834
+ }
41835
+ for (const key of unusedBudgets(stats, budgets)) {
41836
+ error(`warning: the budget for "${key}" matches no route or view.`);
41837
+ }
41838
+ const problems = overBudget(stats, budgets);
41839
+ if (problems.length) {
41840
+ error(`
41841
+ Over budget (stats.budgets in gemi.config.ts):
41842
+ ${problems.join(`
41843
+ `)}`);
41844
+ return 1;
41845
+ }
41846
+ return 0;
41847
+ }
41848
+ async function loadRouteTable(rootDir, preloadArgs, options = {}) {
41849
+ let entry;
41850
+ try {
41851
+ entry = Bun.resolveSync("gemi/stats/route-table", rootDir);
41852
+ } catch {
41853
+ return { ok: false, message: `gemi/stats/route-table does not resolve from ${rootDir}.` };
41854
+ }
41855
+ const dir = mkdtempSync(path7.join(tmpdir(), "gemi-stats-"));
41856
+ const out = path7.join(dir, "routes.json");
41857
+ try {
41858
+ const child = Bun.spawn({
41859
+ cmd: ["bun", "--preload", "gemi/bun/preload", ...preloadArgs, entry, out],
41860
+ cwd: rootDir,
41861
+ env: { ...process.env, GEMI_NO_SCHEDULE: "1" },
41862
+ stdout: "ignore",
41863
+ stderr: "pipe"
41864
+ });
41865
+ const timeoutMs = options.timeoutMs ?? 60000;
41866
+ let timedOut = false;
41867
+ const timer = setTimeout(() => {
41868
+ timedOut = true;
41869
+ child.kill();
41870
+ }, timeoutMs);
41871
+ const [code, stderr] = await Promise.all([child.exited, new Response(child.stderr).text()]);
41872
+ clearTimeout(timer);
41873
+ if (timedOut) {
41874
+ return { ok: false, message: `reading the route table took over ${timeoutMs / 1000}s.` };
41875
+ }
41876
+ if (code !== 0 || !existsSync9(out)) {
41877
+ return {
41878
+ ok: false,
41879
+ message: stderr.trim() || `the route table process exited with ${code}.`
41880
+ };
41881
+ }
41882
+ return { ok: true, routes: JSON.parse(readFileSync6(out, "utf8")) };
41883
+ } finally {
41884
+ rmSync3(dir, { recursive: true, force: true });
41885
+ }
41886
+ }
41887
+
41488
41888
  // bin/gemi.ts
41489
41889
  function appPreloadArgs(appDir) {
41490
- const preloadPath = path9.join(appDir, "preload.ts");
41491
- return existsSync8(preloadPath) ? ["--preload", preloadPath] : [];
41890
+ const preloadPath = path10.join(appDir, "preload.ts");
41891
+ return existsSync10(preloadPath) ? ["--preload", preloadPath] : [];
41492
41892
  }
41493
41893
  program.command("dev").action(async () => {
41494
41894
  console.log("Starting dev server...");
41495
- const rootDir = path9.resolve(process.cwd());
41496
- const appDir = path9.join(rootDir, "app");
41895
+ const rootDir = path10.resolve(process.cwd());
41896
+ const appDir = path10.join(rootDir, "app");
41497
41897
  process.env.NODE_ENV = "development";
41498
41898
  const exited = spawnForwardingSignals({
41499
41899
  cmd: [
@@ -41503,16 +41903,34 @@ program.command("dev").action(async () => {
41503
41903
  "--preload",
41504
41904
  "gemi/bun/preload",
41505
41905
  ...appPreloadArgs(appDir),
41506
- `${path9.join(appDir, "server.ts")}`
41906
+ `${path10.join(appDir, "server.ts")}`
41507
41907
  ]
41508
41908
  });
41509
41909
  reportUpdate({ rootDir });
41510
41910
  process.exit(await exited);
41511
41911
  });
41512
- program.command("build").action(async () => {
41912
+ function withStatsOptions(command) {
41913
+ return command.option("--json <file>", "Also write the stats as JSON (for CI diffs)").option("--base <file>", "Another build's JSON to compare with in --markdown (e.g. main's)").option("--markdown <file>", "Write the stats as a Markdown table, compared with --base").option("--no-routes", "Don't read the route table; report per view");
41914
+ }
41915
+ async function printStats(rootDir, options) {
41916
+ const config = await loadGemiConfig(rootDir);
41917
+ return runStats({
41918
+ rootDir,
41919
+ config: config.stats,
41920
+ json: options.json && path10.resolve(options.json),
41921
+ base: options.base && path10.resolve(options.base),
41922
+ markdown: options.markdown && path10.resolve(options.markdown),
41923
+ routes: options.routes,
41924
+ preloadArgs: appPreloadArgs(path10.join(rootDir, "app"))
41925
+ });
41926
+ }
41927
+ withStatsOptions(program.command("stats").description("Print the initial JavaScript each route loads (raw, gzip, brotli) from the " + "last `gemi build`, and fail when a route is over its budget " + "(`stats.budgets` in gemi.config.ts)")).action(async (options) => {
41928
+ process.exit(await printStats(path10.resolve(process.cwd()), options));
41929
+ });
41930
+ withStatsOptions(program.command("build").option("--stats", "After building, print the initial JS per route and check the budgets")).action(async (options) => {
41513
41931
  if (process.env.GEMI_BUILD_PROD !== "1") {
41514
41932
  const proc = Bun.spawn({
41515
- cmd: ["bun", process.argv[1], "build"],
41933
+ cmd: ["bun", process.argv[1], ...process.argv.slice(2)],
41516
41934
  env: { ...process.env, NODE_ENV: "production", GEMI_BUILD_PROD: "1" },
41517
41935
  stdout: "inherit",
41518
41936
  stderr: "inherit"
@@ -41521,14 +41939,14 @@ program.command("build").action(async () => {
41521
41939
  process.exit(proc.exitCode ?? 0);
41522
41940
  }
41523
41941
  process.env.NODE_ENV = "production";
41524
- const rootDir = path9.resolve(process.cwd());
41525
- const appDir = path9.join(rootDir, "app");
41942
+ const rootDir = path10.resolve(process.cwd());
41943
+ const appDir = path10.join(rootDir, "app");
41526
41944
  const config = await loadGemiConfig(rootDir);
41527
41945
  const input = await createRollupInput_default(appDir);
41528
41946
  process.env.GEMI_INPUT = JSON.stringify(input);
41529
41947
  const previousAssets = resolvePreviousAssets(config.previousAssets, rootDir);
41530
- const stagingDir = previousAssets ? await mkdtemp(path9.join(tmpdir(), "gemi-previous-assets-")) : undefined;
41531
- const clientDir = path9.join(rootDir, "dist", "client");
41948
+ const stagingDir = previousAssets ? await mkdtemp(path10.join(tmpdir2(), "gemi-previous-assets-")) : undefined;
41949
+ const clientDir = path10.join(rootDir, "dist", "client");
41532
41950
  const emitted = [];
41533
41951
  let carriedPaths = [];
41534
41952
  try {
@@ -41567,8 +41985,8 @@ program.command("build").action(async () => {
41567
41985
  await writeStaticAssetsRecord(clientDir, {
41568
41986
  files: { ...carried.record.files, ...fresh.record.files }
41569
41987
  });
41570
- const kb = (bytes) => `${(bytes / 1024).toFixed(1)} kB`;
41571
- console.log(`Precompressed ${fresh.stats.files} asset(s): ${kb(fresh.stats.identityBytes)} \u2192 ` + `${kb(fresh.stats.brBytes)} br / ${kb(fresh.stats.gzipBytes)} gzip ` + `(${Math.round(performance.now() - startedAt)} ms).`);
41988
+ const kb2 = (bytes) => `${(bytes / 1024).toFixed(1)} kB`;
41989
+ console.log(`Precompressed ${fresh.stats.files} asset(s): ${kb2(fresh.stats.identityBytes)} \u2192 ` + `${kb2(fresh.stats.brBytes)} br / ${kb2(fresh.stats.gzipBytes)} gzip ` + `(${Math.round(performance.now() - startedAt)} ms).`);
41572
41990
  console.log("Building server...");
41573
41991
  await build({
41574
41992
  configFile: false,
@@ -41591,12 +42009,16 @@ program.command("build").action(async () => {
41591
42009
  console.error(message);
41592
42010
  process.exit(1);
41593
42011
  }
42012
+ if (options.stats || options.json || options.markdown) {
42013
+ console.log("");
42014
+ process.exit(await printStats(rootDir, options));
42015
+ }
41594
42016
  process.exit();
41595
42017
  });
41596
42018
  program.command("start").action(async () => {
41597
42019
  console.log("Starting server...");
41598
- const rootDir = path9.resolve(process.cwd());
41599
- const appDir = path9.join(rootDir, "app");
42020
+ const rootDir = path10.resolve(process.cwd());
42021
+ const appDir = path10.join(rootDir, "app");
41600
42022
  const code = await spawnForwardingSignals({
41601
42023
  cmd: [
41602
42024
  "bun",
@@ -41610,8 +42032,8 @@ program.command("start").action(async () => {
41610
42032
  process.exit(code);
41611
42033
  });
41612
42034
  program.command("queue:work").description("Boot the app and run queued jobs, without serving HTTP, so job capacity " + "scales apart from web traffic. Needs a queue driver every process can " + 'reach, such as "database". Drains on SIGTERM/SIGINT like `gemi start`').action(async () => {
41613
- const rootDir = path9.resolve(process.cwd());
41614
- const appDir = path9.join(rootDir, "app");
42035
+ const rootDir = path10.resolve(process.cwd());
42036
+ const appDir = path10.join(rootDir, "app");
41615
42037
  let entry;
41616
42038
  try {
41617
42039
  entry = Bun.resolveSync("gemi/queue/work", rootDir);
@@ -41627,8 +42049,8 @@ program.command("queue:work").description("Boot the app and run queued jobs, wit
41627
42049
  });
41628
42050
  program.enablePositionalOptions();
41629
42051
  program.command("run").description("Run a Command from app/commands. Everything after the name is the " + "command's own, including its flags. Omit the name to list them").argument("[name]", "The command's name").argument("[args...]", "Passed through to the command untouched").passThroughOptions().action(async (name, args) => {
41630
- const rootDir = path9.resolve(process.cwd());
41631
- const appDir = path9.join(rootDir, "app");
42052
+ const rootDir = path10.resolve(process.cwd());
42053
+ const appDir = path10.join(rootDir, "app");
41632
42054
  let entry;
41633
42055
  try {
41634
42056
  entry = Bun.resolveSync("gemi/console/run", rootDir);
@@ -41652,13 +42074,13 @@ program.command("run").description("Run a Command from app/commands. Everything
41652
42074
  process.exit(code);
41653
42075
  });
41654
42076
  program.command("migrate").description("Migrate an app from the 0.42 service-provider layout to the config + " + "container layout, flagging APIs retired since").option("--dry-run", "Print the plan without writing anything").action(async (options) => {
41655
- const rootDir = path9.resolve(process.cwd());
42077
+ const rootDir = path10.resolve(process.cwd());
41656
42078
  console.log(options.dryRun ? `Planning migration of ${rootDir}...` : `Migrating ${rootDir}...`);
41657
42079
  await runMigrate({ rootDir, dryRun: options.dryRun });
41658
42080
  });
41659
42081
  program.command("upgrade").description("Upgrade the `gemi` package. With no argument it moves to the newest " + "release on the channel you are already on \u2014 `rc` for a release " + "candidate, `latest` otherwise \u2014 so an rc is never 'upgraded' backwards " + "onto the older stable release").argument("[target]", "A version (`0.59.0`) to pin or roll back to, or a dist-tag (`rc`, " + "`latest`). Defaults to the current channel's tag").option("--dry-run", "Resolve the version and print the install command, run nothing").action(async (target, options) => {
41660
42082
  const code = await runUpgrade({
41661
- rootDir: path9.resolve(process.cwd()),
42083
+ rootDir: path10.resolve(process.cwd()),
41662
42084
  target,
41663
42085
  dryRun: options.dryRun
41664
42086
  });
@@ -41666,7 +42088,7 @@ program.command("upgrade").description("Upgrade the `gemi` package. With no argu
41666
42088
  });
41667
42089
  program.command("install-skill").description(`Install the \`${SKILL_NAME}\` agent skill that ships with your gemi into ` + `.agents/skills/. \`gemi upgrade\` re-runs this afterwards, so the rules an ` + `agent reads stay pinned to the gemi the app actually runs`).option("--force", "Replace an installed copy that has local edits, or one this command did not write").action(async (options) => {
41668
42090
  process.exit(installSkill({
41669
- rootDir: path9.resolve(process.cwd()),
42091
+ rootDir: path10.resolve(process.cwd()),
41670
42092
  force: options.force
41671
42093
  }));
41672
42094
  });
@@ -41680,7 +42102,7 @@ check.command("models").description("Report policied model classes that the modu
41680
42102
  ], []).action(async (options) => {
41681
42103
  try {
41682
42104
  const report2 = await checkModels({
41683
- rootDir: path9.resolve(process.cwd()),
42105
+ rootDir: path10.resolve(process.cwd()),
41684
42106
  modelsDir: options.dir,
41685
42107
  ignore: options.ignore,
41686
42108
  models: options.models
@@ -41699,7 +42121,7 @@ program.command("ai:generate-client").description("Generate an agent's tool and
41699
42121
  const { file, warnings } = await generateClient2({ agent, ...options });
41700
42122
  for (const warning of warnings)
41701
42123
  console.warn(`warning: ${warning}`);
41702
- console.log(`Wrote ${path9.relative(process.cwd(), file)}`);
42124
+ console.log(`Wrote ${path10.relative(process.cwd(), file)}`);
41703
42125
  process.exit(0);
41704
42126
  } catch (error) {
41705
42127
  if (!(error instanceof GenerateClientError2))
@@ -41724,5 +42146,5 @@ program.command("app:route-manifest").action(async () => {
41724
42146
  });
41725
42147
  program.parse();
41726
42148
 
41727
- //# debugId=C2424D7419BD4C9164756E2164756E21
42149
+ //# debugId=0E49B3FD0C1F8A9E64756E2164756E21
41728
42150
  //# sourceMappingURL=gemi.js.map