gemi 0.156.0 → 0.157.1
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.
- package/dist/ai/Agent.d.ts.map +1 -1
- package/dist/ai/ImageModel.d.ts +2 -0
- package/dist/ai/ImageModel.d.ts.map +1 -1
- package/dist/ai/eval/Eval.d.ts +333 -0
- package/dist/ai/eval/Eval.d.ts.map +1 -0
- package/dist/ai/eval/stats.d.ts +70 -0
- package/dist/ai/eval/stats.d.ts.map +1 -0
- package/dist/ai/generate.d.ts.map +1 -1
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +27 -26
- package/dist/ai/index.js.map +6 -4
- package/dist/ai/usageMeter.d.ts +23 -0
- package/dist/ai/usageMeter.d.ts.map +1 -0
- package/dist/app/index.js +1 -1
- package/dist/bun/plugin.js +1 -1
- package/dist/bun/preload.js +1 -1
- package/dist/{chunk-rb7518zz.js → chunk-00z7s34q.js} +2 -2
- package/dist/{chunk-rb7518zz.js.map → chunk-00z7s34q.js.map} +1 -1
- package/dist/{chunk-2r2j2nvq.js → chunk-0v3bca8k.js} +3 -3
- package/dist/{chunk-2r2j2nvq.js.map → chunk-0v3bca8k.js.map} +1 -1
- package/dist/{chunk-4y74s15p.js → chunk-0vc2akg0.js} +1 -1
- package/dist/{chunk-877yc341.js → chunk-0yjm936b.js} +3 -3
- package/dist/{chunk-877yc341.js.map → chunk-0yjm936b.js.map} +1 -1
- package/dist/{chunk-a8n9ec43.js → chunk-159j20yr.js} +2 -2
- package/dist/{chunk-a8n9ec43.js.map → chunk-159j20yr.js.map} +1 -1
- package/dist/{chunk-3csz8pfk.js → chunk-1de3awrh.js} +3 -3
- package/dist/{chunk-3csz8pfk.js.map → chunk-1de3awrh.js.map} +1 -1
- package/dist/{chunk-3nf0nmpp.js → chunk-38kjpa6q.js} +1 -1
- package/dist/{chunk-afaff2se.js → chunk-3ndc8adc.js} +2 -2
- package/dist/{chunk-afaff2se.js.map → chunk-3ndc8adc.js.map} +1 -1
- package/dist/{chunk-z38m1nh5.js → chunk-3t4nw1n2.js} +2 -2
- package/dist/{chunk-z38m1nh5.js.map → chunk-3t4nw1n2.js.map} +1 -1
- package/dist/{chunk-rnd8s0n5.js → chunk-42646nt7.js} +2 -2
- package/dist/{chunk-rnd8s0n5.js.map → chunk-42646nt7.js.map} +1 -1
- package/dist/{chunk-9xyd5r54.js → chunk-4t2j3zcg.js} +2 -2
- package/dist/{chunk-9xyd5r54.js.map → chunk-4t2j3zcg.js.map} +1 -1
- package/dist/{chunk-hh5bs656.js → chunk-4vnrnbn3.js} +3 -3
- package/dist/{chunk-hh5bs656.js.map → chunk-4vnrnbn3.js.map} +1 -1
- package/dist/{chunk-m5f6ksqe.js → chunk-517fjfme.js} +3 -3
- package/dist/{chunk-m5f6ksqe.js.map → chunk-517fjfme.js.map} +1 -1
- package/dist/{chunk-wckbrbzx.js → chunk-56a3vnrj.js} +2 -2
- package/dist/{chunk-wckbrbzx.js.map → chunk-56a3vnrj.js.map} +1 -1
- package/dist/{chunk-ja1289jh.js → chunk-5zxxd7qp.js} +1 -1
- package/dist/{chunk-4ptz62pz.js → chunk-69c2s43a.js} +2 -2
- package/dist/{chunk-4ptz62pz.js.map → chunk-69c2s43a.js.map} +1 -1
- package/dist/chunk-6np1r9gk.js +5 -0
- package/dist/{chunk-49s8wwp2.js.map → chunk-6np1r9gk.js.map} +1 -1
- package/dist/{chunk-bstn00nx.js → chunk-72f6pbap.js} +2 -2
- package/dist/{chunk-bstn00nx.js.map → chunk-72f6pbap.js.map} +1 -1
- package/dist/{chunk-0mgswwbj.js → chunk-7426gfgw.js} +2 -2
- package/dist/{chunk-0mgswwbj.js.map → chunk-7426gfgw.js.map} +1 -1
- package/dist/{chunk-baj76zja.js → chunk-78wht1ph.js} +2 -2
- package/dist/{chunk-baj76zja.js.map → chunk-78wht1ph.js.map} +1 -1
- package/dist/{chunk-mzkzgp2j.js → chunk-7yww9aq7.js} +2 -2
- package/dist/{chunk-mzkzgp2j.js.map → chunk-7yww9aq7.js.map} +1 -1
- package/dist/{chunk-djyx6eyh.js → chunk-7zy6nq9e.js} +2 -2
- package/dist/{chunk-djyx6eyh.js.map → chunk-7zy6nq9e.js.map} +1 -1
- package/dist/{chunk-w6jff43c.js → chunk-8eyxj78g.js} +3 -3
- package/dist/{chunk-w6jff43c.js.map → chunk-8eyxj78g.js.map} +1 -1
- package/dist/{chunk-twrf6d08.js → chunk-986eh0n3.js} +2 -2
- package/dist/{chunk-twrf6d08.js.map → chunk-986eh0n3.js.map} +1 -1
- package/dist/{chunk-mv1rs9he.js → chunk-9gt9qdge.js} +1 -1
- package/dist/{chunk-v9z4x5j2.js → chunk-9kyfaeey.js} +2 -2
- package/dist/{chunk-v9z4x5j2.js.map → chunk-9kyfaeey.js.map} +1 -1
- package/dist/{chunk-198ywkt2.js → chunk-9md6acv2.js} +1 -1
- package/dist/{chunk-6tkkvaqg.js → chunk-ah2jy1vx.js} +2 -2
- package/dist/{chunk-6tkkvaqg.js.map → chunk-ah2jy1vx.js.map} +1 -1
- package/dist/{chunk-xv58jnpb.js → chunk-aq5zx3vg.js} +2 -2
- package/dist/{chunk-xv58jnpb.js.map → chunk-aq5zx3vg.js.map} +1 -1
- package/dist/{chunk-tdvjrftz.js → chunk-cmt3jw6j.js} +2 -2
- package/dist/{chunk-tdvjrftz.js.map → chunk-cmt3jw6j.js.map} +1 -1
- package/dist/{chunk-v1460k0a.js → chunk-ctrae98c.js} +2 -2
- package/dist/{chunk-v1460k0a.js.map → chunk-ctrae98c.js.map} +1 -1
- package/dist/{chunk-0hqg6ema.js → chunk-dce3w52r.js} +2 -2
- package/dist/{chunk-0hqg6ema.js.map → chunk-dce3w52r.js.map} +1 -1
- package/dist/{chunk-403b2rfp.js → chunk-dhq7zv0t.js} +2 -2
- package/dist/{chunk-403b2rfp.js.map → chunk-dhq7zv0t.js.map} +1 -1
- package/dist/{chunk-rq8b8pr5.js → chunk-exb35whf.js} +2 -2
- package/dist/{chunk-rq8b8pr5.js.map → chunk-exb35whf.js.map} +1 -1
- package/dist/{chunk-73rzf7ys.js → chunk-fe12f946.js} +2 -2
- package/dist/{chunk-73rzf7ys.js.map → chunk-fe12f946.js.map} +1 -1
- package/dist/{chunk-nh01ncyy.js → chunk-g5d62d1n.js} +2 -2
- package/dist/{chunk-nh01ncyy.js.map → chunk-g5d62d1n.js.map} +1 -1
- package/dist/{chunk-ydkv9e8w.js → chunk-h3gcxf2k.js} +3 -3
- package/dist/{chunk-ydkv9e8w.js.map → chunk-h3gcxf2k.js.map} +1 -1
- package/dist/{chunk-2t61pc8v.js → chunk-jrv31jp9.js} +2 -2
- package/dist/{chunk-2t61pc8v.js.map → chunk-jrv31jp9.js.map} +1 -1
- package/dist/{chunk-dewn1kmd.js → chunk-k1aw97dm.js} +2 -2
- package/dist/{chunk-dewn1kmd.js.map → chunk-k1aw97dm.js.map} +1 -1
- package/dist/{chunk-313593t3.js → chunk-kbdt84xg.js} +2 -2
- package/dist/{chunk-313593t3.js.map → chunk-kbdt84xg.js.map} +1 -1
- package/dist/{chunk-vfwpbveq.js → chunk-kwc68y45.js} +2 -2
- package/dist/{chunk-vfwpbveq.js.map → chunk-kwc68y45.js.map} +1 -1
- package/dist/{chunk-86zhngpg.js → chunk-n95dppzm.js} +2 -2
- package/dist/{chunk-86zhngpg.js.map → chunk-n95dppzm.js.map} +1 -1
- package/dist/{chunk-apga49vp.js → chunk-nvhbkqmd.js} +2 -2
- package/dist/{chunk-apga49vp.js.map → chunk-nvhbkqmd.js.map} +1 -1
- package/dist/{chunk-qned028z.js → chunk-p2c72zx3.js} +2 -2
- package/dist/{chunk-qned028z.js.map → chunk-p2c72zx3.js.map} +1 -1
- package/dist/{chunk-0t531zdt.js → chunk-p83cjehh.js} +2 -2
- package/dist/{chunk-0t531zdt.js.map → chunk-p83cjehh.js.map} +1 -1
- package/dist/{chunk-wf4kywta.js → chunk-pgdxqrjv.js} +3 -3
- package/dist/{chunk-wf4kywta.js.map → chunk-pgdxqrjv.js.map} +1 -1
- package/dist/{chunk-f4hx69cr.js → chunk-pw5h5935.js} +2 -2
- package/dist/{chunk-f4hx69cr.js.map → chunk-pw5h5935.js.map} +1 -1
- package/dist/{chunk-4d4td4k9.js → chunk-px3ctjxh.js} +2 -2
- package/dist/{chunk-4d4td4k9.js.map → chunk-px3ctjxh.js.map} +1 -1
- package/dist/{chunk-5gq41j99.js → chunk-q3e1bqrs.js} +3 -3
- package/dist/{chunk-5gq41j99.js.map → chunk-q3e1bqrs.js.map} +1 -1
- package/dist/{chunk-c94a3qsx.js → chunk-q7k2hc45.js} +2 -2
- package/dist/{chunk-c94a3qsx.js.map → chunk-q7k2hc45.js.map} +1 -1
- package/dist/{chunk-41bvpent.js → chunk-qbvm5q1g.js} +1 -1
- package/dist/{chunk-7j8x62yb.js → chunk-qvngsa1c.js} +2 -2
- package/dist/{chunk-7j8x62yb.js.map → chunk-qvngsa1c.js.map} +1 -1
- package/dist/{chunk-g8sh9btf.js → chunk-r5y2khw4.js} +2 -2
- package/dist/{chunk-g8sh9btf.js.map → chunk-r5y2khw4.js.map} +1 -1
- package/dist/{chunk-1a11x8ww.js → chunk-rrz2ry81.js} +2 -2
- package/dist/{chunk-1a11x8ww.js.map → chunk-rrz2ry81.js.map} +1 -1
- package/dist/{chunk-e9z8p2fy.js → chunk-rtv4ax8z.js} +2 -2
- package/dist/{chunk-e9z8p2fy.js.map → chunk-rtv4ax8z.js.map} +1 -1
- package/dist/{chunk-gmsst3fx.js → chunk-set6qmjw.js} +2 -2
- package/dist/{chunk-gmsst3fx.js.map → chunk-set6qmjw.js.map} +1 -1
- package/dist/{chunk-sbzqxtqg.js → chunk-ss3yn4g2.js} +3 -3
- package/dist/{chunk-sbzqxtqg.js.map → chunk-ss3yn4g2.js.map} +1 -1
- package/dist/{chunk-fe9fvtvt.js → chunk-t66ex43f.js} +4 -4
- package/dist/{chunk-fe9fvtvt.js.map → chunk-t66ex43f.js.map} +1 -1
- package/dist/{chunk-rv751mxq.js → chunk-t7yt8egz.js} +2 -2
- package/dist/{chunk-rv751mxq.js.map → chunk-t7yt8egz.js.map} +1 -1
- package/dist/{chunk-rnegd7ya.js → chunk-tr8se94g.js} +3 -3
- package/dist/{chunk-rnegd7ya.js.map → chunk-tr8se94g.js.map} +1 -1
- package/dist/{chunk-1fyn63ka.js → chunk-tzheb6ak.js} +3 -3
- package/dist/{chunk-1fyn63ka.js.map → chunk-tzheb6ak.js.map} +1 -1
- package/dist/{chunk-h0kyymhv.js → chunk-v10xzpqs.js} +2 -2
- package/dist/{chunk-h0kyymhv.js.map → chunk-v10xzpqs.js.map} +1 -1
- package/dist/{chunk-30gw44g9.js → chunk-vp6t1gmt.js} +2 -2
- package/dist/{chunk-30gw44g9.js.map → chunk-vp6t1gmt.js.map} +1 -1
- package/dist/{chunk-2b3hh9xw.js → chunk-wbv6218d.js} +3 -3
- package/dist/{chunk-2b3hh9xw.js.map → chunk-wbv6218d.js.map} +1 -1
- package/dist/{chunk-mp3ecfnh.js → chunk-wg0ttent.js} +2 -2
- package/dist/{chunk-mp3ecfnh.js.map → chunk-wg0ttent.js.map} +1 -1
- package/dist/{chunk-7jnawtcm.js → chunk-wnjvfmqc.js} +2 -2
- package/dist/{chunk-7jnawtcm.js.map → chunk-wnjvfmqc.js.map} +1 -1
- package/dist/{chunk-nhhnkv0e.js → chunk-x82f3q6a.js} +4 -4
- package/dist/{chunk-nhhnkv0e.js.map → chunk-x82f3q6a.js.map} +1 -1
- package/dist/{chunk-mr3szvr3.js → chunk-xff7tkde.js} +2 -2
- package/dist/{chunk-mr3szvr3.js.map → chunk-xff7tkde.js.map} +1 -1
- package/dist/{chunk-y959p390.js → chunk-xp5axyb5.js} +15 -15
- package/dist/chunk-xp5axyb5.js.map +28 -0
- package/dist/{chunk-2x6cv37t.js → chunk-xtqd9vpp.js} +2 -2
- package/dist/{chunk-2x6cv37t.js.map → chunk-xtqd9vpp.js.map} +1 -1
- package/dist/{chunk-cee5gq7t.js → chunk-xyyq577r.js} +2 -2
- package/dist/{chunk-cee5gq7t.js.map → chunk-xyyq577r.js.map} +1 -1
- package/dist/{chunk-eqv7yxk7.js → chunk-ycn7w2e9.js} +2 -2
- package/dist/{chunk-eqv7yxk7.js.map → chunk-ycn7w2e9.js.map} +1 -1
- package/dist/{chunk-0fjn202c.js → chunk-yewj83ez.js} +3 -3
- package/dist/{chunk-0fjn202c.js.map → chunk-yewj83ez.js.map} +1 -1
- package/dist/{chunk-2ery6a75.js → chunk-yzsyg1f7.js} +3 -3
- package/dist/{chunk-2ery6a75.js.map → chunk-yzsyg1f7.js.map} +1 -1
- package/dist/{chunk-jgpbr2k1.js → chunk-z7224rhm.js} +2 -2
- package/dist/{chunk-jgpbr2k1.js.map → chunk-z7224rhm.js.map} +1 -1
- package/dist/{chunk-attr793y.js → chunk-zcg6m7gf.js} +2 -2
- package/dist/{chunk-attr793y.js.map → chunk-zcg6m7gf.js.map} +1 -1
- package/dist/{chunk-yhgt9dxj.js → chunk-zfbqgzwa.js} +2 -2
- package/dist/{chunk-yhgt9dxj.js.map → chunk-zfbqgzwa.js.map} +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/services/index.js +2 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/stats/route-table.js +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-49s8wwp2.js +0 -5
- package/dist/chunk-y959p390.js.map +0 -27
- /package/dist/{chunk-4y74s15p.js.map → chunk-0vc2akg0.js.map} +0 -0
- /package/dist/{chunk-3nf0nmpp.js.map → chunk-38kjpa6q.js.map} +0 -0
- /package/dist/{chunk-ja1289jh.js.map → chunk-5zxxd7qp.js.map} +0 -0
- /package/dist/{chunk-mv1rs9he.js.map → chunk-9gt9qdge.js.map} +0 -0
- /package/dist/{chunk-198ywkt2.js.map → chunk-9md6acv2.js.map} +0 -0
- /package/dist/{chunk-41bvpent.js.map → chunk-qbvm5q1g.js.map} +0 -0
|
@@ -29,6 +29,6 @@ export { h } from ${JSON.stringify("virtual:gemi-island-runtime")};
|
|
|
29
29
|
import { hydrateRoot } from "react-dom/client";
|
|
30
30
|
export ${z}
|
|
31
31
|
`,Q='const d=document,c=JSON.parse(d.getElementById("gemi-islands").textContent),w=f=>(window.requestIdleCallback||setTimeout)(f),m=(e,o)=>{if(!e.g){e.g=1;import(o.s).then(x=>x.h(e,x.m[o.e])).catch(r=>console.error(r))}};for(const e of d.querySelectorAll("gemi-island")){const o=c.i[e.dataset.island];if(!o)continue;if(o.l=="eager")m(e,o);else if(o.l=="idle"||!window.IntersectionObserver||!e.children.length)w(()=>m(e,o));else{const v=new IntersectionObserver(n=>{if(n.some(x=>x.isIntersecting)){v.disconnect();m(e,o)}});for(const k of e.children)v.observe(k)}}';
|
|
32
|
-
export{B as
|
|
32
|
+
export{B as bl,F as cl,G as dl,J as el,M as fl,Q as gl};
|
|
33
33
|
|
|
34
|
-
//# debugId=
|
|
34
|
+
//# debugId=57297D4382E7E87D64756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"/**\n * The browser side of islands, shared by the Vite plugin (which builds it), the\n * servers (which point the loader at it) and the tests.\n *\n * No imports: the Vite plugin is built on its own and the servers load it at\n * boot, so this file stays plain strings.\n */\n\n/**\n * The module that hydrates islands: React, `react-dom/client` and the small\n * `h(marker, Component)` below. A virtual module of gemi's Vite plugin that\n * every island entry imports, so the islands on a page share one copy of\n * React, in one chunk.\n */\nexport const ISLAND_RUNTIME_ID = \"virtual:gemi-island-runtime\";\n\n/** What `resolveId` turns `ISLAND_RUNTIME_ID` into (Vite's virtual-module convention). */\nexport const RESOLVED_ISLAND_RUNTIME_ID = `\\0${ISLAND_RUNTIME_ID}`;\n\n/**\n * The query that turns a module into its island entry: `Counter.tsx?gemi-island`\n * is a module of the plugin's that re-exports `Counter.tsx` as `m` next to the\n * runtime's `h`. It is what a static page imports for an island, and so it\n * is what the client manifest lists, keyed `app/…/Counter.tsx?gemi-island`,\n * with React and `react-dom/client` among its imports.\n */\nexport const ISLAND_ENTRY_QUERY = \"?gemi-island\";\n\n/** The island entry module for `file` (an absolute path or a root-relative URL). */\nexport function islandEntrySource(file: string) {\n return `import * as m from ${JSON.stringify(file)};\nexport { m };\nexport { h } from ${JSON.stringify(ISLAND_RUNTIME_ID)};\n`;\n}\n\n/**\n * `h(marker, Component)`: hydrates one `<gemi-island>` marker with the island's\n * component and the props the server serialised into `data-props`.\n *\n * The island's static children were rendered on the server into a\n * `<gemi-slot>` (the first one that belongs to this marker, not to an island\n * nested in it). They are handed back to the component as that same element\n * with the server's HTML, so hydration matches and React leaves them alone.\n *\n * `data-uid` is the `identifierPrefix` the server rendered the island with, so\n * `useId` agrees on both sides and two islands never share an id.\n *\n * Written as a function body with `createElement` and `hydrateRoot` free, so a\n * test can run it against real React without a bundler.\n */\nexport const ISLAND_HYDRATE_SOURCE = `function h(marker, Component) {\n if (typeof Component !== \"function\" && (typeof Component !== \"object\" || Component === null)) {\n throw new Error(\"gemi: island module has no component export for \" + marker.outerHTML.slice(0, 80));\n }\n const json = marker.getAttribute(\"data-props\");\n const props = json ? JSON.parse(json) : {};\n let slot = null;\n for (const candidate of marker.querySelectorAll(\"gemi-slot\")) {\n if (candidate.closest(\"gemi-island\") === marker) {\n slot = candidate;\n break;\n }\n }\n const children = slot\n ? [createElement(\"gemi-slot\", {\n style: { display: \"contents\" },\n suppressHydrationWarning: true,\n dangerouslySetInnerHTML: { __html: slot.innerHTML },\n })]\n : [];\n return hydrateRoot(marker, createElement(Component, props, ...children), {\n identifierPrefix: marker.getAttribute(\"data-uid\") || undefined,\n });\n}`;\n\n/** The runtime module's source, as the plugin serves and builds it. */\nexport const ISLAND_RUNTIME_SOURCE = `import { createElement } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nexport ${ISLAND_HYDRATE_SOURCE}\n`;\n\n/**\n * The island loader, inlined into a static document that uses islands.\n *\n * Kept byte-for-byte constant (the per-page island table travels in a\n * separate `<script type=\"application/json\">`, which a Content Security Policy\n * does not treat as script), so a strict policy can allow it by hash:\n * `script-src 'sha256-…'` with `ISLAND_LOADER_CSP_HASH`. Everything it loads\n * is a plain `import()` of a same-origin (or asset-base) file.\n *\n * The table is `{ i: [{ s: entry URL, e: export, l: load }] }` and each\n * marker's `data-island` indexes `i`. Per marker, on its schedule: import the\n * island's entry (the module as `m`, the runtime's `h`), then\n * `h(marker, m[export])`, which calls `hydrateRoot`. A failure is logged and\n * leaves the server-rendered markup in place.\n */\nexport const ISLAND_LOADER_SOURCE =\n 'const d=document,c=JSON.parse(d.getElementById(\"gemi-islands\").textContent),' +\n \"w=f=>(window.requestIdleCallback||setTimeout)(f),\" +\n \"m=(e,o)=>{if(!e.g){e.g=1;import(o.s).then(x=>x.h(e,x.m[o.e])).catch(r=>console.error(r))}};\" +\n 'for(const e of d.querySelectorAll(\"gemi-island\")){const o=c.i[e.dataset.island];if(!o)continue;' +\n 'if(o.l==\"eager\")m(e,o);else if(o.l==\"idle\"||!window.IntersectionObserver||!e.children.length)w(()=>m(e,o));' +\n \"else{const v=new IntersectionObserver(n=>{if(n.some(x=>x.isIntersecting)){v.disconnect();m(e,o)}});for(const k of e.children)v.observe(k)}}\";\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";AAcO,IAAM,EAAoB,8BAGpB,EAA6B,kCAS7B,EAAqB,eAG3B,SAAS,CAAiB,CAAC,EAAc,CAC9C,MAAO,sBAAsB,KAAK,UAAU,CAAI;AAAA;AAAA,oBAE9B,KAAK,UAlBQ,6BAkBmB;AAAA,EAmB7C,IAAM,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA0BxB,EAAwB;AAAA;AAAA,SAE5B;AAAA,EAkBI,EACX",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "57297D4382E7E87D64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{Vi as l}from"./chunk-159j20yr.js";import{bj as O,cj as E,dj as k}from"./chunk-ss3yn4g2.js";import{Cj as R,Ej as i,Fj as C,Gj as M,Hj as Xz,sj as T}from"./chunk-aq5zx3vg.js";import{jk as a}from"./chunk-yzsyg1f7.js";var $z=["every","none","some"],Vz=["is","isNot"];function g(z){return z==="many"?$z:Vz}function h(z,J){let W=Object.keys(z);return W.length>0&&W.every((Z)=>J.includes(Z))}var m="_count";function y(z){return Object.keys(z.relations).filter((J)=>z.relations[J]?.kind==="many").sort()}function N(z,J,W,Z){let X={model:z,operation:J,hasUser:W!=null};return Object.defineProperty(X,"user",{enumerable:!0,get(){if(W==null&&!Z)throw new R(z,J,"no-user");return W}}),X}class n{}class Qz extends n{}var qz=new Set(["findMany","findFirst","findFirstOrThrow","findUnique","findUniqueOrThrow","count","aggregate","groupBy","update","updateMany","delete","deleteMany"]),Yz=new Set(["create","createMany","upsert"]),jz=new Set(["update","updateMany","upsert"]),Lz=new Set(["update","updateMany"]),Kz=new Set(["create","createMany"]),p=new WeakMap;function Gz(z,J,W){if(typeof z!=="function")return z;let Z=p.get(z);if(Z!==void 0)return Z;let X;try{X=new z}catch($){throw new M(b(J),W,"constructor-threw",`${f(z)}, and constructing it threw:
|
|
3
3
|
|
|
4
4
|
${$?.message??String($)}`,H,void 0,{cause:$})}return t(X,J,W),p.set(z,X),X}function S(z,J){return z.map((W,Z)=>Gz(W,J,Z))}var H=["before","scope","onCreate","onUpdate","redact"];var u=new WeakSet;function s(z,J){if(u.has(J))return;for(let W=0;W<J.length;W++)Uz(J[W],z,W);u.add(J)}function Uz(z,J,W){let Z=b(J),X=typeof z;if(z===null||Array.isArray(z)||X!=="object"&&X!=="function")throw new M(Z,W,"not-a-policy",o(z),H);if(X==="function"){if(!Mz(z))throw new M(Z,W,"not-constructable",f(z),H);return}t(z,J,W)}function t(z,J,W){let Z=b(J),X=0,$=[];for(let Y of H){let q=z[Y];if(q===void 0||q===null){if(Y in z)$.push(Y);continue}if(typeof q!=="function")throw new M(Z,W,"hook-not-callable",`'${Y}' that is ${o(q)} rather than a function`,H);X++}if(X>0)return;if($.length>0)throw new M(Z,W,"no-hooks",`It writes ${$.map((Y)=>`'${Y}'`).join(", ")} down and leaves ${$.length===1?"it":"them"} unset, which reads as `+"absent \u2014 so nothing is left to run.",H);let V=Fz(z),Q=Iz(V);throw new M(Z,W,"no-hooks",V.length===0?"It is empty.":`It spells ${Hz(V)}.`+(V.length===1&&V[0]==="default"?" A lone 'default' is a module namespace rather than the policy "+"inside it \u2014 put `entry.default` in the array, or import the "+"policy by name.":""),H,Q)}function Hz(z){let J=z.slice(0,8).map((W)=>`'${W}'`);return z.length>J.length?`${J.join(", ")} and ${z.length-J.length} more`:J.join(", ")}function Mz(z){try{return Reflect.construct(Bz,[],z),!0}catch{return!1}}var Bz=function(){};function Fz(z){let J=new Set,W=z;while(W!==null&&W!==Object.prototype){for(let Z of Object.getOwnPropertyNames(W))if(Z!=="constructor")J.add(Z);W=Object.getPrototypeOf(W)}return[...J]}function Iz(z){let J,W=2;for(let Z of z)for(let X of H){let $=Tz(Z.toLowerCase(),X.toLowerCase());if($<W)W=$,J={key:Z,hook:X}}return J}function Tz(z,J){if(z===J)return 0;let W=Array.from({length:J.length+1},(Z,X)=>X);for(let Z=1;Z<=z.length;Z++){let X=W[0];W[0]=Z;for(let $=1;$<=J.length;$++){let V=W[$];W[$]=Math.min(W[$]+1,W[$-1]+1,X+(z[Z-1]===J[$-1]?0:1)),X=V}}return W[J.length]}function o(z){if(z===null)return"null";if(z===void 0)return"undefined";if(typeof z==="string")return`the string ${JSON.stringify(z)}`;if(typeof z==="function")return f(z);if(Array.isArray(z))return"an array";if(typeof z==="object")return"an object";return`the ${typeof z} ${String(z)}`}function f(z){return z.name?`the function \`${z.name}\``:"an anonymous function"}function _(z){let J,W,Z,X=z;while(X&&X!==Function.prototype){if(Object.hasOwn(X,"$policy"))throw Error(`${X.name??"This model"} declares \`$policy\`, which is now \`$policies\` and takes a list. The old `+"name is not read, so this model is currently unpolicied \u2014 every "+"scope, onCreate and redact on it is being skipped.");if(Object.hasOwn(X,"$policies")&&X.$policies){let $=X.$policies;if($.length>0){let V=X;if(s(V,$),W===void 0&&J===void 0)W=$,Z=V;else J??=S(W,Z),W=void 0,J.unshift(...S($,V))}}X=Object.getPrototypeOf(X)}if(J!==void 0)return J;if(W===void 0)return Nz;return W.some(($)=>typeof $==="function")?S(W,Z):W}function r(z){let J=z;while(J&&J!==Function.prototype){if(Object.hasOwn(J,"$policies")&&J.$policies){let W=J.$policies;if(W.length>0)s(J,W)}J=Object.getPrototypeOf(J)}}function b(z){return z?.name??"This model"}var Nz=Object.freeze([]);function D(z,J,W,Z=[]){if(z.length===0)return W;let X=W,$;for(let V of z)if(V.before){if(V.before(J)===!1)throw new R(J.model,J.operation)}for(let V of z){if(!V.scope)continue;if(Kz.has(J.operation)){Sz(V,J);continue}let Q=V.scope(J);if(Q===void 0||Q===null)continue;if(Rz(J),Lz.has(J.operation)&&!V.onUpdate){let Y=Pz(Q);if(Y.length>0)($??=[]).push(...Y)}X=_z(X,Q)}if(Yz.has(J.operation)){for(let V of z)if(V.onCreate)X=Dz(X,J,V)}if(jz.has(J.operation)){for(let V of z)if(V.onUpdate)X=Az(X,J,V)}if($!==void 0)Cz($,J,X,Z);return X}function _z(z,J){let W=z?.where;if(W===void 0||W===null)return{...z,where:J};if(typeof W!=="object"||Array.isArray(W))return{...z,where:{AND:[W,J]}};let Z=W.AND,X=Z===void 0||Z===null?[]:Array.isArray(Z)?Z:[Z];return{...z,where:{...W,AND:[...X,J]}}}function Dz(z,J,W){let Z=(X)=>W.onCreate(J,{...X});if(J.operation==="createMany"){let X=z?.data;return{...z,data:Array.isArray(X)?X.map(Z):Z(X)}}if(J.operation==="upsert")return{...z,create:Z(z?.create)};return{...z,data:Z(z?.data)}}function Az(z,J,W){let Z=J.operation==="upsert"?"update":"data",X=z?.[Z];if(X===void 0||X===null)return z;return{...z,[Z]:W.onUpdate(J,{...X})}}function Cz(z,J,W,Z=[]){let X=W?.data;if(typeof X!=="object"||X===null)return;let $=z.filter((V)=>(V in X)&&!Z.includes(V));if($.length===0)return;throw new i(J.model,J.operation,[...new Set($)])}function Pz(z){if(typeof z!=="object"||z===null||Array.isArray(z))return[];let J=[];for(let W of Object.keys(z)){if(W==="AND"||W==="OR"||W==="NOT")continue;J.push(W)}return J}function Sz(z,J){if(z.onCreate)return;throw new T(J.operation,J.model,J.operation,`${J.model} has a policy that scopes reads but no 'onCreate', and ${J.operation} has no where clause for a scope to narrow. As written the policy would confine reads to the caller and let an insert name any value it likes. Add an onCreate that sets the scoped `+"column \u2014 or, if unscoped creates are intended, say so with an onCreate "+"that returns its data unchanged.")}function Rz(z){if(qz.has(z.operation))return;throw new T(z.operation,z.model,z.operation,`${z.model} has a policy with a scope, and ${z.operation} cannot carry one: its where clause compiles to an 'on conflict' target, which is a key rather than a filter. Running it would write outside the scope.
|
|
5
5
|
|
|
6
6
|
Two ways out. Use update and create separately, which both scope `+"normally \u2014 or leave the conflict key out of 'create', which Model.upsert "+"runs as a scoped read and a scoped write inside one transaction. The refusal is about 'on conflict' specifically, not about upsert.")}function dz(z,J,W){if(z.length===0)return;let Z=z.filter((X)=>X.redact);if(Z.length===0)return;for(let X of fz(W))for(let $ of Z)$.redact(J,X)}function fz(z){if(Array.isArray(z))return z;if(z===null||z===void 0)return[];if(typeof z!=="object")return[];return[z]}function lz(z,J,W){for(let Z of W){let X=z.fields[Z];if(X&&!X.nullable)throw new T(`redact.${Z}`,z.name,"redact",`'${Z}' is not nullable, so setting it to null would contradict `+"the generated type \u2014 which still says the field is there. Make the "+"field optional in schema.prisma, omit it with 'select' instead, or delete the key yourself if a runtime-only guarantee is enough.");if(Z in J)J[Z]=null}}function iz(){let z=a();if(z)return z.user;return bz()?.user??null}function bz(){try{return l.getStore()}catch{return}}var e=Symbol("gemi.orm.policiesAppliedByCaller");function az(z){return{...z,[e]:!0}}function nz(z){return typeof z==="object"&&z!==null&&z[e]===!0}var zz=Symbol("gemi.orm.columnsWrittenByTheOrm");function sz(z,J){return{...z,[zz]:J}}function tz(z){if(typeof z!=="object"||z===null)return c;let J=z[zz];return Array.isArray(J)?J:c}var c=[],Jz=Symbol("gemi.orm.operationTheRowIsReturnedFor");function oz(z,J){return{...z,[Jz]:J}}function rz(z){if(typeof z!=="object"||z===null)return;let J=z[Jz];return typeof J==="string"?J:void 0}var A="findMany";function Oz(z,J,W,Z,X){if(J===void 0||J===null)return J;if(typeof J!=="object")return J;let $=J;for(let Y of["include","select"]){let q=J[Y];if(typeof q!=="object"||q===null||Array.isArray(q))continue;let j;for(let L of Object.keys(q)){if(L===m){let w=Ez(z,q[L],W,Z,X);if(w!==q[L])j??={...q},j[L]=w;continue}let G=z.relations[L];if(!G)continue;let K=q[L];if(K===void 0||K===!1)continue;let U=X(G.model);if(!U)continue;let F=K===!0?{}:K;if(typeof F!=="object"||Array.isArray(F))continue;let x=Oz(U.schema,F,W,Z,X),v=!Z&&U.policies.length>0?D(U.policies,N(U.schema.name,A,W,Z),x):x;if(v!==F)j??={...q},j[L]=v}if(j)$={...$,[Y]:j}}let V=Wz(z,$.orderBy,W,Z,X);if(V!==$.orderBy)$={...$,orderBy:V};let Q=I(z,$.where,W,Z,X);if(Q!==$.where)$={...$,where:Q};return $}function Wz(z,J,W,Z,X){if(Z)return J;if(typeof J!=="object"||J===null)return J;if(Array.isArray(J)){let Q=!1,Y=J.map((q)=>{let j=Wz(z,q,W,Z,X);if(j!==q)Q=!0;return j});return Q?Y:J}let $,V=J;for(let Q of Object.keys(V)){let Y=z.relations[Q];if(!Y)continue;let q=V[Q];if(typeof q!=="object"||q===null||Array.isArray(q))continue;let j=X(Y.model);if(!j||j.policies.length===0)continue;let L=D(j.policies,N(j.schema.name,A,W,Z),q);if(L!==q)$??={...V},$[Q]=L}return $??J}function Ez(z,J,W,Z,X){if(Z)return J;let $=J===!0;if(!$&&(typeof J!=="object"||J===null||Array.isArray(J)))return J;let V=$?Object.fromEntries(y(z).map((q)=>[q,!0])):J.select;if(typeof V!=="object"||V===null||Array.isArray(V))return J;let Q,Y=V;for(let q of Object.keys(Y)){let j=Y[q];if(j===void 0||j===!1)continue;let L=z.relations[q];if(!L)continue;let G=X(L.model);if(!G||G.policies.length===0)continue;let K=j===!0?{}:j;if(typeof K!=="object"||Array.isArray(K))continue;let U=D(G.policies,N(G.schema.name,A,W,Z),K);if(U!==K)Q??={...Y},Q[q]=U}if(!Q)return J;return $?{select:Q}:{...J,select:Q}}function I(z,J,W,Z,X){if(typeof J!=="object"||J===null)return J;if(Array.isArray(J)){let Q=!1,Y=J.map((q)=>{let j=I(z,q,W,Z,X);if(j!==q)Q=!0;return j});return Q?Y:J}let $,V=J;for(let Q of Object.keys(V)){let Y=V[Q];if(Y===void 0)continue;if(Q==="AND"||Q==="OR"||Q==="NOT"){let L=I(z,Y,W,Z,X);if(L!==Y)$??={...V},$[Q]=L;continue}let q=z.relations[Q];if(!q)continue;let j=kz(q,Y,W,Z,X);if(j!==Y)$??={...V},$[Q]=j}return $??J}function kz(z,J,W,Z,X){if(typeof J!=="object"||J===null||Array.isArray(J))return J;let $=X(z.model);if(!$)return J;let V=g(z.kind),Q=!h(J,V),Y=Q?[["is",J]]:Object.entries(J),q;for(let[j,L]of Y){if(L===null||L===void 0)continue;let G=I($.schema,L,W,Z,X),K=!Z&&$.policies.length>0?D($.policies,N($.schema.name,A,W,Z),{where:G}).where:G,U=j==="every"?xz(G,K):K;if(U!==L)q??=Q?{}:{...J},q[j]=U}if(!q)return J;return q}function xz(z,J){if(J===z)return z;let W=d(z),X=d(J).slice(W.length);if(X.length===0)return z;return{OR:[{NOT:X.length===1?X[0]:{AND:X}},z]}}function d(z){if(typeof z!=="object"||z===null)return[];let J=z.AND;if(J===void 0)return[];return Array.isArray(J)?J:[J]}function vz(...z){let[J]=wz(...z);if(J!==void 0)throw J}function wz(...z){let J=[];for(let W of z)for(let Z of Object.values(W)){let X=Zz(Z);if(X===null)continue;r(X);let $=X.$schema.name,V=E($)?k($):void 0;if(V===void 0||V===X)continue;let Q=_(X),Y=_(V),q=Q.length!==Y.length||Q.some((j,L)=>j!==Y[L]);if(P(V,X)||P(X,V)){let j=P(X,V)?V:X,L=j===V?X:V;if(_(j).length===0){if(V===L)continue;if(!q)continue;J.push(new C($,B(V),B(X),Q.length>0?"queried":"registered"));continue}if(q)J.push(new C($,B(j),B(L),"narrowing"));continue}if(!q)continue;J.push(new C($,B(V),B(X),Q.length>0?"queried":"registered"))}return J}function XJ(...z){let J=new Map;for(let Z of z){let X=new Map;for(let $ of new Set(Object.values(Z))){let V=Zz($);if(V===null)continue;let Q=V.$schema.name,Y=X.get(Q);if(Y===void 0)X.set(Q,[V]);else Y.push(V)}for(let[$,V]of X)J.set($,gz($,V))}let W=[...J.keys()].filter((Z)=>E(Z)).map((Z)=>[Z,k(Z)]);for(let[Z,X]of J)O(Z,X);try{vz(...z)}catch(Z){for(let[X,$]of W)O(X,$);throw Z}}function gz(z,J){if(J.length===1)return J[0];let W=J.filter(($)=>!hz($)),Z=W.length>0?W:J;if(Z.length===1)return Z[0];let X=Z.filter(($)=>Z.every((V)=>V===$||P(V,$)));if(X.length===1)return X[0];throw new Xz(z,Z.map(($)=>B($)))}function hz(z){if("$generated"in z)return Object.hasOwn(z,"$generated")&&z.$generated===!0;return Object.hasOwn(z,"$schema")}function P(z,J){let W=Object.getPrototypeOf(z);while(W!==null&&W!==Function.prototype){if(W===J)return!0;W=Object.getPrototypeOf(W)}return!1}function B(z){return z?.name??String(z)}function Zz(z){if(typeof z!=="function")return null;let J=z.$schema;if(J===void 0||typeof J.name!=="string")return null;return z}
|
|
7
7
|
export{g as Fa,h as Ga,m as Ha,y as Ia,N as Ja,n as Ka,Qz as La,_ as Ma,D as Na,dz as Oa,lz as Pa,iz as Qa,az as Ra,nz as Sa,sz as Ta,tz as Ua,oz as Va,rz as Wa,A as Xa,Oz as Ya,vz as Za,wz as _a,XJ as $a};
|
|
8
8
|
|
|
9
|
-
//# debugId=
|
|
9
|
+
//# debugId=A95481CD700B32CD64756E2164756E21
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"import {\n AmbiguousModelRegistrationError,\n UnregisteredPolicyClassError,\n} from \"./errors\";\nimport { assertPolicyShapes, policiesFor } from \"./policy\";\nimport * as registry from \"./registry\";\nimport type { ModelSchema } from \"./schema\";\n\n/** A model class, as much of one as anything below `Model.ts` can name. */\ntype ModelClass = object & { $schema: ModelSchema };\n\n/**\n * Checks that every policied model class an application defines is the one the\n * registry resolves its name to — **ahead of any query**, rather than when one\n * happens to be run.\n *\n * ### Why this exists\n *\n * `Model.$exec` already refuses a query whose class carries policies the\n * registered class does not (`UnregisteredPolicyClassError`). That guard closed\n * the two shapes found in #51, and it is the right check, but it can only fire\n * on a class somebody actually queries **at the root**. Its condition begins\n * `registered !== this`, and there is a case where that is false and the leak is\n * real:\n *\n * export class Membership extends MembershipModel {\n * static $policies = [{ scope: (ctx) => ({ orgId: ctx.user.orgId }) }]\n * }\n * // ...and no `register(\"Membership\", Membership)`\n *\n * If nothing ever calls `Membership.findMany()` — because memberships are only\n * ever read through `include: { memberships: true }` — then the include resolves\n * the name to the *generated base*, `this` **is** that base, the comparison\n * never runs, and rows come back unscoped with no error. Not a policy chain that\n * fails to diverge: a check that is never reached.\n *\n * A model reached only through includes is usually a membership or a pivot,\n * which is exactly the kind that carries a tenant scope. So the residual runs\n * the wrong way: the guard is weakest where the data is most sensitive.\n *\n * ### What this does about it\n *\n * The same rule, triggered differently. Instead of waiting for a root query,\n * it takes the modules where an application's model classes live and applies the\n * divergence comparison to every one of them:\n *\n * import * as models from \"@/app/models\"\n * assertPoliciesRegistered(models)\n *\n * Reading a class out of a module namespace is what makes the unqueried case\n * visible — the class exists and is exported whether or not anything queries it.\n *\n * `registerModels` runs this after registering, and `Kernel.models` runs\n * `registerModels` at boot, so an application that declares its model modules\n * gets it without asking. This is the same check for modules the Kernel does\n * not own — a test over a package's models, a script that boots nothing.\n *\n * It can only see modules it is handed, which is the residual either way: a\n * policied class in a file no barrel re-exports is invisible to it.\n * `gemi check models` closes that by handing it the files instead of the\n * barrel — see `auditModelRegistrations`, which is the same rule without the\n * throw.\n */\nexport function assertPoliciesRegistered(\n ...modules: Array<Record<string, unknown>>\n): void {\n const [first] = auditModelRegistrations(...modules);\n if (first !== undefined) throw first;\n}\n\n/**\n * Every problem `assertPoliciesRegistered` would report, as values rather than\n * as a throw — in the order it would have reported them, so the first element is\n * exactly what that function throws.\n *\n * ### Why the rule needed a second caller\n *\n * A throw is the right shape at boot: the first policied class that does not own\n * its name is a reason not to start, and the rest of the list is noise nobody\n * reads before fixing the first one.\n *\n * It is the wrong shape for a checker. `gemi check models` walks\n * `app/models/**` and audits each file, so it wants *all* of them, and it wants\n * to sort them — a policied class the Kernel never sees is a leak to report,\n * while a policied view deliberately kept out of the declared modules is the\n * arrangement the error for that case actually recommends, and reporting it\n * would be telling an author to undo what the framework told them to do.\n * `UnregisteredPolicyClassError.carries` is what separates the two, and it can\n * only be read off an error somebody is holding.\n *\n * Errors rather than a plain finding type, because the message is the useful\n * part and it is already written once, in the error. Constructing them is not\n * free — a stack per finding — and it is a check somebody runs, not a request\n * path.\n */\nexport function auditModelRegistrations(\n ...modules: Array<Record<string, unknown>>\n): UnregisteredPolicyClassError[] {\n const problems: UnregisteredPolicyClassError[] = [];\n\n for (const module of modules) {\n for (const exported of Object.values(module)) {\n const model = asModelClass(exported);\n if (model === null) continue;\n\n // #321's boot-time half, run **before** the early return below and for\n // every class rather than only the diverging ones. Left below the return,\n // the two commonest arrangements were never checked at all — a class that\n // already owns its name, and one whose name nothing else claims — so a\n // `{ scopes: … }` typo registered, reported green, and read unscoped.\n //\n // `assertPolicyShapes` and not `policiesFor`, and the difference is the\n // point: this walk checks the entries and constructs nothing. Resolving\n // here instead is one line and would additionally catch a policy class\n // whose constructor throws — at the price of constructing every policy\n // class in the application at `registerModels` time, ahead of whatever\n // config or container the constructor reaches for. A guard against a\n // policy that does nothing must not become the reason a working\n // application stops booting, so the cases that need an instance are left\n // to `policiesFor`, which is reached below, on the first query, and by\n // `Model.$exec`.\n assertPolicyShapes(model);\n\n const name = model.$schema.name;\n const registered = registry.has(name)\n ? (registry.get<unknown>(name) as object)\n : undefined;\n\n // Nothing registered under the name at all. The generated `index.ts`\n // registers every model, so reaching this means it was never imported —\n // a different mistake, and one the first query reports clearly through\n // `ModelNotRegisteredError`. Not this function's business.\n if (registered === undefined || registered === model) continue;\n\n const ours = policiesFor(model);\n const theirs = policiesFor(registered);\n const diverges =\n ours.length !== theirs.length ||\n ours.some((policy, index) => policy !== theirs[index]);\n\n // The two classes are on one prototype chain — a base and something\n // extending it — which is the arrangement almost every application has,\n // and the one this audit used to get wrong in both directions.\n //\n // `policiesFor` accumulates upwards, so a descendant's chain always\n // contains its ancestor's. What separates the two shapes is therefore\n // whether the **ancestor** carries anything of its own.\n if (descendsFrom(registered, model) || descendsFrom(model, registered)) {\n const ancestor = descendsFrom(model, registered) ? registered : model;\n const descendant = ancestor === registered ? model : registered;\n\n if (policiesFor(ancestor).length === 0) {\n // The ancestor contributes nothing, so the descendant is the first\n // class to carry a policy: it is not a view over the model, it *is*\n // the model. A generated base is the usual ancestor here, and a\n // hand-written intermediate behaves the same way.\n //\n // Registered already? Then this is the correct arrangement, and it\n // has to be skipped rather than reported — it used not to be, and\n // that is why the documented\n //\n // assertPoliciesRegistered(generated, models)\n //\n // threw the moment an application wrote its first policy: it walked\n // the generated namespace, found `UserModel` diverging from the\n // registered `User`, and refused the thing it exists to protect.\n // Being reachable through a base is not the bug; querying through one\n // is, and that is a property of a call site rather than of a module's\n // export list, so `Model.$exec` keeps that direction.\n if (registered === descendant) continue;\n\n // Neither class carries anything, so which one owns the name changes\n // no query's scope. An unregistered plain subclass is not a mistake.\n if (!diverges) continue;\n\n // Not registered, and it has policies: #316 itself. The policied\n // class is not the one the name resolves to, so every nested read\n // runs the ancestor and skips it.\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(registered),\n nameOf(model),\n ours.length > 0 ? \"queried\" : \"registered\",\n ),\n );\n continue;\n }\n\n // The ancestor carries policies of its own, so it is a registered model\n // in good standing and the descendant is narrowing it. The registry\n // holds one class per name: registering the view applies its narrowing\n // to every nested read, and leaving the ancestor registered skips the\n // view's policies entirely. Both are silent, so neither is chosen.\n if (diverges) {\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(ancestor),\n nameOf(descendant),\n \"narrowing\",\n ),\n );\n }\n\n // Same chain, same policies — a plain typed view. Nothing to report.\n continue;\n }\n\n if (!diverges) continue;\n\n // Unrelated classes claiming one name. Whichever is registered, the\n // other's policies are simply not in effect.\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(registered),\n nameOf(model),\n ours.length > 0 ? \"queried\" : \"registered\",\n ),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Registers every model class the given modules export, under the name each\n * one's schema carries, and then audits the result.\n *\n * ### The line this exists to delete\n *\n * `register(\"User\", User)` next to every subclass is a correct instruction and\n * a bad mechanism, because forgetting it is invisible. A relation read resolves\n * its target by name, so an unregistered policied subclass leaves the generated\n * base owning the name and every nested `include` of that model comes back\n * unscoped — no error, no warning, and an authorization hole in the direction\n * nobody checks. `assertPoliciesRegistered` turns that into a loud failure, but\n * only for someone who remembered to run it.\n *\n * Deriving the registration from the module removes the mistake instead of\n * reporting it. The name is not a string an author repeats; it is\n * `$schema.name`, which the generator wrote and the subclass inherits:\n *\n * import * as generated from \"./generated\"\n * import * as models from \"./models\"\n *\n * registerModels(generated, models)\n *\n * Later modules win, so the application's classes replace the generated bases\n * they extend. `register` still exists and still works — this is what an\n * application calls once instead of writing it thirteen times.\n *\n * ### What it still cannot see\n *\n * Modules it is handed. A policied class in a file nothing imports is invisible\n * to this exactly as it is to `assertPoliciesRegistered`, and closing *that*\n * would take the framework enumerating the filesystem at boot. Handing it a\n * barrel is the whole discipline: one file to add a model to, and the audit\n * covers everything in it.\n *\n * `Kernel.models` is that call, wired at boot, so an application declares its\n * model modules the way it already declares config slices and providers.\n */\nexport function registerModels(\n ...modules: Array<Record<string, unknown>>\n): void {\n // Elected into a local map first, and only committed once the audit passes.\n //\n // The registry is process-wide and outlives the throw. Registering as we went\n // meant a refused call left the arrangement it had just refused installed —\n // `registerModels({Ours}, {Theirs})` threw, and `\"User\"` resolved to `Theirs`\n // afterwards, which is the leaking mapping the audit exists to reject. A\n // server whose boot dies never notices; a dev server that catches and keeps\n // serving, or a test harness that continues past the error, serves the rest\n // of the process from it.\n const staged = new Map<string, ModelClass>();\n\n for (const module of modules) {\n const candidates = new Map<string, ModelClass[]>();\n\n // Deduped by identity first: `export { User }` alongside a default export\n // is the same class under two keys, not two classes competing for a name.\n for (const exported of new Set(Object.values(module))) {\n const model = asModelClass(exported);\n if (model === null) continue;\n\n const name = model.$schema.name;\n const existing = candidates.get(name);\n if (existing === undefined) candidates.set(name, [model]);\n else existing.push(model);\n }\n\n // Later modules win, which is what lets an application's classes replace\n // the generated bases they extend.\n for (const [name, classes] of candidates) {\n staged.set(name, elect(name, classes));\n }\n }\n\n // What the registry said before, so a failed audit can put it back. `register`\n // has no inverse, so a name that was previously *absent* cannot be made\n // absent again — it is left pointing at what this call elected. That is the\n // one residue, and it is the harmless direction: the alternative to a wrong\n // registration under a name nothing claimed is `ModelNotRegisteredError`, and\n // the class elected here is the one this module set would have used anyway.\n const previous = [...staged.keys()]\n .filter((name) => registry.has(name))\n .map((name) => [name, registry.get<unknown>(name)] as const);\n\n for (const [name, model] of staged) registry.register(name, model);\n\n try {\n assertPoliciesRegistered(...modules);\n } catch (error) {\n for (const [name, model] of previous) registry.register(name, model);\n throw error;\n }\n}\n\n/**\n * Which of several classes claiming one name in one module gets it.\n *\n * Two shapes put more than one candidate in a namespace, and they want opposite\n * answers, so neither \"most derived\" nor \"least derived\" is the rule on its\n * own:\n *\n * export * from \"./generated\" // UserModel, and\n * export class User extends UserModel { static $policies = [...] }\n *\n * wants the subclass — electing the base here *is* the leak, in the one file an\n * author most plausibly writes it in. While\n *\n * export class User extends UserModel { static $policies = [...] }\n * export class AdminUser extends User {}\n *\n * wants `User`. `AdminUser` is a typed view over the same rows; it inherits the\n * policies either way, so registering it changes nothing when it adds none and\n * silently applies its own narrowing to every nested read when it does.\n *\n * What separates them is which class the *generator* wrote. It emits\n * `static $schema = schema.User` on the base, and a subclass inherits that\n * property rather than declaring one — so an own `$schema` is the mark of a\n * generated base, and it is a fact about the classes rather than about the\n * order somebody exported them in. Application classes are preferred over\n * bases; among application classes the least derived wins, for the reason\n * `AdminUser` gives.\n *\n * When that leaves no single answer the candidates are unrelated classes with a\n * genuine claim each, and there is nothing left to infer. That case is refused\n * rather than guessed at: `register` says which, in the application's own\n * words.\n */\nfunction elect(name: string, classes: ModelClass[]): ModelClass {\n if (classes.length === 1) return classes[0]!;\n\n const written = classes.filter((candidate) => !isGeneratedBase(candidate));\n const eligible = written.length > 0 ? written : classes;\n\n if (eligible.length === 1) return eligible[0]!;\n\n const roots = eligible.filter((candidate) =>\n eligible.every(\n (other) => other === candidate || descendsFrom(other, candidate),\n ),\n );\n\n if (roots.length === 1) return roots[0]!;\n\n throw new AmbiguousModelRegistrationError(\n name,\n eligible.map((candidate) => nameOf(candidate)),\n );\n}\n\n/**\n * Whether the generator wrote this class, rather than an application extending\n * one it wrote.\n *\n * The generator marks its own output — `static $generated = true` on each\n * emitted base, and on nothing else — so for artifacts that carry the mark this\n * is a fact the generator stated rather than a property of how it happens to be\n * written. A subclass *inherits* the mark and does not own it, which is what\n * makes own-vs-inherited the whole test.\n *\n * ### The fallback, and why it is second\n *\n * `$schema` is also declared on the emitted base and inherited below it, so\n * owning *that* used to answer the same question, and it answered it wrongly for\n * one shape (#318): a subclass that redeclares `static $schema` — pointing at a\n * modified schema object, or by copy-paste — read as a base, every candidate\n * looked generated, and the least derived won. That did not pass quietly, since\n * `assertPoliciesRegistered` runs immediately after `elect` and refuses a\n * policied class that lost its name. But loud-and-wrong is still wrong, and the\n * silent half — a subclass with statics and row methods but no policies, whose\n * methods then never run inside a nested read — had nothing to refuse.\n *\n * The inference survives as the fallback for artifacts generated *before* the\n * mark existed, where it is the only signal there is. `\"$generated\" in candidate`\n * is what separates the two worlds: it walks the prototype chain, so it is true\n * for a marked base and for everything under it, and false for every class in an\n * app whose `app/models/generated` predates 0.51. Asking `Object.hasOwn` first\n * and falling back on `false` would send a subclass of a *marked* base back into\n * the inference — which is exactly the case the mark was added to fix.\n *\n * `registration.test.ts` in the template asserts the contract against real\n * generator output, because this is the one place a generator change could\n * quietly invalidate an assumption made here.\n */\nfunction isGeneratedBase(candidate: ModelClass): boolean {\n // Owning the mark, not merely having it — and owning it set to `true`. The\n // declared type is `?: true`, so TypeScript already refuses `false`; reading\n // the value anyway is what makes `static $generated = false` mean the thing\n // it plainly says in an app with no typechecking between it and here.\n if (\"$generated\" in candidate) {\n return (\n Object.hasOwn(candidate, \"$generated\") &&\n (candidate as { $generated?: unknown }).$generated === true\n );\n }\n\n return Object.hasOwn(candidate, \"$schema\");\n}\n\n/**\n * Whether `derived` has `base` in its static prototype chain — the `extends`\n * relation between two classes, walked on the constructor side because that is\n * where `$schema` and `$policies` live.\n */\nfunction descendsFrom(derived: unknown, base: unknown): boolean {\n let current = Object.getPrototypeOf(derived);\n\n while (current !== null && current !== Function.prototype) {\n if (current === base) return true;\n current = Object.getPrototypeOf(current);\n }\n\n return false;\n}\n\nfunction nameOf(value: unknown): string {\n return (value as { name?: string })?.name ?? String(value);\n}\n\n/**\n * A model class, structurally.\n *\n * Structural rather than `instanceof Model` on purpose: this module sits below\n * `Model.ts` in the import graph, and importing it here to answer a question\n * about shape would put a cycle between the registry, the policy hook and the\n * model base for no gain. `$schema` carrying a `name` is what every operation\n * already relies on.\n *\n * A module namespace holds anything the author exported — types erase, but\n * constants, helpers and re-exported values do not — so everything that is not\n * a model class is skipped rather than treated as an error.\n */\nfunction asModelClass(value: unknown): ModelClass | null {\n if (typeof value !== \"function\") return null;\n\n const schema = (value as { $schema?: ModelSchema }).$schema;\n if (schema === undefined || typeof schema.name !== \"string\") return null;\n\n return value as unknown as ModelClass;\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "A95481CD700B32CD64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
class A extends Error{constructor(p,q){super(`Target [${p}] is not bound in the container.`+(q.length>0?` Bound tokens: ${q.join(", ")}.`:" No tokens are bound \u2014 was the application booted?"));this.name="BindingResolutionError"}}class C{bindings=new Map;instances=new Map;bind(p,q){this.bindings.set(p.token,{factory:q,shared:!1}),this.instances.delete(p.token)}singleton(p,q){this.bindings.set(p.token,{factory:q,shared:!0}),this.instances.delete(p.token)}instance(p,q){return this.instances.set(p.token,q),q}bound(p){return this.bindings.has(p.token)||this.instances.has(p.token)}resolved(p){return this.instances.has(p.token)}make(p){let q=p.token;if(this.instances.has(q))return this.instances.get(q);let v=this.bindings.get(q);if(!v)throw new A(q,this.keys());let x=v.factory(this);if(v.shared)this.instances.set(q,x);return x}forget(p){this.instances.delete(p.token)}keys(){return[...new Set([...this.bindings.keys(),...this.instances.keys()])]}flush(){this.bindings.clear(),this.instances.clear()}}
|
|
3
|
-
export{A as
|
|
3
|
+
export{A as $k,C as al};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
5
|
+
//# debugId=2680A8C6B1B1C96864756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"/**\n * Tokens are the service classes themselves, so `make(MailManager)` is typed\n * `MailManager` without a cast. The container keys its bindings off the class's\n * `static token` string rather than the constructor object: the built binary\n * (`dist/bin/gemi.js`) bundles its own copy of gemi while the app resolves\n * `gemi/*` to source, so the same service is two distinct class objects across\n * that boundary. A string survives it. Laravel binds both `'mail'` and\n * `MailManager::class` for the same reason.\n */\nexport type ServiceToken<T> = (abstract new (...args: any[]) => T) & {\n token: string;\n};\n\nexport type Factory<T> = (app: Container) => T;\n\ninterface Binding {\n factory: Factory<any>;\n shared: boolean;\n}\n\nexport class BindingResolutionError extends Error {\n constructor(token: string, known: string[]) {\n super(\n `Target [${token}] is not bound in the container.` +\n (known.length > 0\n ? ` Bound tokens: ${known.join(\", \")}.`\n : \" No tokens are bound — was the application booted?\"),\n );\n this.name = \"BindingResolutionError\";\n }\n}\n\nexport class Container {\n private bindings = new Map<string, Binding>();\n private instances = new Map<string, any>();\n\n bind<T>(token: ServiceToken<T>, factory: Factory<T>) {\n this.bindings.set(token.token, { factory, shared: false });\n this.instances.delete(token.token);\n }\n\n /**\n * Lazy by design — `factory` is not called until the first `make()`.\n */\n singleton<T>(token: ServiceToken<T>, factory: Factory<T>) {\n this.bindings.set(token.token, { factory, shared: true });\n this.instances.delete(token.token);\n }\n\n instance<T>(token: ServiceToken<T>, object: T): T {\n this.instances.set(token.token, object);\n return object;\n }\n\n bound<T>(token: ServiceToken<T>): boolean {\n return (\n this.bindings.has(token.token) || this.instances.has(token.token)\n );\n }\n\n resolved<T>(token: ServiceToken<T>): boolean {\n return this.instances.has(token.token);\n }\n\n make<T>(token: ServiceToken<T>): T {\n const key = token.token;\n\n if (this.instances.has(key)) {\n return this.instances.get(key) as T;\n }\n\n const binding = this.bindings.get(key);\n if (!binding) {\n throw new BindingResolutionError(key, this.keys());\n }\n\n const object = binding.factory(this) as T;\n if (binding.shared) {\n this.instances.set(key, object);\n }\n return object;\n }\n\n forget<T>(token: ServiceToken<T>) {\n this.instances.delete(token.token);\n }\n\n keys(): string[] {\n return [\n ...new Set([...this.bindings.keys(), ...this.instances.keys()]),\n ];\n }\n\n flush() {\n this.bindings.clear();\n this.instances.clear();\n }\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";AAoBO,MAAM,UAA+B,KAAM,CAChD,WAAW,CAAC,EAAe,EAAiB,CAC1C,MACE,WAAW,qCACR,EAAM,OAAS,EACZ,kBAAkB,EAAM,KAAK,IAAI,KACjC,0DACR,EACA,KAAK,KAAO,yBAEhB,CAEO,MAAM,CAAU,CACb,SAAW,IAAI,IACf,UAAY,IAAI,IAExB,IAAO,CAAC,EAAwB,EAAqB,CACnD,KAAK,SAAS,IAAI,EAAM,MAAO,CAAE,UAAS,OAAQ,EAAM,CAAC,EACzD,KAAK,UAAU,OAAO,EAAM,KAAK,EAMnC,SAAY,CAAC,EAAwB,EAAqB,CACxD,KAAK,SAAS,IAAI,EAAM,MAAO,CAAE,UAAS,OAAQ,EAAK,CAAC,EACxD,KAAK,UAAU,OAAO,EAAM,KAAK,EAGnC,QAAW,CAAC,EAAwB,EAAc,CAEhD,OADA,KAAK,UAAU,IAAI,EAAM,MAAO,CAAM,EAC/B,EAGT,KAAQ,CAAC,EAAiC,CACxC,OACE,KAAK,SAAS,IAAI,EAAM,KAAK,GAAK,KAAK,UAAU,IAAI,EAAM,KAAK,EAIpE,QAAW,CAAC,EAAiC,CAC3C,OAAO,KAAK,UAAU,IAAI,EAAM,KAAK,EAGvC,IAAO,CAAC,EAA2B,CACjC,IAAM,EAAM,EAAM,MAElB,GAAI,KAAK,UAAU,IAAI,CAAG,EACxB,OAAO,KAAK,UAAU,IAAI,CAAG,EAG/B,IAAM,EAAU,KAAK,SAAS,IAAI,CAAG,EACrC,GAAI,CAAC,EACH,MAAM,IAAI,EAAuB,EAAK,KAAK,KAAK,CAAC,EAGnD,IAAM,EAAS,EAAQ,QAAQ,IAAI,EACnC,GAAI,EAAQ,OACV,KAAK,UAAU,IAAI,EAAK,CAAM,EAEhC,OAAO,EAGT,MAAS,CAAC,EAAwB,CAChC,KAAK,UAAU,OAAO,EAAM,KAAK,EAGnC,IAAI,EAAa,CACf,MAAO,CACL,GAAG,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,KAAK,EAAG,GAAG,KAAK,UAAU,KAAK,CAAC,CAAC,CAChE,EAGF,KAAK,EAAG,CACN,KAAK,SAAS,MAAM,EACpB,KAAK,UAAU,MAAM,EAEzB",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "2680A8C6B1B1C96864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{$b as K3,Kc as F9,Xb as k9,ac as M9,ec as e,md as N9,rc as U9,xc as J9}from"./chunk-y959p390.js";import{Ad as V$,Cd as L$,td as p3,vd as B3,yd as d9,zd as p9}from"./chunk-2b3hh9xw.js";import{Fd as w9,Kd as v9,Md as h9,Td as x,Ud as g9,Vd as m9,Xd as u9,Yd as B$}from"./chunk-877yc341.js";import{$d as P}from"./chunk-eqv7yxk7.js";import{Af as k,Ag as x$,Bg as L3,Cg as d3,Df as Y$,Ef as G$,Ff as W$,Hf as w,Hg as X$,Ie as H$,Ig as K$,Je as c3,Ne as J3,Oe as X3,Og as D$,Uf as a3,dg as t3,ef as m3,fg as n,jg as o3,kg as t9,lg as o9,ne as l,oe as z$,re as T9,rg as f3,sf as Z3,sg as a9,tg as G3,ug as r9,ve as O$,vg as e9,wg as w3,xg as a,ye as Q$,yf as H3,zf as g3}from"./chunk-fe9fvtvt.js";import{Ai as P3,Bi as F3,Ci as z3,Th as c,Vh as m,ii as s3,wi as H9}from"./chunk-2r2j2nvq.js";import{Ii as i9}from"./chunk-cee5gq7t.js";import{Ti as h}from"./chunk-a8n9ec43.js";import{Zi as u3}from"./chunk-w6jff43c.js";import{aj as U$,bj as i3,ej as N3,fj as n3,ij as F$}from"./chunk-sbzqxtqg.js";import{Bj as n9,wj as l9}from"./chunk-xv58jnpb.js";import{Rj as f9,Tj as u}from"./chunk-86zhngpg.js";import{Uj as A}from"./chunk-attr793y.js";import{_j as I$}from"./chunk-2ery6a75.js";import{Ok as l3}from"./chunk-m5f6ksqe.js";import{Vk as U3,Yk as y}from"./chunk-1fyn63ka.js";import{fl as h3}from"./chunk-mzkzgp2j.js";import{rl as s9}from"./chunk-6tkkvaqg.js";var C$="mcp",S$=/^[\x21\x23-\x5B\x5D-\x7E]+$/;class O extends e{status;constructor($,Z){super($);this.status=Z;this.name="McpToolError"}}class v extends Error{reason;constructor($,Z){super($);this.reason=Z;this.name="McpCallRefusedError"}}var r3=/^[A-Za-z0-9_-]{1,64}$/,q$=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,e3=4000,M=1e5,T$=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i,B9=new WeakMap;function X6($){return B9.get($)}class i{router;dispatcher;static token="router.mcp";plans=new Map;scopeTools=new Map;files;featureOn;constructor($,Z,z={}){this.router=$;this.dispatcher=Z;this.files=b$(z.files),this.featureOn=z.featureOn??X3;for(let[G,W]of Object.entries($.routes??{}))this.plans.set(G,k$(W)?this.planNative(G,W):this.plan(G,W));this.resolveScopes()}list($,Z){if(D3($),$.kind==="local")return this.descriptors(Z);let z=[];for(let[G,W]of this.plans){if(!W.remote||!this.grants($.principal,G))continue;if(W9(W.remote,Z))z.push(W.remote)}return z}async available($,Z){let z=[];for(let G of this.list($,Z))if(await this.isOn(G))z.push(G);return z}descriptors($){let Z=[];for(let{descriptor:z}of this.plans.values())if(W9(z,$))Z.push(z);return Z}get maxFileBytes(){return this.files.maxBytes}scopes(){return[...this.scopeTools].map(([$,{description:Z}])=>({name:$,description:Z}))}scopesFor($){return[...this.scopeTools].filter(([,{tools:Z}])=>Z.has($)).map(([Z])=>Z)}async execute($,Z,z,G,W={}){D3($);let X=this.plans.get(Z);if(X&&!await this.isOn(X.descriptor)){if($.kind==="remote")throw new v(`There is no tool named "${Z}".`,"unknown-tool");throw new O(`There is no tool named "${Z}".`,404)}if($.kind==="remote"){if(!X?.remote||!this.grants($.principal,Z))throw new v(`There is no tool named "${Z}".`,"unknown-tool");if(X.descriptor.requiresApproval&&W.approved!==!0&&!W3(X))throw new v(`"${Z}" needs the user's approval, and this call does not have it.`,"approval-required");G=void 0}if(!X)throw Error(`McpRegistry: there is no tool named "${Z}".`);if(X.kind==="tool")return await this.executeNative(X,$,z,G,W);let Y=X,K=$.kind==="remote"?Y.remote:Y.descriptor,Q=K.inputSchema.safeParse(z);if(Q.ok===!1)throw new O(`Invalid arguments for "${Z}": ${Q.errors.join(", ")}`);let V=Q.value,H={caller:$,req:$.req,tool:K,input:V,ctx:G},J=await this.fillPath(Y,H),{path:I}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${J}`));if(I!==K.url)throw new O(`"${Z}" has nothing at ${J}.`,404);let U={};for(let _ of Y.jsonKeys)if(V[_]!==void 0)U[_]=V[_];let F,B="";if(Y.fileFields.length>0)F=await this.formData(Y,U,H);else if(K.method==="GET")B=p$(U);else if(Y.jsonKeys.length>0)F=U;let T=this.router.credentials?await this.bind(Y,"the credentials",()=>this.router.credentials(H)):void 0,j={...T?{credentials:T}:{},...W.signal?{signal:W.signal}:{},...W.progress?{progress:W.progress}:{},...$.kind==="remote"?{identity:{user:$.principal.user,grant:{via:$.principal.via,id:$.principal.id,scopes:$.principal.scopes,...$.principal.clientId?{clientId:$.principal.clientId}:{}}}}:{}},C;try{let _=B?`${J}?${B}`:J;C=Object.keys(j).length>0?await this.dispatcher.dispatchAs($.req,K.method,_,F,j):await this.dispatcher.dispatchAs($.req,K.method,_,F)}catch(_){throw console.error(`[gemi/mcp] Dispatching "${Z}" failed:`,_),new O(`"${Z}" failed on the server.`,500)}if(!Y.result&&!K.outputSchema)return await V9(Z,C);return await this.project(Y,H,C)}async isOn($){return $.feature===void 0||await this.featureOn($.feature)===!0}plan($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (${Z?.method} ${Z?.url})`;if(!(Z instanceof Object)||Z.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${$}" is not a route or a tool. Declare it with this.fromApiRoute(...) or this.fromTool(...).`);let{method:G,url:W,meta:X}=Z;if(X.feature!==void 0&&(typeof X.feature!=="string"||X.feature===""))throw Error(`${z}: feature must be a feature key from app/features.`);if(W.startsWith("/__gemi__"))throw Error(`${z} is a framework route, not an app route.`);let Y=this.dispatcher.flatRoutes[W]?.[G];if(!Y)throw Error(`${z} names no route of this app. Expose a route by the path and verb it is mounted at.`);let K=[...W.matchAll(q$)].map(([,N,S])=>({name:N,modifier:S})),Q=X.params??{};for(let N of K)if(!(N.name in Q))throw Error(`${z}: the path param "${N.name}" must be bound or declared "input".`);for(let[N,S]of Object.entries(Q)){if(!K.some((g)=>g.name===N))throw Error(`${z}: "${N}" in params is not a param of the url.`);if(Y9(S))h$(z,`params.${N}`,S);else X9(z,`params.${N}`,S)}let V=[],H;if(X.input){if(H=X.input.toJSONSchema(),H.type!=="object"||!H.properties)throw Error(`${z}: input must be an s.object(...), the fields of the request body.`);V=Object.keys(H.properties)}let J=Object.entries(X.files??{}).map(([N,S])=>({name:N,binder:S}));for(let N of J)X9(z,`files.${N.name}`,N.binder);if(X.result!==void 0&&typeof X.result!=="function")throw Error(`${z}: result must be a function.`);if(X.output!==void 0&&typeof X.output?.safeParse!=="function")throw Error(`${z}: output must be a schema, built with s.`);if(X.title!==void 0&&(typeof X.title!=="string"||X.title===""))throw Error(`${z}: title must be a non-empty string.`);let I=K9(z,G,X.annotations);if(J.length>0&&G==="GET")throw Error(`${z}: a GET has no body to carry a file.`);let U={},F=(N,S)=>{if(N in U)throw Error(`${z}: "${N}" is the input key of two params or files, and the model can only send one.`);U[N]=S},B=new Map,T=new Map;for(let N of K){let S=Q[N.name];if(S==="input"){let g=c.string().describe(`The ":${N.name}" segment of the url.`);F(N.name,N.modifier==="?"||N.modifier==="*"?g.optional():g)}else if(Y9(S)){let g=S.as??N.name;F(g,S.input),T.set(N.name,{key:g,param:S})}else B.set(N.name,S)}let j={};for(let N of J)if(N.binder==="input")F(N.name,c.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.")),j[N.name]=this.remoteFileSchema();let C=[...Object.keys(U),...J.map((N)=>N.name)];for(let N of new Set(C))if(V.includes(N))throw Error(`${z}: "${N}" is both an input field and a param or file, and the model can only send one.`);let _=Object.freeze({kind:"route",name:$,description:X.description,method:G,url:W,inputSchema:Q9(X.input,H,c.object(U)),...X.output?{outputSchema:X.output}:{},...X.title?{title:X.title}:{},annotations:I,tags:Object.freeze([...X.tags??[]]),requiresApproval:X.requiresApproval===!0,...X.feature!==void 0?{feature:X.feature}:{},...Y.source?{source:Y.source}:{}}),r=!J.every((N)=>N.binder==="input")?null:J.length===0?_:Object.freeze({..._,inputSchema:Q9(X.input,H,c.object(u$(U,Object.keys(j))),j)});return{kind:"route",descriptor:_,remote:r,params:K,paramBinders:B,modelParams:T,fileFields:J,jsonKeys:V,...X.result?{result:X.result}:{}}}remoteFileSchema(){let{maxBytes:$,fetch:Z}=this.files,z={name:{type:"string",description:"The file's name, like report.pdf."},mimeType:{type:"string",description:"The file's media type, like application/pdf."},data:{type:"string",contentEncoding:"base64",description:`The file's bytes, base64-encoded (RFC 4648, standard alphabet). At most ${$} bytes decoded.`}};if(Z)z.url={type:"string",format:"uri",description:"An https URL the server downloads the file from, instead of data."};let G={type:"object",description:Z?"A file, sent as base64 in data or fetched from url: exactly one of the two.":"A file, sent as base64 in data.",properties:z,required:["name","mimeType"],additionalProperties:!1},W=Object.keys(z),X=(Y)=>{if(typeof Y!=="object"||Y===null||Array.isArray(Y))return{ok:!1,errors:["a file must be an object"]};let K=[],Q={};for(let V of Object.keys(Y))if(!W.includes(V))K.push(`a file has no field "${V}"`);for(let V of W){let H=Y[V];if(H===void 0||H===null){if(V==="name"||V==="mimeType")K.push(`a file needs "${V}"`);continue}if(typeof H!=="string")K.push(`a file's "${V}" must be a string`);else Q[V]=H}return K.length>0?{ok:!1,errors:K}:{ok:!0,value:Q}};return{toJSONSchema:()=>G,safeParse:X,parse(Y){let K=X(Y);if(K.ok===!1)throw Error(K.errors.join(", "));return K.value}}}planNative($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (a native tool)`,{tool:G,meta:W={}}=Z;if(!(G instanceof Object)||typeof G.name!=="string")throw Error(`${z} is not an AgentTool. Pass one built with AgentTool.create(...).`);if(G.answeredBy==="client"||typeof G.execute!=="function")throw Error(`${z}: "${G.name}" is answered by the client, and only a tool the server runs can be called through the registry.`);if(typeof G.inputSchema==="function")throw Error(`${z}: "${G.name}" resolves its input schema per run, and the registry lists one schema to every caller. Give it a fixed inputSchema.`);if(typeof G.inputSchema?.safeParse!=="function")throw Error(`${z}: its inputSchema must be a schema, built with s.`);if(typeof W!=="object"||W===null)throw Error(`${z}: the meta must be an object.`);if(W.description!==void 0&&(typeof W.description!=="string"||W.description.trim()===""))throw Error(`${z}: description must be a non-empty string.`);if(W.title!==void 0&&(typeof W.title!=="string"||W.title===""))throw Error(`${z}: title must be a non-empty string.`);if(W.tags!==void 0&&(!Array.isArray(W.tags)||W.tags.some((Q)=>typeof Q!=="string")))throw Error(`${z}: tags must be an array of strings.`);if(W.requiresApproval===!1&&G.requiresApproval)throw Error(`${z}: "${G.name}" requires approval, and requiresApproval: false would run it without asking. Leave it out, or register a tool that does not ask.`);let X=W.remote;if(X!==void 0){if(typeof X!=="object"||X===null||typeof X.context!=="function")throw Error(`${z}: remote must be { context(call) }, building the AgentContext a remote call runs with.`);if(X.progress!==void 0&&typeof X.progress!=="function")throw Error(`${z}: remote.progress must be a function.`)}let Y=W.description??G.description;if(typeof Y!=="string"||Y.trim()==="")throw Error(`${z} needs a description: the tool's own, or the meta's.`);let K=Object.freeze({kind:"tool",name:$,description:Y,inputSchema:G.inputSchema,...G.outputSchema?{outputSchema:G.outputSchema}:{},...W.title?{title:W.title}:{},annotations:K9(z,void 0,W.annotations),tags:Object.freeze([...W.tags??[]]),requiresApproval:G.requiresApproval||W.requiresApproval===!0});return{kind:"tool",descriptor:K,remote:X?K:null,tool:G,meta:W}}async approvalRequired($,Z,z,G={}){let W=this.plans.get(Z);if(!W)return!0;if(!W3(W))return W.descriptor.requiresApproval;let X=W;if($.kind!=="remote"||!X.meta.remote)return!0;let Y=X.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)return!0;let K={caller:$,req:$.req,tool:X.descriptor,input:Y.value},Q;try{Q=await this.bind(X,"the remote context",()=>X.meta.remote.context(K))}catch{return!0}if(typeof Q!=="object"||Q===null)return!0;let V=G.signal??new AbortController().signal;return G9(X,Y.value,z9(Z9(X,Q,V)))}nativeApproval($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return W3(Z)??Z.descriptor.requiresApproval}nativeTool($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return Z.tool}startNative($,Z,z,G){let W=this.plans.get(Z);if(W?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${Z}".`);if($===void 0)return W.tool.execute(z,G);if(D3($),$.kind!=="local")throw Error("McpRegistry: startNative is for a local caller. A remote call goes through execute().");let X=W.descriptor.inputSchema.safeParse(z);if(X.ok===!1)throw new O(`Invalid arguments for "${Z}": ${X.errors.join(", ")}`);return this.runNative(W,{caller:$,req:$.req,tool:W.descriptor,input:X.value},G)}runNative($,Z,z){let G={...z};return B9.set(G,{...Z,ctx:G}),$.tool.execute(Z.input,G)}async executeNative($,Z,z,G,W){let{name:X}=$.descriptor,Y=$.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)throw new O(`Invalid arguments for "${X}": ${Y.errors.join(", ")}`);let K={caller:Z,req:Z.req,tool:$.descriptor,input:Y.value},Q=(_,_3)=>{if(!W.progress)return;let r;try{r=$.meta.remote?.progress?$.meta.remote.progress(_,_3):R$(_,_3)}catch(N){console.error(`[gemi/mcp] The progress mapping of "${X}" failed:`,N);return}if(r)W.progress(r)};if(Z.kind==="local"){if(!G)throw Error(`McpRegistry: "${X}" is a native tool, which runs with the tool context of an agent call, and none was passed to execute().`);return await $9(this.runNative($,{...K,ctx:G},G),Q)}let V=$.meta.remote,H=await this.bind($,"the remote context",()=>V.context(K));if(typeof H!=="object"||H===null)throw console.error(`[gemi/mcp] The remote context of "${X}" is not an object:`,H),new O(`"${X}" failed on the server.`,500);let J=$.tool.timeoutMs,I=[...W.signal?[W.signal]:[],...J!==void 0?[AbortSignal.timeout(J)]:[]],U=I.length===0?new AbortController().signal:I.length===1?I[0]:AbortSignal.any(I),F=Z9($,H,U);if(!W.approved&&W3($)&&await G9($,K.input,z9(F)))throw new v(`"${X}" needs the user's approval, and this call does not have it.`,"approval-required");let B;try{B=await $9(this.runNative($,{...K,ctx:F},F),Q,U)}catch(_){if(U.aborted&&_===U.reason){if(W.signal?.aborted)throw new O(`"${X}" was cancelled.`,499);throw new O(`"${X}" did not finish within ${J} ms.`,504)}if(_ instanceof O)throw _;if(_ instanceof e||_ instanceof v)throw new O(_.message);throw console.error(`[gemi/mcp] "${X}" failed for a remote caller:`,_),new O(`"${X}" failed on the server.`,500)}let T=(_)=>{return console.error(`[gemi/mcp] "${X}" ${_}`),new O(`"${X}" failed on the server.`,500)};if(U9(B))throw T("answered a job handle, and a remote call has no background jobs.");let j=B;if($.descriptor.outputSchema){let _=$.descriptor.outputSchema.safeParse(j);if(_.ok===!1)throw T(`answered what its output schema refuses: ${_.errors.join(", ")}`);j=_.value}if(j===void 0)return null;if(typeof j==="string")return j.length>M?`${j.slice(0,M)}\u2026 [cut at ${M} of ${j.length} characters]`:j;let C=JSON.stringify(j);if(C!==void 0&&C.length>M)return`${C.slice(0,M)}\u2026 [cut at ${M} of ${C.length} characters]`;return j}async fillPath($,Z){let{input:z,req:G}=Z,W=$.descriptor.url;for(let X of $.params){let Y=$.paramBinders.get(X.name),K=$.modelParams.get(X.name),Q;if(Y||K){if(Q=K?await this.bind($,`the param "${X.name}"`,()=>K.param.bind(z[K.key],G,Z),{refusals:!0}):await this.bind($,`the param "${X.name}"`,()=>Y(G,Z)),Q===void 0||Q===null||Q==="")throw console.error(`[gemi/mcp] The ${K?"resolver":"binder"} for "${X.name}" of "${$.descriptor.name}" returned ${JSON.stringify(Q)}.`),new O(`"${$.descriptor.name}" failed on the server.`,500)}else Q=z[X.name];let V=`:${X.name}${X.modifier}`;if(Q===void 0||Q===null||Q===""){if(X.modifier!=="?"&&X.modifier!=="*")throw new O(`"${X.name}" of "${$.descriptor.name}" must not be empty.`);W=W.replace(`/${V}`,"");continue}W=W.replace(V,d$($.descriptor.name,X,String(Q)))}return W}async formData($,Z,z){let{input:G,ctx:W}=z,X=$.descriptor.name;if(z.caller.kind==="remote"){let K=new FormData;for(let[Q,V]of Object.entries(Z))O3(K,Q,V);for(let Q of $.fileFields)K.append(Q.name,await this.remoteFile(X,Q.name,G[Q.name]));return K}if(!W)throw Error(`McpRegistry: "${X}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let Y=new FormData;for(let[K,Q]of Object.entries(Z))O3(Y,K,Q);for(let K of $.fileFields){let Q=K.binder==="input"?G[K.name]:await this.bind($,`the file "${K.name}"`,()=>K.binder(W,z));if(typeof Q!=="string"||Q==="")throw new O(`"${X}" needs a file for "${K.name}", and this turn has none. Ask the user to attach one.`);Y.append(K.name,await W.attachments.file(Q))}return Y}async remoteFile($,Z,z){let G=(H)=>new O(`"${Z}" of "${$}" ${H}`,400),W=z,{maxBytes:X,fetch:Y}=this.files;if(!y$(W.name))throw G("needs a name of 1 to 255 characters, without control characters or slashes.");if(!f$.test(W.mimeType))throw G(`has a mimeType that is not a media type: "${W.mimeType.slice(0,100)}".`);let K=typeof W.data==="string",Q=typeof W.url==="string";if(K===Q)throw G(Y?"needs exactly one of data or url.":"needs its bytes, base64, in data.");if(K){let H=W.data.replace(/\s+/g,"");if(Math.floor(H.length*3/4)-v$(H)>X)throw G(`is larger than the ${X} bytes a file may be.`);if(H.length%4!==0||!w$.test(H))throw G("has data that is not base64 (RFC 4648, standard alphabet, padded).");return new File([Buffer.from(H,"base64")],W.name,{type:W.mimeType})}if(!Y)throw G("cannot be fetched from a URL here. Send its bytes, base64, in data.");let V;try{V=new URL(W.url)}catch{throw G("has a url that is not a URL.")}if(V.protocol!=="https:")throw G("can only be fetched from an https URL.");try{let H=await H9(V.href,{...Y,maxSize:Math.min(Y.maxSize??X,X),redirect:"follow"});if(!H.ok)throw G(`could not be fetched: ${V.host} answered ${H.status}.`);let J=await H.arrayBuffer();return new File([J],W.name,{type:W.mimeType})}catch(H){if(H instanceof O)throw H;throw G(`could not be fetched from ${V.host}: ${H instanceof Error?H.message:"failed"}.`)}}grants($,Z){for(let z of $.scopes??[])if(this.scopeTools.get(z)?.tools.has(Z))return!0;return!1}resolveScopes(){let $=this.router.scopes;if($===void 0){this.scopeTools.set(C$,{description:"Use this app's tools as you",tools:new Set(this.plans.keys())});return}if(typeof $!=="object"||$===null)throw Error("McpRouter: scopes must be an object of scope names.");let Z=new Set([...this.plans.values()].flatMap(({descriptor:z})=>z.tags));for(let[z,G]of Object.entries($)){let W=`McpRouter: scope "${z}"`;if(!S$.test(z))throw Error(`${W} is not a valid OAuth scope: printable ASCII, no spaces or quotes.`);if(typeof G?.description!=="string"||G.description==="")throw Error(`${W} needs a description: it is what a consent screen shows.`);let X=new Set;for(let Y of G.tags??[]){if(!Z.has(Y))throw Error(`${W} names the tag "${Y}", which no tool has.`);for(let[K,{descriptor:Q}]of this.plans)if(Q.tags.includes(Y))X.add(K)}for(let Y of G.names??[]){if(!this.plans.has(Y))throw Error(`${W} names "${Y}", which is no tool.`);X.add(Y)}if(X.size===0)throw Error(`${W} reaches no tool. Give it tags or names.`);this.scopeTools.set(z,{description:G.description,tools:X})}}async project($,Z,z){let{name:G,outputSchema:W}=$.descriptor;if(z.status<200||z.status>=300)return await V9(G,z);let X=(J,I)=>{if(I===void 0)console.error(`[gemi/mcp] "${G}" ${J}`);else console.error(`[gemi/mcp] "${G}" ${J}`,I);return new O(`"${G}" failed on the server.`,500)},Y=z.headers.get("Content-Type"),K=await z.text(),Q=null;if(K!=="")try{Q=JSON.parse(K)}catch{throw X(`answered ${Y??"a body with no content-type"} that is not JSON, and its result or output needs JSON.`)}let V=Q;if($.result)try{V=await $.result(Q,Z)}catch(J){throw X("failed in its result projection:",J)}if(W){let J=W.safeParse(V);if(J.ok===!1)throw X(`answered what its output schema refuses: ${J.errors.join(", ")}`);V=J.value}if(V===void 0)return null;let H=JSON.stringify(V);if(H!==void 0&&H.length>M)return`${H.slice(0,M)}\u2026 [cut at ${M} of ${H.length} characters]`;return V}async bind($,Z,z,G={}){try{return await z()}catch(W){if(G.refusals&&W instanceof e)throw W;throw console.error(`[gemi/mcp] Binding ${Z} of "${$.descriptor.name}" failed:`,W),new O(`"${$.descriptor.name}" failed on the server.`,500)}}}function k$($){return $ instanceof Object&&$.__internal_brand==="McpTool"}function M$($){return typeof $==="object"&&$!==null&&typeof $.next==="function"&&Symbol.asyncIterator in $}async function $9($,Z,z){let G;if(z)G=new Promise((X,Y)=>{if(z.aborted)Y(z.reason);else z.addEventListener("abort",()=>Y(z.reason),{once:!0})}),G.catch(()=>{});let W=(X)=>G?Promise.race([X,G]):X;if(!M$($))return await W(Promise.resolve($));try{let X=0,Y=await W($.next());while(!Y.done)Z(Y.value,++X),Y=await W($.next());return Y.value}catch(X){throw $.return(void 0).catch(()=>{}),X}}function R$($,Z){if(typeof $==="string")return{progress:Z,message:$};if(typeof $==="object"&&$!==null){let{progress:z,total:G,message:W}=$;if(typeof z==="number"&&Number.isFinite(z))return{progress:z,...typeof G==="number"?{total:G}:{},...typeof W==="string"?{message:W}:{}};if(typeof W==="string")return{progress:Z,message:W}}return{progress:Z}}function Z9($,Z,z){let G=$.descriptor.name,W=`mcp_${crypto.randomUUID()}`,X=`mcp_call_${crypto.randomUUID()}`,Y=(Q)=>async()=>{throw new e(`"${G}" was called by a remote MCP client, which has no ${Q}.`,{retryable:!1})},K={put:Y("attachment store"),get:Y("attachment store"),read:Y("attachment store"),file:Y("attachment store")};return{context:Z,body:{},runId:W,toolCallId:X,signal:z,step:1,depth:0,resumed:!1,attachments:K,turn:Object.freeze({attachments:Object.freeze([])}),runAgent:Y("agent run to nest a sub-agent in"),generateImage:Y("attachment store to put an image in"),editImage:Y("attachment store to put an image in"),generate:(Q)=>N9({...Q,signal:Q.signal?AbortSignal.any([z,Q.signal]):z},{origin:{mcp:G,runId:W,toolCallId:X}}),jobs:J9({jobs:void 0,threadId:void 0,runId:W,toolCallId:X,toolName:G,depth:0,async:$.tool.async,attachments:null}),memory:F9()}}function W3($){if($.kind!=="tool"||$.meta.requiresApproval===!0)return;return $.tool.approvalPredicate}function z9($){return{context:$.context,body:$.body,runId:$.runId,threadId:$.threadId,toolCallId:$.toolCallId,step:$.step,depth:$.depth,signal:$.signal}}async function G9($,Z,z){try{return await $.tool.approvalPredicate(Z,z)!==!1}catch(G){return console.error(`[gemi/mcp] The requiresApproval of "${$.descriptor.name}" threw, so the call asks the user:`,G),!0}}function D3($){if($?.kind==="local"&&$.req)return;if($?.kind==="remote"&&$.req&&$.principal?.user&&typeof $.principal.id==="string"&&Array.isArray($.principal.scopes))return;throw Error('McpRegistry: a caller is { kind: "local", req } or { kind: "remote", req, principal }, with the principal a caller resolver verified.')}function W9($,Z){if(Z?.names&&!Z.names.includes($.name))return!1;if(Z?.tags&&!$.tags.some((z)=>Z.tags.includes(z)))return!1;return!0}var E$=10485760;function b$($){let Z=$?.maxBytes??E$;if(!Number.isSafeInteger(Z)||Z<=0)throw Error("McpRegistry: files.maxBytes must be a positive whole number of bytes.");let z=$?.fetchUrls===!0?{}:typeof $?.fetchUrls==="object"&&$.fetchUrls!==null?$.fetchUrls:null;return{maxBytes:Z,fetch:z}}function y$($){if($.length===0||$.length>255)return!1;for(let Z of $){let z=Z.codePointAt(0);if(z<32||z===127||Z==="/"||Z==="\\")return!1}return!0}var f$=/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(\s*;.{0,200})?$/,w$=/^[A-Za-z0-9+/]*={0,2}$/;function v$($){return $.endsWith("==")?2:$.endsWith("=")?1:0}function X9($,Z,z){if(z!=="input"&&typeof z!=="function")throw Error(`${$}: ${Z} must be a function or "input".`)}function Y9($){return $ instanceof Object&&$.__internal_brand==="McpModelParam"}function h$($,Z,z){if(z.as!==void 0&&(typeof z.as!=="string"||z.as===""))throw Error(`${$}: ${Z}.as must be a non-empty string.`);let G=z.input;if(typeof G?.safeParse!=="function"||typeof G.toJSONSchema!=="function")throw Error(`${$}: ${Z}.input must be a schema, built with s.`);if(typeof z.bind!=="function")throw Error(`${$}: ${Z}.bind must be a function.`)}var g$=new Set(["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"]);function m$($){switch($){case"GET":return{readOnlyHint:!0};case"DELETE":return{destructiveHint:!0};case"PUT":return{idempotentHint:!0};default:return{}}}function K9($,Z,z){if(z!==void 0&&(typeof z!=="object"||z===null))throw Error(`${$}: annotations must be an object of hints.`);let G=Z?m$(Z):{};for(let[W,X]of Object.entries(z??{})){if(!g$.has(W))throw Error(`${$}: "${W}" is not a tool annotation. Use readOnlyHint, destructiveHint, idempotentHint or openWorldHint.`);if(X===void 0)continue;if(typeof X!=="boolean")throw Error(`${$}: annotations.${W} must be true or false.`);G[W]=X}if(G.readOnlyHint===!0&&(G.destructiveHint||G.idempotentHint))throw Error(`${$} is read-only${z?.readOnlyHint?"":` (a ${Z})`} and also ${G.destructiveHint?"destructive":"idempotent"}, which only a tool that is not read-only can be. Set readOnlyHint: false if it changes something.`);return Object.freeze(G)}function Q9($,Z,z,G={}){let W=z.toJSONSchema(),X=Object.fromEntries(Object.entries(G).map(([Q,V])=>[Q,V.toJSONSchema()])),Y={...Z??{},type:"object",properties:{...Z?.properties??{},...W.properties,...X},required:[...Z?.required??[],...W.required??[],...Object.keys(G)],additionalProperties:!1},K=(Q)=>{if(typeof Q!=="object"||Q===null||Array.isArray(Q))return{ok:!1,errors:["expected an object"]};let V=[],H={};if($){let I=$.safeParse(Q);if(I.ok===!1)V.push(...I.errors);else H={...I.value}}let J=z.safeParse(Q);if(J.ok===!1)V.push(...J.errors);else H={...H,...J.value};for(let[I,U]of Object.entries(G)){let F=Q[I];if(F===void 0){V.push(`"${I}" is required`);continue}let B=U.safeParse(F);if(B.ok===!1)V.push(...B.errors.map((T)=>`${I}: ${T}`));else H[I]=B.value}return V.length>0?{ok:!1,errors:V}:{ok:!0,value:H}};return{toJSONSchema:()=>Y,safeParse:K,parse(Q){let V=K(Q);if(V.ok===!1)throw Error(V.errors.join(", "));return V.value}}}function u$($,Z){return Object.fromEntries(Object.entries($).filter(([z])=>!Z.includes(z)))}function d$($,Z,z){let G=Z.modifier==="*"||Z.modifier==="+"?z.split("/"):[z];if(G.some((W)=>W==="."||W===".."))throw new O(`"${z}" is not a valid value for "${Z.name}" of "${$}".`);return G.map(encodeURIComponent).join("/")}function O3($,Z,z){if(z===void 0||z===null)return;if(Array.isArray(z)){for(let G of z)O3($,Z,G);return}$.append(Z,typeof z==="object"?JSON.stringify(z):String(z))}function p$($){let Z=new URLSearchParams,z=(G,W)=>{if(W===void 0||W===null)return;if(Array.isArray(W)){for(let X of W)z(G,X);return}Z.append(G,typeof W==="object"?JSON.stringify(W):String(W))};for(let[G,W]of Object.entries($))z(G,W);return Z.toString()}async function V9($,Z){if(Z.status>=200&&Z.status<300){let G=Z.headers.get("Content-Type");if(G&&!T$.test(G)){let X=(await Z.arrayBuffer()).byteLength;return`"${$}" answered with ${X} bytes of ${G}, which is not shown.`}let W=await Z.text();if(W==="")return null;if(W.length>M)return`${W.slice(0,M)}\u2026 [cut at ${M} of ${W.length} characters]`;try{return JSON.parse(W)}catch{return W}}let z=await Z.text();if(Z.status>=400&&Z.status<500){let G=z.length>e3?`${z.slice(0,e3)}\u2026`:z;throw new O(`"${$}" was refused with ${Z.status}${G?`: ${G}`:"."}`,Z.status)}if(Z.status<500)console.error(`[gemi/mcp] "${$}" answered ${Z.status}${Z.headers.get("Location")?` to ${Z.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new O(`"${$}" failed on the server.`,Z.status)}import{createHash as c$,randomBytes as i$,timingSafeEqual as l$}from"crypto";function j3($){let Z=$.headers.get("authorization");if(!Z)return null;let z=/^Bearer[ ]+([\x21-\x7e]+)$/i.exec(Z.trim());return z?z[1]:null}class n${options;name="api-key";constructor($){this.options=$;if(typeof $?.prefix!=="string"||!/^[A-Za-z0-9_-]{3,32}$/.test($.prefix))throw Error('McpApiKeyResolver: prefix is required: 3 to 32 letters, digits, _ or -, like "myapp_mcp_".');if(typeof $.verify!=="function")throw Error("McpApiKeyResolver: verify must be a function that looks a key up.")}static generate($){return`${$}${i$(32).toString("base64url")}`}static hash($){return c$("sha256").update($).digest("hex")}static hashesMatch($,Z){let z=Buffer.from($),G=Buffer.from(Z);return z.length===G.length&&l$(z,G)}async resolve($){let Z=j3($);if(!Z?.startsWith(this.options.prefix))return null;let z=await this.options.verify(Z,$);if(!z)return{ok:!1,error:"invalid_token",description:"The API key is not valid."};if(!z.user||typeof z.id!=="string"||z.id===""||!Array.isArray(z.scopes))throw Error("McpApiKeyResolver: verify must answer { user, id, scopes } for a key it knows, or null.");return{ok:!0,principal:{user:z.user,via:this.name,id:z.id,scopes:[...z.scopes]}}}}import{createHash as R9,randomBytes as _9}from"crypto";async function A3($,Z){let z=s$();if(!z)return null;let G=await z.consume($,Z);return G.allowed?null:Math.max(1,Math.ceil(G.retryAfter/1000))}function s$(){try{let $=y();return $.bound(l)?$.make(l):null}catch{return null}}var x3=["2026-07-28"],Y3=["2025-11-25","2025-06-18","2025-03-26"],C3=[...x3,...Y3],S3="io.modelcontextprotocol/protocolVersion",q3="io.modelcontextprotocol/clientCapabilities";var T3="io.modelcontextprotocol/serverInfo",D={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,HeaderMismatch:-32020,MissingRequiredClientCapability:-32021,UnsupportedProtocolVersion:-32022};class L extends Error{code;data;status;constructor($,Z,z,G=200){super(Z);this.code=$;this.data=z;this.status=G;this.name="JsonRpcError"}}function R($,Z){return{jsonrpc:"2.0",id:$,error:{code:Z.code,message:Z.message,...Z.data!==void 0?{data:Z.data}:{}}}}function P9($){if(Array.isArray($))throw new L(D.InvalidRequest,"Batched requests are not supported.",void 0,400);if(typeof $!=="object"||$===null||$.jsonrpc!=="2.0")throw new L(D.InvalidRequest,"Not a JSON-RPC 2.0 message.",void 0,400);let Z=$,z=Z.id,G=typeof z==="string"||typeof z==="number"&&Number.isFinite(z);if(typeof Z.method==="string"){if(Z.params!==void 0&&(typeof Z.params!=="object"||Z.params===null||Array.isArray(Z.params)))throw new L(D.InvalidRequest,"params must be an object.",void 0,400);if(z===void 0)return{kind:"notification",message:Z};if(!G)throw new L(D.InvalidRequest,"id must be a string or a number.",void 0,400);return{kind:"request",message:Z}}if(G&&(("result"in Z)||("error"in Z)))return{kind:"response",message:Z};throw new L(D.InvalidRequest,"Not a JSON-RPC request, notification or response.",void 0,400)}function k3($,Z){let z=$.outputSchema?.toJSONSchema(),G={...$.annotations,...$.title&&!Z?{title:$.title}:{}};return{name:$.name,...$.title?{title:$.title}:{},description:$.description,inputSchema:$.inputSchema.toJSONSchema(),...z&&(Z||z.type==="object")?{outputSchema:z}:{},...Object.keys(G).length>0?{annotations:G}:{}}}function q($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function I9($){let Z=/^=\?base64\?([A-Za-z0-9+/]*={0,2})\?=$/.exec($);if(!Z)return $;try{let z=Buffer.from(Z[1],"base64");return new TextDecoder("utf-8",{fatal:!0}).decode(z)}catch{return null}}import{createHmac as t$,timingSafeEqual as o$}from"crypto";function M3($,Z,z){let G=Buffer.from(JSON.stringify(z)).toString("base64url");return`${Z}.${G}.${L9($,Z,G).toString("base64url")}`}function R3($,Z,z,G=Date.now()){if(typeof z!=="string"||z.length>8192)return null;let W=z.split(".");if(W.length!==3||W[0]!==Z)return null;let[,X,Y]=W,K=Buffer.from(Y,"base64url"),Q=L9($,Z,X);if(K.length!==Q.length||!o$(K,Q))return null;let V;try{V=JSON.parse(Buffer.from(X,"base64url").toString("utf8"))}catch{return null}if(typeof V!=="object"||V===null)return null;if(typeof V.exp!=="number"||V.exp<=G)return null;return V}function L9($,Z,z){return t$("sha256",K3($)).update(`${Z}.${z}`).digest()}var E3="gemi.mcp.request-state.v1",D9="gemi.mcp.session.v1",a$=86400000,O9=600000,j9="gemi_approval",b3=2000,r$={limit:600,window:60},e$={limit:30,window:60};class $3{registry;static token="router.mcp.http";endpoint;resolvers;context;allowedOrigins;rateLimit;maxBodyBytes;serverInfo;instructions;nonces;approvalTimeoutMs;onCall;feature;featureOn;pending=new Map;inflight=new Map;constructor($,Z,z={}){this.registry=$;if(typeof Z.url!=="string")throw Error(`route.mcp.remote.url is required: the endpoint's canonical URL, like "https://example.com/mcp".`);this.endpoint=z2(Z.url);let G=Z.resolvers??[];if(!Array.isArray(G)||G.length===0)throw Error("route.mcp.remote is enabled without a caller resolver. Configure route.mcp.remote.resolvers \u2014 an McpOAuthServer, an McpApiKeyResolver, or your own \u2014 or leave the endpoint off. Without one every request would be refused, or answered as nobody.");for(let W of G)if(typeof W?.resolve!=="function"||typeof W.name!=="string"||W.name==="")throw Error("route.mcp.remote.resolvers: each resolver needs a name and a resolve().");if(this.resolvers=G,K3(E3),this.context={resource:this.resource,registry:$},this.allowedOrigins=new Set((Z.allowedOrigins??[]).map((W)=>{if(new URL(W).origin!==W)throw Error(`route.mcp.remote.allowedOrigins: "${W}" is not an origin (scheme://host[:port]).`);return W})),this.allowedOrigins.add(this.endpoint.origin),this.rateLimit=Z.rateLimit===!1?!1:Z.rateLimit??r$,this.maxBodyBytes=Z.maxBodyBytes??Math.ceil($.maxFileBytes*1.4)+1048576,this.serverInfo={name:Z.server?.name??"gemi",version:Z.server?.version??"1.0.0"},this.instructions=Z.server?.instructions,this.nonces=Z.nonces??new k9,this.approvalTimeoutMs=Z.approvalTimeoutMs??O9,Z.onCall!==void 0&&typeof Z.onCall!=="function")throw Error("route.mcp.remote.onCall must be a function.");if(this.onCall=Z.onCall,Z.feature!==void 0){if(typeof Z.feature!=="string"||Z.feature==="")throw Error("route.mcp.remote.feature must be a feature key from app/features.");this.feature=Z.feature}this.featureOn=z.featureOn??X3;for(let W of G)W.boot?.(this.context)}get resource(){return this.endpoint.href.replace(/\/$/,"")}async handle($){let Z=new URL($.url);if(Z.host!==this.endpoint.host)return null;if(this.feature!==void 0){if(!this.ownsPath(Z.pathname))return null;if(await this.featureOn(this.feature)!==!0)return null}for(let W of this.resolvers){let X=await W.handle?.($,this.context);if(X)return X}if(Z.pathname!==this.endpoint.pathname)return null;let z=$.headers.get("origin");if(z!==null&&!this.allowedOrigins.has(z))return f(R(null,new L(D.InvalidRequest,"Origin not allowed.")),403);let G=z?Z2(z):{};if($.method==="OPTIONS")return new Response(null,{status:204,headers:{...G,"Access-Control-Allow-Methods":"POST","Access-Control-Allow-Headers":"Authorization, Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id, Mcp-Method, Mcp-Name, Last-Event-ID","Access-Control-Max-Age":"600"}});if($.method!=="POST")return A9(new Response(null,{status:405,headers:{Allow:"POST, OPTIONS"}}),G);return A9(await this.post($),G)}ownsPath($){let Z=this.endpoint.pathname.replace(/\/$/,"");return $===this.endpoint.pathname||$===Z||$.startsWith(`${Z}/`)||$.startsWith("/.well-known/")}async post($){let Z=null;for(let Y of this.resolvers){let K=await Y.resolve($,this.context);if(K===null)continue;if(K.ok===!1)return await this.failedAttempt($)??this.unauthorized(K.description);Z={...K.principal,via:Y.name};break}if(!Z)return(j3($)!==null?await this.failedAttempt($):null)??this.unauthorized();let z=await this.spend(Z);if(z)return z;let G=$.headers.get("content-type")??"";if(!/^application\/json\s*(;|$)/i.test(G))return new Response("Content-Type must be application/json.",{status:415});let W;try{W=JSON.parse(await $2($,this.maxBodyBytes))}catch(Y){if(Y instanceof V3)return f(R(null,new L(D.InvalidRequest,`The request is larger than ${this.maxBodyBytes} bytes.`)),413);return f(R(null,new L(D.ParseError,"Parse error.")),400)}let X=new m($,{},"api",this.endpoint.pathname);return await h.run(X,async()=>{try{return await this.dispatch($,X,Z,W)}catch(Y){if(Y instanceof L){let K=q(W)&&(typeof W.id==="string"||typeof W.id==="number")?W.id:null;return f(R(K,Y),Y.status)}return console.error("[gemi/mcp] The MCP endpoint failed:",Y),f(R(null,new L(D.InternalError,"Internal error.")),500)}},{user:Z.user})}async dispatch($,Z,z,G){let W=P9(G),X={kind:"remote",req:Z,principal:z};if(W.kind==="response"){let F=this.session($,z),B=this.pending.get(String(W.message.id));if(B&&B.session===F.id)this.pending.delete(String(W.message.id)),B.resolve(W.message);return new Response(null,{status:202})}let{message:Y}=W,K=Y.params??{},Q=q(K._meta)?K._meta:{};if(typeof Q[S3]==="string"){if(this.checkModernHeaders($,Y,Q[S3]),W.kind==="notification")return new Response(null,{status:202});return await this.respond(Y,async(F,B)=>this.modern({principal:z,caller:X,message:Y,params:K,era:{modern:!0},stream:F,signal:B}),C9(K),$.signal)}if(Y.method==="initialize"){if(W.kind!=="request")throw new L(D.InvalidRequest,"initialize is a request.",void 0,400);return this.initialize(W.message,K,z)}let V=this.session($,z),H=$.headers.get("mcp-protocol-version");if(H!==null&&H!==V.state.v)throw new L(D.InvalidRequest,`MCP-Protocol-Version ${H} is not the session's ${V.state.v}.`,void 0,400);if(W.kind==="notification"){if(Y.method==="notifications/cancelled"){let F=K.requestId;this.inflight.get(`${V.id}:${String(F)}`)?.abort()}return new Response(null,{status:202})}let J=`${V.id}:${String(Y.id)}`,I=new AbortController;this.inflight.set(J,I);let U=AbortSignal.any([I.signal,$.signal]);try{return await this.respond(Y,async(F,B)=>this.legacy({principal:z,caller:X,message:Y,params:K,era:{modern:!1,session:V.state,sessionId:V.id},stream:F,signal:B}),C9(K)||W2(this.registry,Y,V.state),U,()=>this.inflight.delete(J))}catch(F){throw this.inflight.delete(J),F}}async modern($){switch($.message.method){case"server/discover":return this.complete({supportedVersions:C3,capabilities:{tools:{}},...this.instructions?{instructions:this.instructions}:{},ttlMs:60000,cacheScope:"private"});case"tools/list":return this.complete({tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!0)),ttlMs:60000,cacheScope:"private"});case"tools/call":return await this.callTool($);default:throw new L(D.MethodNotFound,`Method not found: ${$.message.method}`,void 0,404)}}async legacy($){switch($.message.method){case"ping":return{};case"tools/list":return{tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!1))};case"tools/call":return await this.callTool($);default:throw new L(D.MethodNotFound,`Method not found: ${$.message.method}`)}}complete($){return{resultType:"complete",...$,_meta:{[T3]:this.serverInfo}}}initialize($,Z,z){let G=Z.protocolVersion,W=Y3.includes(G)?G:Y3[0],X=q(Z.capabilities)?Z.capabilities:{},Y={v:W,e:x9(X.elicitation),p:Q3(z),exp:Date.now()+a$},K=M3(D9,"gms1",Y);return f({jsonrpc:"2.0",id:$.id,result:{protocolVersion:W,capabilities:{tools:{listChanged:!1}},serverInfo:this.serverInfo,...this.instructions?{instructions:this.instructions}:{}}},200,{"Mcp-Session-Id":K})}session($,Z){let z=$.headers.get("mcp-session-id");if(!z)throw new L(D.InvalidRequest,"Missing Mcp-Session-Id. Send initialize first, or a request carrying io.modelcontextprotocol/protocolVersion in _meta.",void 0,400);let G=R3(D9,"gms1",z);if(!G||G.p!==Q3(Z))throw new L(D.InvalidRequest,"Session not found.",void 0,404);return{id:z,state:G}}checkModernHeaders($,Z,z){if(!x3.includes(z))throw new L(D.UnsupportedProtocolVersion,"Unsupported protocol version",{supported:C3,requested:z},400);let G=(Y)=>new L(D.HeaderMismatch,`Header mismatch: ${Y}`,void 0,400);if($.headers.get("mcp-protocol-version")!==z)throw G("MCP-Protocol-Version does not match the protocol version in _meta.");if($.headers.get("mcp-method")!==Z.method)throw G("Mcp-Method does not match the method.");let W=Z.params??{},X=Z.method==="tools/call"||Z.method==="prompts/get"?W.name:Z.method==="resources/read"?W.uri:void 0;if(X!==void 0){let Y=$.headers.get("mcp-name");if(Y===null||I9(Y)!==X)throw G("Mcp-Name does not match the request's name.")}}async callTool($){let Z=$.params.name;if(typeof Z!=="string")throw new L(D.InvalidParams,"tools/call needs a tool name.");let z=$.params.arguments??{};if(!this.onCall)return await this.runTool($,Z,z,{approved:!1});let G=performance.now(),W={approved:!1};try{let X=await this.runTool($,Z,z,W);if(!W.pending)await this.report($,Z,z,W,G);return X}catch(X){if(!W.outcome){if(W.outcome="error",W.message=X instanceof L?X.message:"Internal error.",!(X instanceof L))W.error=X}throw await this.report($,Z,z,W,G),X}}async report($,Z,z,G,W){let{principal:X}=$;try{await this.onCall({user:X.user,via:X.via,credentialId:X.id,clientId:X.clientId??null,scopes:X.scopes,tool:Z,arguments:z,outcome:G.outcome??"ok",...G.reason!==void 0?{reason:G.reason}:{},...G.message!==void 0?{message:G.message}:{},...G.status!==void 0?{status:G.status}:{},...G.error!==void 0?{error:G.error}:{},approved:G.approved,durationMs:Math.round((performance.now()-W)*1000)/1000,req:$.caller.req})}catch(Y){console.error(`[gemi/mcp] route.mcp.remote.onCall failed for "${Z}":`,Y)}}async runTool($,Z,z,G){let{caller:W,principal:X}=$,Y=(U,F)=>{G.outcome="denied",G.reason=U,G.message=F},K=(U,F,B)=>{if(G.outcome="error",G.message=U,F!==void 0)G.status=F;if(B!==void 0)G.error=B},Q=(await this.registry.available(W,{names:[Z]}))[0];if(!Q)throw Y("unknown-tool",`Unknown tool: ${Z}`),new L(D.InvalidParams,`Unknown tool: ${Z}`);if(Q.requiresApproval){let U=Q.inputSchema.safeParse(z);if(U.ok===!1){let B=`Invalid arguments for "${Z}": ${U.errors.join(", ")}`;return K(B),this.toolResult($,{content:[{type:"text",text:B}],isError:!0})}if($.era.modern&&q($.params.inputResponses)&&$.params.requestState!==void 0||await this.registry.approvalRequired(W,Z,z,{signal:$.signal})){let B=await this.approval($,Q,z,Y,G);if(B.kind==="answer")return B.result;G.approved=!0}}let V=X2($),H;try{H=await this.registry.execute(W,Z,z,void 0,{approved:G.approved,signal:$.signal,...V?{progress:V}:{}})}catch(U){if(U instanceof O){if(U.status===401||U.status===403)Y("forbidden",U.message),G.status=U.status;else K(U.message,U.status);return this.toolResult($,{content:[{type:"text",text:U.message}],isError:!0})}if(U instanceof v){let B=U.reason==="unknown-tool"?`Unknown tool: ${Z}`:U.message;throw Y(U.reason,B),new L(D.InvalidParams,B)}console.error(`[gemi/mcp] "${Z}" failed for ${X.via}:${X.id}:`,U);let F=`"${Z}" failed on the server.`;return K(F,void 0,U),this.toolResult($,{content:[{type:"text",text:F}],isError:!0})}let J=typeof H==="string"?H:JSON.stringify(H??null),I=Q.outputSchema&&($.era.modern||q(H))?{structuredContent:H}:{};return G.outcome="ok",this.toolResult($,{content:[{type:"text",text:J}],...I,isError:!1})}toolResult($,Z){return $.era.modern?this.complete(Z):Z}async approval($,Z,z,G,W){let X=Y2(Z,z),Y=(I,U="approval-declined")=>{return G(U,I),{kind:"answer",result:this.toolResult($,{content:[{type:"text",text:I}],isError:!0})}},K=(I,U)=>{return G(I,U.message),U};if($.era.modern){let I=q($.params._meta)?$.params._meta:{},U=q(I[q3])?I[q3]:{},F=q($.params.inputResponses)?$.params.inputResponses:null,B=$.params.requestState,T=G2(z);if(F&&B!==void 0){let C=R3(E3,"grs1",B);if(!C||C.p!==Q3($.principal)||C.t!==Z.name||C.a!==T)throw K("approval-invalid",new L(D.InvalidParams,"requestState is not valid for this call."));if(!await this.spendNonce(C.n,C.exp))throw K("approval-replayed",new L(D.InvalidParams,"requestState has already been used."));return S9(F[j9])?{kind:"approved"}:Y(`The user did not approve "${Z.name}", and it did not run.`)}if(!x9(U.elicitation))throw K("approval-unavailable",new L(D.MissingRequiredClientCapability,`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation).`,{requiredCapabilities:{elicitation:{form:{}}}},400));let j={p:Q3($.principal),t:Z.name,a:T,n:_9(16).toString("base64url"),exp:Date.now()+O9};return W.pending=!0,{kind:"answer",result:{resultType:"input_required",inputRequests:{[j9]:{method:"elicitation/create",params:{mode:"form",...X}}},requestState:M3(E3,"grs1",j),_meta:{[T3]:this.serverInfo}}}}let Q=$.era;if(!Q.session.e||!$.stream)return Y(`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation). It did not run.`,"approval-unavailable");let V=`gemi-approval-${_9(12).toString("base64url")}`,H=Q.sessionId,J=await new Promise((I)=>{let U=setTimeout(()=>{this.pending.delete(V),I(null)},this.approvalTimeoutMs),F=(B)=>{clearTimeout(U),I(B)};this.pending.set(V,{session:H,resolve:F}),$.signal.addEventListener("abort",()=>{this.pending.delete(V),F(null)}),$.stream.send({jsonrpc:"2.0",id:V,method:"elicitation/create",params:Q.session.v==="2025-11-25"?{mode:"form",...X}:X})});return J&&!J.error&&S9(J.result)?{kind:"approved"}:Y(`The user did not approve "${Z.name}", and it did not run.`)}async spendNonce($,Z){try{return await this.nonces.consume($,Z)}catch(z){return console.error("[gemi/mcp] Spending an approval failed:",z),!1}}async respond($,Z,z,G,W){if(!z)try{let Q=await Z(null,G);return f({jsonrpc:"2.0",id:$.id,result:Q},200)}finally{W?.()}let X=new AbortController,Y=AbortSignal.any([X.signal,G]),K=new E9(()=>X.abort());return(async()=>{try{let Q=await Z(K,Y);K.send({jsonrpc:"2.0",id:$.id,result:Q})}catch(Q){if(Q instanceof L)K.send(R($.id,Q));else console.error("[gemi/mcp] The MCP endpoint failed:",Q),K.send(R($.id,new L(D.InternalError,"Internal error.")))}finally{W?.(),K.close()}})(),new Response(K.readable,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"}})}unauthorized($){let Z=this.resolvers.map((G)=>G.challenge?.(this.context)).find(Boolean)??'Bearer realm="mcp"',z=$?`${Z}, error="invalid_token", error_description="${$.replace(/["\\]/g,"")}"`:Z;return f(R(null,new L(D.InvalidRequest,"Unauthorized.")),401,{"WWW-Authenticate":z})}async failedAttempt($){let Z=T9(new m($,{},"api",this.endpoint.pathname)),z=await A3(`mcp-auth-failed:${Z}`,e$);return z===null?null:q9(z)}async spend($){if(!this.rateLimit)return null;let Z=await A3(`mcp-endpoint:${$.via}:${$.id}`,this.rateLimit);return Z===null?null:q9(Z)}}class E9{readable;controller;closed=!1;encoder=new TextEncoder;constructor($){this.readable=new ReadableStream({start:(Z)=>{this.controller=Z},cancel:()=>{this.closed=!0,$()}})}send($){if(this.closed)return;this.controller.enqueue(this.encoder.encode(`event: message
|
|
2
|
+
import{$b as K3,Mc as F9,Xb as k9,ac as M9,gc as e,od as N9,tc as U9,zc as J9}from"./chunk-xp5axyb5.js";import{Ad as d9,Bd as p9,Cd as V$,Ed as L$,vd as p3,xd as B3}from"./chunk-wbv6218d.js";import{Hd as w9,Md as v9,Od as h9,Vd as x,Wd as g9,Xd as m9,Zd as u9,_d as B$}from"./chunk-0yjm936b.js";import{be as P}from"./chunk-ycn7w2e9.js";import{Ae as Q$,Af as H3,Bf as g3,Cf as k,Cg as x$,Dg as L3,Eg as d3,Ff as Y$,Gf as G$,Hf as W$,Jf as w,Jg as X$,Ke as H$,Kg as K$,Le as c3,Pe as J3,Qe as X3,Qg as D$,Wf as a3,fg as t3,gf as m3,hg as n,lg as o3,mg as t9,ng as o9,pe as l,qe as z$,te as T9,tg as f3,uf as Z3,ug as a9,vg as G3,wg as r9,xe as O$,xg as e9,yg as w3,zg as a}from"./chunk-t66ex43f.js";import{Ci as P3,Di as F3,Ei as z3,Vh as c,Xh as m,ki as s3,yi as H9}from"./chunk-0v3bca8k.js";import{Ki as i9}from"./chunk-xyyq577r.js";import{Vi as h}from"./chunk-159j20yr.js";import{$i as u3}from"./chunk-8eyxj78g.js";import{cj as U$,dj as i3,gj as N3,hj as n3,kj as F$}from"./chunk-ss3yn4g2.js";import{Dj as n9,yj as l9}from"./chunk-aq5zx3vg.js";import{Tj as f9,Vj as u}from"./chunk-n95dppzm.js";import{Wj as A}from"./chunk-zcg6m7gf.js";import{ak as I$}from"./chunk-yzsyg1f7.js";import{Qk as l3}from"./chunk-517fjfme.js";import{Xk as U3,_k as y}from"./chunk-tzheb6ak.js";import{hl as h3}from"./chunk-7yww9aq7.js";import{tl as s9}from"./chunk-ah2jy1vx.js";var C$="mcp",S$=/^[\x21\x23-\x5B\x5D-\x7E]+$/;class O extends e{status;constructor($,Z){super($);this.status=Z;this.name="McpToolError"}}class v extends Error{reason;constructor($,Z){super($);this.reason=Z;this.name="McpCallRefusedError"}}var r3=/^[A-Za-z0-9_-]{1,64}$/,q$=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,e3=4000,M=1e5,T$=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i,B9=new WeakMap;function X6($){return B9.get($)}class i{router;dispatcher;static token="router.mcp";plans=new Map;scopeTools=new Map;files;featureOn;constructor($,Z,z={}){this.router=$;this.dispatcher=Z;this.files=b$(z.files),this.featureOn=z.featureOn??X3;for(let[G,W]of Object.entries($.routes??{}))this.plans.set(G,k$(W)?this.planNative(G,W):this.plan(G,W));this.resolveScopes()}list($,Z){if(D3($),$.kind==="local")return this.descriptors(Z);let z=[];for(let[G,W]of this.plans){if(!W.remote||!this.grants($.principal,G))continue;if(W9(W.remote,Z))z.push(W.remote)}return z}async available($,Z){let z=[];for(let G of this.list($,Z))if(await this.isOn(G))z.push(G);return z}descriptors($){let Z=[];for(let{descriptor:z}of this.plans.values())if(W9(z,$))Z.push(z);return Z}get maxFileBytes(){return this.files.maxBytes}scopes(){return[...this.scopeTools].map(([$,{description:Z}])=>({name:$,description:Z}))}scopesFor($){return[...this.scopeTools].filter(([,{tools:Z}])=>Z.has($)).map(([Z])=>Z)}async execute($,Z,z,G,W={}){D3($);let X=this.plans.get(Z);if(X&&!await this.isOn(X.descriptor)){if($.kind==="remote")throw new v(`There is no tool named "${Z}".`,"unknown-tool");throw new O(`There is no tool named "${Z}".`,404)}if($.kind==="remote"){if(!X?.remote||!this.grants($.principal,Z))throw new v(`There is no tool named "${Z}".`,"unknown-tool");if(X.descriptor.requiresApproval&&W.approved!==!0&&!W3(X))throw new v(`"${Z}" needs the user's approval, and this call does not have it.`,"approval-required");G=void 0}if(!X)throw Error(`McpRegistry: there is no tool named "${Z}".`);if(X.kind==="tool")return await this.executeNative(X,$,z,G,W);let Y=X,K=$.kind==="remote"?Y.remote:Y.descriptor,Q=K.inputSchema.safeParse(z);if(Q.ok===!1)throw new O(`Invalid arguments for "${Z}": ${Q.errors.join(", ")}`);let V=Q.value,H={caller:$,req:$.req,tool:K,input:V,ctx:G},J=await this.fillPath(Y,H),{path:I}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${J}`));if(I!==K.url)throw new O(`"${Z}" has nothing at ${J}.`,404);let U={};for(let _ of Y.jsonKeys)if(V[_]!==void 0)U[_]=V[_];let F,B="";if(Y.fileFields.length>0)F=await this.formData(Y,U,H);else if(K.method==="GET")B=p$(U);else if(Y.jsonKeys.length>0)F=U;let T=this.router.credentials?await this.bind(Y,"the credentials",()=>this.router.credentials(H)):void 0,j={...T?{credentials:T}:{},...W.signal?{signal:W.signal}:{},...W.progress?{progress:W.progress}:{},...$.kind==="remote"?{identity:{user:$.principal.user,grant:{via:$.principal.via,id:$.principal.id,scopes:$.principal.scopes,...$.principal.clientId?{clientId:$.principal.clientId}:{}}}}:{}},C;try{let _=B?`${J}?${B}`:J;C=Object.keys(j).length>0?await this.dispatcher.dispatchAs($.req,K.method,_,F,j):await this.dispatcher.dispatchAs($.req,K.method,_,F)}catch(_){throw console.error(`[gemi/mcp] Dispatching "${Z}" failed:`,_),new O(`"${Z}" failed on the server.`,500)}if(!Y.result&&!K.outputSchema)return await V9(Z,C);return await this.project(Y,H,C)}async isOn($){return $.feature===void 0||await this.featureOn($.feature)===!0}plan($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (${Z?.method} ${Z?.url})`;if(!(Z instanceof Object)||Z.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${$}" is not a route or a tool. Declare it with this.fromApiRoute(...) or this.fromTool(...).`);let{method:G,url:W,meta:X}=Z;if(X.feature!==void 0&&(typeof X.feature!=="string"||X.feature===""))throw Error(`${z}: feature must be a feature key from app/features.`);if(W.startsWith("/__gemi__"))throw Error(`${z} is a framework route, not an app route.`);let Y=this.dispatcher.flatRoutes[W]?.[G];if(!Y)throw Error(`${z} names no route of this app. Expose a route by the path and verb it is mounted at.`);let K=[...W.matchAll(q$)].map(([,N,S])=>({name:N,modifier:S})),Q=X.params??{};for(let N of K)if(!(N.name in Q))throw Error(`${z}: the path param "${N.name}" must be bound or declared "input".`);for(let[N,S]of Object.entries(Q)){if(!K.some((g)=>g.name===N))throw Error(`${z}: "${N}" in params is not a param of the url.`);if(Y9(S))h$(z,`params.${N}`,S);else X9(z,`params.${N}`,S)}let V=[],H;if(X.input){if(H=X.input.toJSONSchema(),H.type!=="object"||!H.properties)throw Error(`${z}: input must be an s.object(...), the fields of the request body.`);V=Object.keys(H.properties)}let J=Object.entries(X.files??{}).map(([N,S])=>({name:N,binder:S}));for(let N of J)X9(z,`files.${N.name}`,N.binder);if(X.result!==void 0&&typeof X.result!=="function")throw Error(`${z}: result must be a function.`);if(X.output!==void 0&&typeof X.output?.safeParse!=="function")throw Error(`${z}: output must be a schema, built with s.`);if(X.title!==void 0&&(typeof X.title!=="string"||X.title===""))throw Error(`${z}: title must be a non-empty string.`);let I=K9(z,G,X.annotations);if(J.length>0&&G==="GET")throw Error(`${z}: a GET has no body to carry a file.`);let U={},F=(N,S)=>{if(N in U)throw Error(`${z}: "${N}" is the input key of two params or files, and the model can only send one.`);U[N]=S},B=new Map,T=new Map;for(let N of K){let S=Q[N.name];if(S==="input"){let g=c.string().describe(`The ":${N.name}" segment of the url.`);F(N.name,N.modifier==="?"||N.modifier==="*"?g.optional():g)}else if(Y9(S)){let g=S.as??N.name;F(g,S.input),T.set(N.name,{key:g,param:S})}else B.set(N.name,S)}let j={};for(let N of J)if(N.binder==="input")F(N.name,c.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.")),j[N.name]=this.remoteFileSchema();let C=[...Object.keys(U),...J.map((N)=>N.name)];for(let N of new Set(C))if(V.includes(N))throw Error(`${z}: "${N}" is both an input field and a param or file, and the model can only send one.`);let _=Object.freeze({kind:"route",name:$,description:X.description,method:G,url:W,inputSchema:Q9(X.input,H,c.object(U)),...X.output?{outputSchema:X.output}:{},...X.title?{title:X.title}:{},annotations:I,tags:Object.freeze([...X.tags??[]]),requiresApproval:X.requiresApproval===!0,...X.feature!==void 0?{feature:X.feature}:{},...Y.source?{source:Y.source}:{}}),r=!J.every((N)=>N.binder==="input")?null:J.length===0?_:Object.freeze({..._,inputSchema:Q9(X.input,H,c.object(u$(U,Object.keys(j))),j)});return{kind:"route",descriptor:_,remote:r,params:K,paramBinders:B,modelParams:T,fileFields:J,jsonKeys:V,...X.result?{result:X.result}:{}}}remoteFileSchema(){let{maxBytes:$,fetch:Z}=this.files,z={name:{type:"string",description:"The file's name, like report.pdf."},mimeType:{type:"string",description:"The file's media type, like application/pdf."},data:{type:"string",contentEncoding:"base64",description:`The file's bytes, base64-encoded (RFC 4648, standard alphabet). At most ${$} bytes decoded.`}};if(Z)z.url={type:"string",format:"uri",description:"An https URL the server downloads the file from, instead of data."};let G={type:"object",description:Z?"A file, sent as base64 in data or fetched from url: exactly one of the two.":"A file, sent as base64 in data.",properties:z,required:["name","mimeType"],additionalProperties:!1},W=Object.keys(z),X=(Y)=>{if(typeof Y!=="object"||Y===null||Array.isArray(Y))return{ok:!1,errors:["a file must be an object"]};let K=[],Q={};for(let V of Object.keys(Y))if(!W.includes(V))K.push(`a file has no field "${V}"`);for(let V of W){let H=Y[V];if(H===void 0||H===null){if(V==="name"||V==="mimeType")K.push(`a file needs "${V}"`);continue}if(typeof H!=="string")K.push(`a file's "${V}" must be a string`);else Q[V]=H}return K.length>0?{ok:!1,errors:K}:{ok:!0,value:Q}};return{toJSONSchema:()=>G,safeParse:X,parse(Y){let K=X(Y);if(K.ok===!1)throw Error(K.errors.join(", "));return K.value}}}planNative($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (a native tool)`,{tool:G,meta:W={}}=Z;if(!(G instanceof Object)||typeof G.name!=="string")throw Error(`${z} is not an AgentTool. Pass one built with AgentTool.create(...).`);if(G.answeredBy==="client"||typeof G.execute!=="function")throw Error(`${z}: "${G.name}" is answered by the client, and only a tool the server runs can be called through the registry.`);if(typeof G.inputSchema==="function")throw Error(`${z}: "${G.name}" resolves its input schema per run, and the registry lists one schema to every caller. Give it a fixed inputSchema.`);if(typeof G.inputSchema?.safeParse!=="function")throw Error(`${z}: its inputSchema must be a schema, built with s.`);if(typeof W!=="object"||W===null)throw Error(`${z}: the meta must be an object.`);if(W.description!==void 0&&(typeof W.description!=="string"||W.description.trim()===""))throw Error(`${z}: description must be a non-empty string.`);if(W.title!==void 0&&(typeof W.title!=="string"||W.title===""))throw Error(`${z}: title must be a non-empty string.`);if(W.tags!==void 0&&(!Array.isArray(W.tags)||W.tags.some((Q)=>typeof Q!=="string")))throw Error(`${z}: tags must be an array of strings.`);if(W.requiresApproval===!1&&G.requiresApproval)throw Error(`${z}: "${G.name}" requires approval, and requiresApproval: false would run it without asking. Leave it out, or register a tool that does not ask.`);let X=W.remote;if(X!==void 0){if(typeof X!=="object"||X===null||typeof X.context!=="function")throw Error(`${z}: remote must be { context(call) }, building the AgentContext a remote call runs with.`);if(X.progress!==void 0&&typeof X.progress!=="function")throw Error(`${z}: remote.progress must be a function.`)}let Y=W.description??G.description;if(typeof Y!=="string"||Y.trim()==="")throw Error(`${z} needs a description: the tool's own, or the meta's.`);let K=Object.freeze({kind:"tool",name:$,description:Y,inputSchema:G.inputSchema,...G.outputSchema?{outputSchema:G.outputSchema}:{},...W.title?{title:W.title}:{},annotations:K9(z,void 0,W.annotations),tags:Object.freeze([...W.tags??[]]),requiresApproval:G.requiresApproval||W.requiresApproval===!0});return{kind:"tool",descriptor:K,remote:X?K:null,tool:G,meta:W}}async approvalRequired($,Z,z,G={}){let W=this.plans.get(Z);if(!W)return!0;if(!W3(W))return W.descriptor.requiresApproval;let X=W;if($.kind!=="remote"||!X.meta.remote)return!0;let Y=X.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)return!0;let K={caller:$,req:$.req,tool:X.descriptor,input:Y.value},Q;try{Q=await this.bind(X,"the remote context",()=>X.meta.remote.context(K))}catch{return!0}if(typeof Q!=="object"||Q===null)return!0;let V=G.signal??new AbortController().signal;return G9(X,Y.value,z9(Z9(X,Q,V)))}nativeApproval($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return W3(Z)??Z.descriptor.requiresApproval}nativeTool($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return Z.tool}startNative($,Z,z,G){let W=this.plans.get(Z);if(W?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${Z}".`);if($===void 0)return W.tool.execute(z,G);if(D3($),$.kind!=="local")throw Error("McpRegistry: startNative is for a local caller. A remote call goes through execute().");let X=W.descriptor.inputSchema.safeParse(z);if(X.ok===!1)throw new O(`Invalid arguments for "${Z}": ${X.errors.join(", ")}`);return this.runNative(W,{caller:$,req:$.req,tool:W.descriptor,input:X.value},G)}runNative($,Z,z){let G={...z};return B9.set(G,{...Z,ctx:G}),$.tool.execute(Z.input,G)}async executeNative($,Z,z,G,W){let{name:X}=$.descriptor,Y=$.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)throw new O(`Invalid arguments for "${X}": ${Y.errors.join(", ")}`);let K={caller:Z,req:Z.req,tool:$.descriptor,input:Y.value},Q=(_,_3)=>{if(!W.progress)return;let r;try{r=$.meta.remote?.progress?$.meta.remote.progress(_,_3):R$(_,_3)}catch(N){console.error(`[gemi/mcp] The progress mapping of "${X}" failed:`,N);return}if(r)W.progress(r)};if(Z.kind==="local"){if(!G)throw Error(`McpRegistry: "${X}" is a native tool, which runs with the tool context of an agent call, and none was passed to execute().`);return await $9(this.runNative($,{...K,ctx:G},G),Q)}let V=$.meta.remote,H=await this.bind($,"the remote context",()=>V.context(K));if(typeof H!=="object"||H===null)throw console.error(`[gemi/mcp] The remote context of "${X}" is not an object:`,H),new O(`"${X}" failed on the server.`,500);let J=$.tool.timeoutMs,I=[...W.signal?[W.signal]:[],...J!==void 0?[AbortSignal.timeout(J)]:[]],U=I.length===0?new AbortController().signal:I.length===1?I[0]:AbortSignal.any(I),F=Z9($,H,U);if(!W.approved&&W3($)&&await G9($,K.input,z9(F)))throw new v(`"${X}" needs the user's approval, and this call does not have it.`,"approval-required");let B;try{B=await $9(this.runNative($,{...K,ctx:F},F),Q,U)}catch(_){if(U.aborted&&_===U.reason){if(W.signal?.aborted)throw new O(`"${X}" was cancelled.`,499);throw new O(`"${X}" did not finish within ${J} ms.`,504)}if(_ instanceof O)throw _;if(_ instanceof e||_ instanceof v)throw new O(_.message);throw console.error(`[gemi/mcp] "${X}" failed for a remote caller:`,_),new O(`"${X}" failed on the server.`,500)}let T=(_)=>{return console.error(`[gemi/mcp] "${X}" ${_}`),new O(`"${X}" failed on the server.`,500)};if(U9(B))throw T("answered a job handle, and a remote call has no background jobs.");let j=B;if($.descriptor.outputSchema){let _=$.descriptor.outputSchema.safeParse(j);if(_.ok===!1)throw T(`answered what its output schema refuses: ${_.errors.join(", ")}`);j=_.value}if(j===void 0)return null;if(typeof j==="string")return j.length>M?`${j.slice(0,M)}\u2026 [cut at ${M} of ${j.length} characters]`:j;let C=JSON.stringify(j);if(C!==void 0&&C.length>M)return`${C.slice(0,M)}\u2026 [cut at ${M} of ${C.length} characters]`;return j}async fillPath($,Z){let{input:z,req:G}=Z,W=$.descriptor.url;for(let X of $.params){let Y=$.paramBinders.get(X.name),K=$.modelParams.get(X.name),Q;if(Y||K){if(Q=K?await this.bind($,`the param "${X.name}"`,()=>K.param.bind(z[K.key],G,Z),{refusals:!0}):await this.bind($,`the param "${X.name}"`,()=>Y(G,Z)),Q===void 0||Q===null||Q==="")throw console.error(`[gemi/mcp] The ${K?"resolver":"binder"} for "${X.name}" of "${$.descriptor.name}" returned ${JSON.stringify(Q)}.`),new O(`"${$.descriptor.name}" failed on the server.`,500)}else Q=z[X.name];let V=`:${X.name}${X.modifier}`;if(Q===void 0||Q===null||Q===""){if(X.modifier!=="?"&&X.modifier!=="*")throw new O(`"${X.name}" of "${$.descriptor.name}" must not be empty.`);W=W.replace(`/${V}`,"");continue}W=W.replace(V,d$($.descriptor.name,X,String(Q)))}return W}async formData($,Z,z){let{input:G,ctx:W}=z,X=$.descriptor.name;if(z.caller.kind==="remote"){let K=new FormData;for(let[Q,V]of Object.entries(Z))O3(K,Q,V);for(let Q of $.fileFields)K.append(Q.name,await this.remoteFile(X,Q.name,G[Q.name]));return K}if(!W)throw Error(`McpRegistry: "${X}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let Y=new FormData;for(let[K,Q]of Object.entries(Z))O3(Y,K,Q);for(let K of $.fileFields){let Q=K.binder==="input"?G[K.name]:await this.bind($,`the file "${K.name}"`,()=>K.binder(W,z));if(typeof Q!=="string"||Q==="")throw new O(`"${X}" needs a file for "${K.name}", and this turn has none. Ask the user to attach one.`);Y.append(K.name,await W.attachments.file(Q))}return Y}async remoteFile($,Z,z){let G=(H)=>new O(`"${Z}" of "${$}" ${H}`,400),W=z,{maxBytes:X,fetch:Y}=this.files;if(!y$(W.name))throw G("needs a name of 1 to 255 characters, without control characters or slashes.");if(!f$.test(W.mimeType))throw G(`has a mimeType that is not a media type: "${W.mimeType.slice(0,100)}".`);let K=typeof W.data==="string",Q=typeof W.url==="string";if(K===Q)throw G(Y?"needs exactly one of data or url.":"needs its bytes, base64, in data.");if(K){let H=W.data.replace(/\s+/g,"");if(Math.floor(H.length*3/4)-v$(H)>X)throw G(`is larger than the ${X} bytes a file may be.`);if(H.length%4!==0||!w$.test(H))throw G("has data that is not base64 (RFC 4648, standard alphabet, padded).");return new File([Buffer.from(H,"base64")],W.name,{type:W.mimeType})}if(!Y)throw G("cannot be fetched from a URL here. Send its bytes, base64, in data.");let V;try{V=new URL(W.url)}catch{throw G("has a url that is not a URL.")}if(V.protocol!=="https:")throw G("can only be fetched from an https URL.");try{let H=await H9(V.href,{...Y,maxSize:Math.min(Y.maxSize??X,X),redirect:"follow"});if(!H.ok)throw G(`could not be fetched: ${V.host} answered ${H.status}.`);let J=await H.arrayBuffer();return new File([J],W.name,{type:W.mimeType})}catch(H){if(H instanceof O)throw H;throw G(`could not be fetched from ${V.host}: ${H instanceof Error?H.message:"failed"}.`)}}grants($,Z){for(let z of $.scopes??[])if(this.scopeTools.get(z)?.tools.has(Z))return!0;return!1}resolveScopes(){let $=this.router.scopes;if($===void 0){this.scopeTools.set(C$,{description:"Use this app's tools as you",tools:new Set(this.plans.keys())});return}if(typeof $!=="object"||$===null)throw Error("McpRouter: scopes must be an object of scope names.");let Z=new Set([...this.plans.values()].flatMap(({descriptor:z})=>z.tags));for(let[z,G]of Object.entries($)){let W=`McpRouter: scope "${z}"`;if(!S$.test(z))throw Error(`${W} is not a valid OAuth scope: printable ASCII, no spaces or quotes.`);if(typeof G?.description!=="string"||G.description==="")throw Error(`${W} needs a description: it is what a consent screen shows.`);let X=new Set;for(let Y of G.tags??[]){if(!Z.has(Y))throw Error(`${W} names the tag "${Y}", which no tool has.`);for(let[K,{descriptor:Q}]of this.plans)if(Q.tags.includes(Y))X.add(K)}for(let Y of G.names??[]){if(!this.plans.has(Y))throw Error(`${W} names "${Y}", which is no tool.`);X.add(Y)}if(X.size===0)throw Error(`${W} reaches no tool. Give it tags or names.`);this.scopeTools.set(z,{description:G.description,tools:X})}}async project($,Z,z){let{name:G,outputSchema:W}=$.descriptor;if(z.status<200||z.status>=300)return await V9(G,z);let X=(J,I)=>{if(I===void 0)console.error(`[gemi/mcp] "${G}" ${J}`);else console.error(`[gemi/mcp] "${G}" ${J}`,I);return new O(`"${G}" failed on the server.`,500)},Y=z.headers.get("Content-Type"),K=await z.text(),Q=null;if(K!=="")try{Q=JSON.parse(K)}catch{throw X(`answered ${Y??"a body with no content-type"} that is not JSON, and its result or output needs JSON.`)}let V=Q;if($.result)try{V=await $.result(Q,Z)}catch(J){throw X("failed in its result projection:",J)}if(W){let J=W.safeParse(V);if(J.ok===!1)throw X(`answered what its output schema refuses: ${J.errors.join(", ")}`);V=J.value}if(V===void 0)return null;let H=JSON.stringify(V);if(H!==void 0&&H.length>M)return`${H.slice(0,M)}\u2026 [cut at ${M} of ${H.length} characters]`;return V}async bind($,Z,z,G={}){try{return await z()}catch(W){if(G.refusals&&W instanceof e)throw W;throw console.error(`[gemi/mcp] Binding ${Z} of "${$.descriptor.name}" failed:`,W),new O(`"${$.descriptor.name}" failed on the server.`,500)}}}function k$($){return $ instanceof Object&&$.__internal_brand==="McpTool"}function M$($){return typeof $==="object"&&$!==null&&typeof $.next==="function"&&Symbol.asyncIterator in $}async function $9($,Z,z){let G;if(z)G=new Promise((X,Y)=>{if(z.aborted)Y(z.reason);else z.addEventListener("abort",()=>Y(z.reason),{once:!0})}),G.catch(()=>{});let W=(X)=>G?Promise.race([X,G]):X;if(!M$($))return await W(Promise.resolve($));try{let X=0,Y=await W($.next());while(!Y.done)Z(Y.value,++X),Y=await W($.next());return Y.value}catch(X){throw $.return(void 0).catch(()=>{}),X}}function R$($,Z){if(typeof $==="string")return{progress:Z,message:$};if(typeof $==="object"&&$!==null){let{progress:z,total:G,message:W}=$;if(typeof z==="number"&&Number.isFinite(z))return{progress:z,...typeof G==="number"?{total:G}:{},...typeof W==="string"?{message:W}:{}};if(typeof W==="string")return{progress:Z,message:W}}return{progress:Z}}function Z9($,Z,z){let G=$.descriptor.name,W=`mcp_${crypto.randomUUID()}`,X=`mcp_call_${crypto.randomUUID()}`,Y=(Q)=>async()=>{throw new e(`"${G}" was called by a remote MCP client, which has no ${Q}.`,{retryable:!1})},K={put:Y("attachment store"),get:Y("attachment store"),read:Y("attachment store"),file:Y("attachment store")};return{context:Z,body:{},runId:W,toolCallId:X,signal:z,step:1,depth:0,resumed:!1,attachments:K,turn:Object.freeze({attachments:Object.freeze([])}),runAgent:Y("agent run to nest a sub-agent in"),generateImage:Y("attachment store to put an image in"),editImage:Y("attachment store to put an image in"),generate:(Q)=>N9({...Q,signal:Q.signal?AbortSignal.any([z,Q.signal]):z},{origin:{mcp:G,runId:W,toolCallId:X}}),jobs:J9({jobs:void 0,threadId:void 0,runId:W,toolCallId:X,toolName:G,depth:0,async:$.tool.async,attachments:null}),memory:F9()}}function W3($){if($.kind!=="tool"||$.meta.requiresApproval===!0)return;return $.tool.approvalPredicate}function z9($){return{context:$.context,body:$.body,runId:$.runId,threadId:$.threadId,toolCallId:$.toolCallId,step:$.step,depth:$.depth,signal:$.signal}}async function G9($,Z,z){try{return await $.tool.approvalPredicate(Z,z)!==!1}catch(G){return console.error(`[gemi/mcp] The requiresApproval of "${$.descriptor.name}" threw, so the call asks the user:`,G),!0}}function D3($){if($?.kind==="local"&&$.req)return;if($?.kind==="remote"&&$.req&&$.principal?.user&&typeof $.principal.id==="string"&&Array.isArray($.principal.scopes))return;throw Error('McpRegistry: a caller is { kind: "local", req } or { kind: "remote", req, principal }, with the principal a caller resolver verified.')}function W9($,Z){if(Z?.names&&!Z.names.includes($.name))return!1;if(Z?.tags&&!$.tags.some((z)=>Z.tags.includes(z)))return!1;return!0}var E$=10485760;function b$($){let Z=$?.maxBytes??E$;if(!Number.isSafeInteger(Z)||Z<=0)throw Error("McpRegistry: files.maxBytes must be a positive whole number of bytes.");let z=$?.fetchUrls===!0?{}:typeof $?.fetchUrls==="object"&&$.fetchUrls!==null?$.fetchUrls:null;return{maxBytes:Z,fetch:z}}function y$($){if($.length===0||$.length>255)return!1;for(let Z of $){let z=Z.codePointAt(0);if(z<32||z===127||Z==="/"||Z==="\\")return!1}return!0}var f$=/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(\s*;.{0,200})?$/,w$=/^[A-Za-z0-9+/]*={0,2}$/;function v$($){return $.endsWith("==")?2:$.endsWith("=")?1:0}function X9($,Z,z){if(z!=="input"&&typeof z!=="function")throw Error(`${$}: ${Z} must be a function or "input".`)}function Y9($){return $ instanceof Object&&$.__internal_brand==="McpModelParam"}function h$($,Z,z){if(z.as!==void 0&&(typeof z.as!=="string"||z.as===""))throw Error(`${$}: ${Z}.as must be a non-empty string.`);let G=z.input;if(typeof G?.safeParse!=="function"||typeof G.toJSONSchema!=="function")throw Error(`${$}: ${Z}.input must be a schema, built with s.`);if(typeof z.bind!=="function")throw Error(`${$}: ${Z}.bind must be a function.`)}var g$=new Set(["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"]);function m$($){switch($){case"GET":return{readOnlyHint:!0};case"DELETE":return{destructiveHint:!0};case"PUT":return{idempotentHint:!0};default:return{}}}function K9($,Z,z){if(z!==void 0&&(typeof z!=="object"||z===null))throw Error(`${$}: annotations must be an object of hints.`);let G=Z?m$(Z):{};for(let[W,X]of Object.entries(z??{})){if(!g$.has(W))throw Error(`${$}: "${W}" is not a tool annotation. Use readOnlyHint, destructiveHint, idempotentHint or openWorldHint.`);if(X===void 0)continue;if(typeof X!=="boolean")throw Error(`${$}: annotations.${W} must be true or false.`);G[W]=X}if(G.readOnlyHint===!0&&(G.destructiveHint||G.idempotentHint))throw Error(`${$} is read-only${z?.readOnlyHint?"":` (a ${Z})`} and also ${G.destructiveHint?"destructive":"idempotent"}, which only a tool that is not read-only can be. Set readOnlyHint: false if it changes something.`);return Object.freeze(G)}function Q9($,Z,z,G={}){let W=z.toJSONSchema(),X=Object.fromEntries(Object.entries(G).map(([Q,V])=>[Q,V.toJSONSchema()])),Y={...Z??{},type:"object",properties:{...Z?.properties??{},...W.properties,...X},required:[...Z?.required??[],...W.required??[],...Object.keys(G)],additionalProperties:!1},K=(Q)=>{if(typeof Q!=="object"||Q===null||Array.isArray(Q))return{ok:!1,errors:["expected an object"]};let V=[],H={};if($){let I=$.safeParse(Q);if(I.ok===!1)V.push(...I.errors);else H={...I.value}}let J=z.safeParse(Q);if(J.ok===!1)V.push(...J.errors);else H={...H,...J.value};for(let[I,U]of Object.entries(G)){let F=Q[I];if(F===void 0){V.push(`"${I}" is required`);continue}let B=U.safeParse(F);if(B.ok===!1)V.push(...B.errors.map((T)=>`${I}: ${T}`));else H[I]=B.value}return V.length>0?{ok:!1,errors:V}:{ok:!0,value:H}};return{toJSONSchema:()=>Y,safeParse:K,parse(Q){let V=K(Q);if(V.ok===!1)throw Error(V.errors.join(", "));return V.value}}}function u$($,Z){return Object.fromEntries(Object.entries($).filter(([z])=>!Z.includes(z)))}function d$($,Z,z){let G=Z.modifier==="*"||Z.modifier==="+"?z.split("/"):[z];if(G.some((W)=>W==="."||W===".."))throw new O(`"${z}" is not a valid value for "${Z.name}" of "${$}".`);return G.map(encodeURIComponent).join("/")}function O3($,Z,z){if(z===void 0||z===null)return;if(Array.isArray(z)){for(let G of z)O3($,Z,G);return}$.append(Z,typeof z==="object"?JSON.stringify(z):String(z))}function p$($){let Z=new URLSearchParams,z=(G,W)=>{if(W===void 0||W===null)return;if(Array.isArray(W)){for(let X of W)z(G,X);return}Z.append(G,typeof W==="object"?JSON.stringify(W):String(W))};for(let[G,W]of Object.entries($))z(G,W);return Z.toString()}async function V9($,Z){if(Z.status>=200&&Z.status<300){let G=Z.headers.get("Content-Type");if(G&&!T$.test(G)){let X=(await Z.arrayBuffer()).byteLength;return`"${$}" answered with ${X} bytes of ${G}, which is not shown.`}let W=await Z.text();if(W==="")return null;if(W.length>M)return`${W.slice(0,M)}\u2026 [cut at ${M} of ${W.length} characters]`;try{return JSON.parse(W)}catch{return W}}let z=await Z.text();if(Z.status>=400&&Z.status<500){let G=z.length>e3?`${z.slice(0,e3)}\u2026`:z;throw new O(`"${$}" was refused with ${Z.status}${G?`: ${G}`:"."}`,Z.status)}if(Z.status<500)console.error(`[gemi/mcp] "${$}" answered ${Z.status}${Z.headers.get("Location")?` to ${Z.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new O(`"${$}" failed on the server.`,Z.status)}import{createHash as c$,randomBytes as i$,timingSafeEqual as l$}from"crypto";function j3($){let Z=$.headers.get("authorization");if(!Z)return null;let z=/^Bearer[ ]+([\x21-\x7e]+)$/i.exec(Z.trim());return z?z[1]:null}class n${options;name="api-key";constructor($){this.options=$;if(typeof $?.prefix!=="string"||!/^[A-Za-z0-9_-]{3,32}$/.test($.prefix))throw Error('McpApiKeyResolver: prefix is required: 3 to 32 letters, digits, _ or -, like "myapp_mcp_".');if(typeof $.verify!=="function")throw Error("McpApiKeyResolver: verify must be a function that looks a key up.")}static generate($){return`${$}${i$(32).toString("base64url")}`}static hash($){return c$("sha256").update($).digest("hex")}static hashesMatch($,Z){let z=Buffer.from($),G=Buffer.from(Z);return z.length===G.length&&l$(z,G)}async resolve($){let Z=j3($);if(!Z?.startsWith(this.options.prefix))return null;let z=await this.options.verify(Z,$);if(!z)return{ok:!1,error:"invalid_token",description:"The API key is not valid."};if(!z.user||typeof z.id!=="string"||z.id===""||!Array.isArray(z.scopes))throw Error("McpApiKeyResolver: verify must answer { user, id, scopes } for a key it knows, or null.");return{ok:!0,principal:{user:z.user,via:this.name,id:z.id,scopes:[...z.scopes]}}}}import{createHash as R9,randomBytes as _9}from"crypto";async function A3($,Z){let z=s$();if(!z)return null;let G=await z.consume($,Z);return G.allowed?null:Math.max(1,Math.ceil(G.retryAfter/1000))}function s$(){try{let $=y();return $.bound(l)?$.make(l):null}catch{return null}}var x3=["2026-07-28"],Y3=["2025-11-25","2025-06-18","2025-03-26"],C3=[...x3,...Y3],S3="io.modelcontextprotocol/protocolVersion",q3="io.modelcontextprotocol/clientCapabilities";var T3="io.modelcontextprotocol/serverInfo",D={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,HeaderMismatch:-32020,MissingRequiredClientCapability:-32021,UnsupportedProtocolVersion:-32022};class L extends Error{code;data;status;constructor($,Z,z,G=200){super(Z);this.code=$;this.data=z;this.status=G;this.name="JsonRpcError"}}function R($,Z){return{jsonrpc:"2.0",id:$,error:{code:Z.code,message:Z.message,...Z.data!==void 0?{data:Z.data}:{}}}}function P9($){if(Array.isArray($))throw new L(D.InvalidRequest,"Batched requests are not supported.",void 0,400);if(typeof $!=="object"||$===null||$.jsonrpc!=="2.0")throw new L(D.InvalidRequest,"Not a JSON-RPC 2.0 message.",void 0,400);let Z=$,z=Z.id,G=typeof z==="string"||typeof z==="number"&&Number.isFinite(z);if(typeof Z.method==="string"){if(Z.params!==void 0&&(typeof Z.params!=="object"||Z.params===null||Array.isArray(Z.params)))throw new L(D.InvalidRequest,"params must be an object.",void 0,400);if(z===void 0)return{kind:"notification",message:Z};if(!G)throw new L(D.InvalidRequest,"id must be a string or a number.",void 0,400);return{kind:"request",message:Z}}if(G&&(("result"in Z)||("error"in Z)))return{kind:"response",message:Z};throw new L(D.InvalidRequest,"Not a JSON-RPC request, notification or response.",void 0,400)}function k3($,Z){let z=$.outputSchema?.toJSONSchema(),G={...$.annotations,...$.title&&!Z?{title:$.title}:{}};return{name:$.name,...$.title?{title:$.title}:{},description:$.description,inputSchema:$.inputSchema.toJSONSchema(),...z&&(Z||z.type==="object")?{outputSchema:z}:{},...Object.keys(G).length>0?{annotations:G}:{}}}function q($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function I9($){let Z=/^=\?base64\?([A-Za-z0-9+/]*={0,2})\?=$/.exec($);if(!Z)return $;try{let z=Buffer.from(Z[1],"base64");return new TextDecoder("utf-8",{fatal:!0}).decode(z)}catch{return null}}import{createHmac as t$,timingSafeEqual as o$}from"crypto";function M3($,Z,z){let G=Buffer.from(JSON.stringify(z)).toString("base64url");return`${Z}.${G}.${L9($,Z,G).toString("base64url")}`}function R3($,Z,z,G=Date.now()){if(typeof z!=="string"||z.length>8192)return null;let W=z.split(".");if(W.length!==3||W[0]!==Z)return null;let[,X,Y]=W,K=Buffer.from(Y,"base64url"),Q=L9($,Z,X);if(K.length!==Q.length||!o$(K,Q))return null;let V;try{V=JSON.parse(Buffer.from(X,"base64url").toString("utf8"))}catch{return null}if(typeof V!=="object"||V===null)return null;if(typeof V.exp!=="number"||V.exp<=G)return null;return V}function L9($,Z,z){return t$("sha256",K3($)).update(`${Z}.${z}`).digest()}var E3="gemi.mcp.request-state.v1",D9="gemi.mcp.session.v1",a$=86400000,O9=600000,j9="gemi_approval",b3=2000,r$={limit:600,window:60},e$={limit:30,window:60};class $3{registry;static token="router.mcp.http";endpoint;resolvers;context;allowedOrigins;rateLimit;maxBodyBytes;serverInfo;instructions;nonces;approvalTimeoutMs;onCall;feature;featureOn;pending=new Map;inflight=new Map;constructor($,Z,z={}){this.registry=$;if(typeof Z.url!=="string")throw Error(`route.mcp.remote.url is required: the endpoint's canonical URL, like "https://example.com/mcp".`);this.endpoint=z2(Z.url);let G=Z.resolvers??[];if(!Array.isArray(G)||G.length===0)throw Error("route.mcp.remote is enabled without a caller resolver. Configure route.mcp.remote.resolvers \u2014 an McpOAuthServer, an McpApiKeyResolver, or your own \u2014 or leave the endpoint off. Without one every request would be refused, or answered as nobody.");for(let W of G)if(typeof W?.resolve!=="function"||typeof W.name!=="string"||W.name==="")throw Error("route.mcp.remote.resolvers: each resolver needs a name and a resolve().");if(this.resolvers=G,K3(E3),this.context={resource:this.resource,registry:$},this.allowedOrigins=new Set((Z.allowedOrigins??[]).map((W)=>{if(new URL(W).origin!==W)throw Error(`route.mcp.remote.allowedOrigins: "${W}" is not an origin (scheme://host[:port]).`);return W})),this.allowedOrigins.add(this.endpoint.origin),this.rateLimit=Z.rateLimit===!1?!1:Z.rateLimit??r$,this.maxBodyBytes=Z.maxBodyBytes??Math.ceil($.maxFileBytes*1.4)+1048576,this.serverInfo={name:Z.server?.name??"gemi",version:Z.server?.version??"1.0.0"},this.instructions=Z.server?.instructions,this.nonces=Z.nonces??new k9,this.approvalTimeoutMs=Z.approvalTimeoutMs??O9,Z.onCall!==void 0&&typeof Z.onCall!=="function")throw Error("route.mcp.remote.onCall must be a function.");if(this.onCall=Z.onCall,Z.feature!==void 0){if(typeof Z.feature!=="string"||Z.feature==="")throw Error("route.mcp.remote.feature must be a feature key from app/features.");this.feature=Z.feature}this.featureOn=z.featureOn??X3;for(let W of G)W.boot?.(this.context)}get resource(){return this.endpoint.href.replace(/\/$/,"")}async handle($){let Z=new URL($.url);if(Z.host!==this.endpoint.host)return null;if(this.feature!==void 0){if(!this.ownsPath(Z.pathname))return null;if(await this.featureOn(this.feature)!==!0)return null}for(let W of this.resolvers){let X=await W.handle?.($,this.context);if(X)return X}if(Z.pathname!==this.endpoint.pathname)return null;let z=$.headers.get("origin");if(z!==null&&!this.allowedOrigins.has(z))return f(R(null,new L(D.InvalidRequest,"Origin not allowed.")),403);let G=z?Z2(z):{};if($.method==="OPTIONS")return new Response(null,{status:204,headers:{...G,"Access-Control-Allow-Methods":"POST","Access-Control-Allow-Headers":"Authorization, Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id, Mcp-Method, Mcp-Name, Last-Event-ID","Access-Control-Max-Age":"600"}});if($.method!=="POST")return A9(new Response(null,{status:405,headers:{Allow:"POST, OPTIONS"}}),G);return A9(await this.post($),G)}ownsPath($){let Z=this.endpoint.pathname.replace(/\/$/,"");return $===this.endpoint.pathname||$===Z||$.startsWith(`${Z}/`)||$.startsWith("/.well-known/")}async post($){let Z=null;for(let Y of this.resolvers){let K=await Y.resolve($,this.context);if(K===null)continue;if(K.ok===!1)return await this.failedAttempt($)??this.unauthorized(K.description);Z={...K.principal,via:Y.name};break}if(!Z)return(j3($)!==null?await this.failedAttempt($):null)??this.unauthorized();let z=await this.spend(Z);if(z)return z;let G=$.headers.get("content-type")??"";if(!/^application\/json\s*(;|$)/i.test(G))return new Response("Content-Type must be application/json.",{status:415});let W;try{W=JSON.parse(await $2($,this.maxBodyBytes))}catch(Y){if(Y instanceof V3)return f(R(null,new L(D.InvalidRequest,`The request is larger than ${this.maxBodyBytes} bytes.`)),413);return f(R(null,new L(D.ParseError,"Parse error.")),400)}let X=new m($,{},"api",this.endpoint.pathname);return await h.run(X,async()=>{try{return await this.dispatch($,X,Z,W)}catch(Y){if(Y instanceof L){let K=q(W)&&(typeof W.id==="string"||typeof W.id==="number")?W.id:null;return f(R(K,Y),Y.status)}return console.error("[gemi/mcp] The MCP endpoint failed:",Y),f(R(null,new L(D.InternalError,"Internal error.")),500)}},{user:Z.user})}async dispatch($,Z,z,G){let W=P9(G),X={kind:"remote",req:Z,principal:z};if(W.kind==="response"){let F=this.session($,z),B=this.pending.get(String(W.message.id));if(B&&B.session===F.id)this.pending.delete(String(W.message.id)),B.resolve(W.message);return new Response(null,{status:202})}let{message:Y}=W,K=Y.params??{},Q=q(K._meta)?K._meta:{};if(typeof Q[S3]==="string"){if(this.checkModernHeaders($,Y,Q[S3]),W.kind==="notification")return new Response(null,{status:202});return await this.respond(Y,async(F,B)=>this.modern({principal:z,caller:X,message:Y,params:K,era:{modern:!0},stream:F,signal:B}),C9(K),$.signal)}if(Y.method==="initialize"){if(W.kind!=="request")throw new L(D.InvalidRequest,"initialize is a request.",void 0,400);return this.initialize(W.message,K,z)}let V=this.session($,z),H=$.headers.get("mcp-protocol-version");if(H!==null&&H!==V.state.v)throw new L(D.InvalidRequest,`MCP-Protocol-Version ${H} is not the session's ${V.state.v}.`,void 0,400);if(W.kind==="notification"){if(Y.method==="notifications/cancelled"){let F=K.requestId;this.inflight.get(`${V.id}:${String(F)}`)?.abort()}return new Response(null,{status:202})}let J=`${V.id}:${String(Y.id)}`,I=new AbortController;this.inflight.set(J,I);let U=AbortSignal.any([I.signal,$.signal]);try{return await this.respond(Y,async(F,B)=>this.legacy({principal:z,caller:X,message:Y,params:K,era:{modern:!1,session:V.state,sessionId:V.id},stream:F,signal:B}),C9(K)||W2(this.registry,Y,V.state),U,()=>this.inflight.delete(J))}catch(F){throw this.inflight.delete(J),F}}async modern($){switch($.message.method){case"server/discover":return this.complete({supportedVersions:C3,capabilities:{tools:{}},...this.instructions?{instructions:this.instructions}:{},ttlMs:60000,cacheScope:"private"});case"tools/list":return this.complete({tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!0)),ttlMs:60000,cacheScope:"private"});case"tools/call":return await this.callTool($);default:throw new L(D.MethodNotFound,`Method not found: ${$.message.method}`,void 0,404)}}async legacy($){switch($.message.method){case"ping":return{};case"tools/list":return{tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!1))};case"tools/call":return await this.callTool($);default:throw new L(D.MethodNotFound,`Method not found: ${$.message.method}`)}}complete($){return{resultType:"complete",...$,_meta:{[T3]:this.serverInfo}}}initialize($,Z,z){let G=Z.protocolVersion,W=Y3.includes(G)?G:Y3[0],X=q(Z.capabilities)?Z.capabilities:{},Y={v:W,e:x9(X.elicitation),p:Q3(z),exp:Date.now()+a$},K=M3(D9,"gms1",Y);return f({jsonrpc:"2.0",id:$.id,result:{protocolVersion:W,capabilities:{tools:{listChanged:!1}},serverInfo:this.serverInfo,...this.instructions?{instructions:this.instructions}:{}}},200,{"Mcp-Session-Id":K})}session($,Z){let z=$.headers.get("mcp-session-id");if(!z)throw new L(D.InvalidRequest,"Missing Mcp-Session-Id. Send initialize first, or a request carrying io.modelcontextprotocol/protocolVersion in _meta.",void 0,400);let G=R3(D9,"gms1",z);if(!G||G.p!==Q3(Z))throw new L(D.InvalidRequest,"Session not found.",void 0,404);return{id:z,state:G}}checkModernHeaders($,Z,z){if(!x3.includes(z))throw new L(D.UnsupportedProtocolVersion,"Unsupported protocol version",{supported:C3,requested:z},400);let G=(Y)=>new L(D.HeaderMismatch,`Header mismatch: ${Y}`,void 0,400);if($.headers.get("mcp-protocol-version")!==z)throw G("MCP-Protocol-Version does not match the protocol version in _meta.");if($.headers.get("mcp-method")!==Z.method)throw G("Mcp-Method does not match the method.");let W=Z.params??{},X=Z.method==="tools/call"||Z.method==="prompts/get"?W.name:Z.method==="resources/read"?W.uri:void 0;if(X!==void 0){let Y=$.headers.get("mcp-name");if(Y===null||I9(Y)!==X)throw G("Mcp-Name does not match the request's name.")}}async callTool($){let Z=$.params.name;if(typeof Z!=="string")throw new L(D.InvalidParams,"tools/call needs a tool name.");let z=$.params.arguments??{};if(!this.onCall)return await this.runTool($,Z,z,{approved:!1});let G=performance.now(),W={approved:!1};try{let X=await this.runTool($,Z,z,W);if(!W.pending)await this.report($,Z,z,W,G);return X}catch(X){if(!W.outcome){if(W.outcome="error",W.message=X instanceof L?X.message:"Internal error.",!(X instanceof L))W.error=X}throw await this.report($,Z,z,W,G),X}}async report($,Z,z,G,W){let{principal:X}=$;try{await this.onCall({user:X.user,via:X.via,credentialId:X.id,clientId:X.clientId??null,scopes:X.scopes,tool:Z,arguments:z,outcome:G.outcome??"ok",...G.reason!==void 0?{reason:G.reason}:{},...G.message!==void 0?{message:G.message}:{},...G.status!==void 0?{status:G.status}:{},...G.error!==void 0?{error:G.error}:{},approved:G.approved,durationMs:Math.round((performance.now()-W)*1000)/1000,req:$.caller.req})}catch(Y){console.error(`[gemi/mcp] route.mcp.remote.onCall failed for "${Z}":`,Y)}}async runTool($,Z,z,G){let{caller:W,principal:X}=$,Y=(U,F)=>{G.outcome="denied",G.reason=U,G.message=F},K=(U,F,B)=>{if(G.outcome="error",G.message=U,F!==void 0)G.status=F;if(B!==void 0)G.error=B},Q=(await this.registry.available(W,{names:[Z]}))[0];if(!Q)throw Y("unknown-tool",`Unknown tool: ${Z}`),new L(D.InvalidParams,`Unknown tool: ${Z}`);if(Q.requiresApproval){let U=Q.inputSchema.safeParse(z);if(U.ok===!1){let B=`Invalid arguments for "${Z}": ${U.errors.join(", ")}`;return K(B),this.toolResult($,{content:[{type:"text",text:B}],isError:!0})}if($.era.modern&&q($.params.inputResponses)&&$.params.requestState!==void 0||await this.registry.approvalRequired(W,Z,z,{signal:$.signal})){let B=await this.approval($,Q,z,Y,G);if(B.kind==="answer")return B.result;G.approved=!0}}let V=X2($),H;try{H=await this.registry.execute(W,Z,z,void 0,{approved:G.approved,signal:$.signal,...V?{progress:V}:{}})}catch(U){if(U instanceof O){if(U.status===401||U.status===403)Y("forbidden",U.message),G.status=U.status;else K(U.message,U.status);return this.toolResult($,{content:[{type:"text",text:U.message}],isError:!0})}if(U instanceof v){let B=U.reason==="unknown-tool"?`Unknown tool: ${Z}`:U.message;throw Y(U.reason,B),new L(D.InvalidParams,B)}console.error(`[gemi/mcp] "${Z}" failed for ${X.via}:${X.id}:`,U);let F=`"${Z}" failed on the server.`;return K(F,void 0,U),this.toolResult($,{content:[{type:"text",text:F}],isError:!0})}let J=typeof H==="string"?H:JSON.stringify(H??null),I=Q.outputSchema&&($.era.modern||q(H))?{structuredContent:H}:{};return G.outcome="ok",this.toolResult($,{content:[{type:"text",text:J}],...I,isError:!1})}toolResult($,Z){return $.era.modern?this.complete(Z):Z}async approval($,Z,z,G,W){let X=Y2(Z,z),Y=(I,U="approval-declined")=>{return G(U,I),{kind:"answer",result:this.toolResult($,{content:[{type:"text",text:I}],isError:!0})}},K=(I,U)=>{return G(I,U.message),U};if($.era.modern){let I=q($.params._meta)?$.params._meta:{},U=q(I[q3])?I[q3]:{},F=q($.params.inputResponses)?$.params.inputResponses:null,B=$.params.requestState,T=G2(z);if(F&&B!==void 0){let C=R3(E3,"grs1",B);if(!C||C.p!==Q3($.principal)||C.t!==Z.name||C.a!==T)throw K("approval-invalid",new L(D.InvalidParams,"requestState is not valid for this call."));if(!await this.spendNonce(C.n,C.exp))throw K("approval-replayed",new L(D.InvalidParams,"requestState has already been used."));return S9(F[j9])?{kind:"approved"}:Y(`The user did not approve "${Z.name}", and it did not run.`)}if(!x9(U.elicitation))throw K("approval-unavailable",new L(D.MissingRequiredClientCapability,`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation).`,{requiredCapabilities:{elicitation:{form:{}}}},400));let j={p:Q3($.principal),t:Z.name,a:T,n:_9(16).toString("base64url"),exp:Date.now()+O9};return W.pending=!0,{kind:"answer",result:{resultType:"input_required",inputRequests:{[j9]:{method:"elicitation/create",params:{mode:"form",...X}}},requestState:M3(E3,"grs1",j),_meta:{[T3]:this.serverInfo}}}}let Q=$.era;if(!Q.session.e||!$.stream)return Y(`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation). It did not run.`,"approval-unavailable");let V=`gemi-approval-${_9(12).toString("base64url")}`,H=Q.sessionId,J=await new Promise((I)=>{let U=setTimeout(()=>{this.pending.delete(V),I(null)},this.approvalTimeoutMs),F=(B)=>{clearTimeout(U),I(B)};this.pending.set(V,{session:H,resolve:F}),$.signal.addEventListener("abort",()=>{this.pending.delete(V),F(null)}),$.stream.send({jsonrpc:"2.0",id:V,method:"elicitation/create",params:Q.session.v==="2025-11-25"?{mode:"form",...X}:X})});return J&&!J.error&&S9(J.result)?{kind:"approved"}:Y(`The user did not approve "${Z.name}", and it did not run.`)}async spendNonce($,Z){try{return await this.nonces.consume($,Z)}catch(z){return console.error("[gemi/mcp] Spending an approval failed:",z),!1}}async respond($,Z,z,G,W){if(!z)try{let Q=await Z(null,G);return f({jsonrpc:"2.0",id:$.id,result:Q},200)}finally{W?.()}let X=new AbortController,Y=AbortSignal.any([X.signal,G]),K=new E9(()=>X.abort());return(async()=>{try{let Q=await Z(K,Y);K.send({jsonrpc:"2.0",id:$.id,result:Q})}catch(Q){if(Q instanceof L)K.send(R($.id,Q));else console.error("[gemi/mcp] The MCP endpoint failed:",Q),K.send(R($.id,new L(D.InternalError,"Internal error.")))}finally{W?.(),K.close()}})(),new Response(K.readable,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"}})}unauthorized($){let Z=this.resolvers.map((G)=>G.challenge?.(this.context)).find(Boolean)??'Bearer realm="mcp"',z=$?`${Z}, error="invalid_token", error_description="${$.replace(/["\\]/g,"")}"`:Z;return f(R(null,new L(D.InvalidRequest,"Unauthorized.")),401,{"WWW-Authenticate":z})}async failedAttempt($){let Z=T9(new m($,{},"api",this.endpoint.pathname)),z=await A3(`mcp-auth-failed:${Z}`,e$);return z===null?null:q9(z)}async spend($){if(!this.rateLimit)return null;let Z=await A3(`mcp-endpoint:${$.via}:${$.id}`,this.rateLimit);return Z===null?null:q9(Z)}}class E9{readable;controller;closed=!1;encoder=new TextEncoder;constructor($){this.readable=new ReadableStream({start:(Z)=>{this.controller=Z},cancel:()=>{this.closed=!0,$()}})}send($){if(this.closed)return;this.controller.enqueue(this.encoder.encode(`event: message
|
|
3
3
|
data: ${JSON.stringify($)}
|
|
4
4
|
|
|
5
5
|
`))}close(){if(this.closed)return;this.closed=!0,this.controller.close()}}class V3 extends Error{}async function $2($,Z){let z=Number($.headers.get("content-length"));if(Number.isFinite(z)&&z>Z)throw new V3;if(!$.body)return"";let G=$.body.getReader(),W=[],X=0;for(;;){let{done:Y,value:K}=await G.read();if(Y)break;if(X+=K.byteLength,X>Z)throw await G.cancel(),new V3;W.push(K)}return Buffer.concat(W).toString("utf8")}function f($,Z,z={}){return new Response(JSON.stringify($),{status:Z,headers:{"Content-Type":"application/json","Cache-Control":"no-store",...z}})}function A9($,Z){for(let[z,G]of Object.entries(Z))$.headers.set(z,G);return $}function Z2($){return{"Access-Control-Allow-Origin":$,"Access-Control-Expose-Headers":"Mcp-Session-Id, WWW-Authenticate",Vary:"Origin"}}function z2($){let Z;try{Z=new URL($)}catch{throw Error(`route.mcp.remote.url: "${$}" is not a URL.`)}let z=Z.hostname==="localhost"||Z.hostname==="127.0.0.1"||Z.hostname==="[::1]";if(Z.protocol!=="https:"&&!(Z.protocol==="http:"&&z))throw Error("route.mcp.remote.url must be https (http only on localhost): tokens travel to it.");if(Z.search||Z.hash||Z.username||Z.password)throw Error("route.mcp.remote.url must have no query, fragment or credentials.");if(Z.pathname==="/"||Z.pathname.endsWith("/"))throw Error('route.mcp.remote.url needs a path of its own, like "/mcp", without a trailing slash.');return Z}function Q3($){return R9("sha256").update(`${$.via}\x00${$.id}\x00${$.user?.id}`).digest("base64url").slice(0,32)}function G2($){return R9("sha256").update(M9($??{})).digest("base64url")}function x9($){if(!q($))return!1;if(Object.keys($).length===0)return!0;return"form"in $}function C9($){let Z=q($._meta)?$._meta:{};return typeof Z.progressToken==="string"||typeof Z.progressToken==="number"}function W2($,Z,z){if(Z.method!=="tools/call"||!z.e)return!1;let G=Z.params?.name;return typeof G==="string"&&$.descriptors({names:[G]})[0]?.requiresApproval===!0}function X2($){let z=(q($.params._meta)?$.params._meta:{}).progressToken;if(!$.stream||typeof z!=="string"&&typeof z!=="number")return;let G=-1/0;return(W)=>{if(typeof W?.progress!=="number"||!Number.isFinite(W.progress)||W.progress<=G)return;G=W.progress,$.stream.send({jsonrpc:"2.0",method:"notifications/progress",params:{progressToken:z,progress:W.progress,...typeof W.total==="number"?{total:W.total}:{},...typeof W.message==="string"?{message:W.message.slice(0,1000)}:{}}})}}function Y2($,Z){let z=JSON.stringify(Z??{},null,1),G=z.length>b3?`${z.slice(0,b3)}\u2026 (${z.length-b3} more characters not shown)`:z;return{message:`Allow "${$.title??$.name}" to run? ${$.description}
|
|
@@ -7,4 +7,4 @@ data: ${JSON.stringify($)}
|
|
|
7
7
|
Arguments: ${G}`,requestedSchema:{type:"object",properties:{approve:{type:"boolean",title:"Approve",description:`Run "${$.title??$.name}" with these arguments.`}},required:["approve"]}}}function S9($){return q($)&&$.action==="accept"&&q($.content)&&$.content.approve===!0}function q9($){return f(R(null,new L(D.InvalidRequest,"Rate limit exceeded.")),429,{"Retry-After":String($)})}async function K2($,Z={}){try{if(!await $.shouldRun.call($))return}catch(W){console.error(`Error evaluating shouldRun for cron job ${$.name}:`,W);return}let z=Q2($.withoutOverlapping);if(!$.onOneServer&&z===void 0){await y3($);return}let G;try{if(G=Z.locks?.()??V2(),$.onOneServer){let W=Math.floor((Z.now??Date.now())/60000);if(!await G.store.advance(`gemi:cron-tick:${$.name}`,W))return}}catch(W){console.error(`Could not claim the tick of cron job ${$.name}; skipped it:`,W);return}if(z===void 0){await y3($);return}try{await G.run(`gemi:cron:${$.name}`,{ttl:z},(W)=>y3($,W))}catch(W){if(W instanceof f9)console.error(`Cron job ${$.name} lost its withoutOverlapping lock while running: another tick may have started alongside it.`,W);else console.error(`Could not take the withoutOverlapping lock of cron job ${$.name}:`,W)}}var b9=300000;function Q2($){if(!$)return;if($===!0)return b9;return $.expiresAfter??b9}var y9;function V2(){return y9??=new u(new w9),y9}async function y3($,Z){try{await $.onTick.call($)}catch(z){console.error(`Error executing cron job ${$.name}:`,z)}try{await $.callback.call($,Z)}catch(z){console.error(`Error in cron job ${$.name}:`,z)}try{await $.onComplete.call($)}catch(z){console.error(`Error completing cron job ${$.name}:`,z)}}class d{static token="scheduler";handles=[];resolved;inFlight=new Map;stopped=!1;locks;constructor($){this.resolved=$.jobs}get jobs(){return[...this.resolved]}useJobs($){this.resolved=$}useLocks($){this.locks=$}start($=(Z)=>Z()){if(this.stopped=!1,this.resolved.length===0)return;let Z=globalThis.__gemiCronJobs??=new Map,z=new Map;for(let G of this.resolved){let W=new G;if(!W.name){console.error(`Cron job must have a name \u2014 ${G.name||"an anonymous class"} has none, so it is not scheduled. If this is a base class that other jobs extend, move it out of the discovered directory: \`abstract\` does not survive to runtime, so a class under app/cron is indistinguishable from a job.`);continue}if(!W.cron){console.error(`Cron job must have an expression. Job: ${W.name}`);continue}let X=z.get(W.name);if(X!==void 0){console.error(`Two cron jobs claim the name "${W.name}" \u2014 ${X} is scheduled and ${G.name||"an anonymous class"} is not. A name is the scheduler's key, so only one job can hold it. Rename one.`);continue}z.set(W.name,G.name||"an anonymous class"),Z.get(W.name)?.stop();let Y=Bun.cron(W.cron,()=>{if(this.stopped)return;let K=this.locks;return this.track(W.name,()=>$(()=>K2(W,{locks:K})))});Z.set(W.name,Y),this.handles.push(Y)}}stop(){this.stopped=!0;for(let $ of this.handles)$.stop();this.handles=[]}async drain($=1/0){this.stop();let Z,z=new Promise((G)=>{if($!==1/0)Z=setTimeout(G,$)});return await Promise.race([Promise.allSettled([...this.inFlight.values()].map((G)=>G.done)),z]),clearTimeout(Z),{unfinished:[...this.inFlight.values()].map((G)=>({...G.tick}))}}get running(){return this.inFlight.size}track($,Z){let z={},G=Promise.resolve().then(Z).finally(()=>this.inFlight.delete(z));return this.inFlight.set(z,{tick:{name:$,startedAt:new Date},done:G}),G}}import{isMainThread as H2}from"worker_threads";var U2=100,J2=($)=>Math.min(U2,Math.floor($/10));class F2 extends P{register(){this.app.singleton(x,()=>new x(this.app.config.get("queue",{}),{application:this.app})),this.app.singleton(u,()=>this.app.make(x).locks)}async boot(){let $=this.app.config.get("queue",{}),{jobsDir:Z,workflowsDir:z}=A(v9(),$);if($.jobs===void 0)this.app.make(x).useJobs(await d9(Z));if($.workflows===void 0){let G=await p9(z);if(G.length>0)this.app.make(x).useWorkflows(G)}}async shutdown($){if(!this.app.resolved(x))return;let Z=this.app.make(x);if(Z.running>0)console.log(`[gemi] Shutting down: waiting for ${Z.running} running queued job(s).`);let z=$?.timeoutMs,{unfinished:G}=await Z.drain(z===void 0?1/0:Math.max(0,z-J2(z)));if(G.length>0)return console.error("[gemi] Queued jobs still running at shutdown: "+G.map((W)=>`${W.name} (${W.id})`).join(", ")),{abandoned:!0}}}function u6($){if(B2($),Bun.env.NODE_ENV!=="production")return P2($);if(c9($))return;if(!g9())return;if(!$.bound(x))return;$.make(x).start()}function c9($){let Z=$.config.get("queue",{}).driver??"memory";return Z==="memory"||Z instanceof h9}function N2($){if(c9($))return!0;if(typeof $.config.get("queue",{}).driver!=="function"||!$.bound(x))return!1;try{return!$.make(x).durable}catch{return!1}}function B2($){let Z=process.env.GEMI_QUEUE_CLAIM;if(Z===void 0||u9())return;if(process.env.ROOT_DIR===void 0||!H2)return;if(m9()){if(!N2($))return;console.warn('[gemi] GEMI_QUEUE_CLAIM=off is ignored: the memory queue driver keeps jobs in the process that dispatched them, so no worker could run them. This server runs its own jobs. Use a driver other processes can read, such as "database", to hand jobs to `gemi queue:work`.')}else if(Z.trim().toLowerCase()!=="on")console.warn(`[gemi] GEMI_QUEUE_CLAIM="${Z}" is not "off" or "on", so this server claims jobs. Set it to "off" to leave them to \`gemi queue:work\`.`)}function P2($){let Z=globalThis.__gemiDevQueue;if(!Z)return;if(globalThis.__gemiDevQueue=void 0,Z.stop(),$.bound(x))$.make(x).start()}function I2($){let Z=$.headers.get("Cache-Control")?.toLowerCase()??"";return/(^|[\s,])(public|s-maxage)\b/.test(Z)}var L2=new Set,_2={refusal:null,apply:($)=>$,carried:null};async function $$($){let Z=y(n);if(Z.config.global.length===0)return _2;let{pathname:z}=new URL($.url),G=s9(z),W=new m($,{},G?"api":"view","");return await h.run(W,async()=>{let X=h.getStore(),{headers:Y,cookies:K}=X,Q=(V)=>{if(!I2(V))return w3(V,Y,K);let H=new Headers(Y);return H.delete("Set-Cookie"),w3(V,H,L2)};try{return await Z.runGlobalMiddleware(),{refusal:null,apply:Q,carried:{user:X.user,state:W.state}}}catch(V){let H=!G&&z.endsWith(".json");if(V?.kind===i9){let J=G?e9(V.payload.api):H?a9(V.payload.viewData??V.payload.api):f3(V.payload.view);return{refusal:Q(J),apply:Q,carried:null}}if(l9(V)&&(G||H))return{refusal:Q(r9()),apply:Q,carried:null};if(n9(V)){console.error(V);let J=G||H?t9():f3(o9());return{refusal:Q(J),apply:Q,carried:null}}throw V}finally{X.destroy()}})}var D2=120,O2=2000,j2=3;class t{manager;application;static token="broadcast.sockets";server=null;sockets=new Set;byTopic=new Map;topicReady=new Map;perIp=new Map;perUser=new Map;connections=0;revocationSeq=0;revokedAt=new Map;closing=!1;closed=null;onAllClosed=null;startPromise=null;constructor($,Z){this.manager=$;this.application=Z}get config(){return this.manager.config}matches($){try{return new URL($.url).pathname===this.config.path}catch{return!1}}get size(){return this.sockets.size}start($){return this.server=$,this.startPromise??=this.manager.start((Z,z)=>this.deliver(Z,z),{onGap:()=>this.onGap(),onRevoke:(Z)=>this.applyRevocation(Z)}).catch((Z)=>{this.startPromise=null,console.error("[gemi] The broadcast driver could not start; events reach no socket.",Z)}),this.startPromise}upgrade($,Z){return this.run(()=>this.tryUpgrade($,Z))}async tryUpgrade($,Z){if(this.closing||h3())return b(503,"The server is restarting.",{"Retry-After":"5"});if($.method!=="GET"||$.headers.get("upgrade")?.toLowerCase()!=="websocket")return b(426,"This endpoint only accepts WebSocket upgrades.",{Upgrade:"websocket"});if(!($.headers.get("sec-websocket-protocol")??"").split(",").map((K)=>K.trim()).includes(H3))return b(400,`Open the socket with the "${H3}" subprotocol.`);let G=this.checkOrigin($);if(G!==!0)return b(403,G);if(this.connections>=this.config.maxConnectionsPerProcess)return b(503,"Too many connections.",{"Retry-After":"10"});let W=S2($,Z);if(W&&(this.perIp.get(W)??0)>=this.config.maxConnectionsPerIp)return b(429,"Too many connections from this address.",{"Retry-After":"30"});let X=this.reserve(W),Y=!1;try{let K=await this.authenticate($,Z,X);return Y=K===void 0,K}finally{if(!Y)this.release(X)}}async authenticate($,Z,z){let G=await $$($);if(G.refusal)return G.refusal;let W=G.carried;if(this.closing||h3())return b(503,"The server is restarting.",{"Retry-After":"5"});let X;try{let H=new m($,{},"api",this.config.path);X=await h.run(H,async()=>{let J=h.getStore();try{return await X$(H)}finally{J.destroy()}},W)}catch(H){return console.error("[gemi] Resolving the session of a socket upgrade failed.",H),b(503,"The session could not be checked.",{"Retry-After":"5"})}let Y=C2(X);if(Y&&(this.perUser.get(Y)??0)>=this.config.maxConnectionsPerUser)return b(429,"Too many connections for this user.",{"Retry-After":"30"});if(Y)z.userId=Y,this.perUser.set(Y,(this.perUser.get(Y)??0)+1);let K=W$(),Q={gemiSocket:!0,hub:this,socketId:K,tag:G$(K),request:{url:$.url,headers:[...$.headers]},carried:W,userId:Y,ip:z.ip,subs:new Map,topics:new Map,rate:{windowStart:Date.now(),subs:0,pings:0},reservation:z,closing:!1,closed:!1};if(!Z.upgrade($,{headers:{"Sec-WebSocket-Protocol":H3},data:Q}))return b(400,"The WebSocket upgrade failed.");return}checkOrigin($){let Z=$.headers.get("origin"),z=Boolean($.headers.get("cookie"));if(!Z)return z?"A socket that carries cookies must send an Origin header.":!0;return this.originAllowed(Z,$)?!0:"This origin may not open a socket."}originAllowed($,Z){let z;try{z=new URL($)}catch{return!1}if(z.protocol!=="https:"&&z.protocol!=="http:")return!1;let G=Z.headers.get("host");if(G&&z.host.toLowerCase()===G.toLowerCase())return!0;for(let W of[process.env.APP_URL,process.env.HOST_NAME,...this.config.allowedOrigins])if(W&&A2(W.trim(),z))return!0;return!1}reserve($){if(this.connections++,$)this.perIp.set($,(this.perIp.get($)??0)+1);return{ip:$,userId:null}}release($){this.connections--,Z$(this.perIp,$.ip),Z$(this.perUser,$.userId)}get websocket(){return{open:($)=>$.data.hub.onOpen($),message:($,Z)=>$.data.hub.onMessage($,Z),close:($)=>$.data.hub.onClose($),...this.socketOptions()}}socketOptions(){return{maxPayloadLength:this.config.maxInboundMessageBytes,idleTimeout:this.config.idleTimeout,backpressureLimit:this.config.backpressureLimit*2,closeOnBackpressureLimit:!0,sendPings:!0,perMessageDeflate:!1}}onOpen($){let Z=$.data;if(this.closing){this.sayBye($);return}this.sockets.add($),s($,{op:"hello",socketId:Z.socketId,tag:Z.tag,heartbeatMs:this.config.heartbeatMs})}onMessage($,Z){if(typeof Z!=="string"){$.close(k.UnsupportedData,"Frames are JSON text.");return}if(Z.length>this.config.maxInboundMessageBytes){$.close(k.PolicyViolation,"Frame too large.");return}let z;try{z=JSON.parse(Z)}catch{$.close(k.UnsupportedData,"Frames are JSON text.");return}switch(z?.op){case"ping":if(this.countPing($))s($,{op:"pong"});return;case"sub":this.subscribe($,z).catch((G)=>{if(console.error("[gemi] A socket subscription failed.",G),typeof z.id==="string"&&$.data.subs.has(z.id)){let W=$.data.subs.get(z.id);if($.data.subs.delete(z.id),W.topic&&!$.data.closed)this.leave($,W.topic);if(!$.data.closed)E($,z.id,"error")}});return;case"unsub":this.unsubscribeFrame($,z);return;default:$.close(k.UnsupportedData,"Unknown op.")}}onClose($){let Z=$.data;if(Z.closed)return;Z.closed=!0;for(let[,z]of Z.subs)if(z.topic)this.leave($,z.topic);if(Z.subs.clear(),this.sockets.delete($),Z.reservation)this.release(Z.reservation),Z.reservation=null;if(this.closing&&this.sockets.size===0)this.onAllClosed?.()}rateWindow($){let Z=$.data.rate,z=Date.now();if(z-Z.windowStart>=this.config.subscribeRate.windowMs)Z.windowStart=z,Z.subs=0,Z.pings=0;return Z}countSub($){let{limit:Z}=this.config.subscribeRate,z=this.rateWindow($);if(z.subs++,z.subs>Z*2)return console.warn("[gemi] Socket closed for sending too many subscribe frames (1008)."),$.close(k.PolicyViolation,"Too many subscribe frames."),"closed";return z.subs>Z?"limited":"ok"}countPing($){let Z=this.rateWindow($);if(Z.pings++,Z.pings<=D2)return!0;return $.close(k.PolicyViolation,"Too many pings."),!1}async subscribe($,Z){let z=$.data,G=Z.id;if(typeof G!=="string"||!g3.test(G)){$.close(k.UnsupportedData,"A sub needs an id.");return}let W=this.countSub($);if(W==="closed")return;if(W==="limited")return E($,G,"rate_limited");let X=Z.ch,Y=Z.p??{};if(typeof X!=="string"||!x2(Y))return E($,G,"invalid");if(z.subs.has(G))return E($,G,"invalid");if(z.subs.size>=this.config.maxChannelsPerSocket)return E($,G,"limit");let K={pattern:X,params:Y,topic:null};if(z.subs.set(G,K),!this.manager.channels)return z.subs.delete(G),E($,G,"unknown_channel");let Q;for(let V=1;;V++){let H=this.revocationSeq;if(Q=await this.authorize($,K),z.closed||z.subs.get(G)!==K)return;if(Q.ok!==!0)break;if((this.revokedAt.get(Q.topic)??0)<=H)break;if(V>=j2)return z.subs.delete(G),E($,G,"error")}if(Q.ok!==!0)return z.subs.delete(G),E($,G,Q.code);K.topic=Q.topic;try{await this.join($,Q.topic)}catch(V){if(console.error(`[gemi] The broadcast driver could not subscribe to "${Q.topic}".`,V),z.subs.get(G)===K){if(z.subs.delete(G),!z.closed)this.leave($,Q.topic);E($,G,"error")}return}if(z.closed||z.subs.get(G)!==K)return;s($,{op:"subscribed",id:G,t:Q.topic})}authorize($,Z){let z=$.data,G=this.manager.channels;if(!G)return Promise.resolve({ok:!1,code:"unknown_channel"});return this.run(()=>G.authorize(new Request(z.request.url,{headers:z.request.headers}),Z.pattern,Z.params,{carried:z.carried}))}unsubscribeFrame($,Z){let z=Z.id;if(typeof z!=="string"||!g3.test(z)){$.close(k.UnsupportedData,"An unsub needs an id.");return}let G=$.data.subs.get(z);if(!G)return;if($.data.subs.delete(z),G.topic)this.leave($,G.topic)}join($,Z){let z=$.data,G=z.topics.get(Z)??0;if(z.topics.set(Z,G+1),G===0){$.subscribe(Z);let W=this.byTopic.get(Z);if(!W){W=new Set,this.byTopic.set(Z,W);let X=Promise.resolve().then(()=>this.manager.topicAdded(Z));this.topicReady.set(Z,X),X.catch(()=>{if(this.topicReady.get(Z)===X)this.topicReady.delete(Z)})}W.add($)}return this.topicReady.get(Z)??Promise.resolve()}leave($,Z){let z=$.data,G=z.topics.get(Z)??0;if(G>1){z.topics.set(Z,G-1);return}if(z.topics.delete(Z),!z.closed)$.unsubscribe(Z);let W=this.byTopic.get(Z);if(!W)return;if(W.delete($),W.size>0)return;this.byTopic.delete(Z),this.topicReady.delete(Z),Promise.resolve().then(()=>this.manager.topicRemoved(Z)).catch((X)=>console.error(`[gemi] The broadcast driver could not unsubscribe from "${Z}".`,X))}deliver($,Z){let z=this.byTopic.get($);if(!z||!this.server)return;let G=this.config.backpressureLimit;for(let W of z)if(!W.data.closing&&W.getBufferedAmount()>G)console.warn(`[gemi] Socket closed for backpressure (1013) on "${$}".`),v3(W,k.TryAgainLater,"Too far behind; reconnect.");this.server.publish($,Z)}onGap(){this.sendAll({op:"gap"});for(let $ of this.byTopic.keys()){let Z=Math.floor(Math.random()*O2);setTimeout(()=>{if(!this.closing)this.applyRevocation({topic:$})},Z).unref?.()}}applyRevocation($){if("user"in $){for(let W of this.sockets)if(W.data.userId===$.user&&!W.data.closing)v3(W,k.Revoked,"Revoked.");return}let Z=$.topic,z=++this.revocationSeq;this.revokedAt.set(Z,z);let G=this.byTopic.get(Z);if(!G)return;for(let W of G)this.reauthorize(W,Z,z)}async reauthorize($,Z,z){let G=$.data,W=[...G.subs].filter(([,Y])=>Y.topic===Z);if(W.length===0)return;$.unsubscribe(Z);let X=await Promise.all(W.map(([,Y])=>this.authorize($,Y).catch((K)=>{return console.error(`[gemi] Authorizing "${Z}" again after a revoke failed.`,K),{ok:!1,code:"revoked"}})));if(G.closed)return;if(this.revokedAt.get(Z)!==z)return;if(W.forEach(([Y,K],Q)=>{let V=X[Q];if(G.subs.get(Y)!==K)return;if(V.ok===!0&&V.topic===Z)return;G.subs.delete(Y),this.leave($,Z),E($,Y,"revoked")}),!G.topics.has(Z))return;$.subscribe(Z);for(let[Y,K]of G.subs)if(K.topic===Z)s($,{op:"subscribed",id:Y,t:Z})}sendAll($){let Z=JSON.stringify($);for(let z of this.sockets)z.send(Z)}shutdown($={}){if(this.closed)return this.closed;this.closing=!0,this.closed=new Promise((G)=>{this.onAllClosed=G});let Z=[...this.sockets];if(Z.length===0)this.onAllClosed?.();if(Z.length>0)console.log(`[gemi] Closing ${Z.length} broadcast socket(s) (1012).`);for(let G of Z)this.sayBye(G);return setTimeout(()=>{for(let G of Z)try{G.terminate()}catch{}this.onAllClosed?.()},$.terminateAfterMs??2000).unref?.(),this.closed}get isClosing(){return this.closing}sayBye($){s($,{op:"bye",code:k.Restart,retryAfter:1000+Math.floor(Math.random()*4000)}),v3($,k.Restart,"Server restarting.")}run($){return U3.run(this.application,$)}}function A2($,Z){let z=/^(?:(https?):\/\/)?\*\.([^/:]+)(?::(\d+))?\/?$/i.exec($);if(z){let[,G,W,X]=z;if(G&&`${G.toLowerCase()}:`!==Z.protocol)return!1;if((X??"")!==Z.port)return!1;return Z.hostname.toLowerCase().endsWith(`.${W.toLowerCase().replace(/\.$/,"")}`)}if(/^https?:\/\//i.test($))try{return new URL($).origin===Z.origin}catch{return!1}return $.toLowerCase().replace(/\/$/,"")===Z.host.toLowerCase()}function v3($,Z,z){$.data.closing=!0,$.close(Z,z)}function s($,Z){$.send(JSON.stringify(Z))}function E($,Z,z){s($,{op:"denied",id:Z,code:z})}function b($,Z,z={}){return new Response(Z,{status:$,headers:{"Content-Type":"text/plain; charset=utf-8",...z}})}function x2($){if(typeof $!=="object"||$===null||Array.isArray($))return!1;return Object.values($).every((Z)=>typeof Z==="string"||typeof Z==="number")}function C2($){let Z=$?.id;return typeof Z==="string"||typeof Z==="number"?String(Z):null}function S2($,Z){let z=$.headers.get("x-forwarded-for")?.split(",")[0]?.trim();if(z)return z$(z)??z;try{return Z.requestIP($)?.address??null}catch{return null}}function Z$($,Z){if(!Z)return;let z=($.get(Z)??0)-1;if(z<=0)$.delete(Z);else $.set(Z,z)}class q2 extends P{register(){this.app.singleton(w,()=>new w(this.app.config.get("broadcast",{}),{application:this.app,channels:this.app.config.get("route.channels")})),this.app.singleton(t,()=>new t(this.app.make(w),this.app))}boot(){let $=this.app.config.get("route.channels");if($)K$(new $);let Z=this.app.config.get("broadcast",{}),z=typeof Z.driver==="function"||typeof Z.driver==="object"?this.app.make(w).driver:void 0;T2(Z,process.env,z)}async shutdown(){if(this.app.resolved(t))this.app.make(t).shutdown();if(!this.app.resolved(w))return;await this.app.make(w).close()}}function T2($,Z=process.env,z){if(!($.driver==="redis"||z instanceof Y$)||Z.SECRET)return;let W=`[gemi] The "redis" broadcast driver needs SECRET set, the same on every instance: Broadcast.toOthers tags the sender's socket with a key derived from it, and every instance must derive the same one.`;if(Z.NODE_ENV==="production")throw Error(W);console.warn(W)}class k2 extends P{register(){this.app.singleton(m3,()=>new m3(this.app.config.get("cache",{}),{application:this.app}))}}class M2 extends P{register(){this.app.singleton(Z3,()=>new Z3(this.app.config.get("changeFeed",{}),{application:this.app}))}async shutdown(){if(!this.app.resolved(Z3))return;await this.app.make(Z3).close()}}class R2 extends P{register(){this.app.singleton(d3,()=>new d3(this.app.config.get("auth",{}))),this.app.singleton(u3,()=>{let $=this.app.config.get("auth",{});return new u3({providers:$.connections??{},store:$.connectionStore??void 0})})}boot(){Q$(this.app.config.get("auth",{}))}}var E2=100,b2=($)=>Math.min(E2,Math.floor($/10));class y2 extends P{register(){this.app.singleton(d,()=>new d(A(p3(),this.app.config.get("schedule",{}))))}async boot(){let $=this.app.make(d),Z=this.app.config.get("schedule",{});if(Z.jobs===void 0){let{jobsDir:G}=A(p3(),Z);$.useJobs(await V$(G))}if(process.env.GEMI_NO_SCHEDULE==="1")return;let z=this.app;if(z.bound(u))$.useLocks(()=>z.make(u));$.start((G)=>U3.run(z,G))}async shutdown($){if(!this.app.resolved(d))return;let Z=this.app.make(d);if(Z.running>0)console.log(`[gemi] Shutting down: waiting for ${Z.running} running cron tick(s).`);let z=$?.timeoutMs,{unfinished:G}=await Z.drain(z===void 0?1/0:Math.max(0,z-b2(z)));if(G.length>0)return console.error("[gemi] Cron jobs still running at shutdown: "+G.map((W)=>`${W.name} (started ${W.startedAt.toISOString()})`).join(", ")),{abandoned:!0}}}class o extends H${modelName;constructor($="FeatureFlag"){super();this.modelName=$}get available(){return U$(this.modelName)}async load(){if(!this.available)throw new c3(this.modelName);let $=i3(this.modelName);return await $.asSystem(()=>$.findMany())}async write($,Z,z){if(!this.available)throw new c3(this.modelName);let G=i3(this.modelName),W=this.hasActorColumn(G),X={active:Z};if(W)X.updatedBy=z.actor;return await G.asSystem(()=>G.upsert({where:{key:$},create:{key:$,...X},update:X})),{actorRecorded:W}}hasActorColumn($){let Z=$?.$schema?.fields?.updatedBy;return Z!==void 0&&Z.type==="String"}}function m8($){return $}function J$(){return{features:void 0,enabled:!0,source:new o,model:"FeatureFlag",ttl:30,context:void 0,onEvaluate:void 0,maxClientFlags:200}}class f2 extends P{register(){this.app.singleton(J3,()=>{let $=this.app.config.get("features",{}),Z=A(J$(),$);if($?.model!==void 0&&$?.source===void 0)Z.source=new o($.model);else if($?.model!==void 0&&$.source instanceof o&&$.source.modelName!==$.model)F3.warning(`app/config/features.ts sets \`model: "${$.model}"\` and a source reading "${$.source.modelName}". The source wins; drop \`model\` to silence this.`);return new J3(Z,(z)=>F3.warning(z))})}async boot(){let $=this.app.make(J3);if(!$.config.enabled)return;try{await $.refresh()}catch(Z){F3.error(`Could not warm the feature flag cache at boot. ${Z instanceof Error?Z.message:String(Z)}`)}}}class w2 extends P{register(){this.app.singleton(l3,()=>new l3(this.app.config.get("mail",{})))}}class v2 extends P{register(){this.app.singleton(N3,()=>new N3(this.app.config.get("encryption",{})))}boot(){if(this.app.make(N3).configured)return;let Z=this.app.config.get("auth",{}),z=Object.keys(Z?.connections??{});if(z.length>0&&!Z?.connectionStore)throw new n3(`auth.connections (${z.join(", ")}) keeps OAuth tokens encrypted, but no encryption key is configured. Add app/config/encryption.ts (defineEncryptionConfig({ keys: { k1: process.env.APP_ENCRYPTION_KEY } })) and list it as \`encryption\` in your Kernel's config. Generate a key with \`openssl rand -base64 32\`.`);let G=F$();if(G.length===0)return;throw new n3(`${G.join(", ")} ${G.length===1?"is an encrypted column":"are encrypted columns"}, but no encryption key is configured. Add app/config/encryption.ts (defineEncryptionConfig({ keys: { k1: process.env.APP_ENCRYPTION_KEY } })) and list it as \`encryption\` in your Kernel's config. Generate a key with \`openssl rand -base64 32\`.`)}}var h2=Symbol.for("gemi.broadcastEvent");function N$($){return typeof $==="object"&&$!==null&&$[h2]===!0}function g2($){return`listener:${$}`}function P$($,Z){m2($);let{maxAttempts:z,backoff:G,worker:W}=Z,X=$.event.name,Y=class extends B${maxAttempts=z;backoff=G;worker=W;async run(...K){let[Q,V]=u2(K),H=y(p).rehydrate(Q,V);await new $().handle(H)}onFail(K){console.error(`The listener ${$.name} threw while handling ${X} off the queue. The queue will retry it up to ${z} times in total; nothing the dispatcher did is waiting on it.`,K)}onDeadletter(K){console.error(`The listener ${$.name} failed every one of its ${z} attempts at ${X} and has been dead-lettered, so this side effect did not happen and will not be retried.`,K)}};return Object.defineProperty(Y,"name",{value:g2($.name),writable:!0}),Y}function m2($){if(Object.getOwnPropertyDescriptor($,"name")?.writable)return;throw Error(`The listener ${$.name} sets \`queued = true\` but does not declare \`static name\`, so it would be registered with the queue `+"under its class name \u2014 which a production build renames while the "+`payload that names it does not. Add: static name = "${$.name}";`)}function u2($){return typeof $[0]==="string"?$:$[0]}class p{static token="events";listeners={};events={};warnedFor=new Set;warnedAboutWaiting=new Set;config;constructor($={}){this.config=A(B3(),$),this.useListeners(this.config.listeners)}useListeners($){this.config.listeners=$,this.listeners={},this.events={};let Z=new Set;for(let z of $){if(!z.event){console.error(`Listener ${z.name} does not declare \`static event\`, so there is no event name to register it under and its handle will never run. Add: static event = SomeEvent;`);continue}if(Z.has(z.name)){console.error(`Two event listeners are named "${z.name}" \u2014 the first is `+"registered and this one is not. A listener's name identifies it across the framework, so only one class can hold it. Rename one.");continue}Z.add(z.name);let G=z.event.name,W=new z;this.events[G]??=z.event,(this.listeners[G]??=[]).push({listener:z,job:W.queued?P$(z,W):null})}}get queuedListenerJobs(){return Object.values(this.listeners).flat().flatMap(({job:$})=>$?[$]:[])}get registeredListeners(){return[...this.config.listeners]}dispatch($,Z){if(this.deferToCommit($,Z,!1))return;this.runListeners($,Z)}async dispatchAndWait($,Z){if(this.deferToCommit($,Z,!0))return;return this.runListeners($,Z)}deferToCommit($,Z,z){let{name:G,afterCommit:W}=$.constructor;if(!W)return!1;let X=I$(()=>this.runListeners($,Z));if(X&&z)this.warnNothingIsWaitedFor(G);return X}async runListeners($,Z){let z=$.constructor.name,G=this.listeners[z]??[],W=N$($);if(G.length===0&&!W){this.warnNothingIsListening(z);return}for(let{listener:X,job:Y}of G){if(Y){this.enqueue(Y,X,z,Z);continue}try{await new X().handle($)}catch(K){console.error(`The listener ${X.name} threw while handling ${z}. The `+"listeners after it still ran \u2014 a listener's failure is its own.",K)}}if(W)this.broadcast($,z)}broadcast($,Z){try{y(w).broadcastEvent($)}catch(z){console.error(`The event ${Z} could not be broadcast.`,z)}}rehydrate($,Z=[]){let z=this.events[$];if(!z)throw Error(`Cannot rebuild the event "${$}" that came off the queue: no registered listener binds to an event of that name, so there is no class to construct. A queued listener runs in an application that `+"discovered its own listeners \u2014 check that this process sees the "+`same app/listeners as the one that dispatched, and that the event declares \`static name = "${$}"\`.`);return new z(...Z)}enqueue($,Z,z,G){if(G===void 0){console.error(`The listener ${Z.name} is queued, but ${z} reached the dispatcher without its constructor arguments, so there is nothing for the queue to rebuild it from and the listener was skipped. Dispatch through ${z}.dispatch(...) or ${z}.dispatchAndWait(...), which carry them.`);return}let W=(X)=>console.error(`The listener ${Z.name} could not be queued for ${z}, so it did not run and will not be retried. The listeners after it still ran.`,X);try{y(x).push($,JSON.stringify([z,G]),{reportFailure:!1}).catch(W)}catch(X){W(X)}}warnNothingIsWaitedFor($){if(Bun.env.NODE_ENV==="production")return;if(this.warnedAboutWaiting.has($))return;this.warnedAboutWaiting.add($),console.warn(`[gemi] ${$}.dispatchAndWait() was called inside a transaction and ${$} declares \`static afterCommit = true\`, so it resolved `+"immediately with no listener having run \u2014 they run when the "+"transaction commits. Await the transaction instead, or drop afterCommit if the caller needs the side effects first. Development only.")}warnNothingIsListening($){if(Bun.env.NODE_ENV==="production")return;if(this.warnedFor.has($))return;this.warnedFor.add($),console.warn(`[gemi] ${$} was dispatched and nothing is listening for it. A listener registers under the name its event declares, so check that app/listeners holds a Listener with \`static event = ${$}\` and that ${$} declares \`static name = "${$}"\`. Development only.`)}}class d2 extends P{register(){this.app.singleton(p,()=>new p(this.app.config.get("events",{})))}async boot(){let $=this.app.make(p),Z=this.app.config.get("events",{});if(Z.listeners===void 0){let{listenersDir:W}=A(B3(),Z);$.useListeners(await L$(W))}let z=$.queuedListenerJobs;if(z.length===0)return;let G=this.app.make(x);for(let W of z)G.registerJob(W)}}class p2 extends P{register(){this.app.singleton(s3,()=>new s3(this.app.config.get("filesystem",{})))}}class c2 extends P{register(){this.app.singleton(t3,()=>new t3(this.app.config.get("image",{})))}}class i2 extends P{register(){this.app.instance(o3,new o3)}}function bZ($){return $}function _$(){let $=Bun.env.NODE_ENV==="development";return{maxFileSize:10485760,console:$,consoleFormat:$?"text":"json",onLogFileClosed:()=>{},onLogCreated:()=>{}}}class l2 extends P{register(){this.app.singleton(P3,()=>new P3(A(_$(),this.app.config.get("log",{}))))}async boot(){if(!process.env.ROOT_DIR)return;await this.app.make(P3).boot()}}class n2 extends P{register(){this.app.singleton(n,()=>new n(A(D$(),this.app.config.get("middleware",{}))))}boot(){this.app.make(n).assertGlobalMiddleware()}}function lZ($){return $}function j$(){return{driver:new O$,limit:1000,window:60}}class s2 extends P{register(){this.app.singleton(l,()=>new l(A(j$(),this.app.config.get("ratelimiter",{}))))}}function eZ($){return $}function A$(){return{url:process.env.REDIS_URL,options:void 0}}class t2 extends P{register(){this.app.singleton(z3,()=>new z3(A(A$(),this.app.config.get("redis",{}))))}shutdown(){if(!this.app.resolved(z3))return;this.app.make(z3).close()}}function I3($,Z){let z=$.get(Z);if(!z)throw Error(`Missing "${Z}" configuration. Route dispatching needs a root router \u2014 declare it in "app/config/route.ts".`);return z}class o2 extends P{register(){this.app.singleton(a,()=>new a(I3(this.app.config,"route.api"))),this.app.singleton(G3,()=>new G3(I3(this.app.config,"route.view"))),this.app.singleton(L3,()=>new L3({api:this.app.make(a),view:this.app.make(G3)},{api:I3(this.app.config,"route.api"),view:I3(this.app.config,"route.view"),domains:this.app.config.get("route.domains"),clientIpTrust:x$(process.env)})),this.app.singleton(i,()=>{let $=this.app.config.get("route.mcp");if(!$?.router)throw Error('No MCP router is configured. Declare one as `mcp: { router }` in "app/config/route.ts".');return new i(new $.router,this.app.make(a),{files:$.remote?.files})}),this.registerMcpHttp()}registerMcpHttp(){this.app.singleton($3,()=>{let $=this.app.config.get("route.mcp");if(!$?.remote?.enabled)throw Error("The MCP endpoint is not enabled: set route.mcp.remote.enabled.");return new $3(this.app.make(i),$.remote)})}boot(){if(this.app.make(a),this.app.make(G3),this.app.make(L3),this.app.config.get("route.mcp"))this.app.make(i);let $=this.app.config.get("route.mcp.remote");if($?.enabled===!0)this.app.make($3);else if($?.enabled!==void 0&&$.enabled!==!1)throw Error("route.mcp.remote.enabled must be true or false.")}}class a2 extends P{register(){this.app.singleton(a3,()=>new a3(this.app.config.get("runs",{}),{application:this.app}))}}
|
|
8
8
|
export{C$ as db,O as eb,v as fb,X6 as gb,i as hb,j3 as ib,n$ as jb,A3 as kb,M3 as lb,R3 as mb,$3 as nb,d as ob,F2 as pb,u6 as qb,$$ as rb,t as sb,q2 as tb,k2 as ub,M2 as vb,R2 as wb,y2 as xb,o as yb,m8 as zb,J$ as Ab,f2 as Bb,w2 as Cb,v2 as Db,h2 as Eb,N$ as Fb,p as Gb,d2 as Hb,p2 as Ib,c2 as Jb,i2 as Kb,bZ as Lb,_$ as Mb,l2 as Nb,n2 as Ob,lZ as Pb,j$ as Qb,s2 as Rb,eZ as Sb,A$ as Tb,t2 as Ub,o2 as Vb,a2 as Wb};
|
|
9
9
|
|
|
10
|
-
//# debugId=
|
|
10
|
+
//# debugId=0E309CA23ED68F2F64756E2164756E21
|