gemi 0.100.0 → 0.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/ai/Schema.d.ts +59 -5
  2. package/dist/ai/Schema.d.ts.map +1 -1
  3. package/dist/ai/index.d.ts +1 -1
  4. package/dist/ai/index.d.ts.map +1 -1
  5. package/dist/ai/index.js +13 -13
  6. package/dist/ai/index.js.map +3 -3
  7. package/dist/chunk-23mpa8t7.js +5 -0
  8. package/dist/{chunk-jv38q9n7.js.map → chunk-23mpa8t7.js.map} +3 -3
  9. package/dist/chunk-4x41cmg3.js +9 -0
  10. package/dist/chunk-4x41cmg3.js.map +31 -0
  11. package/dist/chunk-9hs7prvj.js +17 -0
  12. package/dist/{chunk-rc4z7ykq.js.map → chunk-9hs7prvj.js.map} +4 -4
  13. package/dist/{chunk-q2r6b35k.js → chunk-hr0m35tr.js} +1 -1
  14. package/dist/{chunk-kgckt396.js → chunk-mb8chren.js} +2 -2
  15. package/dist/{chunk-kgckt396.js.map → chunk-mb8chren.js.map} +1 -1
  16. package/dist/{chunk-vdynb16s.js → chunk-md8hmejq.js} +1 -1
  17. package/dist/facades/index.js +1 -1
  18. package/dist/http/McpRouter.d.ts +126 -11
  19. package/dist/http/McpRouter.d.ts.map +1 -1
  20. package/dist/http/index.js +1 -1
  21. package/dist/i18n/index.js +1 -1
  22. package/dist/kernel/index.js +1 -1
  23. package/dist/server/index.js +1 -1
  24. package/dist/services/index.d.ts +2 -2
  25. package/dist/services/index.d.ts.map +1 -1
  26. package/dist/services/index.js +1 -1
  27. package/dist/services/mcp/McpRegistry.d.ts +56 -3
  28. package/dist/services/mcp/McpRegistry.d.ts.map +1 -1
  29. package/dist/services/mcp/toAgentTools.d.ts +57 -1
  30. package/dist/services/mcp/toAgentTools.d.ts.map +1 -1
  31. package/dist/services/router/ApiRouteDispatcher.d.ts +27 -1
  32. package/dist/services/router/ApiRouteDispatcher.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/dist/chunk-h15bd9vn.js +0 -9
  35. package/dist/chunk-h15bd9vn.js.map +0 -31
  36. package/dist/chunk-jv38q9n7.js +0 -5
  37. package/dist/chunk-rc4z7ykq.js +0 -17
  38. /package/dist/{chunk-q2r6b35k.js.map → chunk-hr0m35tr.js.map} +0 -0
  39. /package/dist/{chunk-vdynb16s.js.map → chunk-md8hmejq.js.map} +0 -0
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ import{zb as SZ}from"./chunk-wc46df4w.js";import{Lb as u,Nb as w,Pb as zZ,Qb as XZ,Sb as qZ}from"./chunk-3tn480wt.js";import{$b as GZ,Tb as e,Wb as CZ,Yb as ZZ,Zb as $Z,_b as P,ac as WZ,cc as HZ}from"./chunk-z8jf7jwg.js";import{fc as I}from"./chunk-7kedxtbp.js";import{$c as IZ,Cd as S,Dd as m,Ec as OZ,Ed as c,ad as d,ed as M,md as s,nd as b,rd as n,tc as NZ,xc as t,yd as R}from"./chunk-9hs7prvj.js";import{Md as YZ,Nd as p}from"./chunk-bf1q3m7a.js";import{df as g,sf as i,uf as f,vf as j,wf as T}from"./chunk-4x41cmg3.js";import{Ff as a,Hf as Q}from"./chunk-br9p390p.js";import{Nf as BZ}from"./chunk-n4807648.js";import{vg as U}from"./chunk-3fr22rtg.js";import{Bg as l}from"./chunk-77kw61f4.js";import{Hg as KZ,Kg as y}from"./chunk-48dek9s7.js";async function EZ(Z,$={}){try{if(!await Z.shouldRun.call(Z))return}catch(W){console.error(`Error evaluating shouldRun for cron job ${Z.name}:`,W);return}let G=RZ(Z.withoutOverlapping);if(!Z.onOneServer&&G===void 0){await h(Z);return}let H;try{if(H=$.locks?.()??DZ(),Z.onOneServer){let W=Math.floor(($.now??Date.now())/60000);if(!await H.store.advance(`gemi:cron-tick:${Z.name}`,W))return}}catch(W){console.error(`Could not claim the tick of cron job ${Z.name}; skipped it:`,W);return}if(G===void 0){await h(Z);return}try{await H.run(`gemi:cron:${Z.name}`,{ttl:G},(W)=>h(Z,W))}catch(W){if(W instanceof a)console.error(`Cron job ${Z.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 ${Z.name}:`,W)}}var o=300000;function RZ(Z){if(!Z)return;if(Z===!0)return o;return Z.expiresAfter??o}var r;function DZ(){return r??=new Q(new e),r}async function h(Z,$){try{await Z.onTick.call(Z)}catch(G){console.error(`Error executing cron job ${Z.name}:`,G)}try{await Z.callback.call(Z,$)}catch(G){console.error(`Error in cron job ${Z.name}:`,G)}try{await Z.onComplete.call(Z)}catch(G){console.error(`Error completing cron job ${Z.name}:`,G)}}class x{static token="scheduler";handles=[];resolved;inFlight=new Map;stopped=!1;locks;constructor(Z){this.resolved=Z.jobs}get jobs(){return[...this.resolved]}useJobs(Z){this.resolved=Z}useLocks(Z){this.locks=Z}start(Z=($)=>$()){if(this.stopped=!1,this.resolved.length===0)return;let $=globalThis.__gemiCronJobs??=new Map,G=new Map;for(let H of this.resolved){let W=new H;if(!W.name){console.error(`Cron job must have a name \u2014 ${H.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 z=G.get(W.name);if(z!==void 0){console.error(`Two cron jobs claim the name "${W.name}" \u2014 ${z} is scheduled and ${H.name||"an anonymous class"} is not. A name is the scheduler's key, so only one job can hold it. Rename one.`);continue}G.set(W.name,H.name||"an anonymous class"),$.get(W.name)?.stop();let K=Bun.cron(W.cron,()=>{if(this.stopped)return;let V=this.locks;return this.track(W.name,()=>Z(()=>EZ(W,{locks:V})))});$.set(W.name,K),this.handles.push(K)}}stop(){this.stopped=!0;for(let Z of this.handles)Z.stop();this.handles=[]}async drain(Z=1/0){this.stop();let $,G=new Promise((H)=>{if(Z!==1/0)$=setTimeout(H,Z)});return await Promise.race([Promise.allSettled([...this.inFlight.values()].map((H)=>H.done)),G]),clearTimeout($),{unfinished:[...this.inFlight.values()].map((H)=>({...H.tick}))}}get running(){return this.inFlight.size}track(Z,$){let G={},H=Promise.resolve().then($).finally(()=>this.inFlight.delete(G));return this.inFlight.set(G,{tick:{name:Z,startedAt:new Date},done:H}),H}}import{isMainThread as kZ}from"worker_threads";var jZ=100,MZ=(Z)=>Math.min(jZ,Math.floor(Z/10));class yZ extends I{register(){this.app.singleton(P,()=>new P(this.app.config.get("queue",{}),{application:this.app})),this.app.singleton(Q,()=>this.app.make(P).locks)}async boot(){let Z=this.app.config.get("queue",{});if(Z.jobs!==void 0)return;let{jobsDir:$}=U(ZZ(),Z);this.app.make(P).useJobs(await zZ($))}async shutdown(Z){if(!this.app.resolved(P))return;let $=this.app.make(P);if($.running>0)console.log(`[gemi] Shutting down: waiting for ${$.running} running queued job(s).`);let G=Z?.timeoutMs,{unfinished:H}=await $.drain(G===void 0?1/0:Math.max(0,G-MZ(G)));if(H.length>0)return console.error("[gemi] Queued jobs still running at shutdown: "+H.map((W)=>`${W.name} (${W.id})`).join(", ")),{abandoned:!0}}}function x3(Z){if(fZ(Z),Bun.env.NODE_ENV!=="production")return bZ(Z);if(VZ(Z))return;if(!GZ())return;if(!Z.bound(P))return;Z.make(P).start()}function VZ(Z){let $=Z.config.get("queue",{}).driver??"memory";return $==="memory"||$ instanceof $Z}function wZ(Z){if(VZ(Z))return!0;if(typeof Z.config.get("queue",{}).driver!=="function"||!Z.bound(P))return!1;try{return!Z.make(P).durable}catch{return!1}}function fZ(Z){let $=process.env.GEMI_QUEUE_CLAIM;if($===void 0||HZ())return;if(process.env.ROOT_DIR===void 0||!kZ)return;if(WZ()){if(!wZ(Z))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($.trim().toLowerCase()!=="on")console.warn(`[gemi] GEMI_QUEUE_CLAIM="${$}" is not "off" or "on", so this server claims jobs. Set it to "off" to leave them to \`gemi queue:work\`.`)}function bZ(Z){let $=globalThis.__gemiDevQueue;if(!$)return;if(globalThis.__gemiDevQueue=void 0,$.stop(),Z.bound(P))Z.make(P).start()}class gZ extends I{register(){this.app.singleton(c,()=>new c(this.app.config.get("auth",{})))}}var vZ=100,mZ=(Z)=>Math.min(vZ,Math.floor(Z/10));class hZ extends I{register(){this.app.singleton(x,()=>new x(U(u(),this.app.config.get("schedule",{}))))}async boot(){let Z=this.app.make(x),$=this.app.config.get("schedule",{});if($.jobs===void 0){let{jobsDir:H}=U(u(),$);Z.useJobs(await XZ(H))}if(process.env.GEMI_NO_SCHEDULE==="1")return;let G=this.app;if(G.bound(Q))Z.useLocks(()=>G.make(Q));Z.start((H)=>KZ.run(G,H))}async shutdown(Z){if(!this.app.resolved(x))return;let $=this.app.make(x);if($.running>0)console.log(`[gemi] Shutting down: waiting for ${$.running} running cron tick(s).`);let G=Z?.timeoutMs,{unfinished:H}=await $.drain(G===void 0?1/0:Math.max(0,G-mZ(G)));if(H.length>0)return console.error("[gemi] Cron jobs still running at shutdown: "+H.map((W)=>`${W.name} (started ${W.startedAt.toISOString()})`).join(", ")),{abandoned:!0}}}class A extends IZ{modelName;constructor(Z="FeatureFlag"){super();this.modelName=Z}get available(){return YZ(this.modelName)}async load(){if(!this.available)throw new d(this.modelName);let Z=p(this.modelName);return await Z.asSystem(()=>Z.findMany())}async write(Z,$,G){if(!this.available)throw new d(this.modelName);let H=p(this.modelName),W=this.hasActorColumn(H),z={active:$};if(W)z.updatedBy=G.actor;return await H.asSystem(()=>H.upsert({where:{key:Z},create:{key:Z,...z},update:z})),{actorRecorded:W}}hasActorColumn(Z){let $=Z?.$schema?.fields?.updatedBy;return $!==void 0&&$.type==="String"}}function g3(Z){return Z}function JZ(){return{features:void 0,enabled:!0,source:new A,model:"FeatureFlag",ttl:30,context:void 0,onEvaluate:void 0,maxClientFlags:200}}class cZ extends I{register(){this.app.singleton(M,()=>{let Z=this.app.config.get("features",{}),$=U(JZ(),Z);if(Z?.model!==void 0&&Z?.source===void 0)$.source=new A(Z.model);else if(Z?.model!==void 0&&Z.source instanceof A&&Z.source.modelName!==Z.model)j.warning(`app/config/features.ts sets \`model: "${Z.model}"\` and a source reading "${Z.source.modelName}". The source wins; drop \`model\` to silence this.`);return new M($,(G)=>j.warning(G))})}async boot(){let Z=this.app.make(M);if(!Z.config.enabled)return;try{await Z.refresh()}catch($){j.error(`Could not warm the feature flag cache at boot. ${$ instanceof Error?$.message:String($)}`)}}}class uZ extends I{register(){this.app.singleton(l,()=>new l(this.app.config.get("mail",{})))}}function pZ(Z){return`listener:${Z}`}function UZ(Z,$){dZ(Z);let{maxAttempts:G,backoff:H,worker:W}=$,z=Z.event.name,K=class extends CZ{maxAttempts=G;backoff=H;worker=W;async run(...V){let[Y,J]=lZ(V),B=y(F).rehydrate(Y,J);await new Z().handle(B)}onFail(V){console.error(`The listener ${Z.name} threw while handling ${z} off the queue. The queue will retry it up to ${G} times in total; nothing the dispatcher did is waiting on it.`,V)}onDeadletter(V){console.error(`The listener ${Z.name} failed every one of its ${G} attempts at ${z} and has been dead-lettered, so this side effect did not happen and will not be retried.`,V)}};return Object.defineProperty(K,"name",{value:pZ(Z.name),writable:!0}),K}function dZ(Z){if(Object.getOwnPropertyDescriptor(Z,"name")?.writable)return;throw Error(`The listener ${Z.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 = "${Z.name}";`)}function lZ(Z){return typeof Z[0]==="string"?Z:Z[0]}class F{static token="events";listeners={};events={};warnedFor=new Set;warnedAboutWaiting=new Set;config;constructor(Z={}){this.config=U(w(),Z),this.useListeners(this.config.listeners)}useListeners(Z){this.config.listeners=Z,this.listeners={},this.events={};let $=new Set;for(let G of Z){if(!G.event){console.error(`Listener ${G.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($.has(G.name)){console.error(`Two event listeners are named "${G.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}$.add(G.name);let H=G.event.name,W=new G;this.events[H]??=G.event,(this.listeners[H]??=[]).push({listener:G,job:W.queued?UZ(G,W):null})}}get queuedListenerJobs(){return Object.values(this.listeners).flat().flatMap(({job:Z})=>Z?[Z]:[])}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,$,G){let{name:H,afterCommit:W}=Z.constructor;if(!W)return!1;let z=BZ(()=>this.runListeners(Z,$));if(z&&G)this.warnNothingIsWaitedFor(H);return z}async runListeners(Z,$){let G=Z.constructor.name,H=this.listeners[G];if(!H?.length){this.warnNothingIsListening(G);return}for(let{listener:W,job:z}of H){if(z){this.enqueue(z,W,G,$);continue}try{await new W().handle(Z)}catch(K){console.error(`The listener ${W.name} threw while handling ${G}. The `+"listeners after it still ran \u2014 a listener's failure is its own.",K)}}}rehydrate(Z,$=[]){let G=this.events[Z];if(!G)throw Error(`Cannot rebuild the event "${Z}" 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 = "${Z}"\`.`);return new G(...$)}enqueue(Z,$,G,H){if(H===void 0){console.error(`The listener ${$.name} is queued, but ${G} 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 ${G}.dispatch(...) or ${G}.dispatchAndWait(...), which carry them.`);return}let W=(z)=>console.error(`The listener ${$.name} could not be queued for ${G}, so it did not run and will not be retried. The listeners after it still ran.`,z);try{y(P).push(Z,JSON.stringify([G,H]),{reportFailure:!1}).catch(W)}catch(z){W(z)}}warnNothingIsWaitedFor(Z){if(Bun.env.NODE_ENV==="production")return;if(this.warnedAboutWaiting.has(Z))return;this.warnedAboutWaiting.add(Z),console.warn(`[gemi] ${Z}.dispatchAndWait() was called inside a transaction and ${Z} 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(Z){if(Bun.env.NODE_ENV==="production")return;if(this.warnedFor.has(Z))return;this.warnedFor.add(Z),console.warn(`[gemi] ${Z} 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 = ${Z}\` and that ${Z} declares \`static name = "${Z}"\`. Development only.`)}}class iZ extends I{register(){this.app.singleton(F,()=>new F(this.app.config.get("events",{})))}async boot(){let Z=this.app.make(F),$=this.app.config.get("events",{});if($.listeners===void 0){let{listenersDir:W}=U(w(),$);Z.useListeners(await qZ(W))}let G=Z.queuedListenerJobs;if(G.length===0)return;let H=this.app.make(P);for(let W of G)H.registerJob(W)}}class sZ extends I{register(){this.app.singleton(i,()=>new i(this.app.config.get("filesystem",{})))}}class nZ extends I{register(){this.app.singleton(s,()=>new s(this.app.config.get("image",{})))}}class tZ extends I{register(){this.app.instance(n,new n)}}function A4(Z){return Z}function PZ(){return{maxFileSize:10485760,onLogFileClosed:()=>{},onLogCreated:()=>{}}}class oZ extends I{register(){this.app.singleton(f,()=>new f(U(PZ(),this.app.config.get("log",{}))))}async boot(){if(!process.env.ROOT_DIR)return;await this.app.make(f).boot()}}class rZ extends I{register(){this.app.singleton(b,()=>new b(U(NZ(),this.app.config.get("middleware",{}))))}boot(){this.app.make(b).assertGlobalMiddleware()}}function b4(Z){return Z}function QZ(){return{driver:new OZ,limit:1000,window:60}}class aZ extends I{register(){this.app.singleton(t,()=>new t(U(QZ(),this.app.config.get("ratelimiter",{}))))}}function p4(Z){return Z}function xZ(){return{url:process.env.REDIS_URL,options:void 0}}class eZ extends I{register(){this.app.singleton(T,()=>new T(U(xZ(),this.app.config.get("redis",{}))))}shutdown(){if(!this.app.resolved(T))return;this.app.make(T).close()}}class O extends SZ{status;constructor(Z,$){super(Z);this.status=$;this.name="McpToolError"}}var Z3=/^[A-Za-z0-9_-]{1,64}$/,$3=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,FZ=4000,L=1e5,G3=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i;class E{router;dispatcher;static token="router.mcp";plans=new Map;constructor(Z,$){this.router=Z;this.dispatcher=$;for(let[G,H]of Object.entries(Z.routes??{}))this.plans.set(G,this.plan(G,H))}list(Z,$){return _Z(Z),this.descriptors($)}descriptors(Z){let $=[];for(let{descriptor:G}of this.plans.values()){if(Z?.names&&!Z.names.includes(G.name))continue;if(Z?.tags&&!G.tags.some((H)=>Z.tags.includes(H)))continue;$.push(G)}return $}async execute(Z,$,G,H){_Z(Z);let W=this.plans.get($);if(!W)throw Error(`McpRegistry: there is no tool named "${$}".`);let{descriptor:z}=W,K=z.inputSchema.safeParse(G);if(K.ok===!1)throw new O(`Invalid arguments for "${$}": ${K.errors.join(", ")}`);let V=K.value,Y={caller:Z,req:Z.req,tool:z,input:V,ctx:H},J=await this.fillPath(W,Y),{path:B}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${J}`));if(B!==z.url)throw new O(`"${$}" has nothing at ${J}.`,404);let C={};for(let q of W.jsonKeys)if(V[q]!==void 0)C[q]=V[q];let N,_="";if(W.fileFields.length>0)N=await this.formData(W,C,Y);else if(z.method==="GET")_=V3(C);else if(W.jsonKeys.length>0)N=C;let D=this.router.credentials?await this.bind(W,"the credentials",()=>this.router.credentials(Y)):void 0,X;try{let q=_?`${J}?${_}`:J;X=D?await this.dispatcher.dispatchAs(Z.req,z.method,q,N,{credentials:D}):await this.dispatcher.dispatchAs(Z.req,z.method,q,N)}catch(q){throw console.error(`[gemi/mcp] Dispatching "${$}" failed:`,q),new O(`"${$}" failed on the server.`,500)}if(!W.result&&!z.outputSchema)return await LZ($,X);return await this.project(W,Y,X)}plan(Z,$){if(!Z3.test(Z))throw Error(`McpRouter: "${Z}" 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 G=`McpRouter: "${Z}" (${$?.method} ${$?.url})`;if(!($ instanceof Object)||$.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${Z}" is not a route. Declare it with this.fromApiRoute(...).`);let{method:H,url:W,meta:z}=$;if(W.startsWith("/__gemi__"))throw Error(`${G} is a framework route, not an app route.`);let K=this.dispatcher.flatRoutes[W]?.[H];if(!K)throw Error(`${G} names no route of this app. Expose a route by the path and verb it is mounted at.`);let V=[...W.matchAll($3)].map(([,X,q])=>({name:X,modifier:q})),Y=z.params??{};for(let X of V)if(!(X.name in Y))throw Error(`${G}: the path param "${X.name}" must be bound or declared "input".`);for(let[X,q]of Object.entries(Y)){if(!V.some((k)=>k.name===X))throw Error(`${G}: "${X}" in params is not a param of the url.`);AZ(G,`params.${X}`,q)}let J=[],B;if(z.input){if(B=z.input.toJSONSchema(),B.type!=="object"||!B.properties)throw Error(`${G}: input must be an s.object(...), the fields of the request body.`);J=Object.keys(B.properties)}let C=Object.entries(z.files??{}).map(([X,q])=>({name:X,binder:q}));for(let X of C)AZ(G,`files.${X.name}`,X.binder);if(z.result!==void 0&&typeof z.result!=="function")throw Error(`${G}: result must be a function.`);if(z.output!==void 0&&typeof z.output?.safeParse!=="function")throw Error(`${G}: output must be a schema, built with s.`);if(C.length>0&&H==="GET")throw Error(`${G}: a GET has no body to carry a file.`);let N={},_=new Map;for(let X of V){let q=Y[X.name];if(q==="input"){let k=g.string().describe(`The ":${X.name}" segment of the url.`);N[X.name]=X.modifier==="?"||X.modifier==="*"?k.optional():k}else _.set(X.name,q)}for(let X of C)if(X.binder==="input")N[X.name]=g.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.");let D=[...Object.keys(N),...C.map((X)=>X.name)];for(let X of new Set(D))if(J.includes(X))throw Error(`${G}: "${X}" is both an input field and a param or file, and the model can only send one.`);return{descriptor:Object.freeze({name:Z,description:z.description,method:H,url:W,inputSchema:H3(z.input,B,g.object(N)),...z.output?{outputSchema:z.output}:{},annotations:W3(H),tags:Object.freeze([...z.tags??[]]),requiresApproval:z.requiresApproval===!0,...K.source?{source:K.source}:{}}),params:V,paramBinders:_,fileFields:C,jsonKeys:J,...z.result?{result:z.result}:{}}}async fillPath(Z,$){let{input:G,req:H}=$,W=Z.descriptor.url;for(let z of Z.params){let K=Z.paramBinders.get(z.name),V;if(K){if(V=await this.bind(Z,`the param "${z.name}"`,()=>K(H,$)),V===void 0||V===null||V==="")throw console.error(`[gemi/mcp] The binder for "${z.name}" of "${Z.descriptor.name}" returned ${JSON.stringify(V)}.`),new O(`"${Z.descriptor.name}" failed on the server.`,500)}else V=G[z.name];let Y=`:${z.name}${z.modifier}`;if(V===void 0||V===null||V===""){if(z.modifier!=="?"&&z.modifier!=="*")throw new O(`"${z.name}" of "${Z.descriptor.name}" must not be empty.`);W=W.replace(`/${Y}`,"");continue}W=W.replace(Y,z3(Z.descriptor.name,z,String(V)))}return W}async formData(Z,$,G){let{input:H,ctx:W}=G,z=Z.descriptor.name;if(!W)throw Error(`McpRegistry: "${z}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let K=new FormData;for(let[V,Y]of Object.entries($))TZ(K,V,Y);for(let V of Z.fileFields){let Y=V.binder==="input"?H[V.name]:await this.bind(Z,`the file "${V.name}"`,()=>V.binder(W,G));if(typeof Y!=="string"||Y==="")throw new O(`"${z}" needs a file for "${V.name}", and this turn has none. Ask the user to attach one.`);K.append(V.name,await W.attachments.file(Y))}return K}async project(Z,$,G){let{name:H,outputSchema:W}=Z.descriptor;if(G.status<200||G.status>=300)return await LZ(H,G);let z=(C,N)=>{if(N===void 0)console.error(`[gemi/mcp] "${H}" ${C}`);else console.error(`[gemi/mcp] "${H}" ${C}`,N);return new O(`"${H}" failed on the server.`,500)},K=G.headers.get("Content-Type"),V=await G.text(),Y=null;if(V!=="")try{Y=JSON.parse(V)}catch{throw z(`answered ${K??"a body with no content-type"} that is not JSON, and its result or output needs JSON.`)}let J=Y;if(Z.result)try{J=await Z.result(Y,$)}catch(C){throw z("failed in its result projection:",C)}if(W){let C=W.safeParse(J);if(C.ok===!1)throw z(`answered what its output schema refuses: ${C.errors.join(", ")}`);J=C.value}if(J===void 0)return null;let B=JSON.stringify(J);if(B!==void 0&&B.length>L)return`${B.slice(0,L)}\u2026 [cut at ${L} of ${B.length} characters]`;return J}async bind(Z,$,G){try{return await G()}catch(H){throw console.error(`[gemi/mcp] Binding ${$} of "${Z.descriptor.name}" failed:`,H),new O(`"${Z.descriptor.name}" failed on the server.`,500)}}}function _Z(Z){if(Z?.kind!=="local")throw Error("McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have \u2014 and until it does there is no remote surface to call from.")}function AZ(Z,$,G){if(G!=="input"&&typeof G!=="function")throw Error(`${Z}: ${$} must be a function or "input".`)}function W3(Z){switch(Z){case"GET":return Object.freeze({readOnlyHint:!0});case"DELETE":return Object.freeze({destructiveHint:!0});case"PUT":return Object.freeze({idempotentHint:!0});default:return Object.freeze({})}}function H3(Z,$,G){let H=G.toJSONSchema(),W={...$??{},type:"object",properties:{...$?.properties??{},...H.properties},required:[...$?.required??[],...H.required??[]],additionalProperties:!1},z=(K)=>{if(typeof K!=="object"||K===null||Array.isArray(K))return{ok:!1,errors:["expected an object"]};let V=[],Y={};if(Z){let B=Z.safeParse(K);if(B.ok===!1)V.push(...B.errors);else Y={...B.value}}let J=G.safeParse(K);if(J.ok===!1)V.push(...J.errors);else Y={...Y,...J.value};return V.length>0?{ok:!1,errors:V}:{ok:!0,value:Y}};return{toJSONSchema:()=>W,safeParse:z,parse(K){let V=z(K);if(V.ok===!1)throw Error(V.errors.join(", "));return V.value}}}function z3(Z,$,G){let H=$.modifier==="*"||$.modifier==="+"?G.split("/"):[G];if(H.some((W)=>W==="."||W===".."))throw new O(`"${G}" is not a valid value for "${$.name}" of "${Z}".`);return H.map(encodeURIComponent).join("/")}function TZ(Z,$,G){if(G===void 0||G===null)return;if(Array.isArray(G)){for(let H of G)TZ(Z,$,H);return}Z.append($,typeof G==="object"?JSON.stringify(G):String(G))}function V3(Z){let $=new URLSearchParams,G=(H,W)=>{if(W===void 0||W===null)return;if(Array.isArray(W)){for(let z of W)G(H,z);return}$.append(H,typeof W==="object"?JSON.stringify(W):String(W))};for(let[H,W]of Object.entries(Z))G(H,W);return $.toString()}async function LZ(Z,$){if($.status>=200&&$.status<300){let H=$.headers.get("Content-Type");if(H&&!G3.test(H)){let z=(await $.arrayBuffer()).byteLength;return`"${Z}" answered with ${z} bytes of ${H}, which is not shown.`}let W=await $.text();if(W==="")return null;if(W.length>L)return`${W.slice(0,L)}\u2026 [cut at ${L} of ${W.length} characters]`;try{return JSON.parse(W)}catch{return W}}let G=await $.text();if($.status>=400&&$.status<500){let H=G.length>FZ?`${G.slice(0,FZ)}\u2026`:G;throw new O(`"${Z}" was refused with ${$.status}${H?`: ${H}`:"."}`,$.status)}if($.status<500)console.error(`[gemi/mcp] "${Z}" answered ${$.status}${$.headers.get("Location")?` to ${$.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new O(`"${Z}" failed on the server.`,$.status)}function v(Z,$){let G=Z.get($);if(!G)throw Error(`Missing "${$}" configuration. Route dispatching needs a root router \u2014 declare it in "app/config/route.ts".`);return G}class K3 extends I{register(){this.app.singleton(S,()=>new S(v(this.app.config,"route.api"))),this.app.singleton(R,()=>new R(v(this.app.config,"route.view"))),this.app.singleton(m,()=>new m({api:this.app.make(S),view:this.app.make(R)},{api:v(this.app.config,"route.api"),view:v(this.app.config,"route.view"),domains:this.app.config.get("route.domains")})),this.app.singleton(E,()=>{let Z=this.app.config.get("route.mcp");if(!Z?.router)throw Error('No MCP router is configured. Declare one as `mcp: { router }` in "app/config/route.ts".');return new E(new Z.router,this.app.make(S))})}boot(){if(this.app.make(S),this.app.make(R),this.app.make(m),this.app.config.get("route.mcp"))this.app.make(E)}}
3
+ export{x as Za,yZ as _a,x3 as $a,gZ as ab,hZ as bb,A as cb,g3 as db,JZ as eb,cZ as fb,uZ as gb,F as hb,iZ as ib,sZ as jb,nZ as kb,tZ as lb,A4 as mb,PZ as nb,oZ as ob,rZ as pb,b4 as qb,QZ as rb,aZ as sb,p4 as tb,xZ as ub,eZ as vb,O as wb,E as xb,K3 as yb};
4
+
5
+ //# debugId=94EFED1EEB0E7ED064756E2164756E21
@@ -23,10 +23,10 @@
23
23
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { RateLimiter } from \"./RateLimiter\";\nimport { rateLimiterConfigDefaults, type RateLimiterConfig } from \"./config\";\n\nexport class RateLimiterServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n RateLimiter,\n () =>\n new RateLimiter(\n withDefaults(\n rateLimiterConfigDefaults(),\n this.app.config.get<RateLimiterConfig>(\"ratelimiter\", {}),\n ),\n ),\n );\n }\n}\n",
24
24
  "import type { RedisOptions } from \"bun\";\n\n// Config key: `redis`. Derived from `RedisServiceProvider`.\nexport interface RedisConfig {\n // Connection URL for Bun's Redis client. Defaults to the `REDIS_URL`\n // environment variable (Bun itself falls back to `redis://localhost:6379`\n // when unset).\n url?: string;\n\n // Optional Bun Redis client options (TLS, timeouts, auto-reconnect, ...).\n options?: RedisOptions;\n}\n\nexport function defineRedisConfig(config: RedisConfig): RedisConfig {\n return config;\n}\n\nexport function redisConfigDefaults(): RedisConfig {\n return {\n url: process.env.REDIS_URL,\n options: undefined,\n };\n}\n",
25
25
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { withDefaults } from \"../../support/withDefaults\";\nimport { redisConfigDefaults, type RedisConfig } from \"./config\";\nimport { RedisManager } from \"./RedisManager\";\n\nexport class RedisServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n RedisManager,\n () =>\n new RedisManager(\n withDefaults(\n redisConfigDefaults(),\n this.app.config.get<RedisConfig>(\"redis\", {}),\n ),\n ),\n );\n }\n\n /**\n * Closes the client, if anything built one. Under `gemi dev` this is what\n * keeps each `bun --hot` reload from leaving a Redis connection behind; see\n * `DatabaseServiceProvider.shutdown`.\n */\n shutdown() {\n if (!this.app.resolved(RedisManager)) return;\n this.app.make(RedisManager).close();\n }\n}\n",
26
- "import type { ToolContext } from \"../../ai/Agent\";\nimport { ToolError } from \"../../ai/redact\";\nimport { s, type AnySchema, type JSONSchema, type Schema } from \"../../ai/Schema\";\nimport type { RouteSource } from \"../../http/ApiRouter\";\nimport type { HttpRequest } from \"../../http/HttpRequest\";\nimport type {\n McpFileBinder,\n McpMethod,\n McpParamBinder,\n McpRouteDeclaration,\n McpRouter,\n} from \"../../http/McpRouter\";\nimport type { ApiRouteDispatcher } from \"../router/ApiRouteDispatcher\";\n\n/**\n * Who a tool call runs as. Always an argument to the registry, never read from\n * ambient state by it.\n *\n * `local` is an agent running in this server, and `req` is the request that\n * started its run — read by `toAgentTools` at the moment the tool executes,\n * not when the tool was built, which is what lets one set of tools serve every\n * user's run.\n *\n * That producer *does* read ambient state, since a run no longer carries a\n * request (see `AgentContext`), and the boundary is what keeps that from\n * mattering here: the registry is handed a caller and dispatches as that\n * caller, so a second producer — a job, a test, v2's remote client — supplies\n * one however it likes, and a run with no ambient request is refused by\n * `toAgentTools` before the registry is reached rather than dispatching as\n * nobody.\n * The call is dispatched with that request's credentials, so it runs as that\n * user, through that route's middleware.\n *\n * `remote` is v2's MCP client with a bearer token. It is typed so the seam\n * exists and every entry point already takes it; each of them refuses it,\n * because a token resolver is what makes it safe and there is none yet.\n * Reading the caller from `RequestContext` instead would have been shorter,\n * and would have left v2 a registry that only works inside a gemi request.\n */\nexport type McpCaller =\n | { kind: \"local\"; req: HttpRequest<any, any> }\n | { kind: \"remote\"; token: string };\n\n/**\n * MCP's tool annotations, from the verb. They drive confirmation prompts in\n * remote clients, which is why they are set now rather than when v2 lands:\n * every app would otherwise have to revisit its MCP file to get them.\n *\n * Only what the verb says is set. POST and PATCH carry nothing, and MCP's\n * defaults for an unannotated tool — not read-only, possibly destructive — are\n * the honest answer for them.\n */\nexport type McpToolAnnotations = {\n readOnlyHint?: true;\n destructiveHint?: true;\n idempotentHint?: true;\n};\n\n/**\n * One tool, described without committing to who consumes it.\n *\n * The registry's native output. An in-process agent projects it to an\n * `AgentTool` (`toAgentTools`); v2's `tools/list` will project it to JSON.\n * Emitting `AgentTool`s here instead would leave v2 reversing JSON Schema back\n * out of them.\n */\nexport interface McpToolDescriptor {\n /** The `routes` key, verbatim. See `McpRouter`. */\n readonly name: string;\n readonly description: string;\n readonly method: McpMethod;\n /** The route's path as declared, params unfilled. */\n readonly url: string;\n /**\n * What the model fills in: the declared `input`, plus a string for every\n * `\"input\"` path param and every `\"input\"` file field. Bound params and\n * bound files are not in it at all.\n */\n readonly inputSchema: Schema<Record<string, unknown>>;\n readonly annotations: McpToolAnnotations;\n readonly tags: readonly string[];\n readonly requiresApproval: boolean;\n /** The controller method mounted at the route, when there is one (#502). */\n readonly source?: RouteSource;\n}\n\n/**\n * Narrows `list`. Data rather than a predicate, because v2's per-token\n * visibility will come from a token's grants, which are data. Both fields\n * narrow: `names` keeps only those tools, `tags` keeps tools carrying at least\n * one of them.\n */\nexport type McpToolFilter = {\n names?: readonly string[];\n tags?: readonly string[];\n};\n\n/**\n * A failure the model is meant to read: a 4xx from the route, a missing file,\n * a bad argument. v2 turns it into `isError: true` rather than a protocol\n * error. Anything else thrown from `execute` is the caller's mistake or the\n * server's, not the model's.\n */\nexport class McpToolError extends ToolError {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"McpToolError\";\n }\n}\n\n/** Tool names as OpenAI's function tools and MCP clients both accept them. */\nconst TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;\n\n/** `:name`, with URLPattern's modifiers. */\nconst PATH_PARAM = /:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g;\n\n/**\n * A 4xx body goes to the model verbatim, so a validation error can be fixed on\n * the next step — but a route that answers a 4xx with a page of HTML should not\n * be able to fill the context window with it.\n */\nconst MAX_ERROR_BODY = 4000;\n\n/**\n * The same limit for a success, set higher: a list route answering every row,\n * or a route serving a large text file, would otherwise land in the context\n * window whole. Past it the model gets the text cut short and told so, rather\n * than an error — the route has already done what it does, and a model told it\n * failed would do it again.\n */\nconst MAX_RESULT_BODY = 100_000;\n\n/** A body a model can read. A missing content-type is read as text. */\nconst READABLE = /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml))/i;\n\ntype PathParam = { name: string; modifier: string };\n\ntype Plan = {\n descriptor: McpToolDescriptor;\n params: PathParam[];\n paramBinders: Map<string, McpParamBinder>;\n fileFields: { name: string; binder: McpFileBinder | \"input\" }[];\n jsonKeys: string[];\n};\n\n/**\n * The tools an app's `McpRouter` declares, resolved against the api route\n * table, and the one place a call to them is dispatched.\n *\n * Built once, at boot, from the dispatcher's flat route table — so a route\n * that was renamed or unmounted fails the boot here, and at compile time\n * before that, rather than the first model that calls it.\n *\n * THE INVARIANT: a tool call can do nothing its caller could not do with a\n * direct HTTP request. `execute` builds a request and hands it to\n * `ApiRouteDispatcher.dispatchAs`, which runs the route's middleware, auth and\n * policies exactly as for a client. It never reaches for a flat entry's\n * `exec`, which is the handler alone — no auth, no policies, no rate limit —\n * and is the shorter path for exactly that reason.\n */\nexport class McpRegistry {\n static token = \"router.mcp\";\n\n private readonly plans = new Map<string, Plan>();\n\n constructor(\n router: McpRouter<any>,\n private readonly dispatcher: Pick<\n ApiRouteDispatcher,\n \"flatRoutes\" | \"dispatchAs\" | \"getRouteHandlerAndParams\"\n >,\n ) {\n for (const [name, declaration] of Object.entries(router.routes ?? {})) {\n this.plans.set(name, this.plan(name, declaration));\n }\n }\n\n /**\n * The tools `caller` may see. v1 has only local callers, and every declared\n * tool is visible to every one of them; `filter` is taken now so the shape\n * v2's per-token visibility needs is the shape callers already use.\n */\n list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[] {\n assertLocal(caller);\n return this.descriptors(filter);\n }\n\n /**\n * The same listing without a caller, for a projection built once before any\n * caller exists — `toAgentTools`. It is not per-caller visibility, and a v2\n * remote listing must go through `list`.\n */\n descriptors(filter?: McpToolFilter): McpToolDescriptor[] {\n const out: McpToolDescriptor[] = [];\n for (const { descriptor } of this.plans.values()) {\n if (filter?.names && !filter.names.includes(descriptor.name)) continue;\n if (filter?.tags && !descriptor.tags.some((tag) => filter.tags.includes(tag))) continue;\n out.push(descriptor);\n }\n return out;\n }\n\n /**\n * Calls the tool `name` as `caller`, and answers the route's JSON.\n *\n * `ctx` is the tool context of the agent call, and only files need it:\n * `\"input\"` files resolve through `ctx.attachments`, the handle already\n * scoped to the caller, and bound files are chosen by a binder given `ctx`.\n * Nothing here reads an attachment any other way — the store has no\n * unscoped lookup, and this must not become one.\n *\n * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body\n * that is neither — a file a route serves — is described, not shown.\n * A 4xx throws an `McpToolError` carrying the route's body, so a validation\n * error reaches the model word for word. Anything else, or a route that\n * throws, throws an `McpToolError` that says only that the server failed.\n * The app gets the reason in its log, and a stack trace or a database\n * message is not something to hand a model that may be steered by whoever\n * wrote the document it is reading.\n */\n async execute(\n caller: McpCaller,\n name: string,\n args: unknown,\n ctx?: ToolContext,\n ): Promise<unknown> {\n assertLocal(caller);\n const plan = this.plans.get(name);\n if (!plan) {\n throw new Error(`McpRegistry: there is no tool named \"${name}\".`);\n }\n const { descriptor } = plan;\n\n const parsed = descriptor.inputSchema.safeParse(args);\n if (parsed.ok === false) {\n throw new McpToolError(`Invalid arguments for \"${name}\": ${parsed.errors.join(\", \")}`);\n }\n const input = parsed.value;\n\n const path = await this.fillPath(plan, input, caller.req);\n\n // The dispatcher routes `path` afresh and takes the first route that\n // matches it, so a model's \"archive-all\" for `/products/:id` would reach a\n // `/products/archive-all` declared above it — a route the app never\n // exposed, behind none of this tool's approval or annotations.\n const { path: matched } = this.dispatcher.getRouteHandlerAndParams(\n new Request(`http://gemi.internal/api${path}`),\n );\n if (matched !== descriptor.url) {\n throw new McpToolError(`\"${name}\" has nothing at ${path}.`, 404);\n }\n\n const json: Record<string, unknown> = {};\n for (const key of plan.jsonKeys) {\n if (input[key] !== undefined) json[key] = input[key];\n }\n\n let body: FormData | Record<string, unknown> | undefined;\n let query = \"\";\n if (plan.fileFields.length > 0) {\n body = await this.formData(plan, input, json, ctx);\n } else if (descriptor.method === \"GET\") {\n query = toQuery(json);\n } else if (plan.jsonKeys.length > 0) {\n body = json;\n }\n\n let response: Response;\n try {\n response = await this.dispatcher.dispatchAs(\n caller.req,\n descriptor.method,\n query ? `${path}?${query}` : path,\n body,\n );\n } catch (error) {\n // What a client would get as a 500. A handler's throw is logged by the\n // dispatcher too, but dispatchAs's own refusal of the path is not.\n console.error(`[gemi/mcp] Dispatching \"${name}\" failed:`, error);\n throw new McpToolError(`\"${name}\" failed on the server.`, 500);\n }\n return await readResponse(name, response);\n }\n\n // --- building ------------------------------------------------------------\n\n private plan(name: string, declaration: McpRouteDeclaration): Plan {\n if (!TOOL_NAME.test(name)) {\n throw new Error(\n `McpRouter: \"${name}\" 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 — letters, digits, \"_\" and \"-\", at most 64.`,\n );\n }\n const where = `McpRouter: \"${name}\" (${declaration?.method} ${declaration?.url})`;\n if (!(declaration instanceof Object) || declaration.__internal_brand !== \"McpRoute\") {\n throw new Error(\n `McpRouter: \"${name}\" is not a route. Declare it with this.fromApiRoute(...).`,\n );\n }\n const { method, url, meta } = declaration;\n if (url.startsWith(\"/__gemi__\")) {\n throw new Error(`${where} is a framework route, not an app route.`);\n }\n\n const entry = this.dispatcher.flatRoutes[url]?.[method];\n if (!entry) {\n throw new Error(\n `${where} names no route of this app. Expose a route by the path and verb it is mounted at.`,\n );\n }\n\n // Mirrors the compile-time check, for a router written in JavaScript or\n // behind a cast: a param left undeclared would otherwise be the model's.\n const params: PathParam[] = [...url.matchAll(PATH_PARAM)].map(([, param, modifier]) => ({\n name: param,\n modifier,\n }));\n const declared = meta.params ?? {};\n for (const param of params) {\n if (!(param.name in declared)) {\n throw new Error(\n `${where}: the path param \"${param.name}\" must be bound or declared \"input\".`,\n );\n }\n }\n for (const [key, binder] of Object.entries(declared)) {\n if (!params.some((param) => param.name === key)) {\n throw new Error(`${where}: \"${key}\" in params is not a param of the url.`);\n }\n assertBinder(where, `params.${key}`, binder);\n }\n\n let jsonKeys: string[] = [];\n let base: JSONSchema | undefined;\n if (meta.input) {\n base = meta.input.toJSONSchema();\n if (base.type !== \"object\" || !base.properties) {\n throw new Error(\n `${where}: input must be an s.object(...), the fields of the request body.`,\n );\n }\n jsonKeys = Object.keys(base.properties);\n }\n\n const fileFields = Object.entries(meta.files ?? {}).map(([field, binder]) => ({\n name: field,\n binder,\n }));\n for (const file of fileFields) {\n assertBinder(where, `files.${file.name}`, file.binder);\n }\n if (fileFields.length > 0 && method === \"GET\") {\n throw new Error(`${where}: a GET has no body to carry a file.`);\n }\n\n const extras: Record<string, AnySchema> = {};\n const paramBinders = new Map<string, McpParamBinder>();\n for (const param of params) {\n const binder = declared[param.name];\n if (binder === \"input\") {\n const field = s.string().describe(`The \":${param.name}\" segment of the url.`);\n extras[param.name] =\n param.modifier === \"?\" || param.modifier === \"*\" ? field.optional() : field;\n } else {\n paramBinders.set(param.name, binder);\n }\n }\n for (const file of fileFields) {\n if (file.binder === \"input\") {\n extras[file.name] = s\n .string()\n .describe(\n \"The id of an attachment the user uploaded or a tool produced (gemi_att_…), whose file is sent as this field.\",\n );\n }\n }\n // A bound file is not the model's, but it shares the form with the input,\n // so it collides all the same.\n const bodyKeys = [...Object.keys(extras), ...fileFields.map((file) => file.name)];\n for (const key of new Set(bodyKeys)) {\n if (jsonKeys.includes(key)) {\n throw new Error(\n `${where}: \"${key}\" is both an input field and a param or file, and the model can only send one.`,\n );\n }\n }\n\n return {\n descriptor: Object.freeze({\n name,\n description: meta.description,\n method,\n url,\n inputSchema: combineSchemas(meta.input, base, s.object(extras)),\n annotations: annotationsFor(method),\n tags: Object.freeze([...(meta.tags ?? [])]),\n requiresApproval: meta.requiresApproval === true,\n ...(entry.source ? { source: entry.source } : {}),\n }),\n params,\n paramBinders,\n fileFields,\n jsonKeys,\n };\n }\n\n // --- calling -------------------------------------------------------------\n\n private async fillPath(\n plan: Plan,\n input: Record<string, unknown>,\n req: HttpRequest<any, any>,\n ): Promise<string> {\n let path = plan.descriptor.url;\n for (const param of plan.params) {\n const binder = plan.paramBinders.get(param.name);\n let value: unknown;\n if (binder) {\n value = await this.bind(plan, `the param \"${param.name}\"`, () => binder(req));\n if (value === undefined || value === null || value === \"\") {\n console.error(\n `[gemi/mcp] The binder for \"${param.name}\" of \"${plan.descriptor.name}\" returned ${JSON.stringify(value)}.`,\n );\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n } else {\n value = input[param.name];\n }\n\n const token = `:${param.name}${param.modifier}`;\n if (value === undefined || value === null || value === \"\") {\n if (param.modifier !== \"?\" && param.modifier !== \"*\") {\n throw new McpToolError(`\"${param.name}\" of \"${plan.descriptor.name}\" must not be empty.`);\n }\n path = path.replace(`/${token}`, \"\");\n continue;\n }\n path = path.replace(token, encodeSegment(plan.descriptor.name, param, String(value)));\n }\n return path;\n }\n\n private async formData(\n plan: Plan,\n input: Record<string, unknown>,\n json: Record<string, unknown>,\n ctx: ToolContext | undefined,\n ): Promise<FormData> {\n const name = plan.descriptor.name;\n if (!ctx) {\n throw new Error(\n `McpRegistry: \"${name}\" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`,\n );\n }\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n const id =\n field.binder === \"input\"\n ? (input[field.name] as string)\n : await this.bind(plan, `the file \"${field.name}\"`, () =>\n (field.binder as McpFileBinder)(ctx),\n );\n if (typeof id !== \"string\" || id === \"\") {\n throw new McpToolError(\n `\"${name}\" needs a file for \"${field.name}\", and this turn has none. Ask the user to attach one.`,\n );\n }\n // Scoped to the caller: someone else's id is a not-found, worded like an\n // invented one, and that error is what the model reads.\n form.append(field.name, await ctx.attachments.file(id));\n }\n return form;\n }\n\n /**\n * Runs an app's binder. Its failure is the server's, not the model's, so the\n * model is told only that; the app gets the error in its log.\n */\n private async bind<T>(plan: Plan, what: string, fn: () => T | Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n console.error(`[gemi/mcp] Binding ${what} of \"${plan.descriptor.name}\" failed:`, error);\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n }\n}\n\nfunction assertLocal(caller: McpCaller): asserts caller is Extract<McpCaller, { kind: \"local\" }> {\n if (caller?.kind !== \"local\") {\n throw new Error(\n \"McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have — and until it does there is no remote surface to call from.\",\n );\n }\n}\n\n/** A binder is a function or `\"input\"`; anything else would leave the value to nobody. */\nfunction assertBinder(where: string, at: string, binder: unknown) {\n if (binder !== \"input\" && typeof binder !== \"function\") {\n throw new Error(`${where}: ${at} must be a function or \"input\".`);\n }\n}\n\nfunction annotationsFor(method: McpMethod): McpToolAnnotations {\n switch (method) {\n case \"GET\":\n return Object.freeze({ readOnlyHint: true as const });\n case \"DELETE\":\n return Object.freeze({ destructiveHint: true as const });\n case \"PUT\":\n return Object.freeze({ idempotentHint: true as const });\n default:\n return Object.freeze({});\n }\n}\n\n/**\n * One schema out of two: the app's `input`, and the strings for `\"input\"`\n * params and files.\n *\n * Built by hand, like `questionSchema` in `ai/Agent.ts`, rather than by\n * widening `s` with a merge: `Schema.ts` is deliberately the strict\n * structured-output subset and owns no operation on a finished schema. Both\n * halves are real `s` schemas, each parses the whole value and drops the keys\n * that are not its own — which is also where a bound param the model sent\n * anyway disappears, since neither half declares it.\n */\nfunction combineSchemas(\n input: AnySchema | undefined,\n base: JSONSchema | undefined,\n extras: AnySchema,\n): Schema<Record<string, unknown>> {\n const extra = extras.toJSONSchema();\n const json: JSONSchema = {\n ...(base ?? {}),\n type: \"object\",\n properties: { ...(base?.properties ?? {}), ...extra.properties },\n required: [...(base?.required ?? []), ...(extra.required ?? [])],\n additionalProperties: false,\n };\n\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"expected an object\"] };\n }\n const errors: string[] = [];\n let out: Record<string, unknown> = {};\n if (input) {\n const own = input.safeParse(value);\n if (own.ok === false) errors.push(...own.errors);\n else out = { ...own.value };\n }\n const more = extras.safeParse(value);\n if (more.ok === false) errors.push(...more.errors);\n else out = { ...out, ...more.value };\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as Schema<Record<string, unknown>>;\n}\n\n/**\n * A model-supplied param, as one encoded path segment. `.` and `..` are\n * refused rather than encoded: they encode to themselves, and URL parsing\n * would walk them out of the route.\n */\nfunction encodeSegment(tool: string, param: PathParam, value: string): string {\n const parts = param.modifier === \"*\" || param.modifier === \"+\" ? value.split(\"/\") : [value];\n if (parts.some((part) => part === \".\" || part === \"..\")) {\n throw new McpToolError(`\"${value}\" is not a valid value for \"${param.name}\" of \"${tool}\".`);\n }\n return parts.map(encodeURIComponent).join(\"/\");\n}\n\n/**\n * A JSON field as a multipart form field. A form has only strings, so the\n * route reads `\"12\"` where a JSON body would have carried `12` — what a\n * browser form sends the same route. An array becomes the key repeated, which\n * `HttpRequest` reads back as an array.\n */\nfunction appendField(form: FormData, key: string, value: unknown) {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendField(form, key, item);\n return;\n }\n form.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\n\n/** A GET's input, as the query string `HttpRequest.search` reads. */\nfunction toQuery(json: Record<string, unknown>): string {\n const search = new URLSearchParams();\n const add = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) add(key, item);\n return;\n }\n search.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n };\n for (const [key, value] of Object.entries(json)) add(key, value);\n return search.toString();\n}\n\nasync function readResponse(name: string, response: Response): Promise<unknown> {\n if (response.status >= 200 && response.status < 300) {\n const type = response.headers.get(\"Content-Type\");\n if (type && !READABLE.test(type)) {\n const size = (await response.arrayBuffer()).byteLength;\n return `\"${name}\" answered with ${size} bytes of ${type}, which is not shown.`;\n }\n const text = await response.text();\n if (text === \"\") return null;\n if (text.length > MAX_RESULT_BODY) {\n return `${text.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${text.length} characters]`;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n const text = await response.text();\n if (response.status >= 400 && response.status < 500) {\n const shown = text.length > MAX_ERROR_BODY ? `${text.slice(0, MAX_ERROR_BODY)}…` : text;\n throw new McpToolError(\n `\"${name}\" was refused with ${response.status}${shown ? `: ${shown}` : \".\"}`,\n response.status,\n );\n }\n if (response.status < 500) {\n // A redirect, or a 1xx: nothing the model can follow, and nothing the\n // dispatcher logged.\n console.error(\n `[gemi/mcp] \"${name}\" answered ${response.status}${response.headers.get(\"Location\") ? ` to ${response.headers.get(\"Location\")}` : \"\"}, which a tool call cannot follow.`,\n );\n }\n throw new McpToolError(`\"${name}\" failed on the server.`, response.status);\n}\n",
26
+ "import type { ToolContext } from \"../../ai/Agent\";\nimport { ToolError } from \"../../ai/redact\";\nimport { s, type AnySchema, type JSONSchema, type Schema } from \"../../ai/Schema\";\nimport type { RouteSource } from \"../../http/ApiRouter\";\nimport type { HttpRequest } from \"../../http/HttpRequest\";\nimport type {\n McpFileBinder,\n McpMethod,\n McpParamBinder,\n McpResultProjection,\n McpRouteDeclaration,\n McpRouter,\n} from \"../../http/McpRouter\";\nimport type { ApiRouteDispatcher, DispatchCredentials } from \"../router/ApiRouteDispatcher\";\n\n/**\n * Who a tool call runs as. Always an argument to the registry, never read from\n * ambient state by it.\n *\n * `local` is an agent running in this server, and `req` is the request that\n * started its run — read by `toAgentTools` at the moment the tool executes,\n * not when the tool was built, which is what lets one set of tools serve every\n * user's run.\n *\n * That producer *does* read ambient state, since a run no longer carries a\n * request (see `AgentContext`), and the boundary is what keeps that from\n * mattering here: the registry is handed a caller and dispatches as that\n * caller, so a second producer — a job, a test, v2's remote client — supplies\n * one however it likes, and a run with no ambient request is refused by\n * `toAgentTools` before the registry is reached rather than dispatching as\n * nobody.\n * The call is dispatched with that request's credentials, so it runs as that\n * user, through that route's middleware.\n *\n * `remote` is v2's MCP client with a bearer token. It is typed so the seam\n * exists and every entry point already takes it; each of them refuses it,\n * because a token resolver is what makes it safe and there is none yet.\n * Reading the caller from `RequestContext` instead would have been shorter,\n * and would have left v2 a registry that only works inside a gemi request.\n */\nexport type McpCaller =\n | { kind: \"local\"; req: HttpRequest<any, any> }\n | { kind: \"remote\"; token: string };\n\n/**\n * One tool call, as the app's hooks see it: who is calling, the request their\n * identity comes from, which tool, its parsed arguments, and — for a call an\n * agent run makes — the run's tool context.\n *\n * `req` is `caller.req`, repeated so a hook that only wants the request does\n * not have to narrow the caller. `ctx` is absent when `McpRegistry.execute` is\n * called without one (a test, a script dispatching a tool directly).\n */\nexport type McpCallContext = {\n caller: Extract<McpCaller, { kind: \"local\" }>;\n req: HttpRequest<any, any>;\n tool: McpToolDescriptor;\n input: Record<string, unknown>;\n ctx?: ToolContext;\n};\n\n/**\n * What `McpRouter.credentials` answers for a call: the app's own headers and\n * cookies, sent beside gemi's access token. See `DispatchCredentials`.\n */\nexport type McpCredentials = DispatchCredentials;\n\n/**\n * MCP's tool annotations, from the verb. They drive confirmation prompts in\n * remote clients, which is why they are set now rather than when v2 lands:\n * every app would otherwise have to revisit its MCP file to get them.\n *\n * Only what the verb says is set. POST and PATCH carry nothing, and MCP's\n * defaults for an unannotated tool — not read-only, possibly destructive — are\n * the honest answer for them.\n */\nexport type McpToolAnnotations = {\n readOnlyHint?: true;\n destructiveHint?: true;\n idempotentHint?: true;\n};\n\n/**\n * One tool, described without committing to who consumes it.\n *\n * The registry's native output. An in-process agent projects it to an\n * `AgentTool` (`toAgentTools`); v2's `tools/list` will project it to JSON.\n * Emitting `AgentTool`s here instead would leave v2 reversing JSON Schema back\n * out of them.\n */\nexport interface McpToolDescriptor {\n /** The `routes` key, verbatim. See `McpRouter`. */\n readonly name: string;\n readonly description: string;\n readonly method: McpMethod;\n /** The route's path as declared, params unfilled. */\n readonly url: string;\n /**\n * What the model fills in: the declared `input`, plus a string for every\n * `\"input\"` path param and every `\"input\"` file field. Bound params and\n * bound files are not in it at all.\n */\n readonly inputSchema: Schema<Record<string, unknown>>;\n /**\n * The route meta's `output`: the shape of what the tool answers, after\n * `result`. Absent when the meta declares none. v2's `tools/list` emits it\n * as `outputSchema`.\n */\n readonly outputSchema?: AnySchema;\n readonly annotations: McpToolAnnotations;\n readonly tags: readonly string[];\n readonly requiresApproval: boolean;\n /** The controller method mounted at the route, when there is one (#502). */\n readonly source?: RouteSource;\n}\n\n/**\n * Narrows `list`. Data rather than a predicate, because v2's per-token\n * visibility will come from a token's grants, which are data. Both fields\n * narrow: `names` keeps only those tools, `tags` keeps tools carrying at least\n * one of them.\n */\nexport type McpToolFilter = {\n names?: readonly string[];\n tags?: readonly string[];\n};\n\n/**\n * A failure the model is meant to read: a 4xx from the route, a missing file,\n * a bad argument. v2 turns it into `isError: true` rather than a protocol\n * error. Anything else thrown from `execute` is the caller's mistake or the\n * server's, not the model's.\n */\nexport class McpToolError extends ToolError {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"McpToolError\";\n }\n}\n\n/** Tool names as OpenAI's function tools and MCP clients both accept them. */\nconst TOOL_NAME = /^[A-Za-z0-9_-]{1,64}$/;\n\n/** `:name`, with URLPattern's modifiers. */\nconst PATH_PARAM = /:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g;\n\n/**\n * A 4xx body goes to the model verbatim, so a validation error can be fixed on\n * the next step — but a route that answers a 4xx with a page of HTML should not\n * be able to fill the context window with it.\n */\nconst MAX_ERROR_BODY = 4000;\n\n/**\n * The same limit for a success, set higher: a list route answering every row,\n * or a route serving a large text file, would otherwise land in the context\n * window whole. Past it the model gets the text cut short and told so, rather\n * than an error — the route has already done what it does, and a model told it\n * failed would do it again.\n */\nconst MAX_RESULT_BODY = 100_000;\n\n/** A body a model can read. A missing content-type is read as text. */\nconst READABLE = /^(text\\/|application\\/([\\w.+-]*\\+)?(json|xml))/i;\n\ntype PathParam = { name: string; modifier: string };\n\ntype Plan = {\n descriptor: McpToolDescriptor;\n params: PathParam[];\n paramBinders: Map<string, McpParamBinder>;\n fileFields: { name: string; binder: McpFileBinder | \"input\" }[];\n jsonKeys: string[];\n result?: McpResultProjection;\n};\n\n/**\n * The tools an app's `McpRouter` declares, resolved against the api route\n * table, and the one place a call to them is dispatched.\n *\n * Built once, at boot, from the dispatcher's flat route table — so a route\n * that was renamed or unmounted fails the boot here, and at compile time\n * before that, rather than the first model that calls it.\n *\n * THE INVARIANT: a tool call can do nothing its caller could not do with a\n * direct HTTP request. `execute` builds a request and hands it to\n * `ApiRouteDispatcher.dispatchAs`, which runs the route's middleware, auth and\n * policies exactly as for a client. It never reaches for a flat entry's\n * `exec`, which is the handler alone — no auth, no policies, no rate limit —\n * and is the shorter path for exactly that reason.\n */\nexport class McpRegistry {\n static token = \"router.mcp\";\n\n private readonly plans = new Map<string, Plan>();\n\n constructor(\n private readonly router: McpRouter<any>,\n private readonly dispatcher: Pick<\n ApiRouteDispatcher,\n \"flatRoutes\" | \"dispatchAs\" | \"getRouteHandlerAndParams\"\n >,\n ) {\n for (const [name, declaration] of Object.entries(router.routes ?? {})) {\n this.plans.set(name, this.plan(name, declaration));\n }\n }\n\n /**\n * The tools `caller` may see. v1 has only local callers, and every declared\n * tool is visible to every one of them; `filter` is taken now so the shape\n * v2's per-token visibility needs is the shape callers already use.\n */\n list(caller: McpCaller, filter?: McpToolFilter): McpToolDescriptor[] {\n assertLocal(caller);\n return this.descriptors(filter);\n }\n\n /**\n * The same listing without a caller, for a projection built once before any\n * caller exists — `toAgentTools`. It is not per-caller visibility, and a v2\n * remote listing must go through `list`.\n */\n descriptors(filter?: McpToolFilter): McpToolDescriptor[] {\n const out: McpToolDescriptor[] = [];\n for (const { descriptor } of this.plans.values()) {\n if (filter?.names && !filter.names.includes(descriptor.name)) continue;\n if (filter?.tags && !descriptor.tags.some((tag) => filter.tags.includes(tag))) continue;\n out.push(descriptor);\n }\n return out;\n }\n\n /**\n * Calls the tool `name` as `caller`, and answers the route's JSON.\n *\n * Before dispatching, the router's `credentials` hook, when it has one, is\n * asked for the app's own headers and cookies for this call; they ride\n * beside the access token (see `McpRouter.credentials`). A throw from it is a\n * server failure, logged for the app, like a binder's.\n *\n * `ctx` is the tool context of the agent call, and only files need it:\n * `\"input\"` files resolve through `ctx.attachments`, the handle already\n * scoped to the caller, and bound files are chosen by a binder given `ctx`.\n * Nothing here reads an attachment any other way — the store has no\n * unscoped lookup, and this must not become one.\n *\n * A 2xx answers its JSON, or its text, cut at `MAX_RESULT_BODY`; a body\n * that is neither — a file a route serves — is described, not shown. A tool\n * whose meta has a `result` or an `output` answers its JSON put through\n * them instead, and is cut after that, not before (see `project`).\n * A 4xx throws an `McpToolError` carrying the route's body, so a validation\n * error reaches the model word for word. Anything else, or a route that\n * throws, throws an `McpToolError` that says only that the server failed.\n * The app gets the reason in its log, and a stack trace or a database\n * message is not something to hand a model that may be steered by whoever\n * wrote the document it is reading.\n */\n async execute(\n caller: McpCaller,\n name: string,\n args: unknown,\n ctx?: ToolContext,\n ): Promise<unknown> {\n assertLocal(caller);\n const plan = this.plans.get(name);\n if (!plan) {\n throw new Error(`McpRegistry: there is no tool named \"${name}\".`);\n }\n const { descriptor } = plan;\n\n const parsed = descriptor.inputSchema.safeParse(args);\n if (parsed.ok === false) {\n throw new McpToolError(`Invalid arguments for \"${name}\": ${parsed.errors.join(\", \")}`);\n }\n const input = parsed.value;\n\n const call: McpCallContext = { caller, req: caller.req, tool: descriptor, input, ctx };\n const path = await this.fillPath(plan, call);\n\n // The dispatcher routes `path` afresh and takes the first route that\n // matches it, so a model's \"archive-all\" for `/products/:id` would reach a\n // `/products/archive-all` declared above it — a route the app never\n // exposed, behind none of this tool's approval or annotations.\n const { path: matched } = this.dispatcher.getRouteHandlerAndParams(\n new Request(`http://gemi.internal/api${path}`),\n );\n if (matched !== descriptor.url) {\n throw new McpToolError(`\"${name}\" has nothing at ${path}.`, 404);\n }\n\n const json: Record<string, unknown> = {};\n for (const key of plan.jsonKeys) {\n if (input[key] !== undefined) json[key] = input[key];\n }\n\n let body: FormData | Record<string, unknown> | undefined;\n let query = \"\";\n if (plan.fileFields.length > 0) {\n body = await this.formData(plan, json, call);\n } else if (descriptor.method === \"GET\") {\n query = toQuery(json);\n } else if (plan.jsonKeys.length > 0) {\n body = json;\n }\n\n const credentials = this.router.credentials\n ? await this.bind(plan, \"the credentials\", () => this.router.credentials!(call))\n : undefined;\n\n let response: Response;\n try {\n const target = query ? `${path}?${query}` : path;\n response = credentials\n ? await this.dispatcher.dispatchAs(caller.req, descriptor.method, target, body, {\n credentials,\n })\n : await this.dispatcher.dispatchAs(caller.req, descriptor.method, target, body);\n } catch (error) {\n // What a client would get as a 500. A handler's throw is logged by the\n // dispatcher too, but dispatchAs's own refusal of the path is not.\n console.error(`[gemi/mcp] Dispatching \"${name}\" failed:`, error);\n throw new McpToolError(`\"${name}\" failed on the server.`, 500);\n }\n if (!plan.result && !descriptor.outputSchema) {\n return await readResponse(name, response);\n }\n return await this.project(plan, call, response);\n }\n\n // --- building ------------------------------------------------------------\n\n private plan(name: string, declaration: McpRouteDeclaration): Plan {\n if (!TOOL_NAME.test(name)) {\n throw new Error(\n `McpRouter: \"${name}\" 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 — letters, digits, \"_\" and \"-\", at most 64.`,\n );\n }\n const where = `McpRouter: \"${name}\" (${declaration?.method} ${declaration?.url})`;\n if (!(declaration instanceof Object) || declaration.__internal_brand !== \"McpRoute\") {\n throw new Error(\n `McpRouter: \"${name}\" is not a route. Declare it with this.fromApiRoute(...).`,\n );\n }\n const { method, url, meta } = declaration;\n if (url.startsWith(\"/__gemi__\")) {\n throw new Error(`${where} is a framework route, not an app route.`);\n }\n\n const entry = this.dispatcher.flatRoutes[url]?.[method];\n if (!entry) {\n throw new Error(\n `${where} names no route of this app. Expose a route by the path and verb it is mounted at.`,\n );\n }\n\n // Mirrors the compile-time check, for a router written in JavaScript or\n // behind a cast: a param left undeclared would otherwise be the model's.\n const params: PathParam[] = [...url.matchAll(PATH_PARAM)].map(([, param, modifier]) => ({\n name: param,\n modifier,\n }));\n const declared = meta.params ?? {};\n for (const param of params) {\n if (!(param.name in declared)) {\n throw new Error(\n `${where}: the path param \"${param.name}\" must be bound or declared \"input\".`,\n );\n }\n }\n for (const [key, binder] of Object.entries(declared)) {\n if (!params.some((param) => param.name === key)) {\n throw new Error(`${where}: \"${key}\" in params is not a param of the url.`);\n }\n assertBinder(where, `params.${key}`, binder);\n }\n\n let jsonKeys: string[] = [];\n let base: JSONSchema | undefined;\n if (meta.input) {\n base = meta.input.toJSONSchema();\n if (base.type !== \"object\" || !base.properties) {\n throw new Error(\n `${where}: input must be an s.object(...), the fields of the request body.`,\n );\n }\n jsonKeys = Object.keys(base.properties);\n }\n\n const fileFields = Object.entries(meta.files ?? {}).map(([field, binder]) => ({\n name: field,\n binder,\n }));\n for (const file of fileFields) {\n assertBinder(where, `files.${file.name}`, file.binder);\n }\n if (meta.result !== undefined && typeof meta.result !== \"function\") {\n throw new Error(`${where}: result must be a function.`);\n }\n if (meta.output !== undefined && typeof meta.output?.safeParse !== \"function\") {\n throw new Error(`${where}: output must be a schema, built with s.`);\n }\n if (fileFields.length > 0 && method === \"GET\") {\n throw new Error(`${where}: a GET has no body to carry a file.`);\n }\n\n const extras: Record<string, AnySchema> = {};\n const paramBinders = new Map<string, McpParamBinder>();\n for (const param of params) {\n const binder = declared[param.name];\n if (binder === \"input\") {\n const field = s.string().describe(`The \":${param.name}\" segment of the url.`);\n extras[param.name] =\n param.modifier === \"?\" || param.modifier === \"*\" ? field.optional() : field;\n } else {\n paramBinders.set(param.name, binder);\n }\n }\n for (const file of fileFields) {\n if (file.binder === \"input\") {\n extras[file.name] = s\n .string()\n .describe(\n \"The id of an attachment the user uploaded or a tool produced (gemi_att_…), whose file is sent as this field.\",\n );\n }\n }\n // A bound file is not the model's, but it shares the form with the input,\n // so it collides all the same.\n const bodyKeys = [...Object.keys(extras), ...fileFields.map((file) => file.name)];\n for (const key of new Set(bodyKeys)) {\n if (jsonKeys.includes(key)) {\n throw new Error(\n `${where}: \"${key}\" is both an input field and a param or file, and the model can only send one.`,\n );\n }\n }\n\n return {\n descriptor: Object.freeze({\n name,\n description: meta.description,\n method,\n url,\n inputSchema: combineSchemas(meta.input, base, s.object(extras)),\n ...(meta.output ? { outputSchema: meta.output } : {}),\n annotations: annotationsFor(method),\n tags: Object.freeze([...(meta.tags ?? [])]),\n requiresApproval: meta.requiresApproval === true,\n ...(entry.source ? { source: entry.source } : {}),\n }),\n params,\n paramBinders,\n fileFields,\n jsonKeys,\n ...(meta.result ? { result: meta.result } : {}),\n };\n }\n\n // --- calling -------------------------------------------------------------\n\n private async fillPath(plan: Plan, call: McpCallContext): Promise<string> {\n const { input, req } = call;\n let path = plan.descriptor.url;\n for (const param of plan.params) {\n const binder = plan.paramBinders.get(param.name);\n let value: unknown;\n if (binder) {\n value = await this.bind(plan, `the param \"${param.name}\"`, () => binder(req, call));\n if (value === undefined || value === null || value === \"\") {\n console.error(\n `[gemi/mcp] The binder for \"${param.name}\" of \"${plan.descriptor.name}\" returned ${JSON.stringify(value)}.`,\n );\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n } else {\n value = input[param.name];\n }\n\n const token = `:${param.name}${param.modifier}`;\n if (value === undefined || value === null || value === \"\") {\n if (param.modifier !== \"?\" && param.modifier !== \"*\") {\n throw new McpToolError(`\"${param.name}\" of \"${plan.descriptor.name}\" must not be empty.`);\n }\n path = path.replace(`/${token}`, \"\");\n continue;\n }\n path = path.replace(token, encodeSegment(plan.descriptor.name, param, String(value)));\n }\n return path;\n }\n\n private async formData(\n plan: Plan,\n json: Record<string, unknown>,\n call: McpCallContext,\n ): Promise<FormData> {\n const { input, ctx } = call;\n const name = plan.descriptor.name;\n if (!ctx) {\n throw new Error(\n `McpRegistry: \"${name}\" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`,\n );\n }\n const form = new FormData();\n for (const [key, value] of Object.entries(json)) {\n appendField(form, key, value);\n }\n for (const field of plan.fileFields) {\n const id =\n field.binder === \"input\"\n ? (input[field.name] as string)\n : await this.bind(plan, `the file \"${field.name}\"`, () =>\n (field.binder as McpFileBinder)(ctx, call),\n );\n if (typeof id !== \"string\" || id === \"\") {\n throw new McpToolError(\n `\"${name}\" needs a file for \"${field.name}\", and this turn has none. Ask the user to attach one.`,\n );\n }\n // Scoped to the caller: someone else's id is a not-found, worded like an\n // invented one, and that error is what the model reads.\n form.append(field.name, await ctx.attachments.file(id));\n }\n return form;\n }\n\n /**\n * A 2xx put through the meta's `result` and `output`, for a tool that has\n * either.\n *\n * The whole body is parsed and projected before anything is cut: trimming a\n * large answer down is what a projection is for, and cutting first would\n * hand `result` half a JSON document. The projected value is then held to\n * `MAX_RESULT_BODY` the way any answer is.\n *\n * Every failure here is the app's, not the model's — a route that answered\n * something other than JSON, a `result` that threw, an answer `output` does\n * not describe — so each is logged and the model is told only that the\n * tool failed. Telling it more would invite a retry of a call that already\n * did what it does.\n */\n private async project(plan: Plan, call: McpCallContext, response: Response): Promise<unknown> {\n const { name, outputSchema } = plan.descriptor;\n if (response.status < 200 || response.status >= 300) {\n return await readResponse(name, response);\n }\n const failed = (why: string, error?: unknown) => {\n if (error === undefined) console.error(`[gemi/mcp] \"${name}\" ${why}`);\n else console.error(`[gemi/mcp] \"${name}\" ${why}`, error);\n return new McpToolError(`\"${name}\" failed on the server.`, 500);\n };\n\n const type = response.headers.get(\"Content-Type\");\n const text = await response.text();\n let data: unknown = null;\n if (text !== \"\") {\n try {\n data = JSON.parse(text);\n } catch {\n throw failed(\n `answered ${type ?? \"a body with no content-type\"} that is not JSON, and its result or output needs JSON.`,\n );\n }\n }\n\n let value = data;\n if (plan.result) {\n try {\n value = await plan.result(data, call);\n } catch (error) {\n throw failed(\"failed in its result projection:\", error);\n }\n }\n if (outputSchema) {\n const parsed = outputSchema.safeParse(value);\n if (parsed.ok === false) {\n throw failed(`answered what its output schema refuses: ${parsed.errors.join(\", \")}`);\n }\n value = parsed.value;\n }\n\n if (value === undefined) return null;\n const serialised = JSON.stringify(value);\n if (serialised !== undefined && serialised.length > MAX_RESULT_BODY) {\n return `${serialised.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${serialised.length} characters]`;\n }\n return value;\n }\n\n /**\n * Runs an app's binder. Its failure is the server's, not the model's, so the\n * model is told only that; the app gets the error in its log.\n */\n private async bind<T>(plan: Plan, what: string, fn: () => T | Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (error) {\n console.error(`[gemi/mcp] Binding ${what} of \"${plan.descriptor.name}\" failed:`, error);\n throw new McpToolError(`\"${plan.descriptor.name}\" failed on the server.`, 500);\n }\n }\n}\n\nfunction assertLocal(caller: McpCaller): asserts caller is Extract<McpCaller, { kind: \"local\" }> {\n if (caller?.kind !== \"local\") {\n throw new Error(\n \"McpRegistry: only local callers are implemented. A remote caller needs a bearer-token resolver, which v1 does not have — and until it does there is no remote surface to call from.\",\n );\n }\n}\n\n/** A binder is a function or `\"input\"`; anything else would leave the value to nobody. */\nfunction assertBinder(where: string, at: string, binder: unknown) {\n if (binder !== \"input\" && typeof binder !== \"function\") {\n throw new Error(`${where}: ${at} must be a function or \"input\".`);\n }\n}\n\nfunction annotationsFor(method: McpMethod): McpToolAnnotations {\n switch (method) {\n case \"GET\":\n return Object.freeze({ readOnlyHint: true as const });\n case \"DELETE\":\n return Object.freeze({ destructiveHint: true as const });\n case \"PUT\":\n return Object.freeze({ idempotentHint: true as const });\n default:\n return Object.freeze({});\n }\n}\n\n/**\n * One schema out of two: the app's `input`, and the strings for `\"input\"`\n * params and files.\n *\n * Built by hand, like `questionSchema` in `ai/Agent.ts`, rather than by\n * widening `s` with a merge: `Schema.ts` is deliberately the strict\n * structured-output subset and owns no operation on a finished schema. Both\n * halves are real `s` schemas, each parses the whole value and drops the keys\n * that are not its own — which is also where a bound param the model sent\n * anyway disappears, since neither half declares it.\n */\nfunction combineSchemas(\n input: AnySchema | undefined,\n base: JSONSchema | undefined,\n extras: AnySchema,\n): Schema<Record<string, unknown>> {\n const extra = extras.toJSONSchema();\n const json: JSONSchema = {\n ...(base ?? {}),\n type: \"object\",\n properties: { ...(base?.properties ?? {}), ...extra.properties },\n required: [...(base?.required ?? []), ...(extra.required ?? [])],\n additionalProperties: false,\n };\n\n const safeParse = (value: unknown) => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return { ok: false as const, errors: [\"expected an object\"] };\n }\n const errors: string[] = [];\n let out: Record<string, unknown> = {};\n if (input) {\n const own = input.safeParse(value);\n if (own.ok === false) errors.push(...own.errors);\n else out = { ...own.value };\n }\n const more = extras.safeParse(value);\n if (more.ok === false) errors.push(...more.errors);\n else out = { ...out, ...more.value };\n return errors.length > 0 ? { ok: false as const, errors } : { ok: true as const, value: out };\n };\n\n return {\n toJSONSchema: () => json,\n safeParse,\n parse(value: unknown) {\n const result = safeParse(value);\n if (result.ok === false) throw new Error(result.errors.join(\", \"));\n return result.value;\n },\n } as unknown as Schema<Record<string, unknown>>;\n}\n\n/**\n * A model-supplied param, as one encoded path segment. `.` and `..` are\n * refused rather than encoded: they encode to themselves, and URL parsing\n * would walk them out of the route.\n */\nfunction encodeSegment(tool: string, param: PathParam, value: string): string {\n const parts = param.modifier === \"*\" || param.modifier === \"+\" ? value.split(\"/\") : [value];\n if (parts.some((part) => part === \".\" || part === \"..\")) {\n throw new McpToolError(`\"${value}\" is not a valid value for \"${param.name}\" of \"${tool}\".`);\n }\n return parts.map(encodeURIComponent).join(\"/\");\n}\n\n/**\n * A JSON field as a multipart form field. A form has only strings, so the\n * route reads `\"12\"` where a JSON body would have carried `12` — what a\n * browser form sends the same route. An array becomes the key repeated, which\n * `HttpRequest` reads back as an array.\n */\nfunction appendField(form: FormData, key: string, value: unknown) {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) appendField(form, key, item);\n return;\n }\n form.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n}\n\n/** A GET's input, as the query string `HttpRequest.search` reads. */\nfunction toQuery(json: Record<string, unknown>): string {\n const search = new URLSearchParams();\n const add = (key: string, value: unknown) => {\n if (value === undefined || value === null) return;\n if (Array.isArray(value)) {\n for (const item of value) add(key, item);\n return;\n }\n search.append(key, typeof value === \"object\" ? JSON.stringify(value) : String(value));\n };\n for (const [key, value] of Object.entries(json)) add(key, value);\n return search.toString();\n}\n\nasync function readResponse(name: string, response: Response): Promise<unknown> {\n if (response.status >= 200 && response.status < 300) {\n const type = response.headers.get(\"Content-Type\");\n if (type && !READABLE.test(type)) {\n const size = (await response.arrayBuffer()).byteLength;\n return `\"${name}\" answered with ${size} bytes of ${type}, which is not shown.`;\n }\n const text = await response.text();\n if (text === \"\") return null;\n if (text.length > MAX_RESULT_BODY) {\n return `${text.slice(0, MAX_RESULT_BODY)}… [cut at ${MAX_RESULT_BODY} of ${text.length} characters]`;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n const text = await response.text();\n if (response.status >= 400 && response.status < 500) {\n const shown = text.length > MAX_ERROR_BODY ? `${text.slice(0, MAX_ERROR_BODY)}…` : text;\n throw new McpToolError(\n `\"${name}\" was refused with ${response.status}${shown ? `: ${shown}` : \".\"}`,\n response.status,\n );\n }\n if (response.status < 500) {\n // A redirect, or a 1xx: nothing the model can follow, and nothing the\n // dispatcher logged.\n console.error(\n `[gemi/mcp] \"${name}\" answered ${response.status}${response.headers.get(\"Location\") ? ` to ${response.headers.get(\"Location\")}` : \"\"}, which a tool call cannot follow.`,\n );\n }\n throw new McpToolError(`\"${name}\" failed on the server.`, response.status);\n}\n",
27
27
  "import { ServiceProvider } from \"../../support/ServiceProvider\";\nimport { McpRegistry } from \"../mcp/McpRegistry\";\nimport { ApiRouteDispatcher } from \"./ApiRouteDispatcher\";\nimport { DomainRouter } from \"./DomainRouter\";\nimport { ViewRouteDispatcher } from \"./ViewRouteDispatcher\";\nimport type { ApiRouteConfig, DomainsConfig, McpRouteConfig, ViewRouteConfig } from \"./config\";\nimport type { Repository } from \"../../support/Repository\";\n\nfunction readConfig<T>(config: Repository, key: string): T {\n const slice = config.get<T>(key);\n if (!slice) {\n throw new Error(\n `Missing \"${key}\" configuration. Route dispatching needs a root router — declare it in \"app/config/route.ts\".`,\n );\n }\n return slice;\n}\n\n/**\n * Owns both route dispatchers. Laravel ships a single RouteServiceProvider for\n * every route file it loads; the api/view split is a config slice, not a\n * separate provider.\n */\nexport class RouteServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n ApiRouteDispatcher,\n () =>\n new ApiRouteDispatcher(\n readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n ),\n );\n\n this.app.singleton(\n ViewRouteDispatcher,\n () =>\n new ViewRouteDispatcher(\n readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n ),\n );\n\n // The root pair above is the root group's; the other `route.domains`\n // groups get their own only when they bring their own routers.\n this.app.singleton(\n DomainRouter,\n () =>\n new DomainRouter(\n { api: this.app.make(ApiRouteDispatcher), view: this.app.make(ViewRouteDispatcher) },\n {\n api: readConfig<ApiRouteConfig>(this.app.config, \"route.api\"),\n view: readConfig<ViewRouteConfig>(this.app.config, \"route.view\"),\n domains: this.app.config.get<DomainsConfig | undefined>(\"route.domains\"),\n },\n ),\n );\n\n // Bound whether or not the app declares one, so asking for it without\n // `route.mcp` fails with a sentence rather than an unbound token.\n this.app.singleton(McpRegistry, () => {\n const config = this.app.config.get<McpRouteConfig | undefined>(\"route.mcp\");\n if (!config?.router) {\n throw new Error(\n 'No MCP router is configured. Declare one as `mcp: { router }` in \"app/config/route.ts\".',\n );\n }\n return new McpRegistry(new config.router(), this.app.make(ApiRouteDispatcher));\n });\n }\n\n /**\n * The dispatchers of every host group, and the MCP registry when an app declares one, must\n * not be built lazily: constructing the dispatchers flattens the route\n * tables and runs `assertNoReservedRoutePaths`, and constructing the registry\n * resolves every tool against those tables. A missing `route` config, a\n * route under a reserved prefix or a tool naming a route that is gone has to\n * fail the boot rather than the first request, or the first tool call, that\n * happens to hit it.\n */\n boot() {\n this.app.make(ApiRouteDispatcher);\n this.app.make(ViewRouteDispatcher);\n // Builds every host group's dispatchers and validates `route.domains`.\n this.app.make(DomainRouter);\n if (this.app.config.get(\"route.mcp\")) {\n this.app.make(McpRegistry);\n }\n }\n}\n"
28
28
  ],
29
- "mappings": "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",
30
- "debugId": "C0398D840F2B9D2C64756E2164756E21",
29
+ "mappings": "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",
30
+ "debugId": "94EFED1EEB0E7ED064756E2164756E21",
31
31
  "names": []
32
32
  }
@@ -0,0 +1,9 @@
1
+ // @bun
2
+ import{Af as GH,Bf as n,zf as R}from"./chunk-9xf2fx98.js";import{Ef as C}from"./chunk-eqtsfvvd.js";import{Kg as qH}from"./chunk-48dek9s7.js";import{Wg as b}from"./chunk-n63xjrck.js";import{bh as W0}from"./chunk-68zf43ah.js";class YH{static kind="controller";constructor(){}}class gH extends YH{}function t(H){let G=new Map;if(!H)return G;for(let Q of H.split(";")){let Z=Q.indexOf("=");if(Z===-1)continue;let X=Q.slice(0,Z).trim();if(!X)continue;G.set(X,Q.slice(Z+1).trim())}return G}function F0(H){return t(H.headers.get("cookie"))}function I(H){if(!/^\d+$/.test(H))return null;let G=Number(H);return Number.isSafeInteger(G)?G:null}function MH(H){if(!H)return null;let G=H.trim();if(!/^bytes=/i.test(G))return null;let Z=G.slice(6).split(",").map((U)=>U.trim()).filter((U)=>U!=="");if(Z.length!==1)return null;let X=Z[0],$=X.indexOf("-");if($===-1)return null;let K=X.slice(0,$),T=X.slice($+1);if(K===""){let U=I(T);if(U===null)return null;return{kind:"suffix",suffixLength:U}}let W=I(K);if(W===null)return null;if(T==="")return{kind:"offset",start:W,end:null};let Y=I(T);if(Y===null||Y<W)return null;return{kind:"offset",start:W,end:Y}}function DH(H,G){if(!Number.isFinite(G)||G<=0)return null;let Q,Z;if(H.kind==="suffix"){if(H.suffixLength<=0)return null;Q=Math.max(0,G-H.suffixLength),Z=G-1}else{if(H.start>=G)return null;if(Q=H.start,Z=H.end===null?G-1:Math.min(H.end,G-1),Z<Q)return null}return{start:Q,end:Z,length:Z-Q+1}}function L0(H){if(H.kind==="suffix")return`bytes=-${H.suffixLength}`;return H.end===null?`bytes=${H.start}-`:`bytes=${H.start}-${H.end}`}function J0(H){if(!H)return null;let G=/^bytes\s+(\d+)-(\d+)\/(\d+)$/i.exec(H.trim());if(!G)return null;let Q=I(G[1]),Z=I(G[2]),X=I(G[3]);if(Q===null||Z===null||X===null||Z<Q)return null;return{start:Q,end:Z,total:X}}function C0(H,G,Q){return`bytes ${H}-${G}/${Q}`}function UH(H){return`bytes */${H}`}class w extends R{errors={};constructor(H){super("Validation error");this.name="ValidationError",this.errors=H,this.payload={api:{status:400,data:{error:{kind:"validation_error",messages:H,status:400}},headers:{"Content-Type":"application/json"}},view:{status:400}}}}function yH(H){let[G,Q]=H.match(/\d+|\D+/g)??[];if(!G||!Q)return 0;let Z=Number.parseInt(G);switch(Q){case"B":return Z;case"KB":return Z*1024;case"MB":return Z*1024*1024;case"GB":return Z*1024*1024*1024;case"TB":return Z*1024*1024*1024*1024;default:return 0}}function kH(H){switch(H){case"image":return"image";case"png":return"image/png";case"jpg":return"image/jpeg";case"jpeg":return"image/jpeg";case"ttf":return"font/ttf";case"excel":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";case"csv":return"text/csv";case"word":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case"pdf":return"application/pdf";case"json":return"application/json";default:return H}}function PH(H){if(typeof H==="string"||Array.isArray(H))return H.length;return}function r(H){return typeof H==="number"&&!Number.isNaN(H)}var bH=["required","string","boolean","number","email","password","min","max","gte","lte","file","fileType","fileSize","array","object","in"];class J extends Error{name="InvalidValidationRuleError"}function v(H,G){let Q=G===void 0||G.trim()===""?Number.NaN:Number(G);if(Number.isNaN(Q))throw new J(`Validation rule "${H}:${G??""}" needs a number, e.g. "${H}:3"`);return Q}function BH(H){let G=H.indexOf(":"),Q=G===-1?H:H.slice(0,G),Z=G===-1?void 0:H.slice(G+1);switch(Q){case"required":return(X)=>{if(X instanceof Blob)return X.size>0;if(X===null||X===void 0)return!1;if(typeof X==="string"||Array.isArray(X))return X.length>0;return!0};case"string":return(X)=>typeof X==="string";case"boolean":return(X)=>typeof X==="boolean";case"number":return(X)=>r(X);case"password":return(X)=>{return typeof X==="string"&&/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/.test(X)};case"min":{let X=v(Q,Z);return($)=>{let K=PH($);return K!==void 0&&K>=X}}case"max":{let X=v(Q,Z);return($)=>{let K=PH($);return K!==void 0&&K<=X}}case"gte":{let X=v(Q,Z);return($)=>r($)&&$>=X}case"lte":{let X=v(Q,Z);return($)=>r($)&&$<=X}case"email":return(X)=>{return typeof X==="string"&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(X)};case"file":return(X)=>{return X instanceof Blob};case"fileType":{if(!Z)throw new J('Validation rule "fileType" needs a type, e.g. "fileType:png" or "fileType:image"');let X=kH(Z);return($)=>$ instanceof Blob&&$.type.startsWith(X)}case"fileSize":{let X=yH(Z??"");if(X===0&&!/^0+(B|KB|MB|GB|TB)$/.test(Z??""))throw new J(`Validation rule "fileSize:${Z??""}" needs a whole size in B, KB, MB, GB or TB, e.g. "fileSize:5MB"`);return($)=>$ instanceof Blob&&$.size<=X}case"array":return(X)=>Array.isArray(X);case"object":return(X)=>typeof X==="object"&&X!==null&&!Array.isArray(X)&&!(X instanceof Blob);case"in":{let X=(Z??"").split(",").filter(($)=>$!=="");if(X.length===0)throw new J('Validation rule "in" needs a comma-separated list, e.g. "in:draft,published"');return($)=>typeof $==="string"&&X.includes($)}default:throw new J(`Unknown validation rule "${H}". Known rules: ${bH.join(", ")}`)}}function q(H){if(!H.definition)throw Error(`gemi/ai: the recursive schema "${H.name}" was used before its definition returned; \`self\` can be nested into the schema, but not parsed or emitted inside the callback`);return H.definition}var o=new WeakMap;function AH(H){return typeof H==="object"&&H!==null&&o.has(H)}function c(H){let G=o.get(H);if(!G)throw Error("gemi/ai: expected a schema built with `s`, got a foreign object");return G}function fH(H){let G={defs:{},cells:new Map},Q=H;if(H.node.kind==="ref"){let X=q(H.node.cell);Q={...X,...H.description?{description:H.description}:{},optional:H.optional,nullable:H.nullable||X.nullable}}let Z=x(Q,G);return Object.keys(G.defs).length>0?{...Z,$defs:G.defs}:Z}function x(H,G){let Q=(H.optional||H.nullable)&&H.node.kind!=="json",Z=cH(pH(H.node,G),Q),X=[H.description,vH(H.node)].filter(Boolean).join(" ");if(X&&Z.$ref!==void 0)Z={anyOf:[Z]};return X?{description:X,...Z}:Z}function vH(H){let G=[];if(H.kind==="string"||H.kind==="enum"){let Q=H.checks;if(Q?.format)G.push(`Format: ${Q.format.name}.`);if(Q?.minLength!==void 0)G.push(`At least ${Q.minLength} characters.`);if(Q?.maxLength!==void 0)G.push(`At most ${Q.maxLength} characters.`)}else if(H.kind==="number"){let Q=H.checks;if(Q?.minimum!==void 0)G.push(`Minimum ${Q.minimum}.`);if(Q?.exclusiveMinimum!==void 0)G.push(`Greater than ${Q.exclusiveMinimum}.`);if(Q?.maximum!==void 0)G.push(`Maximum ${Q.maximum}.`);if(Q?.exclusiveMaximum!==void 0)G.push(`Less than ${Q.exclusiveMaximum}.`)}else if(H.kind==="array"){let Q=H.checks;if(Q?.minItems!==void 0)G.push(`At least ${Q.minItems} items.`);if(Q?.maxItems!==void 0)G.push(`At most ${Q.maxItems} items.`)}return G.join(" ")}function pH(H,G){switch(H.kind){case"string":return{type:"string"};case"number":return{type:H.checks?.integer?"integer":"number"};case"boolean":return{type:"boolean"};case"literal":return{type:typeof H.value,const:H.value};case"enum":return{type:"string",enum:H.values};case"array":return{type:"array",items:x(H.item,G)};case"object":return{type:"object",properties:Object.fromEntries(Object.entries(H.shape).map(([Q,Z])=>[Q,x(Z,G)])),required:Object.keys(H.shape),additionalProperties:!1};case"union":return{anyOf:H.members.map((Q)=>x(Q,G))};case"json":return{};case"ref":{let{cell:Q}=H,Z=G.cells.get(Q.name);if(Z&&Z!==Q)throw Error(`gemi/ai: two different recursive schemas are named "${Q.name}" in one schema; give each s.recursive(...) its own name`);if(!Z)G.cells.set(Q.name,Q),G.defs[Q.name]={},G.defs[Q.name]=x(q(Q),G);return{$ref:`#/$defs/${Q.name}`}}}}function cH(H,G){if(!G)return H;if(H.anyOf)return{...H,anyOf:[...H.anyOf,{type:"null"}]};if(H.enum||H.const!==void 0)return{anyOf:[H,{type:"null"}]};if(typeof H.type==="string")return{...H,type:[H.type,"null"]};return{anyOf:[H,{type:"null"}]}}function hH(H){if(H===null)return"null";if(Array.isArray(H))return"array";return typeof H}function mH(H,G){if(typeof G==="number"&&!Number.isFinite(G))return String(G);if(H.kind==="literal"||H.kind==="enum"){if(typeof G==="string"||typeof G==="number"||typeof G==="boolean")return JSON.stringify(G)}return hH(G)}function FH(H){let G=H.node,Q=(()=>{switch(G.kind){case"number":return G.checks?.integer?"integer":"number";case"string":case"boolean":return G.kind;case"literal":return JSON.stringify(G.value);case"enum":return`one of ${G.values.map((Z)=>JSON.stringify(Z)).join(" | ")}`;case"array":return"array";case"object":return"object";case"union":return"one of the variants";case"json":return"a JSON value";case"ref":return FH({...q(G.cell),optional:!1,nullable:!1})}})();return H.optional||H.nullable?`${Q} or null`:Q}function dH(H){let G="";for(let Q of H)G+=typeof Q==="number"?`[${Q}]`:G?`.${Q}`:Q;return G}function uH(H){let G=dH(H);return G?`${G}: `:""}function l(H){return`${uH(H.path)}${H.message}`}function h(H,G){if(G===null||G===void 0)return H.optional||H.nullable?1:0;let Q=H.node;switch(Q.kind){case"string":return typeof G==="string"?1:0;case"number":return typeof G==="number"?1:0;case"boolean":return typeof G==="boolean"?1:0;case"literal":return G===Q.value?10:0;case"enum":return typeof G==="string"&&Q.values.includes(G)?10:0;case"array":return Array.isArray(G)?1:0;case"object":{if(typeof G!=="object"||Array.isArray(G))return 0;let Z=G,X=1;for(let[$,K]of Object.entries(Q.shape))X+=h(K,Z[$]);return X}case"union":return Q.members.reduce((Z,X)=>Math.max(Z,h(X,G)),0);case"json":return 1;case"ref":return zH(Q.cell,G,()=>1,()=>h(q(Q.cell),G))}}function zH(H,G,Q,Z){if(typeof G!=="object"||G===null)return Z();if(H.active.has(G))return Q();H.active.add(G);try{return Z()}finally{H.active.delete(G)}}function _(H,G,Q,Z){if(H.optional&&(G===null||G===void 0))return{drop:!0,value:void 0};if(H.nullable&&G===null)return{drop:!1,value:null};return{drop:!1,value:oH(H,G,Q,Z)}}function oH(H,G,Q,Z){let X=H.node,$=()=>{let K=G===void 0?"required":X.kind==="literal"?"const":X.kind==="enum"&&typeof G==="string"?"enum":"type",T=K==="const"?{allowedValue:X.value}:K==="enum"?{allowedValues:X.values}:{};Z.push({path:Q,code:K,message:`expected ${FH(H)}, got ${mH(X,G)}`,params:T});return};switch(X.kind){case"string":if(typeof G!=="string")return $();return RH(X.checks,G,Q,Z),G;case"number":if(typeof G!=="number"||!Number.isFinite(G))return $();if(X.checks?.integer&&!Number.isInteger(G))return $();return iH(X.checks,G,Q,Z),G;case"boolean":return typeof G==="boolean"?G:$();case"literal":return G===X.value?G:$();case"enum":if(typeof G!=="string"||!X.values.includes(G))return $();return RH(X.checks,G,Q,Z),G;case"array":{if(!Array.isArray(G))return $();let K=G.map((Y,U)=>{let N=_(X.item,Y,[...Q,U],Z);return N.drop?void 0:N.value}),{minItems:T,maxItems:W}=X.checks??{};if(T!==void 0&&G.length<T)Z.push({path:Q,code:"minItems",message:`expected at least ${T} items, got ${G.length}`,params:{limit:T}});if(W!==void 0&&G.length>W)Z.push({path:Q,code:"maxItems",message:`expected at most ${W} items, got ${G.length}`,params:{limit:W}});return K}case"object":{if(typeof G!=="object"||G===null||Array.isArray(G))return $();let K=G,T={};for(let[W,Y]of Object.entries(X.shape)){let U=_(Y,K[W],[...Q,W],Z);if(!U.drop)T[W]=U.value}return T}case"union":{let K;for(let T of X.members){let W=[],Y=_(T,G,Q,W);if(W.length===0)return Y.drop?void 0:Y.value;let U=h(T,G);if(!K||U>K.score)K={issues:W,score:U}}Z.push({path:Q,code:"anyOf",message:`no matching variant; closest: ${K.issues.map(l).join("; ")}`,params:{closest:K.issues}});return}case"json":if(G===void 0)return $();return m(G,Q,Z,new Set),G;case"ref":return zH(X.cell,G,()=>{Z.push({path:Q,code:"type",message:"expected a finite tree, got a circular reference",params:{}});return},()=>_(q(X.cell),G,Q,Z).value)}}function nH(H){let G=0;for(let Q of H)G++;return G}function RH(H,G,Q,Z){if(!H)return;let{minLength:X,maxLength:$,format:K}=H;if(X!==void 0||$!==void 0){let T=nH(G);if(X!==void 0&&T<X)Z.push({path:Q,code:"minLength",message:`expected at least ${X} characters, got ${T}`,params:{limit:X}});if($!==void 0&&T>$)Z.push({path:Q,code:"maxLength",message:`expected at most ${$} characters, got ${T}`,params:{limit:$}})}if(K){let T=!1;try{T=K.test(G)===!0}catch{}if(!T)Z.push({path:Q,code:"format",message:`expected a string in format "${K.name}"`,params:{format:K.name}})}}function iH(H,G,Q,Z){if(!H)return;let X=($,K,T,W)=>{if(K===void 0||T(K))return;Z.push({path:Q,code:$,message:`expected ${W} ${K}, got ${G}`,params:{limit:K}})};X("minimum",H.minimum,($)=>G>=$,"at least"),X("exclusiveMinimum",H.exclusiveMinimum,($)=>G>$,"more than"),X("maximum",H.maximum,($)=>G<=$,"at most"),X("exclusiveMaximum",H.exclusiveMaximum,($)=>G<$,"less than")}function m(H,G,Q,Z,X=!0){let $=(T)=>{Q.push({path:G,code:"type",message:`expected a JSON value, got ${T}`,params:{}})};switch(typeof H){case"undefined":case"string":case"boolean":return;case"number":if(!Number.isFinite(H))$(String(H));return;case"bigint":return $("a bigint");case"function":return $("a function");case"symbol":return $("a symbol")}if(H===null)return;let K=H;if(Z.has(K))return $("a circular reference");Z.add(K);try{let T=X?K.toJSON:void 0;if(typeof T==="function"){let W;try{W=T.call(K)}catch{return $("a toJSON that threw")}if(W===void 0)return $("a toJSON that returns undefined");return m(W,G,Q,Z,!1)}if(Array.isArray(H))H.forEach((W,Y)=>m(W,[...G,Y],Q,Z));else for(let[W,Y]of Object.entries(K))m(Y,[...G,W],Q,Z)}finally{Z.delete(K)}}function A(H){return d(H)}function d(H){let G={toJSONSchema:()=>fH(H),parse(Q){let Z=[],X=_(H,Q,[],Z);if(Z.length>0)throw Error(Z.map(l).join("; "));return X.drop?void 0:X.value},safeParse(Q){let Z=[],X=_(H,Q,[],Z);if(Z.length>0)return{ok:!1,errors:Z.map(l)};return{ok:!0,value:X.drop?void 0:X.value}},validate(Q){let Z=[],X=_(H,Q,[],Z);if(Z.length>0)return{ok:!1,issues:Z};return{ok:!0,value:X.drop?void 0:X.value}},describe:(Q)=>d({...H,description:Q}),optional:()=>d({...H,optional:!0}),nullable:()=>d({...H,nullable:!0,optional:!1})};return o.set(G,H),G}function z(H){return{node:H,optional:!1,nullable:!1}}class LH extends Error{problems;constructor(H){super(`gemi/ai: s.fromJSONSchema cannot model this schema:
3
+ ${H.map((G)=>`- ${G}`).join(`
4
+ `)}`);this.name="JSONSchemaError",this.problems=H}}var tH=new Set(["title","$schema","$id","$comment","examples","default","deprecated","readOnly","writeOnly"]),S={string:["minLength","maxLength","format"],number:["minimum","maximum","exclusiveMinimum","exclusiveMaximum"],integer:["minimum","maximum","exclusiveMinimum","exclusiveMaximum"],boolean:[],object:["properties","required","additionalProperties"],array:["items","minItems","maxItems"]};function p(H){return typeof H==="object"&&H!==null&&!Array.isArray(H)}function u(H,G,Q,Z){let X=(M,D=Q)=>{Z.push(D?`${D}: ${M}`:M);return},$=(M)=>Q?`${Q}.${M}`:M;if(!p(H))return X("expected a schema object");let K=new Set(G.ignoreKeywords??[]),T=(M)=>tH.has(M)||M.startsWith("x-")||K.has(M),W=!1,Y=H.type;if(Array.isArray(Y)){let M=Y.filter((D)=>D!=="null");if(M.length!==1)return X(`type ${JSON.stringify(Y)} is not supported; only one type, optionally with "null". Use anyOf for alternatives`,$("type"));W=M.length<Y.length,Y=M[0]}if(Y!==void 0&&(typeof Y!=="string"||!(Y in S)))return X(`type ${JSON.stringify(Y)} is not supported; expected one of ${Object.keys(S).join(", ")}`,$("type"));let U=new Set(["type","description","enum","const","anyOf",...Y?S[Y]:[]]),N=!1;for(let M of Object.keys(H)){if(U.has(M)||T(M))continue;N=!0;let D=Object.entries(S).find(([,B])=>B.includes(M));X(D&&D[0]!==Y?`"${M}" applies to type ${D[0]}, and this schema is ${Y?`type ${Y}`:"untyped"}`:`"${M}" is not supported by s.fromJSONSchema`,$(M))}if(N)return;if(H.description!==void 0&&typeof H.description!=="string")return X("expected a string",$("description"));let f=H.description,L=(M)=>({node:M,optional:!1,nullable:W,...f?{description:f}:{}});if(H.anyOf!==void 0){if(Y!==void 0||H.enum!==void 0||H.const!==void 0)return X("anyOf cannot be combined with type, enum or const here",$("anyOf"));if(!Array.isArray(H.anyOf)||H.anyOf.length===0)return X("expected a non-empty array",$("anyOf"));let M=[],D=!1;if(H.anyOf.forEach((B,P)=>{if(p(B)&&B.type==="null"&&Object.keys(B).length===1){W=!0;return}let F=u(B,G,$(`anyOf[${P}]`),Z);if(F)M.push(F);else D=!0}),D)return;if(M.length===0)return X("anyOf has only null in it",$("anyOf"));if(M.length===1){let B=M[0];return{...B,nullable:B.nullable||W,...f?{description:f}:{}}}return L({kind:"union",members:M})}if(H.const!==void 0){let M=H.const;if(typeof M!=="string"&&typeof M!=="number"&&typeof M!=="boolean")return X("only a string, number or boolean const is supported",$("const"));if(Y!==void 0&&typeof M!==(Y==="integer"?"number":Y))return X(`const ${JSON.stringify(M)} is not of type ${Y}`,$("const"));return L({kind:"literal",value:M})}let O;if(Y==="string"){if(O=rH(H,G,$,Z),O===null)return}if(H.enum!==void 0){if(!Array.isArray(H.enum)||H.enum.length===0)return X("expected a non-empty array",$("enum"));let M=H.enum.filter((P)=>P!==null);if(M.length<H.enum.length)W=!0;let D=M.find((P)=>!(typeof P==="string"||typeof P==="number"||typeof P==="boolean")||Y!==void 0&&typeof P!==(Y==="integer"?"number":Y));if(D!==void 0||M.length===0)return X(Y?`every value must be of type ${Y}${M.length===0?", and there must be one":`; ${JSON.stringify(D)} is not`}`:"only strings, numbers and booleans are supported",$("enum"));if(M.every((P)=>typeof P==="string"))return L({kind:"enum",values:[...new Set(M)],...O?{checks:O}:{}});let B=[...new Set(M)];if(B.length===1)return L({kind:"literal",value:B[0]});return L({kind:"union",members:B.map((P)=>z({kind:"literal",value:P}))})}switch(Y){case void 0:return X("a schema needs a type, an enum, a const or an anyOf");case"string":return L({kind:"string",...O?{checks:O}:{}});case"number":case"integer":{let M=Y==="integer"?{integer:!0}:{},D=!1;for(let B of S.number){let P=H[B];if(P===void 0)continue;if(typeof P!=="number"||!Number.isFinite(P)){X("expected a number",$(B)),D=!0;continue}M[B]=P}if(D)return;return L({kind:"number",...Object.keys(M).length>0?{checks:M}:{}})}case"boolean":return L({kind:"boolean"});case"array":{if(!p(H.items))return X('an array needs "items" to be one schema (tuples are not supported)',$("items"));let M={},D=!1;for(let P of["minItems","maxItems"]){let F=H[P];if(F===void 0)continue;if(typeof F!=="number"||!Number.isInteger(F)||F<0){X("expected a non-negative integer",$(P)),D=!0;continue}M[P]=F}let B=u(H.items,G,$("items"),Z);if(!B||D)return;return L({kind:"array",item:B,...Object.keys(M).length>0?{checks:M}:{}})}case"object":{let M=H.properties??{};if(!p(M))return X("expected an object",$("properties"));if(H.additionalProperties!==void 0&&H.additionalProperties!==!1)return X("only false is supported; a record with arbitrary keys has no strict-mode form (use s.json())",$("additionalProperties"));let D=H.required??[];if(!Array.isArray(D)||!D.every((V)=>typeof V==="string"))return X("expected an array of property names",$("required"));let B=D.filter((V)=>!Object.hasOwn(M,V));if(B.length>0)return X(`lists properties the schema doesn't have: ${B.join(", ")}`,$("required"));let P={},F=!1;for(let[V,xH]of Object.entries(M)){let i=u(xH,G,$(`properties.${V}`),Z);if(!i){F=!0;continue}P[V]=D.includes(V)?i:{...i,optional:!0}}if(F)return;return L({kind:"object",shape:P})}}return}function rH(H,G,Q,Z){let X={},$=!1;for(let K of["minLength","maxLength"]){let T=H[K];if(T===void 0)continue;if(typeof T!=="number"||!Number.isInteger(T)||T<0){Z.push(`${Q(K)}: expected a non-negative integer`),$=!0;continue}X[K]=T}if(H.format!==void 0){let K=H.format,T=typeof K==="string"?G.formats?.[K]:void 0;if(typeof K!=="string")Z.push(`${Q("format")}: expected a string`),$=!0;else if(!T||!Object.hasOwn(G.formats,K))Z.push(`${Q("format")}: unknown format ${JSON.stringify(K)}; pass a check for it in the formats option`),$=!0;else X.format={name:K,test:lH(T)}}if($)return null;return Object.keys(X).length>0?X:void 0}function lH(H){if(H===!0)return()=>!0;if(H instanceof RegExp)return(G)=>{return H.lastIndex=0,H.test(G)};return H}var I0={string:()=>A(z({kind:"string"})),number:()=>A(z({kind:"number"})),boolean:()=>A(z({kind:"boolean"})),literal:(H)=>A(z({kind:"literal",value:H})),enum:(H)=>A(z({kind:"enum",values:H})),object:(H)=>A(z({kind:"object",shape:Object.fromEntries(Object.entries(H).map(([G,Q])=>[G,c(Q)]))})),array:(H)=>A(z({kind:"array",item:c(H)})),union:(H)=>A(z({kind:"union",members:H.map(c)})),json:()=>A(z({kind:"json"})),recursive:aH,fromJSONSchema:(H,G={})=>{let Q=[],Z=u(H,G,"",Q);if(!Z||Q.length>0)throw new LH(Q.length>0?Q:["unreadable schema"]);return A(Z)}};function q0(H){let G=o.get(H);if(G)return y(G.node);return g(H.toJSONSchema())}function g(H){if(!(H.$ref!==void 0||H.type!==void 0||H.enum!==void 0||H.const!==void 0||H.anyOf!==void 0||H.properties!==void 0||H.items!==void 0))return!1;for(let Q of Object.values(H.properties??{}))if(!g(Q))return!1;if(H.items&&!g(H.items))return!1;for(let Q of H.anyOf??[])if(!g(Q))return!1;for(let Q of Object.values(H.$defs??{}))if(!g(Q))return!1;return!0}function y(H,G=new Set){switch(H.kind){case"string":case"number":case"boolean":case"literal":case"enum":return!0;case"object":return Object.values(H.shape).every((Q)=>y(Q.node,G));case"array":return y(H.item.node,G);case"union":return H.members.every((Q)=>y(Q.node,G));case"json":return!1;case"ref":if(G.has(H.cell))return!0;return G.add(H.cell),y(q(H.cell).node,G)}}function s(H,G,Q=new Set){let Z=H.node;if(Z.kind==="union")return Z.members.some((X)=>s(X,G,Q));if(Z.kind!=="ref")return!1;if(Z.cell===G)return!0;if(Q.has(Z.cell)||!Z.cell.definition)return!1;return Q.add(Z.cell),s(Z.cell.definition,G,Q)}var sH=/^[A-Za-z_][A-Za-z0-9_-]{0,63}$/;function aH(H,G){if(typeof H!=="string"||!sH.test(H))throw Error(`gemi/ai: s.recursive needs a name of letters, digits, "_" and "-" (starting with a letter or "_", at most 64), got ${JSON.stringify(H)}`);let Q={name:H,active:new Set},Z=()=>z({kind:"ref",cell:Q}),X=c(G(A(Z())));if(X.optional)throw Error(`gemi/ai: the recursive schema "${H}" is optional() as a whole; mark the places that use it optional instead`);if(s(X,Q))throw Error(`gemi/ai: the recursive schema "${H}" refers to itself outside any object or array, so it describes no finite value; nest \`self\` in an s.object(...) field or an s.array(...)`);return Q.definition=X,A(Z())}function JH(H){if(typeof H!=="string")return null;let[G]=H.split(";",1),Q=G.trim().toLowerCase();return Q===""?null:Q}function CH(H){if(H===null)return!1;if(H==="application/json")return!0;let G=H.indexOf("/");return G>0&&H.endsWith("+json")&&H.length>G+1+5}var a=new WeakMap;function w0(H,G){a.set(H,{clientAddress:G})}function VH(H){return a.has(H)}function S0(H){return a.get(H)?.clientAddress}var _H=new WeakMap;function g0(H,G){_H.set(H,G)}function jH(H){return _H.get(H)??null}var e=new WeakMap;function y0(H,G){let Q=e.get(H)??[];if(!Q.includes(G))e.set(H,[...Q,G])}function k0(H){return e.get(H)??[]}class E{data;constructor(H){this.data=H}get(H){return this.data[H]}has(H){return this.data[H]!==void 0}toJSON(){return this.data}}function OH(H){return typeof H==="object"&&H!==null&&!(H instanceof Blob)}function eH(H,G){if(!G.includes(".")||Object.hasOwn(H,G))return[{path:[G],value:H[G]}];let Q=[{path:[],value:H}];for(let Z of G.split(".")){let X=[];for(let{path:$,value:K}of Q){if(Z==="*"){if(Array.isArray(K))K.forEach((T,W)=>X.push({path:[...$,W],value:T}));else if(OH(K))for(let[T,W]of Object.entries(K))X.push({path:[...$,T],value:W});continue}if(Array.isArray(K)&&/^\d+$/.test(Z)){X.push({path:[...$,Number(Z)],value:K[Number(Z)]});continue}X.push({path:[...$,Z],value:OH(K)&&Object.hasOwn(K,Z)?K[Z]:void 0})}Q=X}return Q}function IH(H){return H.join(".")}class H0{kind;rawRequest;headers;cookies;search;schema={};routePath;params;domain;constructor(H,G,Q,Z){if(!H){let W=C.getStore().req;this.params=W.params,this.rawRequest=W.rawRequest,this.kind=W.kind,this.routePath=W.routePath,this.domain=W.domain??null}else this.params=G,this.rawRequest=H,this.routePath=Z,this.kind=Q??"api",this.domain=jH(H);this.headers=this.rawRequest.headers;let X=t(this.rawRequest.headers.get("Cookie")),$=new URL(this.rawRequest.url),K=new Map;for(let[W,Y]of $.searchParams)if(K.has(W)){let U=K.get(W);if(Array.isArray(U))U.push(Y),K.set(W,U);else K.set(W,[U,Y])}else K.set(W,Y);let T=Object.fromEntries(K.entries());this.search=new E(T),this.cookies=X}locale(){return C.getStore().locale}ctx(){return C.getStore()}isModelOriginated(){return VH(this.rawRequest)}get signal(){return this.rawRequest.signal}range(){return MH(this.rawRequest.headers.get("Range"))}refine(H){return{}}async parseBody(){let H=JH(this.rawRequest.headers.get("Content-Type"));if(CH(H))return new E(await this.parseJsonBody());if(H==="application/x-www-form-urlencoded"||H==="multipart/form-data"){let G;try{G=await this.rawRequest.formData()}catch{throw new R("The request body could not be read as a form.")}let Q=new Map;for(let[Z,X]of G.entries())if(Q.has(Z)){let $=Q.get(Z);if(Array.isArray($))$.push(X);else Q.set(Z,[$,X])}else Q.set(Z,X);return new E(Object.fromEntries(Q.entries()))}return new E({})}async parseJsonBody(){if(!this.rawRequest.body)return{};let H;try{H=await this.rawRequest.text()}catch{throw new R("The request body could not be read.")}if(H.trim()==="")return{};let G;try{G=JSON.parse(H)}catch{throw new R("The request body is not valid JSON.")}if(G===null||typeof G!=="object")throw new R("The request body must be a JSON object.");return G}validateInput(H){if(AH(this.schema))return this.validateWithSchema(H);let G=H.toJSON()??{},Q={},Z=Object.entries(this.schema).map(([X,$])=>({key:X,rules:Object.entries($).map(([K,T])=>({rule:K,message:T,check:typeof T==="function"?null:this.ruleFor(X,K)}))}));for(let{key:X,rules:$}of Z)for(let{path:K,value:T}of eH(G,X)){let W=this.checkField(T,$);if(W.length>0){let Y=Q[IH(K)]??=[];for(let U of W)if(!Y.includes(U))Y.push(U)}}if(this.addRefinements(Q,G),Object.keys(Q).length>0)throw new w(Q);return H}checkField(H,G){let Q=G.some(({rule:$})=>$==="required"),Z=H===void 0||H===null||H==="",X=[];for(let{rule:$,message:K,check:T}of G){let W=K,Y=!1;if(typeof K==="function")W=K(H),Y=typeof W>"u";else Y=T(H);if(Y)continue;if(Z&&!Q)continue;if($==="required")return[String(W)];if(!X.includes(String(W)))X.push(String(W))}return X}validateWithSchema(H){let G=this.schema.validate(H.toJSON()),Q={};if("issues"in G)for(let X of G.issues){let $=IH(X.path),K=Q[$]??=[];if(!K.includes(X.message))K.push(X.message)}let Z="value"in G?new E(G.value):H;if(this.addRefinements(Q,Z.toJSON()),Object.keys(Q).length>0)throw new w(Q);return Z}addRefinements(H,G){for(let[Q,Z]of Object.entries(this.refine(G)??{})){let X=H[Q]??[];H[Q]=X.includes(Z)?X:[...X,Z]}}ruleFor(H,G){try{return BH(G)}catch(Q){if(Q instanceof J)throw new J(`${this.constructor.name}.schema.${H}: ${Q.message}`);throw Q}}async input(){return this.validateInput(await this.parseBody())}async safeInput(){let H=await this.parseBody();try{return{isValid:!0,errors:{},input:this.validateInput(H)}}catch(G){if(!(G instanceof w))throw G;return{isValid:!1,errors:G.errors,input:H}}}}class G0 extends R{error;constructor(H="Not authorized"){super(H);this.name="AuthorizationError",this.error=H,this.payload={api:{status:401,data:{error:n("authorization",this.error,401)}},view:{}}}}class HH extends R{static apiStatus=403;error;constructor(H="Insufficient permissions"){super(H);this.name="InsufficientPermissionsError",this.error=H,this.payload={api:{status:HH.apiStatus,data:{error:n("permission",this.error,HH.apiStatus)}},view:{status:403}}}}class QH extends R{total;constructor(H){super("Range not satisfiable");this.total=H;this.name="RangeNotSatisfiableError",this.payload={api:{status:416,data:{error:GH("range_not_satisfiable","Range not satisfiable",416)},headers:{"Content-Range":UH(H),"Accept-Ranges":"bytes","Cache-Control":"no-store"}},view:{}}}}class j extends R{fileName;constructor(H){super("File not found");this.fileName=H;this.name="FileNotFoundError",this.payload={api:{status:404,data:{error:GH("not_found","Not found",404)},headers:{"Cache-Control":"no-store"}},view:{}}}}class Q0 extends R{constructor(H={}){super("Authentication error");this.name="AuthenticationError";let G=H.redirectTo??"/auth/sign-in";this.payload={api:{status:401,data:{error:n("authentication","Authentication error",401)}},viewData:{status:200,data:{},headers:{"Cache-Control":"private, no-cache, no-store, max-age=0, must-revalidate"},directive:{kind:"Redirect",path:G}},view:{status:302,headers:{"Cache-Control":"private, no-cache, no-store, max-age=0, must-revalidate",Location:G}}}}}class k{static getFacadeAccessor(){throw Error(`Facade [${this.name}] does not implement getFacadeAccessor().`)}static getFacadeRoot(){return qH(this.getFacadeAccessor())}}class XH{async delete(H){throw Error(`${this.constructor.name} does not implement delete(). Override it to remove objects from this backend.`)}async read(H){let G=typeof H==="string"?{name:H}:H,Q=await this.fetch({name:G.name,bucket:G.bucket});if(!Q.ok)throw new j(G.name);let Z=Q.headers.get("Content-Type")??"application/octet-stream",X=Q.headers.get("ETag")??void 0,$=Q.headers.get("Last-Modified"),K=$?new Date($):void 0;if(G.range){let Y=await Q.blob();return{body:Y,start:0,end:Y.size-1,total:Y.size,partial:!1,type:Z,etag:X,lastModified:K,name:G.name}}let T=Number(Q.headers.get("Content-Length")),W=Number.isFinite(T)?T:0;return{body:Q.body,start:0,end:W-1,total:W,partial:!1,type:Z,etag:X,lastModified:K,name:G.name}}async size(H){let G=typeof H==="string"?H:H.name,Q=typeof H==="string"?void 0:H.bucket,Z=await this.fetch({name:G,bucket:Q});if(!Z.ok)throw new j(G);let X=Number(Z.headers.get("Content-Length"));if(Number.isFinite(X))return await Z.body?.cancel(),X;return(await Z.blob()).size}}function EH(H,G){if(!G)return H;let Q=H.getReader(),Z=!1,X,$=()=>{if(Z=!0,X)G.removeEventListener("abort",X)};return new ReadableStream({start(K){if(X=()=>{if(Z)return;$(),K.error(G.reason),Q.cancel(G.reason).catch(()=>{})},G.aborted)X();else G.addEventListener("abort",X,{once:!0})},async pull(K){let T;try{T=await Q.read()}catch(W){if(Z)return;$(),K.error(W);return}if(Z)return;if(T.done){$(),K.close();return}K.enqueue(T.value)},cancel(K){return $(),Q.cancel(K)}},{highWaterMark:0})}import{readdir as X0,unlink as Z0}from"fs/promises";import{isAbsolute as $0,relative as K0,resolve as NH,sep as T0}from"path";class ZH extends XH{configured;constructor(H){super();this.configured=H}get folderPath(){return this.configured??`${b()}/storage`}async put(H,{signal:G}={}){G?.throwIfAborted();let Q,Z;if(H instanceof Blob)Q=H,Z=`${Bun.randomUUIDv7()}.${H.type.split("/")[1].split(";")[0]}`;else Q=H.body,Z=H.name;let X=Q instanceof Buffer?Q:Q instanceof Blob||Q instanceof File?Buffer.from(await Q.arrayBuffer()):"",$=`${this.folderPath}/${Z}`;return G?.throwIfAborted(),await Bun.write($,X),Z}async fetch(H,{signal:G}={}){G?.throwIfAborted();let Q=process.env.BUCKET_NAME,Z;if(typeof H==="string")Z=H;else Q=H.bucket??Q,Z=H.name;if(!Z)throw Error("Object name has to be specified");let X=`${this.folderPath}/${Z}`,$=Bun.file(X),K=EH(Bun.file(X).stream(),G),T=new Date($.lastModified).toUTCString();return new Response(K,{headers:{"Content-Type":$.type,"Content-Length":String($.size),"Cache-Control":"private, max-age=12000, must-revalidate","Last-Modified":T}})}async read(H){let G=typeof H==="string"?{name:H}:H,{name:Q,range:Z=null}=G;if(!Q)throw Error("Object name has to be specified");let X=Bun.file(`${this.folderPath}/${Q}`);if(!await X.exists())throw new j(Q);let $=X.size,K=Z?DH(Z,$):null;if(Z&&!K)throw new QH($);let T=K?.start??0,W=K?K.end:$-1;return{body:K?X.slice(T,W+1):X,start:T,end:W,total:$,partial:Boolean(K),type:X.type||"application/octet-stream",lastModified:new Date(X.lastModified),name:Q}}async size(H){let G=typeof H==="string"?H:H.name,Q=Bun.file(`${this.folderPath}/${G}`);if(!await Q.exists())throw new j(G);return Q.size}async delete(H){let G=typeof H==="string"?H:H.name;if(!G)throw Error("Object name has to be specified");let Q=NH(this.folderPath),Z=NH(Q,G),X=K0(Q,Z);if(!X||X===".."||X.startsWith(`..${T0}`)||$0(X))throw Error(`Refusing to delete "${G}": it is outside the storage folder`);try{await Z0(Z)}catch($){if($?.code==="ENOENT")return;throw $}}async list(){return await X0(this.folderPath)}}function D4(H){return H}function wH(){return{driver:new ZH}}class $H{static token="filesystem";driver;constructor(H={}){this.driver=H.driver??wH().driver}}import{Buffer as Y0}from"buffer";async function SH(H){try{return(await import("sharp")).default}catch(G){throw Error(`${H} requires the 'sharp' package. Install it with \`bun add sharp\`.`,{cause:G})}}class M0 extends k{static getFacadeAccessor(){return $H}static async put(H,G={}){return this.getFacadeRoot().driver.put(H,G)}static async metadata(H){let G=Y0.from(await H.arrayBuffer()),Q=await SH("Storage.metadata()");try{return await Q(G).metadata()}catch{return{}}}static async fetch(H,G={}){return G.signal?.throwIfAborted(),this.getFacadeRoot().driver.fetch(H,G)}static async read(H,G={}){let Q=typeof H==="string"?{name:H}:{...H},Z="range"in G?G.range??null:Q.range!==void 0?Q.range:C.getStore()?.rangeRequest??null;return this.getFacadeRoot().driver.read({...Q,range:Z})}static list(H){return this.getFacadeRoot().driver.list(H)}static async delete(H){return this.getFacadeRoot().driver.delete(H)}}import{mkdir as KH,readdir as D0,access as U0}from"fs/promises";async function TH(H){try{return await U0(H),!0}catch{return!1}}class WH{config;static token="log";writer;isReady=!1;flushTimeout;fileSize=0;writerSize=0;isCreatingFile=!1;bootPromise=null;currentLogFilePath;get logsDirPath(){return`${b()}/storage/logs`}constructor(H){this.config=H}boot(){if(!this.bootPromise)this.bootPromise=this.createStorage().catch((H)=>{console.error("Log storage unavailable, file logging disabled",H)}).then(()=>{this.isReady=!0});return this.bootPromise}async createStorage(){let H=`${b()}/storage`;if(!await TH(H))await KH(H);if(!await TH(this.logsDirPath))await KH(this.logsDirPath);await this.newLogFile()}async newLogFile(){if(!await TH(this.logsDirPath))await KH(this.logsDirPath);if(this.isCreatingFile=!0,this.currentLogFilePath){this.writer.flush(),this.writer.end(),this.writer=null;let Q=new File([await Bun.file(this.currentLogFilePath).arrayBuffer()],this.currentLogFilePath.split("/").pop(),{type:"text/plain"});this.config.onLogFileClosed(Q),this.fileSize=0,this.writerSize=0}let G=(await D0(this.logsDirPath)).sort().reverse()[0];if(G){let Q=Bun.file(`${this.logsDirPath}/${G}`);if(Q.size<this.config.maxFileSize)this.currentLogFilePath=`${this.logsDirPath}/${G}`,this.writer=Q.writer(),this.writer.write(await Q.text()),this.writer.write(`
5
+ `),this.writer.flush(),this.fileSize=Q.size}if(!this.writer){let Q=`${new Date(Date.now()).toISOString()}.log`.replaceAll(":","-");this.currentLogFilePath=`${this.logsDirPath}/${Q}`;let Z=Bun.file(`${this.logsDirPath}/${Q}`);this.writer=Z.writer(),this.fileSize=0,this.writerSize=0}this.isCreatingFile=!1}async log(H,G,Q={}){if(!this.isReady)await this.boot();let Z=C.getStore(),X={};if(Z)X={url:Z.req.rawRequest.url,method:Z.req.rawRequest.method,headers:Z.req.rawRequest.headers,body:Z.req.rawRequest.body};let $={timestamp:new Date(Date.now()).toISOString(),env:Bun.env.NODE_ENV,level:H,message:G,metadata:{...X,...Q}},K="";try{K=JSON.stringify($)}catch(T){console.log("Error parsing log object",T)}try{let T=this.config.onLogCreated($);if(T instanceof Promise)T.catch((W)=>console.error("Error in onLogCreated",W))}catch(T){console.error("Error in onLogCreated",T)}if(!this.writer)return;this.writerSize+=K.length,this.fileSize+=K.length;try{this.writer.write(K),this.writer.write(`
6
+ `),this.tryFlush()}catch(T){console.error("Error writing log",T)}}async tryFlush(){if(this.fileSize>this.config.maxFileSize){if(!this.isCreatingFile)await this.newLogFile()}if(this.writerSize>this.config.maxFileSize/2)await this.writer.flush(),this.writerSize=0,await this.newLogFile();else clearTimeout(this.flushTimeout),this.flushTimeout=setTimeout(async()=>{await this.writer.flush(),this.writerSize=0},100)}}class P0 extends k{static getFacadeAccessor(){return WH}static debug(H,G){this.getFacadeRoot().log("debug",H,G)}static info(H,G){this.getFacadeRoot().log("info",H,G)}static notice(H,G){this.getFacadeRoot().log("notice",H,G)}static warning(H,G){this.getFacadeRoot().log("warning",H,G)}static error(H,G){this.getFacadeRoot().log("error",H,G)}static critical(H,G){this.getFacadeRoot().log("critical",H,G)}static alert(H,G){this.getFacadeRoot().log("alert",H,G)}static emergency(H,G){this.getFacadeRoot().log("emergency",H,G)}}class B0{config;static token="redis";instance=null;constructor(H={}){this.config=H}get client(){return this.instance??=new(R0())(this.config.url,this.config.options)}set client(H){this.instance=H}close(){let H=this.instance;this.instance=null,H?.close()}}function R0(){let H=globalThis.Bun?.RedisClient;if(typeof H!=="function")throw Error("Redis requires Bun's built-in Redis client, which this runtime does not provide. Run the app under Bun, or bind your own client for the 'redis' token.");return H}
7
+ export{YH as Me,gH as Ne,F0 as Oe,JH as Pe,w0 as Qe,S0 as Re,MH as Se,DH as Te,L0 as Ue,J0 as Ve,C0 as We,UH as Xe,g0 as Ye,jH as Ze,y0 as _e,k0 as $e,w as af,J as bf,LH as cf,I0 as df,q0 as ef,H0 as ff,G0 as gf,HH as hf,QH as if,j as jf,Q0 as kf,k as lf,SH as mf,XH as nf,EH as of,ZH as pf,D4 as qf,wH as rf,$H as sf,M0 as tf,WH as uf,P0 as vf,B0 as wf};
8
+
9
+ //# debugId=25FB1B8A02D49E4F64756E2164756E21