gemi 0.143.0 → 0.144.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.
- package/dist/ai/index.js +1 -1
- package/dist/{chunk-j2k408xc.js → chunk-27xsjq8a.js} +1 -1
- package/dist/{chunk-159c392q.js → chunk-6d3m2w2p.js} +1 -1
- package/dist/{chunk-mfn94b95.js → chunk-9zd7c4wq.js} +1 -1
- package/dist/{chunk-kkqw8bqg.js → chunk-a78b9v7h.js} +1 -1
- package/dist/{chunk-9qfd02h8.js → chunk-b4mg6v4g.js} +1 -1
- package/dist/{chunk-r0z27j6t.js → chunk-en33hg1c.js} +1 -1
- package/dist/chunk-fg2k18d2.js +5 -0
- package/dist/{chunk-mnmr27wd.js.map → chunk-fg2k18d2.js.map} +3 -3
- package/dist/{chunk-hnsrwr0p.js → chunk-t0wfj6hy.js} +2 -2
- package/dist/{chunk-hnsrwr0p.js.map → chunk-t0wfj6hy.js.map} +1 -1
- package/dist/{chunk-1rvnk7g8.js → chunk-w4ma7978.js} +1 -1
- package/dist/client/Head.d.ts.map +1 -1
- package/dist/client/index.js +7 -6
- package/dist/client/index.js.map +1 -1
- package/dist/facades/index.js +1 -1
- package/dist/http/Metadata.d.ts +8 -2
- package/dist/http/Metadata.d.ts.map +1 -1
- package/dist/http/index.js +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/kernel/index.js +1 -1
- package/dist/orm/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/dist/services/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-mnmr27wd.js +0 -5
- /package/dist/{chunk-j2k408xc.js.map → chunk-27xsjq8a.js.map} +0 -0
- /package/dist/{chunk-159c392q.js.map → chunk-6d3m2w2p.js.map} +0 -0
- /package/dist/{chunk-mfn94b95.js.map → chunk-9zd7c4wq.js.map} +0 -0
- /package/dist/{chunk-kkqw8bqg.js.map → chunk-a78b9v7h.js.map} +0 -0
- /package/dist/{chunk-9qfd02h8.js.map → chunk-b4mg6v4g.js.map} +0 -0
- /package/dist/{chunk-r0z27j6t.js.map → chunk-en33hg1c.js.map} +0 -0
- /package/dist/{chunk-1rvnk7g8.js.map → chunk-w4ma7978.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{$b as M9,Jc as F9,Xb as k9,_b as K3,dc as e,ld as N9,qc as U9,wc as J9}from"./chunk-mfn94b95.js";import{Bd as L$,sd as c3,ud as B3,xd as d9,yd as c9,zd as V$}from"./chunk-fpz9e3xx.js";import{Ed as w9,Jd as v9,Ld as g9,Sd as x,Td as h9,Ud as m9,Wd as u9,Xd as B$}from"./chunk-ce9wm3r9.js";import{_d as N}from"./chunk-6hs102jh.js";import{Ag as L3,Bg as d3,Cf as Y$,Df as G$,Ef as W$,Fe as H$,Ge as p3,Gf as w,Gg as X$,Hg as K$,Ke as J3,Le as X3,Ng as D$,Tf as a3,cg as s3,df as m3,eg as n,ig as o3,jg as t9,ke as l,kg as s9,le as z$,oe as T9,qg as f3,rf as Z3,rg as o9,se as O$,sg as G3,tg as r9,ug as e9,ve as Q$,vg as w3,wg as a,xf as H3,yf as h3,zf as q,zg as A$}from"./chunk-kkqw8bqg.js";import{Ai as F3,Bi as z3,Sh as p,Uh as m,hi as t3,vi as H9,zi as P3}from"./chunk-j2k408xc.js";import{Hi as i9}from"./chunk-9k46m1vf.js";import{Si as g}from"./chunk-mnmr27wd.js";import{Yi as u3}from"./chunk-ktrm6y5j.js";import{$i as U$,aj as i3,dj as N3,ej as n3,hj as F$}from"./chunk-9xzg05xg.js";import{Aj as n9,vj as l9}from"./chunk-a37shxb1.js";import{Qj as f9,Sj as u}from"./chunk-1skdsmjx.js";import{Tj as j}from"./chunk-yjszzjyj.js";import{Zj as I$}from"./chunk-p81qeav5.js";import{Nk as l3}from"./chunk-5g7m7g4a.js";import{Uk as U3,Xk as y}from"./chunk-1ed75a7b.js";import{el as g3}from"./chunk-s29tgy4y.js";import{pl as a9}from"./chunk-m6t5a0me.js";var C$="mcp",S$=/^[\x21\x23-\x5B\x5D-\x7E]+$/;class D extends e{status;constructor($,Z){super($);this.status=Z;this.name="McpToolError"}}class v extends Error{reason;constructor($,Z){super($);this.reason=Z;this.name="McpCallRefusedError"}}var r3=/^[A-Za-z0-9_-]{1,64}$/,q$=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,e3=4000,T=1e5,T$=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i,B9=new WeakMap;function X6($){return B9.get($)}class i{router;dispatcher;static token="router.mcp";plans=new Map;scopeTools=new Map;files;featureOn;constructor($,Z,z={}){this.router=$;this.dispatcher=Z;this.files=b$(z.files),this.featureOn=z.featureOn??X3;for(let[G,W]of Object.entries($.routes??{}))this.plans.set(G,k$(W)?this.planNative(G,W):this.plan(G,W));this.resolveScopes()}list($,Z){if(D3($),$.kind==="local")return this.descriptors(Z);let z=[];for(let[G,W]of this.plans){if(!W.remote||!this.grants($.principal,G))continue;if(W9(W.remote,Z))z.push(W.remote)}return z}async available($,Z){let z=[];for(let G of this.list($,Z))if(await this.isOn(G))z.push(G);return z}descriptors($){let Z=[];for(let{descriptor:z}of this.plans.values())if(W9(z,$))Z.push(z);return Z}get maxFileBytes(){return this.files.maxBytes}scopes(){return[...this.scopeTools].map(([$,{description:Z}])=>({name:$,description:Z}))}scopesFor($){return[...this.scopeTools].filter(([,{tools:Z}])=>Z.has($)).map(([Z])=>Z)}async execute($,Z,z,G,W={}){D3($);let X=this.plans.get(Z);if(X&&!await this.isOn(X.descriptor)){if($.kind==="remote")throw new v(`There is no tool named "${Z}".`,"unknown-tool");throw new D(`There is no tool named "${Z}".`,404)}if($.kind==="remote"){if(!X?.remote||!this.grants($.principal,Z))throw new v(`There is no tool named "${Z}".`,"unknown-tool");if(X.descriptor.requiresApproval&&W.approved!==!0&&!W3(X))throw new v(`"${Z}" needs the user's approval, and this call does not have it.`,"approval-required");G=void 0}if(!X)throw Error(`McpRegistry: there is no tool named "${Z}".`);if(X.kind==="tool")return await this.executeNative(X,$,z,G,W);let Y=X,K=$.kind==="remote"?Y.remote:Y.descriptor,Q=K.inputSchema.safeParse(z);if(Q.ok===!1)throw new D(`Invalid arguments for "${Z}": ${Q.errors.join(", ")}`);let V=Q.value,H={caller:$,req:$.req,tool:K,input:V,ctx:G},U=await this.fillPath(Y,H),{path:F}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${U}`));if(F!==K.url)throw new D(`"${Z}" has nothing at ${U}.`,404);let O={};for(let L of Y.jsonKeys)if(V[L]!==void 0)O[L]=V[L];let B,I="";if(Y.fileFields.length>0)B=await this.formData(Y,O,H);else if(K.method==="GET")I=c$(O);else if(Y.jsonKeys.length>0)B=O;let k=this.router.credentials?await this.bind(Y,"the credentials",()=>this.router.credentials(H)):void 0,A={...k?{credentials:k}:{},...W.signal?{signal:W.signal}:{},...W.progress?{progress:W.progress}:{},...$.kind==="remote"?{identity:{user:$.principal.user,grant:{via:$.principal.via,id:$.principal.id,scopes:$.principal.scopes,...$.principal.clientId?{clientId:$.principal.clientId}:{}}}}:{}},M;try{let L=I?`${U}?${I}`:U;M=Object.keys(A).length>0?await this.dispatcher.dispatchAs($.req,K.method,L,B,A):await this.dispatcher.dispatchAs($.req,K.method,L,B)}catch(L){throw console.error(`[gemi/mcp] Dispatching "${Z}" failed:`,L),new D(`"${Z}" failed on the server.`,500)}if(!Y.result&&!K.outputSchema)return await V9(Z,M);return await this.project(Y,H,M)}async isOn($){return $.feature===void 0||await this.featureOn($.feature)===!0}plan($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (${Z?.method} ${Z?.url})`;if(!(Z instanceof Object)||Z.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${$}" is not a route or a tool. Declare it with this.fromApiRoute(...) or this.fromTool(...).`);let{method:G,url:W,meta:X}=Z;if(X.feature!==void 0&&(typeof X.feature!=="string"||X.feature===""))throw Error(`${z}: feature must be a feature key from app/features.`);if(W.startsWith("/__gemi__"))throw Error(`${z} is a framework route, not an app route.`);let Y=this.dispatcher.flatRoutes[W]?.[G];if(!Y)throw Error(`${z} names no route of this app. Expose a route by the path and verb it is mounted at.`);let K=[...W.matchAll(q$)].map(([,J,C])=>({name:J,modifier:C})),Q=X.params??{};for(let J of K)if(!(J.name in Q))throw Error(`${z}: the path param "${J.name}" must be bound or declared "input".`);for(let[J,C]of Object.entries(Q)){if(!K.some((h)=>h.name===J))throw Error(`${z}: "${J}" in params is not a param of the url.`);if(Y9(C))g$(z,`params.${J}`,C);else X9(z,`params.${J}`,C)}let V=[],H;if(X.input){if(H=X.input.toJSONSchema(),H.type!=="object"||!H.properties)throw Error(`${z}: input must be an s.object(...), the fields of the request body.`);V=Object.keys(H.properties)}let U=Object.entries(X.files??{}).map(([J,C])=>({name:J,binder:C}));for(let J of U)X9(z,`files.${J.name}`,J.binder);if(X.result!==void 0&&typeof X.result!=="function")throw Error(`${z}: result must be a function.`);if(X.output!==void 0&&typeof X.output?.safeParse!=="function")throw Error(`${z}: output must be a schema, built with s.`);if(X.title!==void 0&&(typeof X.title!=="string"||X.title===""))throw Error(`${z}: title must be a non-empty string.`);let F=K9(z,G,X.annotations);if(U.length>0&&G==="GET")throw Error(`${z}: a GET has no body to carry a file.`);let O={},B=(J,C)=>{if(J in O)throw Error(`${z}: "${J}" is the input key of two params or files, and the model can only send one.`);O[J]=C},I=new Map,k=new Map;for(let J of K){let C=Q[J.name];if(C==="input"){let h=p.string().describe(`The ":${J.name}" segment of the url.`);B(J.name,J.modifier==="?"||J.modifier==="*"?h.optional():h)}else if(Y9(C)){let h=C.as??J.name;B(h,C.input),k.set(J.name,{key:h,param:C})}else I.set(J.name,C)}let A={};for(let J of U)if(J.binder==="input")B(J.name,p.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.")),A[J.name]=this.remoteFileSchema();let M=[...Object.keys(O),...U.map((J)=>J.name)];for(let J of new Set(M))if(V.includes(J))throw Error(`${z}: "${J}" is both an input field and a param or file, and the model can only send one.`);let L=Object.freeze({kind:"route",name:$,description:X.description,method:G,url:W,inputSchema:Q9(X.input,H,p.object(O)),...X.output?{outputSchema:X.output}:{},...X.title?{title:X.title}:{},annotations:F,tags:Object.freeze([...X.tags??[]]),requiresApproval:X.requiresApproval===!0,...X.feature!==void 0?{feature:X.feature}:{},...Y.source?{source:Y.source}:{}}),r=!U.every((J)=>J.binder==="input")?null:U.length===0?L:Object.freeze({...L,inputSchema:Q9(X.input,H,p.object(u$(O,Object.keys(A))),A)});return{kind:"route",descriptor:L,remote:r,params:K,paramBinders:I,modelParams:k,fileFields:U,jsonKeys:V,...X.result?{result:X.result}:{}}}remoteFileSchema(){let{maxBytes:$,fetch:Z}=this.files,z={name:{type:"string",description:"The file's name, like report.pdf."},mimeType:{type:"string",description:"The file's media type, like application/pdf."},data:{type:"string",contentEncoding:"base64",description:`The file's bytes, base64-encoded (RFC 4648, standard alphabet). At most ${$} bytes decoded.`}};if(Z)z.url={type:"string",format:"uri",description:"An https URL the server downloads the file from, instead of data."};let G={type:"object",description:Z?"A file, sent as base64 in data or fetched from url: exactly one of the two.":"A file, sent as base64 in data.",properties:z,required:["name","mimeType"],additionalProperties:!1},W=Object.keys(z),X=(Y)=>{if(typeof Y!=="object"||Y===null||Array.isArray(Y))return{ok:!1,errors:["a file must be an object"]};let K=[],Q={};for(let V of Object.keys(Y))if(!W.includes(V))K.push(`a file has no field "${V}"`);for(let V of W){let H=Y[V];if(H===void 0||H===null){if(V==="name"||V==="mimeType")K.push(`a file needs "${V}"`);continue}if(typeof H!=="string")K.push(`a file's "${V}" must be a string`);else Q[V]=H}return K.length>0?{ok:!1,errors:K}:{ok:!0,value:Q}};return{toJSONSchema:()=>G,safeParse:X,parse(Y){let K=X(Y);if(K.ok===!1)throw Error(K.errors.join(", "));return K.value}}}planNative($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (a native tool)`,{tool:G,meta:W={}}=Z;if(!(G instanceof Object)||typeof G.name!=="string")throw Error(`${z} is not an AgentTool. Pass one built with AgentTool.create(...).`);if(G.answeredBy==="client"||typeof G.execute!=="function")throw Error(`${z}: "${G.name}" is answered by the client, and only a tool the server runs can be called through the registry.`);if(typeof G.inputSchema==="function")throw Error(`${z}: "${G.name}" resolves its input schema per run, and the registry lists one schema to every caller. Give it a fixed inputSchema.`);if(typeof G.inputSchema?.safeParse!=="function")throw Error(`${z}: its inputSchema must be a schema, built with s.`);if(typeof W!=="object"||W===null)throw Error(`${z}: the meta must be an object.`);if(W.description!==void 0&&(typeof W.description!=="string"||W.description.trim()===""))throw Error(`${z}: description must be a non-empty string.`);if(W.title!==void 0&&(typeof W.title!=="string"||W.title===""))throw Error(`${z}: title must be a non-empty string.`);if(W.tags!==void 0&&(!Array.isArray(W.tags)||W.tags.some((Q)=>typeof Q!=="string")))throw Error(`${z}: tags must be an array of strings.`);if(W.requiresApproval===!1&&G.requiresApproval)throw Error(`${z}: "${G.name}" requires approval, and requiresApproval: false would run it without asking. Leave it out, or register a tool that does not ask.`);let X=W.remote;if(X!==void 0){if(typeof X!=="object"||X===null||typeof X.context!=="function")throw Error(`${z}: remote must be { context(call) }, building the AgentContext a remote call runs with.`);if(X.progress!==void 0&&typeof X.progress!=="function")throw Error(`${z}: remote.progress must be a function.`)}let Y=W.description??G.description;if(typeof Y!=="string"||Y.trim()==="")throw Error(`${z} needs a description: the tool's own, or the meta's.`);let K=Object.freeze({kind:"tool",name:$,description:Y,inputSchema:G.inputSchema,...G.outputSchema?{outputSchema:G.outputSchema}:{},...W.title?{title:W.title}:{},annotations:K9(z,void 0,W.annotations),tags:Object.freeze([...W.tags??[]]),requiresApproval:G.requiresApproval||W.requiresApproval===!0});return{kind:"tool",descriptor:K,remote:X?K:null,tool:G,meta:W}}async approvalRequired($,Z,z,G={}){let W=this.plans.get(Z);if(!W)return!0;if(!W3(W))return W.descriptor.requiresApproval;let X=W;if($.kind!=="remote"||!X.meta.remote)return!0;let Y=X.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)return!0;let K={caller:$,req:$.req,tool:X.descriptor,input:Y.value},Q;try{Q=await this.bind(X,"the remote context",()=>X.meta.remote.context(K))}catch{return!0}if(typeof Q!=="object"||Q===null)return!0;let V=G.signal??new AbortController().signal;return G9(X,Y.value,z9(Z9(X,Q,V)))}nativeApproval($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return W3(Z)??Z.descriptor.requiresApproval}nativeTool($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return Z.tool}startNative($,Z,z,G){let W=this.plans.get(Z);if(W?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${Z}".`);if($===void 0)return W.tool.execute(z,G);if(D3($),$.kind!=="local")throw Error("McpRegistry: startNative is for a local caller. A remote call goes through execute().");let X=W.descriptor.inputSchema.safeParse(z);if(X.ok===!1)throw new D(`Invalid arguments for "${Z}": ${X.errors.join(", ")}`);return this.runNative(W,{caller:$,req:$.req,tool:W.descriptor,input:X.value},G)}runNative($,Z,z){let G={...z};return B9.set(G,{...Z,ctx:G}),$.tool.execute(Z.input,G)}async executeNative($,Z,z,G,W){let{name:X}=$.descriptor,Y=$.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)throw new D(`Invalid arguments for "${X}": ${Y.errors.join(", ")}`);let K={caller:Z,req:Z.req,tool:$.descriptor,input:Y.value},Q=(L,_3)=>{if(!W.progress)return;let r;try{r=$.meta.remote?.progress?$.meta.remote.progress(L,_3):R$(L,_3)}catch(J){console.error(`[gemi/mcp] The progress mapping of "${X}" failed:`,J);return}if(r)W.progress(r)};if(Z.kind==="local"){if(!G)throw Error(`McpRegistry: "${X}" is a native tool, which runs with the tool context of an agent call, and none was passed to execute().`);return await $9(this.runNative($,{...K,ctx:G},G),Q)}let V=$.meta.remote,H=await this.bind($,"the remote context",()=>V.context(K));if(typeof H!=="object"||H===null)throw console.error(`[gemi/mcp] The remote context of "${X}" is not an object:`,H),new D(`"${X}" failed on the server.`,500);let U=$.tool.timeoutMs,F=[...W.signal?[W.signal]:[],...U!==void 0?[AbortSignal.timeout(U)]:[]],O=F.length===0?new AbortController().signal:F.length===1?F[0]:AbortSignal.any(F),B=Z9($,H,O);if(!W.approved&&W3($)&&await G9($,K.input,z9(B)))throw new v(`"${X}" needs the user's approval, and this call does not have it.`,"approval-required");let I;try{I=await $9(this.runNative($,{...K,ctx:B},B),Q,O)}catch(L){if(O.aborted&&L===O.reason){if(W.signal?.aborted)throw new D(`"${X}" was cancelled.`,499);throw new D(`"${X}" did not finish within ${U} ms.`,504)}if(L instanceof D)throw L;if(L instanceof e||L instanceof v)throw new D(L.message);throw console.error(`[gemi/mcp] "${X}" failed for a remote caller:`,L),new D(`"${X}" failed on the server.`,500)}let k=(L)=>{return console.error(`[gemi/mcp] "${X}" ${L}`),new D(`"${X}" failed on the server.`,500)};if(U9(I))throw k("answered a job handle, and a remote call has no background jobs.");let A=I;if($.descriptor.outputSchema){let L=$.descriptor.outputSchema.safeParse(A);if(L.ok===!1)throw k(`answered what its output schema refuses: ${L.errors.join(", ")}`);A=L.value}if(A===void 0)return null;if(typeof A==="string")return A.length>T?`${A.slice(0,T)}\u2026 [cut at ${T} of ${A.length} characters]`:A;let M=JSON.stringify(A);if(M!==void 0&&M.length>T)return`${M.slice(0,T)}\u2026 [cut at ${T} of ${M.length} characters]`;return A}async fillPath($,Z){let{input:z,req:G}=Z,W=$.descriptor.url;for(let X of $.params){let Y=$.paramBinders.get(X.name),K=$.modelParams.get(X.name),Q;if(Y||K){if(Q=K?await this.bind($,`the param "${X.name}"`,()=>K.param.bind(z[K.key],G,Z),{refusals:!0}):await this.bind($,`the param "${X.name}"`,()=>Y(G,Z)),Q===void 0||Q===null||Q==="")throw console.error(`[gemi/mcp] The ${K?"resolver":"binder"} for "${X.name}" of "${$.descriptor.name}" returned ${JSON.stringify(Q)}.`),new D(`"${$.descriptor.name}" failed on the server.`,500)}else Q=z[X.name];let V=`:${X.name}${X.modifier}`;if(Q===void 0||Q===null||Q===""){if(X.modifier!=="?"&&X.modifier!=="*")throw new D(`"${X.name}" of "${$.descriptor.name}" must not be empty.`);W=W.replace(`/${V}`,"");continue}W=W.replace(V,d$($.descriptor.name,X,String(Q)))}return W}async formData($,Z,z){let{input:G,ctx:W}=z,X=$.descriptor.name;if(z.caller.kind==="remote"){let K=new FormData;for(let[Q,V]of Object.entries(Z))O3(K,Q,V);for(let Q of $.fileFields)K.append(Q.name,await this.remoteFile(X,Q.name,G[Q.name]));return K}if(!W)throw Error(`McpRegistry: "${X}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let Y=new FormData;for(let[K,Q]of Object.entries(Z))O3(Y,K,Q);for(let K of $.fileFields){let Q=K.binder==="input"?G[K.name]:await this.bind($,`the file "${K.name}"`,()=>K.binder(W,z));if(typeof Q!=="string"||Q==="")throw new D(`"${X}" needs a file for "${K.name}", and this turn has none. Ask the user to attach one.`);Y.append(K.name,await W.attachments.file(Q))}return Y}async remoteFile($,Z,z){let G=(H)=>new D(`"${Z}" of "${$}" ${H}`,400),W=z,{maxBytes:X,fetch:Y}=this.files;if(!y$(W.name))throw G("needs a name of 1 to 255 characters, without control characters or slashes.");if(!f$.test(W.mimeType))throw G(`has a mimeType that is not a media type: "${W.mimeType.slice(0,100)}".`);let K=typeof W.data==="string",Q=typeof W.url==="string";if(K===Q)throw G(Y?"needs exactly one of data or url.":"needs its bytes, base64, in data.");if(K){let H=W.data.replace(/\s+/g,"");if(Math.floor(H.length*3/4)-v$(H)>X)throw G(`is larger than the ${X} bytes a file may be.`);if(H.length%4!==0||!w$.test(H))throw G("has data that is not base64 (RFC 4648, standard alphabet, padded).");return new File([Buffer.from(H,"base64")],W.name,{type:W.mimeType})}if(!Y)throw G("cannot be fetched from a URL here. Send its bytes, base64, in data.");let V;try{V=new URL(W.url)}catch{throw G("has a url that is not a URL.")}if(V.protocol!=="https:")throw G("can only be fetched from an https URL.");try{let H=await H9(V.href,{...Y,maxSize:Math.min(Y.maxSize??X,X),redirect:"follow"});if(!H.ok)throw G(`could not be fetched: ${V.host} answered ${H.status}.`);let U=await H.arrayBuffer();return new File([U],W.name,{type:W.mimeType})}catch(H){if(H instanceof D)throw H;throw G(`could not be fetched from ${V.host}: ${H instanceof Error?H.message:"failed"}.`)}}grants($,Z){for(let z of $.scopes??[])if(this.scopeTools.get(z)?.tools.has(Z))return!0;return!1}resolveScopes(){let $=this.router.scopes;if($===void 0){this.scopeTools.set(C$,{description:"Use this app's tools as you",tools:new Set(this.plans.keys())});return}if(typeof $!=="object"||$===null)throw Error("McpRouter: scopes must be an object of scope names.");let Z=new Set([...this.plans.values()].flatMap(({descriptor:z})=>z.tags));for(let[z,G]of Object.entries($)){let W=`McpRouter: scope "${z}"`;if(!S$.test(z))throw Error(`${W} is not a valid OAuth scope: printable ASCII, no spaces or quotes.`);if(typeof G?.description!=="string"||G.description==="")throw Error(`${W} needs a description: it is what a consent screen shows.`);let X=new Set;for(let Y of G.tags??[]){if(!Z.has(Y))throw Error(`${W} names the tag "${Y}", which no tool has.`);for(let[K,{descriptor:Q}]of this.plans)if(Q.tags.includes(Y))X.add(K)}for(let Y of G.names??[]){if(!this.plans.has(Y))throw Error(`${W} names "${Y}", which is no tool.`);X.add(Y)}if(X.size===0)throw Error(`${W} reaches no tool. Give it tags or names.`);this.scopeTools.set(z,{description:G.description,tools:X})}}async project($,Z,z){let{name:G,outputSchema:W}=$.descriptor;if(z.status<200||z.status>=300)return await V9(G,z);let X=(U,F)=>{if(F===void 0)console.error(`[gemi/mcp] "${G}" ${U}`);else console.error(`[gemi/mcp] "${G}" ${U}`,F);return new D(`"${G}" failed on the server.`,500)},Y=z.headers.get("Content-Type"),K=await z.text(),Q=null;if(K!=="")try{Q=JSON.parse(K)}catch{throw X(`answered ${Y??"a body with no content-type"} that is not JSON, and its result or output needs JSON.`)}let V=Q;if($.result)try{V=await $.result(Q,Z)}catch(U){throw X("failed in its result projection:",U)}if(W){let U=W.safeParse(V);if(U.ok===!1)throw X(`answered what its output schema refuses: ${U.errors.join(", ")}`);V=U.value}if(V===void 0)return null;let H=JSON.stringify(V);if(H!==void 0&&H.length>T)return`${H.slice(0,T)}\u2026 [cut at ${T} of ${H.length} characters]`;return V}async bind($,Z,z,G={}){try{return await z()}catch(W){if(G.refusals&&W instanceof e)throw W;throw console.error(`[gemi/mcp] Binding ${Z} of "${$.descriptor.name}" failed:`,W),new D(`"${$.descriptor.name}" failed on the server.`,500)}}}function k$($){return $ instanceof Object&&$.__internal_brand==="McpTool"}function M$($){return typeof $==="object"&&$!==null&&typeof $.next==="function"&&Symbol.asyncIterator in $}async function $9($,Z,z){let G;if(z)G=new Promise((X,Y)=>{if(z.aborted)Y(z.reason);else z.addEventListener("abort",()=>Y(z.reason),{once:!0})}),G.catch(()=>{});let W=(X)=>G?Promise.race([X,G]):X;if(!M$($))return await W(Promise.resolve($));try{let X=0,Y=await W($.next());while(!Y.done)Z(Y.value,++X),Y=await W($.next());return Y.value}catch(X){throw $.return(void 0).catch(()=>{}),X}}function R$($,Z){if(typeof $==="string")return{progress:Z,message:$};if(typeof $==="object"&&$!==null){let{progress:z,total:G,message:W}=$;if(typeof z==="number"&&Number.isFinite(z))return{progress:z,...typeof G==="number"?{total:G}:{},...typeof W==="string"?{message:W}:{}};if(typeof W==="string")return{progress:Z,message:W}}return{progress:Z}}function Z9($,Z,z){let G=$.descriptor.name,W=`mcp_${crypto.randomUUID()}`,X=`mcp_call_${crypto.randomUUID()}`,Y=(Q)=>async()=>{throw new e(`"${G}" was called by a remote MCP client, which has no ${Q}.`,{retryable:!1})},K={put:Y("attachment store"),get:Y("attachment store"),read:Y("attachment store"),file:Y("attachment store")};return{context:Z,body:{},runId:W,toolCallId:X,signal:z,step:1,depth:0,resumed:!1,attachments:K,turn:Object.freeze({attachments:Object.freeze([])}),runAgent:Y("agent run to nest a sub-agent in"),generateImage:Y("attachment store to put an image in"),editImage:Y("attachment store to put an image in"),generate:(Q)=>N9({...Q,signal:Q.signal?AbortSignal.any([z,Q.signal]):z},{origin:{mcp:G,runId:W,toolCallId:X}}),jobs:J9({jobs:void 0,threadId:void 0,runId:W,toolCallId:X,toolName:G,depth:0,async:$.tool.async,attachments:null}),memory:F9()}}function W3($){if($.kind!=="tool"||$.meta.requiresApproval===!0)return;return $.tool.approvalPredicate}function z9($){return{context:$.context,body:$.body,runId:$.runId,threadId:$.threadId,toolCallId:$.toolCallId,step:$.step,depth:$.depth,signal:$.signal}}async function G9($,Z,z){try{return await $.tool.approvalPredicate(Z,z)!==!1}catch(G){return console.error(`[gemi/mcp] The requiresApproval of "${$.descriptor.name}" threw, so the call asks the user:`,G),!0}}function D3($){if($?.kind==="local"&&$.req)return;if($?.kind==="remote"&&$.req&&$.principal?.user&&typeof $.principal.id==="string"&&Array.isArray($.principal.scopes))return;throw Error('McpRegistry: a caller is { kind: "local", req } or { kind: "remote", req, principal }, with the principal a caller resolver verified.')}function W9($,Z){if(Z?.names&&!Z.names.includes($.name))return!1;if(Z?.tags&&!$.tags.some((z)=>Z.tags.includes(z)))return!1;return!0}var E$=10485760;function b$($){let Z=$?.maxBytes??E$;if(!Number.isSafeInteger(Z)||Z<=0)throw Error("McpRegistry: files.maxBytes must be a positive whole number of bytes.");let z=$?.fetchUrls===!0?{}:typeof $?.fetchUrls==="object"&&$.fetchUrls!==null?$.fetchUrls:null;return{maxBytes:Z,fetch:z}}function y$($){if($.length===0||$.length>255)return!1;for(let Z of $){let z=Z.codePointAt(0);if(z<32||z===127||Z==="/"||Z==="\\")return!1}return!0}var f$=/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(\s*;.{0,200})?$/,w$=/^[A-Za-z0-9+/]*={0,2}$/;function v$($){return $.endsWith("==")?2:$.endsWith("=")?1:0}function X9($,Z,z){if(z!=="input"&&typeof z!=="function")throw Error(`${$}: ${Z} must be a function or "input".`)}function Y9($){return $ instanceof Object&&$.__internal_brand==="McpModelParam"}function g$($,Z,z){if(z.as!==void 0&&(typeof z.as!=="string"||z.as===""))throw Error(`${$}: ${Z}.as must be a non-empty string.`);let G=z.input;if(typeof G?.safeParse!=="function"||typeof G.toJSONSchema!=="function")throw Error(`${$}: ${Z}.input must be a schema, built with s.`);if(typeof z.bind!=="function")throw Error(`${$}: ${Z}.bind must be a function.`)}var h$=new Set(["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"]);function m$($){switch($){case"GET":return{readOnlyHint:!0};case"DELETE":return{destructiveHint:!0};case"PUT":return{idempotentHint:!0};default:return{}}}function K9($,Z,z){if(z!==void 0&&(typeof z!=="object"||z===null))throw Error(`${$}: annotations must be an object of hints.`);let G=Z?m$(Z):{};for(let[W,X]of Object.entries(z??{})){if(!h$.has(W))throw Error(`${$}: "${W}" is not a tool annotation. Use readOnlyHint, destructiveHint, idempotentHint or openWorldHint.`);if(X===void 0)continue;if(typeof X!=="boolean")throw Error(`${$}: annotations.${W} must be true or false.`);G[W]=X}if(G.readOnlyHint===!0&&(G.destructiveHint||G.idempotentHint))throw Error(`${$} is read-only${z?.readOnlyHint?"":` (a ${Z})`} and also ${G.destructiveHint?"destructive":"idempotent"}, which only a tool that is not read-only can be. Set readOnlyHint: false if it changes something.`);return Object.freeze(G)}function Q9($,Z,z,G={}){let W=z.toJSONSchema(),X=Object.fromEntries(Object.entries(G).map(([Q,V])=>[Q,V.toJSONSchema()])),Y={...Z??{},type:"object",properties:{...Z?.properties??{},...W.properties,...X},required:[...Z?.required??[],...W.required??[],...Object.keys(G)],additionalProperties:!1},K=(Q)=>{if(typeof Q!=="object"||Q===null||Array.isArray(Q))return{ok:!1,errors:["expected an object"]};let V=[],H={};if($){let F=$.safeParse(Q);if(F.ok===!1)V.push(...F.errors);else H={...F.value}}let U=z.safeParse(Q);if(U.ok===!1)V.push(...U.errors);else H={...H,...U.value};for(let[F,O]of Object.entries(G)){let B=Q[F];if(B===void 0){V.push(`"${F}" is required`);continue}let I=O.safeParse(B);if(I.ok===!1)V.push(...I.errors.map((k)=>`${F}: ${k}`));else H[F]=I.value}return V.length>0?{ok:!1,errors:V}:{ok:!0,value:H}};return{toJSONSchema:()=>Y,safeParse:K,parse(Q){let V=K(Q);if(V.ok===!1)throw Error(V.errors.join(", "));return V.value}}}function u$($,Z){return Object.fromEntries(Object.entries($).filter(([z])=>!Z.includes(z)))}function d$($,Z,z){let G=Z.modifier==="*"||Z.modifier==="+"?z.split("/"):[z];if(G.some((W)=>W==="."||W===".."))throw new D(`"${z}" is not a valid value for "${Z.name}" of "${$}".`);return G.map(encodeURIComponent).join("/")}function O3($,Z,z){if(z===void 0||z===null)return;if(Array.isArray(z)){for(let G of z)O3($,Z,G);return}$.append(Z,typeof z==="object"?JSON.stringify(z):String(z))}function c$($){let Z=new URLSearchParams,z=(G,W)=>{if(W===void 0||W===null)return;if(Array.isArray(W)){for(let X of W)z(G,X);return}Z.append(G,typeof W==="object"?JSON.stringify(W):String(W))};for(let[G,W]of Object.entries($))z(G,W);return Z.toString()}async function V9($,Z){if(Z.status>=200&&Z.status<300){let G=Z.headers.get("Content-Type");if(G&&!T$.test(G)){let X=(await Z.arrayBuffer()).byteLength;return`"${$}" answered with ${X} bytes of ${G}, which is not shown.`}let W=await Z.text();if(W==="")return null;if(W.length>T)return`${W.slice(0,T)}\u2026 [cut at ${T} of ${W.length} characters]`;try{return JSON.parse(W)}catch{return W}}let z=await Z.text();if(Z.status>=400&&Z.status<500){let G=z.length>e3?`${z.slice(0,e3)}\u2026`:z;throw new D(`"${$}" was refused with ${Z.status}${G?`: ${G}`:"."}`,Z.status)}if(Z.status<500)console.error(`[gemi/mcp] "${$}" answered ${Z.status}${Z.headers.get("Location")?` to ${Z.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new D(`"${$}" failed on the server.`,Z.status)}import{createHash as p$,randomBytes as i$,timingSafeEqual as l$}from"crypto";function j3($){let Z=$.headers.get("authorization");if(!Z)return null;let z=/^Bearer[ ]+([\x21-\x7e]+)$/i.exec(Z.trim());return z?z[1]:null}class n${options;name="api-key";constructor($){this.options=$;if(typeof $?.prefix!=="string"||!/^[A-Za-z0-9_-]{3,32}$/.test($.prefix))throw Error('McpApiKeyResolver: prefix is required: 3 to 32 letters, digits, _ or -, like "myapp_mcp_".');if(typeof $.verify!=="function")throw Error("McpApiKeyResolver: verify must be a function that looks a key up.")}static generate($){return`${$}${i$(32).toString("base64url")}`}static hash($){return p$("sha256").update($).digest("hex")}static hashesMatch($,Z){let z=Buffer.from($),G=Buffer.from(Z);return z.length===G.length&&l$(z,G)}async resolve($){let Z=j3($);if(!Z?.startsWith(this.options.prefix))return null;let z=await this.options.verify(Z,$);if(!z)return{ok:!1,error:"invalid_token",description:"The API key is not valid."};if(!z.user||typeof z.id!=="string"||z.id===""||!Array.isArray(z.scopes))throw Error("McpApiKeyResolver: verify must answer { user, id, scopes } for a key it knows, or null.");return{ok:!0,principal:{user:z.user,via:this.name,id:z.id,scopes:[...z.scopes]}}}}import{createHash as R9,randomBytes as _9}from"crypto";async function x3($,Z){let z=t$();if(!z)return null;let G=await z.consume($,Z);return G.allowed?null:Math.max(1,Math.ceil(G.retryAfter/1000))}function t$(){try{let $=y();return $.bound(l)?$.make(l):null}catch{return null}}var A3=["2026-07-28"],Y3=["2025-11-25","2025-06-18","2025-03-26"],C3=[...A3,...Y3],S3="io.modelcontextprotocol/protocolVersion",q3="io.modelcontextprotocol/clientCapabilities";var T3="io.modelcontextprotocol/serverInfo",_={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,HeaderMismatch:-32020,MissingRequiredClientCapability:-32021,UnsupportedProtocolVersion:-32022};class P extends Error{code;data;status;constructor($,Z,z,G=200){super(Z);this.code=$;this.data=z;this.status=G;this.name="JsonRpcError"}}function R($,Z){return{jsonrpc:"2.0",id:$,error:{code:Z.code,message:Z.message,...Z.data!==void 0?{data:Z.data}:{}}}}function P9($){if(Array.isArray($))throw new P(_.InvalidRequest,"Batched requests are not supported.",void 0,400);if(typeof $!=="object"||$===null||$.jsonrpc!=="2.0")throw new P(_.InvalidRequest,"Not a JSON-RPC 2.0 message.",void 0,400);let Z=$,z=Z.id,G=typeof z==="string"||typeof z==="number"&&Number.isFinite(z);if(typeof Z.method==="string"){if(Z.params!==void 0&&(typeof Z.params!=="object"||Z.params===null||Array.isArray(Z.params)))throw new P(_.InvalidRequest,"params must be an object.",void 0,400);if(z===void 0)return{kind:"notification",message:Z};if(!G)throw new P(_.InvalidRequest,"id must be a string or a number.",void 0,400);return{kind:"request",message:Z}}if(G&&(("result"in Z)||("error"in Z)))return{kind:"response",message:Z};throw new P(_.InvalidRequest,"Not a JSON-RPC request, notification or response.",void 0,400)}function k3($,Z){let z=$.outputSchema?.toJSONSchema(),G={...$.annotations,...$.title&&!Z?{title:$.title}:{}};return{name:$.name,...$.title?{title:$.title}:{},description:$.description,inputSchema:$.inputSchema.toJSONSchema(),...z&&(Z||z.type==="object")?{outputSchema:z}:{},...Object.keys(G).length>0?{annotations:G}:{}}}function S($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function I9($){let Z=/^=\?base64\?([A-Za-z0-9+/]*={0,2})\?=$/.exec($);if(!Z)return $;try{let z=Buffer.from(Z[1],"base64");return new TextDecoder("utf-8",{fatal:!0}).decode(z)}catch{return null}}import{createHmac as s$,timingSafeEqual as o$}from"crypto";function M3($,Z,z){let G=Buffer.from(JSON.stringify(z)).toString("base64url");return`${Z}.${G}.${L9($,Z,G).toString("base64url")}`}function R3($,Z,z,G=Date.now()){if(typeof z!=="string"||z.length>8192)return null;let W=z.split(".");if(W.length!==3||W[0]!==Z)return null;let[,X,Y]=W,K=Buffer.from(Y,"base64url"),Q=L9($,Z,X);if(K.length!==Q.length||!o$(K,Q))return null;let V;try{V=JSON.parse(Buffer.from(X,"base64url").toString("utf8"))}catch{return null}if(typeof V!=="object"||V===null)return null;if(typeof V.exp!=="number"||V.exp<=G)return null;return V}function L9($,Z,z){return s$("sha256",K3($)).update(`${Z}.${z}`).digest()}var E3="gemi.mcp.request-state.v1",D9="gemi.mcp.session.v1",a$=86400000,O9=600000,j9="gemi_approval",b3=2000,r$={limit:600,window:60},e$={limit:30,window:60};class $3{registry;static token="router.mcp.http";endpoint;resolvers;context;allowedOrigins;rateLimit;maxBodyBytes;serverInfo;instructions;nonces;approvalTimeoutMs;feature;featureOn;pending=new Map;inflight=new Map;constructor($,Z,z={}){this.registry=$;if(typeof Z.url!=="string")throw Error(`route.mcp.remote.url is required: the endpoint's canonical URL, like "https://example.com/mcp".`);this.endpoint=z2(Z.url);let G=Z.resolvers??[];if(!Array.isArray(G)||G.length===0)throw Error("route.mcp.remote is enabled without a caller resolver. Configure route.mcp.remote.resolvers \u2014 an McpOAuthServer, an McpApiKeyResolver, or your own \u2014 or leave the endpoint off. Without one every request would be refused, or answered as nobody.");for(let W of G)if(typeof W?.resolve!=="function"||typeof W.name!=="string"||W.name==="")throw Error("route.mcp.remote.resolvers: each resolver needs a name and a resolve().");if(this.resolvers=G,K3(E3),this.context={resource:this.resource,registry:$},this.allowedOrigins=new Set((Z.allowedOrigins??[]).map((W)=>{if(new URL(W).origin!==W)throw Error(`route.mcp.remote.allowedOrigins: "${W}" is not an origin (scheme://host[:port]).`);return W})),this.allowedOrigins.add(this.endpoint.origin),this.rateLimit=Z.rateLimit===!1?!1:Z.rateLimit??r$,this.maxBodyBytes=Z.maxBodyBytes??Math.ceil($.maxFileBytes*1.4)+1048576,this.serverInfo={name:Z.server?.name??"gemi",version:Z.server?.version??"1.0.0"},this.instructions=Z.server?.instructions,this.nonces=Z.nonces??new k9,this.approvalTimeoutMs=Z.approvalTimeoutMs??O9,Z.feature!==void 0){if(typeof Z.feature!=="string"||Z.feature==="")throw Error("route.mcp.remote.feature must be a feature key from app/features.");this.feature=Z.feature}this.featureOn=z.featureOn??X3;for(let W of G)W.boot?.(this.context)}get resource(){return this.endpoint.href.replace(/\/$/,"")}async handle($){let Z=new URL($.url);if(Z.host!==this.endpoint.host)return null;if(this.feature!==void 0){if(!this.ownsPath(Z.pathname))return null;if(await this.featureOn(this.feature)!==!0)return null}for(let W of this.resolvers){let X=await W.handle?.($,this.context);if(X)return X}if(Z.pathname!==this.endpoint.pathname)return null;let z=$.headers.get("origin");if(z!==null&&!this.allowedOrigins.has(z))return f(R(null,new P(_.InvalidRequest,"Origin not allowed.")),403);let G=z?Z2(z):{};if($.method==="OPTIONS")return new Response(null,{status:204,headers:{...G,"Access-Control-Allow-Methods":"POST","Access-Control-Allow-Headers":"Authorization, Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id, Mcp-Method, Mcp-Name, Last-Event-ID","Access-Control-Max-Age":"600"}});if($.method!=="POST")return x9(new Response(null,{status:405,headers:{Allow:"POST, OPTIONS"}}),G);return x9(await this.post($),G)}ownsPath($){let Z=this.endpoint.pathname.replace(/\/$/,"");return $===this.endpoint.pathname||$===Z||$.startsWith(`${Z}/`)||$.startsWith("/.well-known/")}async post($){let Z=null;for(let Y of this.resolvers){let K=await Y.resolve($,this.context);if(K===null)continue;if(K.ok===!1)return await this.failedAttempt($)??this.unauthorized(K.description);Z={...K.principal,via:Y.name};break}if(!Z)return(j3($)!==null?await this.failedAttempt($):null)??this.unauthorized();let z=await this.spend(Z);if(z)return z;let G=$.headers.get("content-type")??"";if(!/^application\/json\s*(;|$)/i.test(G))return new Response("Content-Type must be application/json.",{status:415});let W;try{W=JSON.parse(await $2($,this.maxBodyBytes))}catch(Y){if(Y instanceof V3)return f(R(null,new P(_.InvalidRequest,`The request is larger than ${this.maxBodyBytes} bytes.`)),413);return f(R(null,new P(_.ParseError,"Parse error.")),400)}let X=new m($,{},"api",this.endpoint.pathname);return await g.run(X,async()=>{try{return await this.dispatch($,X,Z,W)}catch(Y){if(Y instanceof P){let K=S(W)&&(typeof W.id==="string"||typeof W.id==="number")?W.id:null;return f(R(K,Y),Y.status)}return console.error("[gemi/mcp] The MCP endpoint failed:",Y),f(R(null,new P(_.InternalError,"Internal error.")),500)}},{user:Z.user})}async dispatch($,Z,z,G){let W=P9(G),X={kind:"remote",req:Z,principal:z};if(W.kind==="response"){let B=this.session($,z),I=this.pending.get(String(W.message.id));if(I&&I.session===B.id)this.pending.delete(String(W.message.id)),I.resolve(W.message);return new Response(null,{status:202})}let{message:Y}=W,K=Y.params??{},Q=S(K._meta)?K._meta:{};if(typeof Q[S3]==="string"){if(this.checkModernHeaders($,Y,Q[S3]),W.kind==="notification")return new Response(null,{status:202});return await this.respond(Y,async(B,I)=>this.modern({principal:z,caller:X,message:Y,params:K,era:{modern:!0},stream:B,signal:I}),C9(K),$.signal)}if(Y.method==="initialize"){if(W.kind!=="request")throw new P(_.InvalidRequest,"initialize is a request.",void 0,400);return this.initialize(W.message,K,z)}let V=this.session($,z),H=$.headers.get("mcp-protocol-version");if(H!==null&&H!==V.state.v)throw new P(_.InvalidRequest,`MCP-Protocol-Version ${H} is not the session's ${V.state.v}.`,void 0,400);if(W.kind==="notification"){if(Y.method==="notifications/cancelled"){let B=K.requestId;this.inflight.get(`${V.id}:${String(B)}`)?.abort()}return new Response(null,{status:202})}let U=`${V.id}:${String(Y.id)}`,F=new AbortController;this.inflight.set(U,F);let O=AbortSignal.any([F.signal,$.signal]);try{return await this.respond(Y,async(B,I)=>this.legacy({principal:z,caller:X,message:Y,params:K,era:{modern:!1,session:V.state,sessionId:V.id},stream:B,signal:I}),C9(K)||W2(this.registry,Y,V.state),O,()=>this.inflight.delete(U))}catch(B){throw this.inflight.delete(U),B}}async modern($){switch($.message.method){case"server/discover":return this.complete({supportedVersions:C3,capabilities:{tools:{}},...this.instructions?{instructions:this.instructions}:{},ttlMs:60000,cacheScope:"private"});case"tools/list":return this.complete({tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!0)),ttlMs:60000,cacheScope:"private"});case"tools/call":return await this.callTool($);default:throw new P(_.MethodNotFound,`Method not found: ${$.message.method}`,void 0,404)}}async legacy($){switch($.message.method){case"ping":return{};case"tools/list":return{tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!1))};case"tools/call":return await this.callTool($);default:throw new P(_.MethodNotFound,`Method not found: ${$.message.method}`)}}complete($){return{resultType:"complete",...$,_meta:{[T3]:this.serverInfo}}}initialize($,Z,z){let G=Z.protocolVersion,W=Y3.includes(G)?G:Y3[0],X=S(Z.capabilities)?Z.capabilities:{},Y={v:W,e:A9(X.elicitation),p:Q3(z),exp:Date.now()+a$},K=M3(D9,"gms1",Y);return f({jsonrpc:"2.0",id:$.id,result:{protocolVersion:W,capabilities:{tools:{listChanged:!1}},serverInfo:this.serverInfo,...this.instructions?{instructions:this.instructions}:{}}},200,{"Mcp-Session-Id":K})}session($,Z){let z=$.headers.get("mcp-session-id");if(!z)throw new P(_.InvalidRequest,"Missing Mcp-Session-Id. Send initialize first, or a request carrying io.modelcontextprotocol/protocolVersion in _meta.",void 0,400);let G=R3(D9,"gms1",z);if(!G||G.p!==Q3(Z))throw new P(_.InvalidRequest,"Session not found.",void 0,404);return{id:z,state:G}}checkModernHeaders($,Z,z){if(!A3.includes(z))throw new P(_.UnsupportedProtocolVersion,"Unsupported protocol version",{supported:C3,requested:z},400);let G=(Y)=>new P(_.HeaderMismatch,`Header mismatch: ${Y}`,void 0,400);if($.headers.get("mcp-protocol-version")!==z)throw G("MCP-Protocol-Version does not match the protocol version in _meta.");if($.headers.get("mcp-method")!==Z.method)throw G("Mcp-Method does not match the method.");let W=Z.params??{},X=Z.method==="tools/call"||Z.method==="prompts/get"?W.name:Z.method==="resources/read"?W.uri:void 0;if(X!==void 0){let Y=$.headers.get("mcp-name");if(Y===null||I9(Y)!==X)throw G("Mcp-Name does not match the request's name.")}}async callTool($){let{params:Z,caller:z,principal:G}=$,W=Z.name;if(typeof W!=="string")throw new P(_.InvalidParams,"tools/call needs a tool name.");let X=Z.arguments??{},Y=(await this.registry.available(z,{names:[W]}))[0];if(!Y)throw new P(_.InvalidParams,`Unknown tool: ${W}`);let K=!1;if(Y.requiresApproval){let F=Y.inputSchema.safeParse(X);if(F.ok===!1)return this.toolResult($,{content:[{type:"text",text:`Invalid arguments for "${W}": ${F.errors.join(", ")}`}],isError:!0});if($.era.modern&&S($.params.inputResponses)&&$.params.requestState!==void 0||await this.registry.approvalRequired(z,W,X,{signal:$.signal})){let B=await this.approval($,Y,X);if(B.kind==="answer")return B.result;K=!0}}let Q=X2($),V;try{V=await this.registry.execute(z,W,X,void 0,{approved:K,signal:$.signal,...Q?{progress:Q}:{}})}catch(F){if(F instanceof D)return this.toolResult($,{content:[{type:"text",text:F.message}],isError:!0});if(F instanceof v)throw new P(_.InvalidParams,F.reason==="unknown-tool"?`Unknown tool: ${W}`:F.message);return console.error(`[gemi/mcp] "${W}" failed for ${G.via}:${G.id}:`,F),this.toolResult($,{content:[{type:"text",text:`"${W}" failed on the server.`}],isError:!0})}let H=typeof V==="string"?V:JSON.stringify(V??null),U=Y.outputSchema&&($.era.modern||S(V))?{structuredContent:V}:{};return this.toolResult($,{content:[{type:"text",text:H}],...U,isError:!1})}toolResult($,Z){return $.era.modern?this.complete(Z):Z}async approval($,Z,z){let G=Y2(Z,z),W=(V)=>({kind:"answer",result:this.toolResult($,{content:[{type:"text",text:V}],isError:!0})});if($.era.modern){let V=S($.params._meta)?$.params._meta:{},H=S(V[q3])?V[q3]:{},U=S($.params.inputResponses)?$.params.inputResponses:null,F=$.params.requestState,O=G2(z);if(U&&F!==void 0){let I=R3(E3,"grs1",F);if(!I||I.p!==Q3($.principal)||I.t!==Z.name||I.a!==O)throw new P(_.InvalidParams,"requestState is not valid for this call.");if(!await this.spendNonce(I.n,I.exp))throw new P(_.InvalidParams,"requestState has already been used.");return S9(U[j9])?{kind:"approved"}:W(`The user did not approve "${Z.name}", and it did not run.`)}if(!A9(H.elicitation))throw new P(_.MissingRequiredClientCapability,`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation).`,{requiredCapabilities:{elicitation:{form:{}}}},400);let B={p:Q3($.principal),t:Z.name,a:O,n:_9(16).toString("base64url"),exp:Date.now()+O9};return{kind:"answer",result:{resultType:"input_required",inputRequests:{[j9]:{method:"elicitation/create",params:{mode:"form",...G}}},requestState:M3(E3,"grs1",B),_meta:{[T3]:this.serverInfo}}}}let X=$.era;if(!X.session.e||!$.stream)return W(`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation). It did not run.`);let Y=`gemi-approval-${_9(12).toString("base64url")}`,K=X.sessionId,Q=await new Promise((V)=>{let H=setTimeout(()=>{this.pending.delete(Y),V(null)},this.approvalTimeoutMs),U=(F)=>{clearTimeout(H),V(F)};this.pending.set(Y,{session:K,resolve:U}),$.signal.addEventListener("abort",()=>{this.pending.delete(Y),U(null)}),$.stream.send({jsonrpc:"2.0",id:Y,method:"elicitation/create",params:X.session.v==="2025-11-25"?{mode:"form",...G}:G})});return Q&&!Q.error&&S9(Q.result)?{kind:"approved"}:W(`The user did not approve "${Z.name}", and it did not run.`)}async spendNonce($,Z){try{return await this.nonces.consume($,Z)}catch(z){return console.error("[gemi/mcp] Spending an approval failed:",z),!1}}async respond($,Z,z,G,W){if(!z)try{let Q=await Z(null,G);return f({jsonrpc:"2.0",id:$.id,result:Q},200)}finally{W?.()}let X=new AbortController,Y=AbortSignal.any([X.signal,G]),K=new E9(()=>X.abort());return(async()=>{try{let Q=await Z(K,Y);K.send({jsonrpc:"2.0",id:$.id,result:Q})}catch(Q){if(Q instanceof P)K.send(R($.id,Q));else console.error("[gemi/mcp] The MCP endpoint failed:",Q),K.send(R($.id,new P(_.InternalError,"Internal error.")))}finally{W?.(),K.close()}})(),new Response(K.readable,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"}})}unauthorized($){let Z=this.resolvers.map((G)=>G.challenge?.(this.context)).find(Boolean)??'Bearer realm="mcp"',z=$?`${Z}, error="invalid_token", error_description="${$.replace(/["\\]/g,"")}"`:Z;return f(R(null,new P(_.InvalidRequest,"Unauthorized.")),401,{"WWW-Authenticate":z})}async failedAttempt($){let Z=T9(new m($,{},"api",this.endpoint.pathname)),z=await x3(`mcp-auth-failed:${Z}`,e$);return z===null?null:q9(z)}async spend($){if(!this.rateLimit)return null;let Z=await x3(`mcp-endpoint:${$.via}:${$.id}`,this.rateLimit);return Z===null?null:q9(Z)}}class E9{readable;controller;closed=!1;encoder=new TextEncoder;constructor($){this.readable=new ReadableStream({start:(Z)=>{this.controller=Z},cancel:()=>{this.closed=!0,$()}})}send($){if(this.closed)return;this.controller.enqueue(this.encoder.encode(`event: message
|
|
2
|
+
import{$b as M9,Jc as F9,Xb as k9,_b as K3,dc as e,ld as N9,qc as U9,wc as J9}from"./chunk-9zd7c4wq.js";import{Bd as L$,sd as c3,ud as B3,xd as d9,yd as c9,zd as V$}from"./chunk-fpz9e3xx.js";import{Ed as w9,Jd as v9,Ld as g9,Sd as x,Td as h9,Ud as m9,Wd as u9,Xd as B$}from"./chunk-ce9wm3r9.js";import{_d as N}from"./chunk-6hs102jh.js";import{Ag as L3,Bg as d3,Cf as Y$,Df as G$,Ef as W$,Fe as H$,Ge as p3,Gf as w,Gg as X$,Hg as K$,Ke as J3,Le as X3,Ng as D$,Tf as a3,cg as s3,df as m3,eg as n,ig as o3,jg as t9,ke as l,kg as s9,le as z$,oe as T9,qg as f3,rf as Z3,rg as o9,se as O$,sg as G3,tg as r9,ug as e9,ve as Q$,vg as w3,wg as a,xf as H3,yf as h3,zf as q,zg as A$}from"./chunk-a78b9v7h.js";import{Ai as F3,Bi as z3,Sh as p,Uh as m,hi as t3,vi as H9,zi as P3}from"./chunk-27xsjq8a.js";import{Hi as i9}from"./chunk-9k46m1vf.js";import{Si as g}from"./chunk-fg2k18d2.js";import{Yi as u3}from"./chunk-ktrm6y5j.js";import{$i as U$,aj as i3,dj as N3,ej as n3,hj as F$}from"./chunk-9xzg05xg.js";import{Aj as n9,vj as l9}from"./chunk-a37shxb1.js";import{Qj as f9,Sj as u}from"./chunk-1skdsmjx.js";import{Tj as j}from"./chunk-yjszzjyj.js";import{Zj as I$}from"./chunk-p81qeav5.js";import{Nk as l3}from"./chunk-5g7m7g4a.js";import{Uk as U3,Xk as y}from"./chunk-1ed75a7b.js";import{el as g3}from"./chunk-s29tgy4y.js";import{pl as a9}from"./chunk-m6t5a0me.js";var C$="mcp",S$=/^[\x21\x23-\x5B\x5D-\x7E]+$/;class D extends e{status;constructor($,Z){super($);this.status=Z;this.name="McpToolError"}}class v extends Error{reason;constructor($,Z){super($);this.reason=Z;this.name="McpCallRefusedError"}}var r3=/^[A-Za-z0-9_-]{1,64}$/,q$=/:([A-Za-z_][A-Za-z0-9_]*)([?*+]?)/g,e3=4000,T=1e5,T$=/^(text\/|application\/([\w.+-]*\+)?(json|xml))/i,B9=new WeakMap;function X6($){return B9.get($)}class i{router;dispatcher;static token="router.mcp";plans=new Map;scopeTools=new Map;files;featureOn;constructor($,Z,z={}){this.router=$;this.dispatcher=Z;this.files=b$(z.files),this.featureOn=z.featureOn??X3;for(let[G,W]of Object.entries($.routes??{}))this.plans.set(G,k$(W)?this.planNative(G,W):this.plan(G,W));this.resolveScopes()}list($,Z){if(D3($),$.kind==="local")return this.descriptors(Z);let z=[];for(let[G,W]of this.plans){if(!W.remote||!this.grants($.principal,G))continue;if(W9(W.remote,Z))z.push(W.remote)}return z}async available($,Z){let z=[];for(let G of this.list($,Z))if(await this.isOn(G))z.push(G);return z}descriptors($){let Z=[];for(let{descriptor:z}of this.plans.values())if(W9(z,$))Z.push(z);return Z}get maxFileBytes(){return this.files.maxBytes}scopes(){return[...this.scopeTools].map(([$,{description:Z}])=>({name:$,description:Z}))}scopesFor($){return[...this.scopeTools].filter(([,{tools:Z}])=>Z.has($)).map(([Z])=>Z)}async execute($,Z,z,G,W={}){D3($);let X=this.plans.get(Z);if(X&&!await this.isOn(X.descriptor)){if($.kind==="remote")throw new v(`There is no tool named "${Z}".`,"unknown-tool");throw new D(`There is no tool named "${Z}".`,404)}if($.kind==="remote"){if(!X?.remote||!this.grants($.principal,Z))throw new v(`There is no tool named "${Z}".`,"unknown-tool");if(X.descriptor.requiresApproval&&W.approved!==!0&&!W3(X))throw new v(`"${Z}" needs the user's approval, and this call does not have it.`,"approval-required");G=void 0}if(!X)throw Error(`McpRegistry: there is no tool named "${Z}".`);if(X.kind==="tool")return await this.executeNative(X,$,z,G,W);let Y=X,K=$.kind==="remote"?Y.remote:Y.descriptor,Q=K.inputSchema.safeParse(z);if(Q.ok===!1)throw new D(`Invalid arguments for "${Z}": ${Q.errors.join(", ")}`);let V=Q.value,H={caller:$,req:$.req,tool:K,input:V,ctx:G},U=await this.fillPath(Y,H),{path:F}=this.dispatcher.getRouteHandlerAndParams(new Request(`http://gemi.internal/api${U}`));if(F!==K.url)throw new D(`"${Z}" has nothing at ${U}.`,404);let O={};for(let L of Y.jsonKeys)if(V[L]!==void 0)O[L]=V[L];let B,I="";if(Y.fileFields.length>0)B=await this.formData(Y,O,H);else if(K.method==="GET")I=c$(O);else if(Y.jsonKeys.length>0)B=O;let k=this.router.credentials?await this.bind(Y,"the credentials",()=>this.router.credentials(H)):void 0,A={...k?{credentials:k}:{},...W.signal?{signal:W.signal}:{},...W.progress?{progress:W.progress}:{},...$.kind==="remote"?{identity:{user:$.principal.user,grant:{via:$.principal.via,id:$.principal.id,scopes:$.principal.scopes,...$.principal.clientId?{clientId:$.principal.clientId}:{}}}}:{}},M;try{let L=I?`${U}?${I}`:U;M=Object.keys(A).length>0?await this.dispatcher.dispatchAs($.req,K.method,L,B,A):await this.dispatcher.dispatchAs($.req,K.method,L,B)}catch(L){throw console.error(`[gemi/mcp] Dispatching "${Z}" failed:`,L),new D(`"${Z}" failed on the server.`,500)}if(!Y.result&&!K.outputSchema)return await V9(Z,M);return await this.project(Y,H,M)}async isOn($){return $.feature===void 0||await this.featureOn($.feature)===!0}plan($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (${Z?.method} ${Z?.url})`;if(!(Z instanceof Object)||Z.__internal_brand!=="McpRoute")throw Error(`McpRouter: "${$}" is not a route or a tool. Declare it with this.fromApiRoute(...) or this.fromTool(...).`);let{method:G,url:W,meta:X}=Z;if(X.feature!==void 0&&(typeof X.feature!=="string"||X.feature===""))throw Error(`${z}: feature must be a feature key from app/features.`);if(W.startsWith("/__gemi__"))throw Error(`${z} is a framework route, not an app route.`);let Y=this.dispatcher.flatRoutes[W]?.[G];if(!Y)throw Error(`${z} names no route of this app. Expose a route by the path and verb it is mounted at.`);let K=[...W.matchAll(q$)].map(([,J,C])=>({name:J,modifier:C})),Q=X.params??{};for(let J of K)if(!(J.name in Q))throw Error(`${z}: the path param "${J.name}" must be bound or declared "input".`);for(let[J,C]of Object.entries(Q)){if(!K.some((h)=>h.name===J))throw Error(`${z}: "${J}" in params is not a param of the url.`);if(Y9(C))g$(z,`params.${J}`,C);else X9(z,`params.${J}`,C)}let V=[],H;if(X.input){if(H=X.input.toJSONSchema(),H.type!=="object"||!H.properties)throw Error(`${z}: input must be an s.object(...), the fields of the request body.`);V=Object.keys(H.properties)}let U=Object.entries(X.files??{}).map(([J,C])=>({name:J,binder:C}));for(let J of U)X9(z,`files.${J.name}`,J.binder);if(X.result!==void 0&&typeof X.result!=="function")throw Error(`${z}: result must be a function.`);if(X.output!==void 0&&typeof X.output?.safeParse!=="function")throw Error(`${z}: output must be a schema, built with s.`);if(X.title!==void 0&&(typeof X.title!=="string"||X.title===""))throw Error(`${z}: title must be a non-empty string.`);let F=K9(z,G,X.annotations);if(U.length>0&&G==="GET")throw Error(`${z}: a GET has no body to carry a file.`);let O={},B=(J,C)=>{if(J in O)throw Error(`${z}: "${J}" is the input key of two params or files, and the model can only send one.`);O[J]=C},I=new Map,k=new Map;for(let J of K){let C=Q[J.name];if(C==="input"){let h=p.string().describe(`The ":${J.name}" segment of the url.`);B(J.name,J.modifier==="?"||J.modifier==="*"?h.optional():h)}else if(Y9(C)){let h=C.as??J.name;B(h,C.input),k.set(J.name,{key:h,param:C})}else I.set(J.name,C)}let A={};for(let J of U)if(J.binder==="input")B(J.name,p.string().describe("The id of an attachment the user uploaded or a tool produced (gemi_att_\u2026), whose file is sent as this field.")),A[J.name]=this.remoteFileSchema();let M=[...Object.keys(O),...U.map((J)=>J.name)];for(let J of new Set(M))if(V.includes(J))throw Error(`${z}: "${J}" is both an input field and a param or file, and the model can only send one.`);let L=Object.freeze({kind:"route",name:$,description:X.description,method:G,url:W,inputSchema:Q9(X.input,H,p.object(O)),...X.output?{outputSchema:X.output}:{},...X.title?{title:X.title}:{},annotations:F,tags:Object.freeze([...X.tags??[]]),requiresApproval:X.requiresApproval===!0,...X.feature!==void 0?{feature:X.feature}:{},...Y.source?{source:Y.source}:{}}),r=!U.every((J)=>J.binder==="input")?null:U.length===0?L:Object.freeze({...L,inputSchema:Q9(X.input,H,p.object(u$(O,Object.keys(A))),A)});return{kind:"route",descriptor:L,remote:r,params:K,paramBinders:I,modelParams:k,fileFields:U,jsonKeys:V,...X.result?{result:X.result}:{}}}remoteFileSchema(){let{maxBytes:$,fetch:Z}=this.files,z={name:{type:"string",description:"The file's name, like report.pdf."},mimeType:{type:"string",description:"The file's media type, like application/pdf."},data:{type:"string",contentEncoding:"base64",description:`The file's bytes, base64-encoded (RFC 4648, standard alphabet). At most ${$} bytes decoded.`}};if(Z)z.url={type:"string",format:"uri",description:"An https URL the server downloads the file from, instead of data."};let G={type:"object",description:Z?"A file, sent as base64 in data or fetched from url: exactly one of the two.":"A file, sent as base64 in data.",properties:z,required:["name","mimeType"],additionalProperties:!1},W=Object.keys(z),X=(Y)=>{if(typeof Y!=="object"||Y===null||Array.isArray(Y))return{ok:!1,errors:["a file must be an object"]};let K=[],Q={};for(let V of Object.keys(Y))if(!W.includes(V))K.push(`a file has no field "${V}"`);for(let V of W){let H=Y[V];if(H===void 0||H===null){if(V==="name"||V==="mimeType")K.push(`a file needs "${V}"`);continue}if(typeof H!=="string")K.push(`a file's "${V}" must be a string`);else Q[V]=H}return K.length>0?{ok:!1,errors:K}:{ok:!0,value:Q}};return{toJSONSchema:()=>G,safeParse:X,parse(Y){let K=X(Y);if(K.ok===!1)throw Error(K.errors.join(", "));return K.value}}}planNative($,Z){if(!r3.test($))throw Error(`McpRouter: "${$}" is not a valid tool name. A routes key is the tool's name as a model and an MCP client see it, used verbatim \u2014 letters, digits, "_" and "-", at most 64.`);let z=`McpRouter: "${$}" (a native tool)`,{tool:G,meta:W={}}=Z;if(!(G instanceof Object)||typeof G.name!=="string")throw Error(`${z} is not an AgentTool. Pass one built with AgentTool.create(...).`);if(G.answeredBy==="client"||typeof G.execute!=="function")throw Error(`${z}: "${G.name}" is answered by the client, and only a tool the server runs can be called through the registry.`);if(typeof G.inputSchema==="function")throw Error(`${z}: "${G.name}" resolves its input schema per run, and the registry lists one schema to every caller. Give it a fixed inputSchema.`);if(typeof G.inputSchema?.safeParse!=="function")throw Error(`${z}: its inputSchema must be a schema, built with s.`);if(typeof W!=="object"||W===null)throw Error(`${z}: the meta must be an object.`);if(W.description!==void 0&&(typeof W.description!=="string"||W.description.trim()===""))throw Error(`${z}: description must be a non-empty string.`);if(W.title!==void 0&&(typeof W.title!=="string"||W.title===""))throw Error(`${z}: title must be a non-empty string.`);if(W.tags!==void 0&&(!Array.isArray(W.tags)||W.tags.some((Q)=>typeof Q!=="string")))throw Error(`${z}: tags must be an array of strings.`);if(W.requiresApproval===!1&&G.requiresApproval)throw Error(`${z}: "${G.name}" requires approval, and requiresApproval: false would run it without asking. Leave it out, or register a tool that does not ask.`);let X=W.remote;if(X!==void 0){if(typeof X!=="object"||X===null||typeof X.context!=="function")throw Error(`${z}: remote must be { context(call) }, building the AgentContext a remote call runs with.`);if(X.progress!==void 0&&typeof X.progress!=="function")throw Error(`${z}: remote.progress must be a function.`)}let Y=W.description??G.description;if(typeof Y!=="string"||Y.trim()==="")throw Error(`${z} needs a description: the tool's own, or the meta's.`);let K=Object.freeze({kind:"tool",name:$,description:Y,inputSchema:G.inputSchema,...G.outputSchema?{outputSchema:G.outputSchema}:{},...W.title?{title:W.title}:{},annotations:K9(z,void 0,W.annotations),tags:Object.freeze([...W.tags??[]]),requiresApproval:G.requiresApproval||W.requiresApproval===!0});return{kind:"tool",descriptor:K,remote:X?K:null,tool:G,meta:W}}async approvalRequired($,Z,z,G={}){let W=this.plans.get(Z);if(!W)return!0;if(!W3(W))return W.descriptor.requiresApproval;let X=W;if($.kind!=="remote"||!X.meta.remote)return!0;let Y=X.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)return!0;let K={caller:$,req:$.req,tool:X.descriptor,input:Y.value},Q;try{Q=await this.bind(X,"the remote context",()=>X.meta.remote.context(K))}catch{return!0}if(typeof Q!=="object"||Q===null)return!0;let V=G.signal??new AbortController().signal;return G9(X,Y.value,z9(Z9(X,Q,V)))}nativeApproval($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return W3(Z)??Z.descriptor.requiresApproval}nativeTool($){let Z=this.plans.get($);if(Z?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${$}".`);return Z.tool}startNative($,Z,z,G){let W=this.plans.get(Z);if(W?.kind!=="tool")throw Error(`McpRegistry: there is no native tool named "${Z}".`);if($===void 0)return W.tool.execute(z,G);if(D3($),$.kind!=="local")throw Error("McpRegistry: startNative is for a local caller. A remote call goes through execute().");let X=W.descriptor.inputSchema.safeParse(z);if(X.ok===!1)throw new D(`Invalid arguments for "${Z}": ${X.errors.join(", ")}`);return this.runNative(W,{caller:$,req:$.req,tool:W.descriptor,input:X.value},G)}runNative($,Z,z){let G={...z};return B9.set(G,{...Z,ctx:G}),$.tool.execute(Z.input,G)}async executeNative($,Z,z,G,W){let{name:X}=$.descriptor,Y=$.descriptor.inputSchema.safeParse(z);if(Y.ok===!1)throw new D(`Invalid arguments for "${X}": ${Y.errors.join(", ")}`);let K={caller:Z,req:Z.req,tool:$.descriptor,input:Y.value},Q=(L,_3)=>{if(!W.progress)return;let r;try{r=$.meta.remote?.progress?$.meta.remote.progress(L,_3):R$(L,_3)}catch(J){console.error(`[gemi/mcp] The progress mapping of "${X}" failed:`,J);return}if(r)W.progress(r)};if(Z.kind==="local"){if(!G)throw Error(`McpRegistry: "${X}" is a native tool, which runs with the tool context of an agent call, and none was passed to execute().`);return await $9(this.runNative($,{...K,ctx:G},G),Q)}let V=$.meta.remote,H=await this.bind($,"the remote context",()=>V.context(K));if(typeof H!=="object"||H===null)throw console.error(`[gemi/mcp] The remote context of "${X}" is not an object:`,H),new D(`"${X}" failed on the server.`,500);let U=$.tool.timeoutMs,F=[...W.signal?[W.signal]:[],...U!==void 0?[AbortSignal.timeout(U)]:[]],O=F.length===0?new AbortController().signal:F.length===1?F[0]:AbortSignal.any(F),B=Z9($,H,O);if(!W.approved&&W3($)&&await G9($,K.input,z9(B)))throw new v(`"${X}" needs the user's approval, and this call does not have it.`,"approval-required");let I;try{I=await $9(this.runNative($,{...K,ctx:B},B),Q,O)}catch(L){if(O.aborted&&L===O.reason){if(W.signal?.aborted)throw new D(`"${X}" was cancelled.`,499);throw new D(`"${X}" did not finish within ${U} ms.`,504)}if(L instanceof D)throw L;if(L instanceof e||L instanceof v)throw new D(L.message);throw console.error(`[gemi/mcp] "${X}" failed for a remote caller:`,L),new D(`"${X}" failed on the server.`,500)}let k=(L)=>{return console.error(`[gemi/mcp] "${X}" ${L}`),new D(`"${X}" failed on the server.`,500)};if(U9(I))throw k("answered a job handle, and a remote call has no background jobs.");let A=I;if($.descriptor.outputSchema){let L=$.descriptor.outputSchema.safeParse(A);if(L.ok===!1)throw k(`answered what its output schema refuses: ${L.errors.join(", ")}`);A=L.value}if(A===void 0)return null;if(typeof A==="string")return A.length>T?`${A.slice(0,T)}\u2026 [cut at ${T} of ${A.length} characters]`:A;let M=JSON.stringify(A);if(M!==void 0&&M.length>T)return`${M.slice(0,T)}\u2026 [cut at ${T} of ${M.length} characters]`;return A}async fillPath($,Z){let{input:z,req:G}=Z,W=$.descriptor.url;for(let X of $.params){let Y=$.paramBinders.get(X.name),K=$.modelParams.get(X.name),Q;if(Y||K){if(Q=K?await this.bind($,`the param "${X.name}"`,()=>K.param.bind(z[K.key],G,Z),{refusals:!0}):await this.bind($,`the param "${X.name}"`,()=>Y(G,Z)),Q===void 0||Q===null||Q==="")throw console.error(`[gemi/mcp] The ${K?"resolver":"binder"} for "${X.name}" of "${$.descriptor.name}" returned ${JSON.stringify(Q)}.`),new D(`"${$.descriptor.name}" failed on the server.`,500)}else Q=z[X.name];let V=`:${X.name}${X.modifier}`;if(Q===void 0||Q===null||Q===""){if(X.modifier!=="?"&&X.modifier!=="*")throw new D(`"${X.name}" of "${$.descriptor.name}" must not be empty.`);W=W.replace(`/${V}`,"");continue}W=W.replace(V,d$($.descriptor.name,X,String(Q)))}return W}async formData($,Z,z){let{input:G,ctx:W}=z,X=$.descriptor.name;if(z.caller.kind==="remote"){let K=new FormData;for(let[Q,V]of Object.entries(Z))O3(K,Q,V);for(let Q of $.fileFields)K.append(Q.name,await this.remoteFile(X,Q.name,G[Q.name]));return K}if(!W)throw Error(`McpRegistry: "${X}" sends a file, which is resolved through the tool context's attachments, and none was passed to execute().`);let Y=new FormData;for(let[K,Q]of Object.entries(Z))O3(Y,K,Q);for(let K of $.fileFields){let Q=K.binder==="input"?G[K.name]:await this.bind($,`the file "${K.name}"`,()=>K.binder(W,z));if(typeof Q!=="string"||Q==="")throw new D(`"${X}" needs a file for "${K.name}", and this turn has none. Ask the user to attach one.`);Y.append(K.name,await W.attachments.file(Q))}return Y}async remoteFile($,Z,z){let G=(H)=>new D(`"${Z}" of "${$}" ${H}`,400),W=z,{maxBytes:X,fetch:Y}=this.files;if(!y$(W.name))throw G("needs a name of 1 to 255 characters, without control characters or slashes.");if(!f$.test(W.mimeType))throw G(`has a mimeType that is not a media type: "${W.mimeType.slice(0,100)}".`);let K=typeof W.data==="string",Q=typeof W.url==="string";if(K===Q)throw G(Y?"needs exactly one of data or url.":"needs its bytes, base64, in data.");if(K){let H=W.data.replace(/\s+/g,"");if(Math.floor(H.length*3/4)-v$(H)>X)throw G(`is larger than the ${X} bytes a file may be.`);if(H.length%4!==0||!w$.test(H))throw G("has data that is not base64 (RFC 4648, standard alphabet, padded).");return new File([Buffer.from(H,"base64")],W.name,{type:W.mimeType})}if(!Y)throw G("cannot be fetched from a URL here. Send its bytes, base64, in data.");let V;try{V=new URL(W.url)}catch{throw G("has a url that is not a URL.")}if(V.protocol!=="https:")throw G("can only be fetched from an https URL.");try{let H=await H9(V.href,{...Y,maxSize:Math.min(Y.maxSize??X,X),redirect:"follow"});if(!H.ok)throw G(`could not be fetched: ${V.host} answered ${H.status}.`);let U=await H.arrayBuffer();return new File([U],W.name,{type:W.mimeType})}catch(H){if(H instanceof D)throw H;throw G(`could not be fetched from ${V.host}: ${H instanceof Error?H.message:"failed"}.`)}}grants($,Z){for(let z of $.scopes??[])if(this.scopeTools.get(z)?.tools.has(Z))return!0;return!1}resolveScopes(){let $=this.router.scopes;if($===void 0){this.scopeTools.set(C$,{description:"Use this app's tools as you",tools:new Set(this.plans.keys())});return}if(typeof $!=="object"||$===null)throw Error("McpRouter: scopes must be an object of scope names.");let Z=new Set([...this.plans.values()].flatMap(({descriptor:z})=>z.tags));for(let[z,G]of Object.entries($)){let W=`McpRouter: scope "${z}"`;if(!S$.test(z))throw Error(`${W} is not a valid OAuth scope: printable ASCII, no spaces or quotes.`);if(typeof G?.description!=="string"||G.description==="")throw Error(`${W} needs a description: it is what a consent screen shows.`);let X=new Set;for(let Y of G.tags??[]){if(!Z.has(Y))throw Error(`${W} names the tag "${Y}", which no tool has.`);for(let[K,{descriptor:Q}]of this.plans)if(Q.tags.includes(Y))X.add(K)}for(let Y of G.names??[]){if(!this.plans.has(Y))throw Error(`${W} names "${Y}", which is no tool.`);X.add(Y)}if(X.size===0)throw Error(`${W} reaches no tool. Give it tags or names.`);this.scopeTools.set(z,{description:G.description,tools:X})}}async project($,Z,z){let{name:G,outputSchema:W}=$.descriptor;if(z.status<200||z.status>=300)return await V9(G,z);let X=(U,F)=>{if(F===void 0)console.error(`[gemi/mcp] "${G}" ${U}`);else console.error(`[gemi/mcp] "${G}" ${U}`,F);return new D(`"${G}" failed on the server.`,500)},Y=z.headers.get("Content-Type"),K=await z.text(),Q=null;if(K!=="")try{Q=JSON.parse(K)}catch{throw X(`answered ${Y??"a body with no content-type"} that is not JSON, and its result or output needs JSON.`)}let V=Q;if($.result)try{V=await $.result(Q,Z)}catch(U){throw X("failed in its result projection:",U)}if(W){let U=W.safeParse(V);if(U.ok===!1)throw X(`answered what its output schema refuses: ${U.errors.join(", ")}`);V=U.value}if(V===void 0)return null;let H=JSON.stringify(V);if(H!==void 0&&H.length>T)return`${H.slice(0,T)}\u2026 [cut at ${T} of ${H.length} characters]`;return V}async bind($,Z,z,G={}){try{return await z()}catch(W){if(G.refusals&&W instanceof e)throw W;throw console.error(`[gemi/mcp] Binding ${Z} of "${$.descriptor.name}" failed:`,W),new D(`"${$.descriptor.name}" failed on the server.`,500)}}}function k$($){return $ instanceof Object&&$.__internal_brand==="McpTool"}function M$($){return typeof $==="object"&&$!==null&&typeof $.next==="function"&&Symbol.asyncIterator in $}async function $9($,Z,z){let G;if(z)G=new Promise((X,Y)=>{if(z.aborted)Y(z.reason);else z.addEventListener("abort",()=>Y(z.reason),{once:!0})}),G.catch(()=>{});let W=(X)=>G?Promise.race([X,G]):X;if(!M$($))return await W(Promise.resolve($));try{let X=0,Y=await W($.next());while(!Y.done)Z(Y.value,++X),Y=await W($.next());return Y.value}catch(X){throw $.return(void 0).catch(()=>{}),X}}function R$($,Z){if(typeof $==="string")return{progress:Z,message:$};if(typeof $==="object"&&$!==null){let{progress:z,total:G,message:W}=$;if(typeof z==="number"&&Number.isFinite(z))return{progress:z,...typeof G==="number"?{total:G}:{},...typeof W==="string"?{message:W}:{}};if(typeof W==="string")return{progress:Z,message:W}}return{progress:Z}}function Z9($,Z,z){let G=$.descriptor.name,W=`mcp_${crypto.randomUUID()}`,X=`mcp_call_${crypto.randomUUID()}`,Y=(Q)=>async()=>{throw new e(`"${G}" was called by a remote MCP client, which has no ${Q}.`,{retryable:!1})},K={put:Y("attachment store"),get:Y("attachment store"),read:Y("attachment store"),file:Y("attachment store")};return{context:Z,body:{},runId:W,toolCallId:X,signal:z,step:1,depth:0,resumed:!1,attachments:K,turn:Object.freeze({attachments:Object.freeze([])}),runAgent:Y("agent run to nest a sub-agent in"),generateImage:Y("attachment store to put an image in"),editImage:Y("attachment store to put an image in"),generate:(Q)=>N9({...Q,signal:Q.signal?AbortSignal.any([z,Q.signal]):z},{origin:{mcp:G,runId:W,toolCallId:X}}),jobs:J9({jobs:void 0,threadId:void 0,runId:W,toolCallId:X,toolName:G,depth:0,async:$.tool.async,attachments:null}),memory:F9()}}function W3($){if($.kind!=="tool"||$.meta.requiresApproval===!0)return;return $.tool.approvalPredicate}function z9($){return{context:$.context,body:$.body,runId:$.runId,threadId:$.threadId,toolCallId:$.toolCallId,step:$.step,depth:$.depth,signal:$.signal}}async function G9($,Z,z){try{return await $.tool.approvalPredicate(Z,z)!==!1}catch(G){return console.error(`[gemi/mcp] The requiresApproval of "${$.descriptor.name}" threw, so the call asks the user:`,G),!0}}function D3($){if($?.kind==="local"&&$.req)return;if($?.kind==="remote"&&$.req&&$.principal?.user&&typeof $.principal.id==="string"&&Array.isArray($.principal.scopes))return;throw Error('McpRegistry: a caller is { kind: "local", req } or { kind: "remote", req, principal }, with the principal a caller resolver verified.')}function W9($,Z){if(Z?.names&&!Z.names.includes($.name))return!1;if(Z?.tags&&!$.tags.some((z)=>Z.tags.includes(z)))return!1;return!0}var E$=10485760;function b$($){let Z=$?.maxBytes??E$;if(!Number.isSafeInteger(Z)||Z<=0)throw Error("McpRegistry: files.maxBytes must be a positive whole number of bytes.");let z=$?.fetchUrls===!0?{}:typeof $?.fetchUrls==="object"&&$.fetchUrls!==null?$.fetchUrls:null;return{maxBytes:Z,fetch:z}}function y$($){if($.length===0||$.length>255)return!1;for(let Z of $){let z=Z.codePointAt(0);if(z<32||z===127||Z==="/"||Z==="\\")return!1}return!0}var f$=/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(\s*;.{0,200})?$/,w$=/^[A-Za-z0-9+/]*={0,2}$/;function v$($){return $.endsWith("==")?2:$.endsWith("=")?1:0}function X9($,Z,z){if(z!=="input"&&typeof z!=="function")throw Error(`${$}: ${Z} must be a function or "input".`)}function Y9($){return $ instanceof Object&&$.__internal_brand==="McpModelParam"}function g$($,Z,z){if(z.as!==void 0&&(typeof z.as!=="string"||z.as===""))throw Error(`${$}: ${Z}.as must be a non-empty string.`);let G=z.input;if(typeof G?.safeParse!=="function"||typeof G.toJSONSchema!=="function")throw Error(`${$}: ${Z}.input must be a schema, built with s.`);if(typeof z.bind!=="function")throw Error(`${$}: ${Z}.bind must be a function.`)}var h$=new Set(["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"]);function m$($){switch($){case"GET":return{readOnlyHint:!0};case"DELETE":return{destructiveHint:!0};case"PUT":return{idempotentHint:!0};default:return{}}}function K9($,Z,z){if(z!==void 0&&(typeof z!=="object"||z===null))throw Error(`${$}: annotations must be an object of hints.`);let G=Z?m$(Z):{};for(let[W,X]of Object.entries(z??{})){if(!h$.has(W))throw Error(`${$}: "${W}" is not a tool annotation. Use readOnlyHint, destructiveHint, idempotentHint or openWorldHint.`);if(X===void 0)continue;if(typeof X!=="boolean")throw Error(`${$}: annotations.${W} must be true or false.`);G[W]=X}if(G.readOnlyHint===!0&&(G.destructiveHint||G.idempotentHint))throw Error(`${$} is read-only${z?.readOnlyHint?"":` (a ${Z})`} and also ${G.destructiveHint?"destructive":"idempotent"}, which only a tool that is not read-only can be. Set readOnlyHint: false if it changes something.`);return Object.freeze(G)}function Q9($,Z,z,G={}){let W=z.toJSONSchema(),X=Object.fromEntries(Object.entries(G).map(([Q,V])=>[Q,V.toJSONSchema()])),Y={...Z??{},type:"object",properties:{...Z?.properties??{},...W.properties,...X},required:[...Z?.required??[],...W.required??[],...Object.keys(G)],additionalProperties:!1},K=(Q)=>{if(typeof Q!=="object"||Q===null||Array.isArray(Q))return{ok:!1,errors:["expected an object"]};let V=[],H={};if($){let F=$.safeParse(Q);if(F.ok===!1)V.push(...F.errors);else H={...F.value}}let U=z.safeParse(Q);if(U.ok===!1)V.push(...U.errors);else H={...H,...U.value};for(let[F,O]of Object.entries(G)){let B=Q[F];if(B===void 0){V.push(`"${F}" is required`);continue}let I=O.safeParse(B);if(I.ok===!1)V.push(...I.errors.map((k)=>`${F}: ${k}`));else H[F]=I.value}return V.length>0?{ok:!1,errors:V}:{ok:!0,value:H}};return{toJSONSchema:()=>Y,safeParse:K,parse(Q){let V=K(Q);if(V.ok===!1)throw Error(V.errors.join(", "));return V.value}}}function u$($,Z){return Object.fromEntries(Object.entries($).filter(([z])=>!Z.includes(z)))}function d$($,Z,z){let G=Z.modifier==="*"||Z.modifier==="+"?z.split("/"):[z];if(G.some((W)=>W==="."||W===".."))throw new D(`"${z}" is not a valid value for "${Z.name}" of "${$}".`);return G.map(encodeURIComponent).join("/")}function O3($,Z,z){if(z===void 0||z===null)return;if(Array.isArray(z)){for(let G of z)O3($,Z,G);return}$.append(Z,typeof z==="object"?JSON.stringify(z):String(z))}function c$($){let Z=new URLSearchParams,z=(G,W)=>{if(W===void 0||W===null)return;if(Array.isArray(W)){for(let X of W)z(G,X);return}Z.append(G,typeof W==="object"?JSON.stringify(W):String(W))};for(let[G,W]of Object.entries($))z(G,W);return Z.toString()}async function V9($,Z){if(Z.status>=200&&Z.status<300){let G=Z.headers.get("Content-Type");if(G&&!T$.test(G)){let X=(await Z.arrayBuffer()).byteLength;return`"${$}" answered with ${X} bytes of ${G}, which is not shown.`}let W=await Z.text();if(W==="")return null;if(W.length>T)return`${W.slice(0,T)}\u2026 [cut at ${T} of ${W.length} characters]`;try{return JSON.parse(W)}catch{return W}}let z=await Z.text();if(Z.status>=400&&Z.status<500){let G=z.length>e3?`${z.slice(0,e3)}\u2026`:z;throw new D(`"${$}" was refused with ${Z.status}${G?`: ${G}`:"."}`,Z.status)}if(Z.status<500)console.error(`[gemi/mcp] "${$}" answered ${Z.status}${Z.headers.get("Location")?` to ${Z.headers.get("Location")}`:""}, which a tool call cannot follow.`);throw new D(`"${$}" failed on the server.`,Z.status)}import{createHash as p$,randomBytes as i$,timingSafeEqual as l$}from"crypto";function j3($){let Z=$.headers.get("authorization");if(!Z)return null;let z=/^Bearer[ ]+([\x21-\x7e]+)$/i.exec(Z.trim());return z?z[1]:null}class n${options;name="api-key";constructor($){this.options=$;if(typeof $?.prefix!=="string"||!/^[A-Za-z0-9_-]{3,32}$/.test($.prefix))throw Error('McpApiKeyResolver: prefix is required: 3 to 32 letters, digits, _ or -, like "myapp_mcp_".');if(typeof $.verify!=="function")throw Error("McpApiKeyResolver: verify must be a function that looks a key up.")}static generate($){return`${$}${i$(32).toString("base64url")}`}static hash($){return p$("sha256").update($).digest("hex")}static hashesMatch($,Z){let z=Buffer.from($),G=Buffer.from(Z);return z.length===G.length&&l$(z,G)}async resolve($){let Z=j3($);if(!Z?.startsWith(this.options.prefix))return null;let z=await this.options.verify(Z,$);if(!z)return{ok:!1,error:"invalid_token",description:"The API key is not valid."};if(!z.user||typeof z.id!=="string"||z.id===""||!Array.isArray(z.scopes))throw Error("McpApiKeyResolver: verify must answer { user, id, scopes } for a key it knows, or null.");return{ok:!0,principal:{user:z.user,via:this.name,id:z.id,scopes:[...z.scopes]}}}}import{createHash as R9,randomBytes as _9}from"crypto";async function x3($,Z){let z=t$();if(!z)return null;let G=await z.consume($,Z);return G.allowed?null:Math.max(1,Math.ceil(G.retryAfter/1000))}function t$(){try{let $=y();return $.bound(l)?$.make(l):null}catch{return null}}var A3=["2026-07-28"],Y3=["2025-11-25","2025-06-18","2025-03-26"],C3=[...A3,...Y3],S3="io.modelcontextprotocol/protocolVersion",q3="io.modelcontextprotocol/clientCapabilities";var T3="io.modelcontextprotocol/serverInfo",_={ParseError:-32700,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602,InternalError:-32603,HeaderMismatch:-32020,MissingRequiredClientCapability:-32021,UnsupportedProtocolVersion:-32022};class P extends Error{code;data;status;constructor($,Z,z,G=200){super(Z);this.code=$;this.data=z;this.status=G;this.name="JsonRpcError"}}function R($,Z){return{jsonrpc:"2.0",id:$,error:{code:Z.code,message:Z.message,...Z.data!==void 0?{data:Z.data}:{}}}}function P9($){if(Array.isArray($))throw new P(_.InvalidRequest,"Batched requests are not supported.",void 0,400);if(typeof $!=="object"||$===null||$.jsonrpc!=="2.0")throw new P(_.InvalidRequest,"Not a JSON-RPC 2.0 message.",void 0,400);let Z=$,z=Z.id,G=typeof z==="string"||typeof z==="number"&&Number.isFinite(z);if(typeof Z.method==="string"){if(Z.params!==void 0&&(typeof Z.params!=="object"||Z.params===null||Array.isArray(Z.params)))throw new P(_.InvalidRequest,"params must be an object.",void 0,400);if(z===void 0)return{kind:"notification",message:Z};if(!G)throw new P(_.InvalidRequest,"id must be a string or a number.",void 0,400);return{kind:"request",message:Z}}if(G&&(("result"in Z)||("error"in Z)))return{kind:"response",message:Z};throw new P(_.InvalidRequest,"Not a JSON-RPC request, notification or response.",void 0,400)}function k3($,Z){let z=$.outputSchema?.toJSONSchema(),G={...$.annotations,...$.title&&!Z?{title:$.title}:{}};return{name:$.name,...$.title?{title:$.title}:{},description:$.description,inputSchema:$.inputSchema.toJSONSchema(),...z&&(Z||z.type==="object")?{outputSchema:z}:{},...Object.keys(G).length>0?{annotations:G}:{}}}function S($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function I9($){let Z=/^=\?base64\?([A-Za-z0-9+/]*={0,2})\?=$/.exec($);if(!Z)return $;try{let z=Buffer.from(Z[1],"base64");return new TextDecoder("utf-8",{fatal:!0}).decode(z)}catch{return null}}import{createHmac as s$,timingSafeEqual as o$}from"crypto";function M3($,Z,z){let G=Buffer.from(JSON.stringify(z)).toString("base64url");return`${Z}.${G}.${L9($,Z,G).toString("base64url")}`}function R3($,Z,z,G=Date.now()){if(typeof z!=="string"||z.length>8192)return null;let W=z.split(".");if(W.length!==3||W[0]!==Z)return null;let[,X,Y]=W,K=Buffer.from(Y,"base64url"),Q=L9($,Z,X);if(K.length!==Q.length||!o$(K,Q))return null;let V;try{V=JSON.parse(Buffer.from(X,"base64url").toString("utf8"))}catch{return null}if(typeof V!=="object"||V===null)return null;if(typeof V.exp!=="number"||V.exp<=G)return null;return V}function L9($,Z,z){return s$("sha256",K3($)).update(`${Z}.${z}`).digest()}var E3="gemi.mcp.request-state.v1",D9="gemi.mcp.session.v1",a$=86400000,O9=600000,j9="gemi_approval",b3=2000,r$={limit:600,window:60},e$={limit:30,window:60};class $3{registry;static token="router.mcp.http";endpoint;resolvers;context;allowedOrigins;rateLimit;maxBodyBytes;serverInfo;instructions;nonces;approvalTimeoutMs;feature;featureOn;pending=new Map;inflight=new Map;constructor($,Z,z={}){this.registry=$;if(typeof Z.url!=="string")throw Error(`route.mcp.remote.url is required: the endpoint's canonical URL, like "https://example.com/mcp".`);this.endpoint=z2(Z.url);let G=Z.resolvers??[];if(!Array.isArray(G)||G.length===0)throw Error("route.mcp.remote is enabled without a caller resolver. Configure route.mcp.remote.resolvers \u2014 an McpOAuthServer, an McpApiKeyResolver, or your own \u2014 or leave the endpoint off. Without one every request would be refused, or answered as nobody.");for(let W of G)if(typeof W?.resolve!=="function"||typeof W.name!=="string"||W.name==="")throw Error("route.mcp.remote.resolvers: each resolver needs a name and a resolve().");if(this.resolvers=G,K3(E3),this.context={resource:this.resource,registry:$},this.allowedOrigins=new Set((Z.allowedOrigins??[]).map((W)=>{if(new URL(W).origin!==W)throw Error(`route.mcp.remote.allowedOrigins: "${W}" is not an origin (scheme://host[:port]).`);return W})),this.allowedOrigins.add(this.endpoint.origin),this.rateLimit=Z.rateLimit===!1?!1:Z.rateLimit??r$,this.maxBodyBytes=Z.maxBodyBytes??Math.ceil($.maxFileBytes*1.4)+1048576,this.serverInfo={name:Z.server?.name??"gemi",version:Z.server?.version??"1.0.0"},this.instructions=Z.server?.instructions,this.nonces=Z.nonces??new k9,this.approvalTimeoutMs=Z.approvalTimeoutMs??O9,Z.feature!==void 0){if(typeof Z.feature!=="string"||Z.feature==="")throw Error("route.mcp.remote.feature must be a feature key from app/features.");this.feature=Z.feature}this.featureOn=z.featureOn??X3;for(let W of G)W.boot?.(this.context)}get resource(){return this.endpoint.href.replace(/\/$/,"")}async handle($){let Z=new URL($.url);if(Z.host!==this.endpoint.host)return null;if(this.feature!==void 0){if(!this.ownsPath(Z.pathname))return null;if(await this.featureOn(this.feature)!==!0)return null}for(let W of this.resolvers){let X=await W.handle?.($,this.context);if(X)return X}if(Z.pathname!==this.endpoint.pathname)return null;let z=$.headers.get("origin");if(z!==null&&!this.allowedOrigins.has(z))return f(R(null,new P(_.InvalidRequest,"Origin not allowed.")),403);let G=z?Z2(z):{};if($.method==="OPTIONS")return new Response(null,{status:204,headers:{...G,"Access-Control-Allow-Methods":"POST","Access-Control-Allow-Headers":"Authorization, Content-Type, Accept, MCP-Protocol-Version, Mcp-Session-Id, Mcp-Method, Mcp-Name, Last-Event-ID","Access-Control-Max-Age":"600"}});if($.method!=="POST")return x9(new Response(null,{status:405,headers:{Allow:"POST, OPTIONS"}}),G);return x9(await this.post($),G)}ownsPath($){let Z=this.endpoint.pathname.replace(/\/$/,"");return $===this.endpoint.pathname||$===Z||$.startsWith(`${Z}/`)||$.startsWith("/.well-known/")}async post($){let Z=null;for(let Y of this.resolvers){let K=await Y.resolve($,this.context);if(K===null)continue;if(K.ok===!1)return await this.failedAttempt($)??this.unauthorized(K.description);Z={...K.principal,via:Y.name};break}if(!Z)return(j3($)!==null?await this.failedAttempt($):null)??this.unauthorized();let z=await this.spend(Z);if(z)return z;let G=$.headers.get("content-type")??"";if(!/^application\/json\s*(;|$)/i.test(G))return new Response("Content-Type must be application/json.",{status:415});let W;try{W=JSON.parse(await $2($,this.maxBodyBytes))}catch(Y){if(Y instanceof V3)return f(R(null,new P(_.InvalidRequest,`The request is larger than ${this.maxBodyBytes} bytes.`)),413);return f(R(null,new P(_.ParseError,"Parse error.")),400)}let X=new m($,{},"api",this.endpoint.pathname);return await g.run(X,async()=>{try{return await this.dispatch($,X,Z,W)}catch(Y){if(Y instanceof P){let K=S(W)&&(typeof W.id==="string"||typeof W.id==="number")?W.id:null;return f(R(K,Y),Y.status)}return console.error("[gemi/mcp] The MCP endpoint failed:",Y),f(R(null,new P(_.InternalError,"Internal error.")),500)}},{user:Z.user})}async dispatch($,Z,z,G){let W=P9(G),X={kind:"remote",req:Z,principal:z};if(W.kind==="response"){let B=this.session($,z),I=this.pending.get(String(W.message.id));if(I&&I.session===B.id)this.pending.delete(String(W.message.id)),I.resolve(W.message);return new Response(null,{status:202})}let{message:Y}=W,K=Y.params??{},Q=S(K._meta)?K._meta:{};if(typeof Q[S3]==="string"){if(this.checkModernHeaders($,Y,Q[S3]),W.kind==="notification")return new Response(null,{status:202});return await this.respond(Y,async(B,I)=>this.modern({principal:z,caller:X,message:Y,params:K,era:{modern:!0},stream:B,signal:I}),C9(K),$.signal)}if(Y.method==="initialize"){if(W.kind!=="request")throw new P(_.InvalidRequest,"initialize is a request.",void 0,400);return this.initialize(W.message,K,z)}let V=this.session($,z),H=$.headers.get("mcp-protocol-version");if(H!==null&&H!==V.state.v)throw new P(_.InvalidRequest,`MCP-Protocol-Version ${H} is not the session's ${V.state.v}.`,void 0,400);if(W.kind==="notification"){if(Y.method==="notifications/cancelled"){let B=K.requestId;this.inflight.get(`${V.id}:${String(B)}`)?.abort()}return new Response(null,{status:202})}let U=`${V.id}:${String(Y.id)}`,F=new AbortController;this.inflight.set(U,F);let O=AbortSignal.any([F.signal,$.signal]);try{return await this.respond(Y,async(B,I)=>this.legacy({principal:z,caller:X,message:Y,params:K,era:{modern:!1,session:V.state,sessionId:V.id},stream:B,signal:I}),C9(K)||W2(this.registry,Y,V.state),O,()=>this.inflight.delete(U))}catch(B){throw this.inflight.delete(U),B}}async modern($){switch($.message.method){case"server/discover":return this.complete({supportedVersions:C3,capabilities:{tools:{}},...this.instructions?{instructions:this.instructions}:{},ttlMs:60000,cacheScope:"private"});case"tools/list":return this.complete({tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!0)),ttlMs:60000,cacheScope:"private"});case"tools/call":return await this.callTool($);default:throw new P(_.MethodNotFound,`Method not found: ${$.message.method}`,void 0,404)}}async legacy($){switch($.message.method){case"ping":return{};case"tools/list":return{tools:(await this.registry.available($.caller)).map((Z)=>k3(Z,!1))};case"tools/call":return await this.callTool($);default:throw new P(_.MethodNotFound,`Method not found: ${$.message.method}`)}}complete($){return{resultType:"complete",...$,_meta:{[T3]:this.serverInfo}}}initialize($,Z,z){let G=Z.protocolVersion,W=Y3.includes(G)?G:Y3[0],X=S(Z.capabilities)?Z.capabilities:{},Y={v:W,e:A9(X.elicitation),p:Q3(z),exp:Date.now()+a$},K=M3(D9,"gms1",Y);return f({jsonrpc:"2.0",id:$.id,result:{protocolVersion:W,capabilities:{tools:{listChanged:!1}},serverInfo:this.serverInfo,...this.instructions?{instructions:this.instructions}:{}}},200,{"Mcp-Session-Id":K})}session($,Z){let z=$.headers.get("mcp-session-id");if(!z)throw new P(_.InvalidRequest,"Missing Mcp-Session-Id. Send initialize first, or a request carrying io.modelcontextprotocol/protocolVersion in _meta.",void 0,400);let G=R3(D9,"gms1",z);if(!G||G.p!==Q3(Z))throw new P(_.InvalidRequest,"Session not found.",void 0,404);return{id:z,state:G}}checkModernHeaders($,Z,z){if(!A3.includes(z))throw new P(_.UnsupportedProtocolVersion,"Unsupported protocol version",{supported:C3,requested:z},400);let G=(Y)=>new P(_.HeaderMismatch,`Header mismatch: ${Y}`,void 0,400);if($.headers.get("mcp-protocol-version")!==z)throw G("MCP-Protocol-Version does not match the protocol version in _meta.");if($.headers.get("mcp-method")!==Z.method)throw G("Mcp-Method does not match the method.");let W=Z.params??{},X=Z.method==="tools/call"||Z.method==="prompts/get"?W.name:Z.method==="resources/read"?W.uri:void 0;if(X!==void 0){let Y=$.headers.get("mcp-name");if(Y===null||I9(Y)!==X)throw G("Mcp-Name does not match the request's name.")}}async callTool($){let{params:Z,caller:z,principal:G}=$,W=Z.name;if(typeof W!=="string")throw new P(_.InvalidParams,"tools/call needs a tool name.");let X=Z.arguments??{},Y=(await this.registry.available(z,{names:[W]}))[0];if(!Y)throw new P(_.InvalidParams,`Unknown tool: ${W}`);let K=!1;if(Y.requiresApproval){let F=Y.inputSchema.safeParse(X);if(F.ok===!1)return this.toolResult($,{content:[{type:"text",text:`Invalid arguments for "${W}": ${F.errors.join(", ")}`}],isError:!0});if($.era.modern&&S($.params.inputResponses)&&$.params.requestState!==void 0||await this.registry.approvalRequired(z,W,X,{signal:$.signal})){let B=await this.approval($,Y,X);if(B.kind==="answer")return B.result;K=!0}}let Q=X2($),V;try{V=await this.registry.execute(z,W,X,void 0,{approved:K,signal:$.signal,...Q?{progress:Q}:{}})}catch(F){if(F instanceof D)return this.toolResult($,{content:[{type:"text",text:F.message}],isError:!0});if(F instanceof v)throw new P(_.InvalidParams,F.reason==="unknown-tool"?`Unknown tool: ${W}`:F.message);return console.error(`[gemi/mcp] "${W}" failed for ${G.via}:${G.id}:`,F),this.toolResult($,{content:[{type:"text",text:`"${W}" failed on the server.`}],isError:!0})}let H=typeof V==="string"?V:JSON.stringify(V??null),U=Y.outputSchema&&($.era.modern||S(V))?{structuredContent:V}:{};return this.toolResult($,{content:[{type:"text",text:H}],...U,isError:!1})}toolResult($,Z){return $.era.modern?this.complete(Z):Z}async approval($,Z,z){let G=Y2(Z,z),W=(V)=>({kind:"answer",result:this.toolResult($,{content:[{type:"text",text:V}],isError:!0})});if($.era.modern){let V=S($.params._meta)?$.params._meta:{},H=S(V[q3])?V[q3]:{},U=S($.params.inputResponses)?$.params.inputResponses:null,F=$.params.requestState,O=G2(z);if(U&&F!==void 0){let I=R3(E3,"grs1",F);if(!I||I.p!==Q3($.principal)||I.t!==Z.name||I.a!==O)throw new P(_.InvalidParams,"requestState is not valid for this call.");if(!await this.spendNonce(I.n,I.exp))throw new P(_.InvalidParams,"requestState has already been used.");return S9(U[j9])?{kind:"approved"}:W(`The user did not approve "${Z.name}", and it did not run.`)}if(!A9(H.elicitation))throw new P(_.MissingRequiredClientCapability,`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation).`,{requiredCapabilities:{elicitation:{form:{}}}},400);let B={p:Q3($.principal),t:Z.name,a:O,n:_9(16).toString("base64url"),exp:Date.now()+O9};return{kind:"answer",result:{resultType:"input_required",inputRequests:{[j9]:{method:"elicitation/create",params:{mode:"form",...G}}},requestState:M3(E3,"grs1",B),_meta:{[T3]:this.serverInfo}}}}let X=$.era;if(!X.session.e||!$.stream)return W(`"${Z.name}" needs the user's approval, and this client cannot ask for it (elicitation). It did not run.`);let Y=`gemi-approval-${_9(12).toString("base64url")}`,K=X.sessionId,Q=await new Promise((V)=>{let H=setTimeout(()=>{this.pending.delete(Y),V(null)},this.approvalTimeoutMs),U=(F)=>{clearTimeout(H),V(F)};this.pending.set(Y,{session:K,resolve:U}),$.signal.addEventListener("abort",()=>{this.pending.delete(Y),U(null)}),$.stream.send({jsonrpc:"2.0",id:Y,method:"elicitation/create",params:X.session.v==="2025-11-25"?{mode:"form",...G}:G})});return Q&&!Q.error&&S9(Q.result)?{kind:"approved"}:W(`The user did not approve "${Z.name}", and it did not run.`)}async spendNonce($,Z){try{return await this.nonces.consume($,Z)}catch(z){return console.error("[gemi/mcp] Spending an approval failed:",z),!1}}async respond($,Z,z,G,W){if(!z)try{let Q=await Z(null,G);return f({jsonrpc:"2.0",id:$.id,result:Q},200)}finally{W?.()}let X=new AbortController,Y=AbortSignal.any([X.signal,G]),K=new E9(()=>X.abort());return(async()=>{try{let Q=await Z(K,Y);K.send({jsonrpc:"2.0",id:$.id,result:Q})}catch(Q){if(Q instanceof P)K.send(R($.id,Q));else console.error("[gemi/mcp] The MCP endpoint failed:",Q),K.send(R($.id,new P(_.InternalError,"Internal error.")))}finally{W?.(),K.close()}})(),new Response(K.readable,{status:200,headers:{"Content-Type":"text/event-stream","Cache-Control":"no-store","X-Accel-Buffering":"no"}})}unauthorized($){let Z=this.resolvers.map((G)=>G.challenge?.(this.context)).find(Boolean)??'Bearer realm="mcp"',z=$?`${Z}, error="invalid_token", error_description="${$.replace(/["\\]/g,"")}"`:Z;return f(R(null,new P(_.InvalidRequest,"Unauthorized.")),401,{"WWW-Authenticate":z})}async failedAttempt($){let Z=T9(new m($,{},"api",this.endpoint.pathname)),z=await x3(`mcp-auth-failed:${Z}`,e$);return z===null?null:q9(z)}async spend($){if(!this.rateLimit)return null;let Z=await x3(`mcp-endpoint:${$.via}:${$.id}`,this.rateLimit);return Z===null?null:q9(Z)}}class E9{readable;controller;closed=!1;encoder=new TextEncoder;constructor($){this.readable=new ReadableStream({start:(Z)=>{this.controller=Z},cancel:()=>{this.closed=!0,$()}})}send($){if(this.closed)return;this.controller.enqueue(this.encoder.encode(`event: message
|
|
3
3
|
data: ${JSON.stringify($)}
|
|
4
4
|
|
|
5
5
|
`))}close(){if(this.closed)return;this.closed=!0,this.controller.close()}}class V3 extends Error{}async function $2($,Z){let z=Number($.headers.get("content-length"));if(Number.isFinite(z)&&z>Z)throw new V3;if(!$.body)return"";let G=$.body.getReader(),W=[],X=0;for(;;){let{done:Y,value:K}=await G.read();if(Y)break;if(X+=K.byteLength,X>Z)throw await G.cancel(),new V3;W.push(K)}return Buffer.concat(W).toString("utf8")}function f($,Z,z={}){return new Response(JSON.stringify($),{status:Z,headers:{"Content-Type":"application/json","Cache-Control":"no-store",...z}})}function x9($,Z){for(let[z,G]of Object.entries(Z))$.headers.set(z,G);return $}function Z2($){return{"Access-Control-Allow-Origin":$,"Access-Control-Expose-Headers":"Mcp-Session-Id, WWW-Authenticate",Vary:"Origin"}}function z2($){let Z;try{Z=new URL($)}catch{throw Error(`route.mcp.remote.url: "${$}" is not a URL.`)}let z=Z.hostname==="localhost"||Z.hostname==="127.0.0.1"||Z.hostname==="[::1]";if(Z.protocol!=="https:"&&!(Z.protocol==="http:"&&z))throw Error("route.mcp.remote.url must be https (http only on localhost): tokens travel to it.");if(Z.search||Z.hash||Z.username||Z.password)throw Error("route.mcp.remote.url must have no query, fragment or credentials.");if(Z.pathname==="/"||Z.pathname.endsWith("/"))throw Error('route.mcp.remote.url needs a path of its own, like "/mcp", without a trailing slash.');return Z}function Q3($){return R9("sha256").update(`${$.via}\x00${$.id}\x00${$.user?.id}`).digest("base64url").slice(0,32)}function G2($){return R9("sha256").update(M9($??{})).digest("base64url")}function A9($){if(!S($))return!1;if(Object.keys($).length===0)return!0;return"form"in $}function C9($){let Z=S($._meta)?$._meta:{};return typeof Z.progressToken==="string"||typeof Z.progressToken==="number"}function W2($,Z,z){if(Z.method!=="tools/call"||!z.e)return!1;let G=Z.params?.name;return typeof G==="string"&&$.descriptors({names:[G]})[0]?.requiresApproval===!0}function X2($){let z=(S($.params._meta)?$.params._meta:{}).progressToken;if(!$.stream||typeof z!=="string"&&typeof z!=="number")return;let G=-1/0;return(W)=>{if(typeof W?.progress!=="number"||!Number.isFinite(W.progress)||W.progress<=G)return;G=W.progress,$.stream.send({jsonrpc:"2.0",method:"notifications/progress",params:{progressToken:z,progress:W.progress,...typeof W.total==="number"?{total:W.total}:{},...typeof W.message==="string"?{message:W.message.slice(0,1000)}:{}}})}}function Y2($,Z){let z=JSON.stringify(Z??{},null,1),G=z.length>b3?`${z.slice(0,b3)}\u2026 (${z.length-b3} more characters not shown)`:z;return{message:`Allow "${$.title??$.name}" to run? ${$.description}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Si as l}from"./chunk-
|
|
2
|
+
import{Si as l}from"./chunk-fg2k18d2.js";import{$i as E,_i as O,aj as k}from"./chunk-9xzg05xg.js";import{Bj as i,Cj as C,Dj as M,Ej as Xz,pj as T,zj as R}from"./chunk-a37shxb1.js";import{gk as a}from"./chunk-p81qeav5.js";var $z=["every","none","some"],Vz=["is","isNot"];function g(z){return z==="many"?$z:Vz}function h(z,J){let W=Object.keys(z);return W.length>0&&W.every((Z)=>J.includes(Z))}var m="_count";function y(z){return Object.keys(z.relations).filter((J)=>z.relations[J]?.kind==="many").sort()}function N(z,J,W,Z){let X={model:z,operation:J,hasUser:W!=null};return Object.defineProperty(X,"user",{enumerable:!0,get(){if(W==null&&!Z)throw new R(z,J,"no-user");return W}}),X}class n{}class Qz extends n{}var qz=new Set(["findMany","findFirst","findFirstOrThrow","findUnique","findUniqueOrThrow","count","aggregate","groupBy","update","updateMany","delete","deleteMany"]),Yz=new Set(["create","createMany","upsert"]),jz=new Set(["update","updateMany","upsert"]),Lz=new Set(["update","updateMany"]),Kz=new Set(["create","createMany"]),p=new WeakMap;function Gz(z,J,W){if(typeof z!=="function")return z;let Z=p.get(z);if(Z!==void 0)return Z;let X;try{X=new z}catch($){throw new M(b(J),W,"constructor-threw",`${f(z)}, and constructing it threw:
|
|
3
3
|
|
|
4
4
|
${$?.message??String($)}`,H,void 0,{cause:$})}return t(X,J,W),p.set(z,X),X}function S(z,J){return z.map((W,Z)=>Gz(W,J,Z))}var H=["before","scope","onCreate","onUpdate","redact"];var u=new WeakSet;function s(z,J){if(u.has(J))return;for(let W=0;W<J.length;W++)Uz(J[W],z,W);u.add(J)}function Uz(z,J,W){let Z=b(J),X=typeof z;if(z===null||Array.isArray(z)||X!=="object"&&X!=="function")throw new M(Z,W,"not-a-policy",o(z),H);if(X==="function"){if(!Mz(z))throw new M(Z,W,"not-constructable",f(z),H);return}t(z,J,W)}function t(z,J,W){let Z=b(J),X=0,$=[];for(let Y of H){let q=z[Y];if(q===void 0||q===null){if(Y in z)$.push(Y);continue}if(typeof q!=="function")throw new M(Z,W,"hook-not-callable",`'${Y}' that is ${o(q)} rather than a function`,H);X++}if(X>0)return;if($.length>0)throw new M(Z,W,"no-hooks",`It writes ${$.map((Y)=>`'${Y}'`).join(", ")} down and leaves ${$.length===1?"it":"them"} unset, which reads as `+"absent \u2014 so nothing is left to run.",H);let V=Fz(z),Q=Iz(V);throw new M(Z,W,"no-hooks",V.length===0?"It is empty.":`It spells ${Hz(V)}.`+(V.length===1&&V[0]==="default"?" A lone 'default' is a module namespace rather than the policy "+"inside it \u2014 put `entry.default` in the array, or import the "+"policy by name.":""),H,Q)}function Hz(z){let J=z.slice(0,8).map((W)=>`'${W}'`);return z.length>J.length?`${J.join(", ")} and ${z.length-J.length} more`:J.join(", ")}function Mz(z){try{return Reflect.construct(Bz,[],z),!0}catch{return!1}}var Bz=function(){};function Fz(z){let J=new Set,W=z;while(W!==null&&W!==Object.prototype){for(let Z of Object.getOwnPropertyNames(W))if(Z!=="constructor")J.add(Z);W=Object.getPrototypeOf(W)}return[...J]}function Iz(z){let J,W=2;for(let Z of z)for(let X of H){let $=Tz(Z.toLowerCase(),X.toLowerCase());if($<W)W=$,J={key:Z,hook:X}}return J}function Tz(z,J){if(z===J)return 0;let W=Array.from({length:J.length+1},(Z,X)=>X);for(let Z=1;Z<=z.length;Z++){let X=W[0];W[0]=Z;for(let $=1;$<=J.length;$++){let V=W[$];W[$]=Math.min(W[$]+1,W[$-1]+1,X+(z[Z-1]===J[$-1]?0:1)),X=V}}return W[J.length]}function o(z){if(z===null)return"null";if(z===void 0)return"undefined";if(typeof z==="string")return`the string ${JSON.stringify(z)}`;if(typeof z==="function")return f(z);if(Array.isArray(z))return"an array";if(typeof z==="object")return"an object";return`the ${typeof z} ${String(z)}`}function f(z){return z.name?`the function \`${z.name}\``:"an anonymous function"}function _(z){let J,W,Z,X=z;while(X&&X!==Function.prototype){if(Object.hasOwn(X,"$policy"))throw Error(`${X.name??"This model"} declares \`$policy\`, which is now \`$policies\` and takes a list. The old `+"name is not read, so this model is currently unpolicied \u2014 every "+"scope, onCreate and redact on it is being skipped.");if(Object.hasOwn(X,"$policies")&&X.$policies){let $=X.$policies;if($.length>0){let V=X;if(s(V,$),W===void 0&&J===void 0)W=$,Z=V;else J??=S(W,Z),W=void 0,J.unshift(...S($,V))}}X=Object.getPrototypeOf(X)}if(J!==void 0)return J;if(W===void 0)return Nz;return W.some(($)=>typeof $==="function")?S(W,Z):W}function r(z){let J=z;while(J&&J!==Function.prototype){if(Object.hasOwn(J,"$policies")&&J.$policies){let W=J.$policies;if(W.length>0)s(J,W)}J=Object.getPrototypeOf(J)}}function b(z){return z?.name??"This model"}var Nz=Object.freeze([]);function D(z,J,W,Z=[]){if(z.length===0)return W;let X=W,$;for(let V of z)if(V.before){if(V.before(J)===!1)throw new R(J.model,J.operation)}for(let V of z){if(!V.scope)continue;if(Kz.has(J.operation)){Sz(V,J);continue}let Q=V.scope(J);if(Q===void 0||Q===null)continue;if(Rz(J),Lz.has(J.operation)&&!V.onUpdate){let Y=Pz(Q);if(Y.length>0)($??=[]).push(...Y)}X=_z(X,Q)}if(Yz.has(J.operation)){for(let V of z)if(V.onCreate)X=Dz(X,J,V)}if(jz.has(J.operation)){for(let V of z)if(V.onUpdate)X=Az(X,J,V)}if($!==void 0)Cz($,J,X,Z);return X}function _z(z,J){let W=z?.where;if(W===void 0||W===null)return{...z,where:J};if(typeof W!=="object"||Array.isArray(W))return{...z,where:{AND:[W,J]}};let Z=W.AND,X=Z===void 0||Z===null?[]:Array.isArray(Z)?Z:[Z];return{...z,where:{...W,AND:[...X,J]}}}function Dz(z,J,W){let Z=(X)=>W.onCreate(J,{...X});if(J.operation==="createMany"){let X=z?.data;return{...z,data:Array.isArray(X)?X.map(Z):Z(X)}}if(J.operation==="upsert")return{...z,create:Z(z?.create)};return{...z,data:Z(z?.data)}}function Az(z,J,W){let Z=J.operation==="upsert"?"update":"data",X=z?.[Z];if(X===void 0||X===null)return z;return{...z,[Z]:W.onUpdate(J,{...X})}}function Cz(z,J,W,Z=[]){let X=W?.data;if(typeof X!=="object"||X===null)return;let $=z.filter((V)=>(V in X)&&!Z.includes(V));if($.length===0)return;throw new i(J.model,J.operation,[...new Set($)])}function Pz(z){if(typeof z!=="object"||z===null||Array.isArray(z))return[];let J=[];for(let W of Object.keys(z)){if(W==="AND"||W==="OR"||W==="NOT")continue;J.push(W)}return J}function Sz(z,J){if(z.onCreate)return;throw new T(J.operation,J.model,J.operation,`${J.model} has a policy that scopes reads but no 'onCreate', and ${J.operation} has no where clause for a scope to narrow. As written the policy would confine reads to the caller and let an insert name any value it likes. Add an onCreate that sets the scoped `+"column \u2014 or, if unscoped creates are intended, say so with an onCreate "+"that returns its data unchanged.")}function Rz(z){if(qz.has(z.operation))return;throw new T(z.operation,z.model,z.operation,`${z.model} has a policy with a scope, and ${z.operation} cannot carry one: its where clause compiles to an 'on conflict' target, which is a key rather than a filter. Running it would write outside the scope.
|
|
5
5
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
function v(j){return Object.freeze({name:j})}class T extends Error{key;constructor(j){super(`Request state "${j.name}" is not set. Check that whatever sets it (a middleware, \`context()\`) ran for this request.`);this.key=j;this.name="MissingRequestStateError"}}class K{#j=new Map;get(j){return this.#j.get(j)}require(j){if(!this.#j.has(j))throw new T(j);return this.#j.get(j)}set(j,J){return this.#j.set(j,J),J}has(j){return this.#j.has(j)}delete(j){return this.#j.delete(j)}static carry(j,J){for(let[Q,V]of j.#j)if(!J.#j.has(Q))J.#j.set(Q,V)}}function P(){for(let j of["HOST_NAME","APP_URL"]){let J=process.env[j]?.trim().replace(/\/+$/,"");if(J)return J}return}function g(j){let J=P(),Q=J===void 0?"fallback":J===process.env.HOST_NAME?.trim().replace(/\/+$/,"")?"HOST_NAME":"APP_URL",V=J??j?.trim().replace(/\/+$/,"");if(!V)throw Error("The app's public origin is not configured: set HOST_NAME (or APP_URL), e.g. HOST_NAME=https://example.com.");let $=URL.canParse(V)?new URL(V).protocol:null;if($!=="http:"&&$!=="https:")throw Error(`The app's public origin from ${Q} (${JSON.stringify(V)}) is not an absolute http(s) URL, e.g. https://example.com.`);return V}import{AsyncLocalStorage as y}from"async_hooks";var C=new Set(["woff2","woff","truetype","opentype","collection","embedded-opentype","svg"]),S={woff2:"woff2",woff:"woff",ttf:"truetype",otf:"opentype",ttc:"collection",eot:"embedded-opentype",svg:"svg"};var I=new Set(["auto","block","swap","fallback","optional"]),w=/^[a-zA-Z0-9.%+\- ]+$/,R=/^[uU]\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?(\s*,\s*[uU]\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?)*$/;function G(j){throw TypeError(`Meta.fonts: ${j}`)}function q(j){let J=(j.split(/[?#]/)[0]??"").split("/").pop()??"",Q=J.lastIndexOf(".");return Q===-1?null:S[J.slice(Q+1).toLowerCase()]??null}function U(j,J){if(J===void 0||J===null)return null;let Q=String(J).trim();if(!Q||!w.test(Q))G(`${j} ${JSON.stringify(J)} is not a valid font-${j} value`);return Q}function W(j){if(!Array.isArray(j))G("expected an array of fonts");return j.map((J)=>{if(typeof J?.family!=="string"||!J.family.trim())G("every font needs a family");let Q=typeof J.src==="string"?[{url:J.src}]:J.src;if(!Array.isArray(Q)||Q.length===0)G(`font "${J.family}" needs a src`);let V=Q.map((Z)=>{if(typeof Z?.url!=="string"||!Z.url.trim())G(`font "${J.family}" has a source without a url`);if(Z.format!==void 0&&!C.has(Z.format))G(`font "${J.family}" has an unknown format ${JSON.stringify(Z.format)}`);return{url:Z.url.trim(),format:Z.format??q(Z.url)}}),$=J.display??"swap";if(!I.has($))G(`display ${JSON.stringify($)} is not a valid font-display value`);let X=J.unicodeRange?.trim()||null;if(X&&!R.test(X))G(`unicodeRange ${JSON.stringify(J.unicodeRange)} is not a valid unicode-range`);return{family:J.family.trim(),src:V,weight:U("weight",J.weight),style:U("style",J.style),stretch:U("stretch",J.stretch),display:$,unicodeRange:X,preload:J.preload===!0}})}class Y{content={title:"Gemi App",description:null,openGraph:null,htmlAttributes:null,canonical:null,alternates:null,fonts:null};touched=!1;render(){return{title:this.content.title,description:this.content.description,openGraph:this.content.openGraph,htmlAttributes:this.content.htmlAttributes,canonical:this.content.canonical,alternates:this.content.alternates,fonts:this.content.fonts}}htmlAttributes(j){this.touched=!0;let J=Object.fromEntries(Object.entries(j).filter(([,Q])=>Q!==void 0));this.content.htmlAttributes={...this.content.htmlAttributes,...J}}canonical(j){this.touched=!0,this.content.canonical=j}alternates(j){this.touched=!0,this.content.alternates=j}fonts(j){let J=W(j);this.touched=!0,this.content.fonts=[...this.content.fonts??[],...J]}title(j){this.touched=!0,this.content.title=j}description(j){this.touched=!0,this.content.description=j}openGraph({title:j,description:J,type:Q,url:V,image:$,imageAlt:X,imageWidth:Z,imageHeight:D,twitterImage:H=$,twitterImageAlt:E=X,twitterImageWidth:b=Z,twitterImageHeight:x=D,twitterCard:A=H?"summary_large_image":"summary"}){this.touched=!0;let N=(z)=>z&&!z.startsWith("http")?`${P()}${z}`:z;this.content.openGraph=Object.fromEntries(Object.entries({title:j,description:J,type:Q,url:V,image:N($),imageAlt:X,imageWidth:Z,imageHeight:D,twitterImage:N(H),twitterImageAlt:E,twitterImageWidth:b,twitterImageHeight:x,twitterCard:A}).filter(([z,O])=>O!==void 0))}}function F(j,J,Q={}){return[`${j}=${J}`,Q.maxAge?`Max-Age=${Q.maxAge}`:"",Q.httpOnly?"HttpOnly":"",Q.secure?"Secure":"",Q.sameSite?`SameSite=${Q.sameSite}`:"SameSite=Strict",Q.path?`Path=${Q.path}`:"Path=/",Q.domain?`Domain=${Q.domain}`:"",Q.expires?`Expires=${Q.expires.toUTCString()}`:"",Q.partitioned?"Partitioned":""].filter((V)=>V!=="").join("; ")}var B=new y;class M{req;cookies=new Set;headers=new Headers;serverQueries=null;user=null;csrfHmac=null;locale=null;metadata=new Y;rangeRequest=null;sessionId=null;featureEvaluations=null;featureContext=null;featureBuckets=null;pendingWork=new Set;ended=!1;constructor(j){this.req=j}waitUntil(j){if(this.ended)return;let J=Promise.resolve(j).then(()=>{},()=>{});this.pendingWork.add(J),J.then(()=>this.pendingWork.delete(J))}hasPendingWork(){return this.pendingWork.size>0}async whenIdle(){while(this.pendingWork.size>0)await Promise.all(Array.from(this.pendingWork))}setLocale(j){this.locale=j}renderMeta(){return this.metadata.render()}setCSRFHmac(j){this.csrfHmac=j}setCookie(j,J,Q={}){this.cookies.add(F(j,J,Q))}deleteCookie(j,J={}){this.cookies.add(F(j,"",{...J,maxAge:-1}))}setHeaders(j,J){this.headers.set(j,J)}setUser(j){this.user=j}setRequest(j){this.req=j}destroy(){this.ended=!0,delete this.cookies,delete this.headers,this.serverQueries=null,this.sessionId=null,this.featureEvaluations=null,this.featureContext=null,this.featureBuckets=null,delete this.user}}var _="session_id";function k(){let j=L.getStore();if(!j)return null;if(j.sessionId)return j.sessionId;let J=j.req?.cookies?.get(_);if(J)j.sessionId=J;return j.sessionId}function a(){let j=L.getStore();if(!j)return null;let J=k();if(J)return J;let Q=Bun.randomUUIDv7();return j.sessionId=Q,j.setCookie(_,Q,{httpOnly:!0,secure:Bun.env.NODE_ENV==="production",sameSite:"Lax",expires:new Date(Date.now()+31536000000)}),Q}class L{static getStore(){return B.getStore()}static setRequest(j){B.getStore().req=j}static run(j,J,Q){let V=new M(j);if(Q){if(V.user=Q.user,Q.state&&j.state)K.carry(Q.state,j.state)}return B.run(V,J)}static runWith(j,J){return B.run(j,J)}static exit(j){return B.exit(j)}}
|
|
3
|
+
export{P as Li,g as Mi,v as Ni,T as Oi,K as Pi,k as Qi,a as Ri,L as Si};
|
|
4
|
+
|
|
5
|
+
//# debugId=8DDA19763EE4F9EC64756E2164756E21
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
"/**\n * The app's public origin as configured: `HOST_NAME`, else `APP_URL`, trimmed\n * and without a trailing `/`. `undefined` when neither is set.\n *\n * `HOST_NAME` comes first because it is the variable gemi has always read, so\n * an app that sets it gets the same value it always did. Read on every call,\n * never cached, so a test that stubs the environment sees its value at once.\n *\n * No validation here: gemi's own call sites keep their behaviour when the value\n * is unset or odd. `Url.origin()` is the checked accessor.\n */\nexport function configuredAppOrigin(): string | undefined {\n for (const name of [\"HOST_NAME\", \"APP_URL\"] as const) {\n const value = process.env[name]?.trim().replace(/\\/+$/, \"\");\n if (value) {\n return value;\n }\n }\n return undefined;\n}\n\n/**\n * `configuredAppOrigin()`, required to be an absolute http(s) URL. Falls back\n * to `fallback` when nothing is configured; throws when there is no fallback\n * either, or when the configured value is not such a URL.\n */\nexport function appOrigin(fallback?: string): string {\n const configured = configuredAppOrigin();\n const source = configured === undefined ? \"fallback\" : configured === process.env.HOST_NAME?.trim().replace(/\\/+$/, \"\") ? \"HOST_NAME\" : \"APP_URL\";\n const value = configured ?? fallback?.trim().replace(/\\/+$/, \"\");\n if (!value) {\n throw new Error(\n \"The app's public origin is not configured: set HOST_NAME (or APP_URL), e.g. HOST_NAME=https://example.com.\",\n );\n }\n const protocol = URL.canParse(value) ? new URL(value).protocol : null;\n if (protocol !== \"http:\" && protocol !== \"https:\") {\n throw new Error(\n `The app's public origin from ${source} (${JSON.stringify(value)}) is not an absolute http(s) URL, e.g. https://example.com.`,\n );\n }\n return value;\n}\n",
|
|
7
7
|
"import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { HttpRequest } from \"./HttpRequest\";\nimport { Metadata } from \"./Metadata\";\nimport type { ByteRange } from \"./range\";\nimport { RequestState } from \"./requestState\";\n// Type-only: `services/router` imports from `http`, so a runtime import here\n// would be circular.\nimport type { ServerQueryStore } from \"../services/router/ServerQueryStore\";\n\nexport interface CreateCookieOptions {\n maxAge?: number;\n expires?: Date;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: \"Strict\" | \"Lax\";\n path?: string;\n domain?: string;\n partitioned?: boolean;\n}\n\nexport function createCookie(\n name: string,\n value: string,\n options: CreateCookieOptions = {},\n) {\n return [\n `${name}=${value}`,\n options.maxAge ? `Max-Age=${options.maxAge}` : \"\",\n options.httpOnly ? \"HttpOnly\" : \"\",\n options.secure ? \"Secure\" : \"\",\n options.sameSite ? `SameSite=${options.sameSite}` : \"SameSite=Strict\",\n options.path ? `Path=${options.path}` : \"Path=/\",\n options.domain ? `Domain=${options.domain}` : \"\",\n options.expires ? `Expires=${options.expires.toUTCString()}` : \"\",\n options.partitioned ? \"Partitioned\" : \"\",\n ]\n .filter((i) => i !== \"\")\n .join(\"; \");\n}\n\nconst requestContext = new AsyncLocalStorage<Store>();\n\n/**\n * What a route's request context takes over from the global middleware list's\n * (see `runGlobalMiddleware`): the user, so one the list resolved is not\n * looked up a second time, and the request state the list set (#887).\n */\nexport interface CarriedContext {\n user: any;\n state?: RequestState;\n}\n\nclass Store {\n cookies: Set<string> = new Set();\n headers: Headers = new Headers();\n /**\n * Every server-side query of this request — prefetched or discovered during\n * the streaming render. Assigned by the view router (or lazily by the\n * `Query` facade); `null` for api requests, which must not query themselves.\n */\n serverQueries: ServerQueryStore | null = null;\n user: any = null;\n csrfHmac: string | null = null;\n locale: string | null = null;\n metadata = new Metadata();\n /**\n * The parsed `Range` of the in-flight request, picked up by\n * `FileStorage.read()` so a range reaches the storage backend without every\n * handler having to thread it through by hand.\n *\n * Only populated inside a `this.stream()` route, and cleared once that route\n * returns: a `FileStorage.read()` in an ordinary handler must never start\n * silently returning partial bytes.\n */\n rangeRequest: ByteRange | null = null;\n\n /**\n * This request's `session_id`, once read or minted.\n *\n * The cookie itself cannot answer for it. `setCookie` appends a *serialized*\n * `Set-Cookie` string to `cookies`, so a value written during this request is\n * not readable back out of it, and `req.cookies` still holds only what the\n * browser sent. Anything needing the id in the same request that mints it —\n * feature-flag bucketing, most obviously — has to read it from here.\n */\n sessionId: string | null = null;\n\n /**\n * This request's feature-flag evaluations, computed once.\n *\n * One map per request is what keeps a handler and the SSR payload from\n * disagreeing: a percentage rollout evaluated twice would be consistent\n * anyway — the bucketing is deterministic — but an attribute hook reading a\n * clock, or a `now`-based rule, would not be. Anything the page renders and\n * anything the server branched on have to be the same answer.\n */\n featureEvaluations: Map<string, unknown> | null = null;\n /** The context those evaluations were made against, built at most once. */\n featureContext: unknown = null;\n /** Bucket memo, shared across every flag evaluated for this request. */\n featureBuckets: Map<string, number> | null = null;\n\n /**\n * What `waitUntil` was handed and has not settled yet. Public only because\n * `req.ctx()`'s declared type spells this class out, which a private field\n * cannot be part of; nothing outside the store should touch either.\n */\n pendingWork = new Set<Promise<void>>();\n ended = false;\n\n constructor(public req: HttpRequest) {}\n\n /**\n * Keeps this request open until `work` settles: the api router holds\n * `onRequestEnd` and `destroy()` back until then, so code in `work` still\n * finds `user`, headers and cookies here.\n *\n * For work that outlives the response on purpose. An agent run is the\n * reason it exists: a client that disconnects has not stopped the run, and\n * its next tool call still reads the user who started it. Ignored once the\n * request has ended — there is nothing left to hold open.\n *\n * Only api routes honour this. A view request ends regardless, so work\n * handed to its store — a run started in a view loader — finds no user.\n */\n waitUntil(work: PromiseLike<unknown>) {\n if (this.ended) {\n return;\n }\n const settled = Promise.resolve(work).then(\n () => {},\n () => {},\n );\n this.pendingWork.add(settled);\n void settled.then(() => this.pendingWork.delete(settled));\n }\n\n /** Whether anything handed to `waitUntil` is still running. */\n hasPendingWork() {\n return this.pendingWork.size > 0;\n }\n\n /**\n * Settles once everything handed to `waitUntil` has, including work added\n * while waiting — a run can start another before it ends.\n */\n async whenIdle() {\n while (this.pendingWork.size > 0) {\n await Promise.all(Array.from(this.pendingWork));\n }\n }\n\n setLocale(locale: string) {\n this.locale = locale;\n }\n\n renderMeta() {\n return this.metadata.render();\n }\n\n setCSRFHmac(hmac: string) {\n this.csrfHmac = hmac;\n }\n\n setCookie(name: string, value: string, options: CreateCookieOptions = {}) {\n this.cookies.add(createCookie(name, value, options));\n }\n\n /**\n * A cookie set with a `domain` or `path` is only cleared by a deletion that\n * names the same ones.\n */\n deleteCookie(name: string, options: Pick<CreateCookieOptions, \"domain\" | \"path\"> = {}) {\n this.cookies.add(createCookie(name, \"\", { ...options, maxAge: -1 }));\n }\n\n setHeaders(name: string, value: string) {\n this.headers.set(name, value);\n }\n\n setUser(user: any) {\n this.user = user;\n }\n\n setRequest(req: HttpRequest<any, any>) {\n this.req = req;\n }\n\n destroy() {\n this.ended = true;\n delete this.cookies;\n delete this.headers;\n this.serverQueries = null;\n this.sessionId = null;\n this.featureEvaluations = null;\n this.featureContext = null;\n this.featureBuckets = null;\n delete this.user;\n }\n}\n\nexport const SESSION_ID_COOKIE = \"session_id\";\n\n/**\n * The `session_id` the browser sent, or the one minted earlier in this request.\n * Never mints one, so it is safe on an api request, where a `Set-Cookie` nobody\n * asked for would be a surprise.\n *\n * `null` outside a request, and for an anonymous visitor whose first request is\n * not a view — both meaning \"no stable subject\", which callers must handle\n * rather than paper over with a random value. A per-call random id would give\n * every request its own bucket, which is worse than no bucketing at all: a\n * percentage rollout would reshuffle on every page load.\n *\n * ## It is client-supplied, and unauthenticated\n *\n * Whatever the browser sent, unvalidated. It is a bucketing subject, not a\n * credential — never authenticate or authorize on it. A visitor can pick a value\n * that lands them in any percentage rollout, and signing it would not change\n * that: they can discard the cookie and collect fresh ones until one does. Load\n * bearing enough to state, because `.feature()` route gating is built on top of\n * evaluation — see its documentation for what may safely gate a route.\n */\nexport function sessionId(): string | null {\n const store = RequestContext.getStore();\n if (!store) {\n return null;\n }\n if (store.sessionId) {\n return store.sessionId;\n }\n const sent = store.req?.cookies?.get(SESSION_ID_COOKIE);\n if (sent) {\n store.sessionId = sent;\n }\n return store.sessionId;\n}\n\n/**\n * The same, but mints and sets the cookie when the browser sent none.\n *\n * Call this once per **view** request, early enough that everything downstream —\n * flag evaluation included — sees the same id the browser is about to be given.\n * It used to live inline in `ViewRouteDispatcher.onRequestEnd`, which ran only\n * on the document path and only after the response was decided, so a client-side\n * navigation minted nothing and a first-ever visitor had no id at the point\n * flags were evaluated.\n */\nexport function ensureSessionId(): string | null {\n const store = RequestContext.getStore();\n if (!store) {\n return null;\n }\n const existing = sessionId();\n if (existing) {\n return existing;\n }\n\n const minted = Bun.randomUUIDv7();\n store.sessionId = minted;\n store.setCookie(SESSION_ID_COOKIE, minted, {\n httpOnly: true,\n secure: process.env.NODE_ENV === \"production\",\n // `Lax`, not `Strict`, and the difference is load-bearing. `Strict`\n // withholds the cookie on cross-site *top-level navigation*, so a visitor\n // arriving from a search result or a shared link would arrive without it,\n // be minted a new id, and overwrite the old one — re-bucketing on every\n // external entry, which is how most anonymous traffic arrives. This is not\n // a credential (`access_token` stays `Strict`); it is an opaque bucketing\n // id, and `Lax` still blocks cross-site POST.\n sameSite: \"Lax\",\n expires: new Date(Date.now() + 1000 * 60 * 60 * 24 * 365),\n });\n return minted;\n}\n\nexport class RequestContext {\n static getStore() {\n return requestContext.getStore()!;\n }\n\n static setRequest(req: HttpRequest<any, any>) {\n requestContext.getStore().req = req;\n }\n\n /**\n * Opens a fresh request scope. `carried` seeds it with what the global\n * middleware list resolved for the same request; nothing else crosses over.\n */\n static run<T>(\n httpRequest: HttpRequest,\n fn: () => T,\n carried?: CarriedContext | null,\n ): T {\n const store = new Store(httpRequest);\n if (carried) {\n store.user = carried.user;\n if (carried.state && httpRequest.state) {\n RequestState.carry(carried.state, httpRequest.state);\n }\n }\n return requestContext.run(store, fn);\n }\n\n /**\n * Re-enters an *existing* request scope. Stream lifecycle callbacks fire\n * after the HTTP server has taken over the response body — outside the\n * AsyncLocalStorage scope the request ran in — so the view router captures\n * the live store and re-enters it around user-facing hooks, keeping\n * `req.ctx()` (and everything context-backed) working inside them.\n */\n static runWith<T>(store: Store, fn: () => T): T {\n return requestContext.run(store, fn);\n }\n\n /**\n * Runs `fn` outside any request scope, as the server's own `fetch` handler\n * is. For a request dispatched from inside another one, which must start from\n * where a client's request would, not from its initiator's store.\n */\n static exit<T>(fn: () => T): T {\n return requestContext.exit(fn);\n }\n}\n",
|
|
8
8
|
"/**\n * `Meta.fonts`: the `@font-face` rules and font preloads of one response.\n * Pure, so the server (validation) and `<Head />` (rendering) share it.\n */\n\n/** A font file format, as `@font-face`'s `format()` names it. */\nexport type FontFormat =\n | \"woff2\"\n | \"woff\"\n | \"truetype\"\n | \"opentype\"\n | \"collection\"\n | \"embedded-opentype\"\n | \"svg\";\n\n/** One file of a font; list the preferred format first. */\nexport type FontSource = {\n url: string;\n /** Inferred from the url's extension when left out. */\n format?: FontFormat;\n};\n\n/** One `@font-face`, see `Meta.fonts`. */\nexport type MetaFont = {\n /** The `font-family` name that CSS refers to, e.g. `\"Acme Sans\"`. */\n family: string;\n /** A url, or several files with the preferred one first. */\n src: string | FontSource[];\n /** `font-weight`: `400`, `\"bold\"`, or a range for a variable font, `\"100 900\"`. */\n weight?: string | number;\n /** `font-style`: `\"normal\"`, `\"italic\"`, `\"oblique 10deg\"`. */\n style?: string;\n /** `font-stretch`: `\"condensed\"`, `\"75% 125%\"`. */\n stretch?: string;\n /** `font-display`. Defaults to `\"swap\"`. */\n display?: \"auto\" | \"block\" | \"swap\" | \"fallback\" | \"optional\";\n /** `unicode-range`, e.g. `\"U+0000-00FF, U+0131\"`. */\n unicodeRange?: string;\n /**\n * Preload the first file with `<link rel=\"preload\" as=\"font\" crossorigin>`.\n * Only for fonts the page renders above the fold: a preloaded font that is\n * never used is a wasted download (and a console warning).\n */\n preload?: boolean;\n};\n\n/** A font after `normalizeFonts`: validated, with every source's format resolved. */\nexport type NormalizedFont = {\n family: string;\n src: { url: string; format: FontFormat | null }[];\n weight: string | null;\n style: string | null;\n stretch: string | null;\n display: NonNullable<MetaFont[\"display\"]>;\n unicodeRange: string | null;\n preload: boolean;\n};\n\nexport type FontPreload = { href: string; type: string | null };\n\nconst FORMATS = new Set<FontFormat>([\n \"woff2\",\n \"woff\",\n \"truetype\",\n \"opentype\",\n \"collection\",\n \"embedded-opentype\",\n \"svg\",\n]);\n\nconst FORMAT_BY_EXTENSION: Record<string, FontFormat> = {\n woff2: \"woff2\",\n woff: \"woff\",\n ttf: \"truetype\",\n otf: \"opentype\",\n ttc: \"collection\",\n eot: \"embedded-opentype\",\n svg: \"svg\",\n};\n\nconst MIME_BY_FORMAT: Partial<Record<FontFormat, string>> = {\n woff2: \"font/woff2\",\n woff: \"font/woff\",\n truetype: \"font/ttf\",\n opentype: \"font/otf\",\n collection: \"font/collection\",\n};\n\nconst DISPLAYS = new Set([\"auto\", \"block\", \"swap\", \"fallback\", \"optional\"]);\n\n// Descriptors are written into the CSS as they are, so only keywords, numbers,\n// angles and percentages pass: nothing that can end the declaration or rule.\nconst DESCRIPTOR = /^[a-zA-Z0-9.%+\\- ]+$/;\nconst UNICODE_RANGE = /^[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?(\\s*,\\s*[uU]\\+[0-9a-fA-F?]{1,6}(-[0-9a-fA-F]{1,6})?)*$/;\n\nfunction invalid(message: string): never {\n throw new TypeError(`Meta.fonts: ${message}`);\n}\n\n/** The format a url's extension implies (`.woff2` → `\"woff2\"`), ignoring query and hash. */\nexport function fontFormatOf(url: string): FontFormat | null {\n const file = (url.split(/[?#]/)[0] ?? \"\").split(\"/\").pop() ?? \"\";\n const dot = file.lastIndexOf(\".\");\n return dot === -1 ? null : (FORMAT_BY_EXTENSION[file.slice(dot + 1).toLowerCase()] ?? null);\n}\n\nfunction descriptor(name: string, value: string | number | undefined): string | null {\n if (value === undefined || value === null) return null;\n const text = String(value).trim();\n if (!text || !DESCRIPTOR.test(text)) {\n invalid(`${name} ${JSON.stringify(value)} is not a valid font-${name} value`);\n }\n return text;\n}\n\n/** Validates what a handler passed; throws a `TypeError` naming the bad value. */\nexport function normalizeFonts(fonts: MetaFont[]): NormalizedFont[] {\n if (!Array.isArray(fonts)) invalid(\"expected an array of fonts\");\n return fonts.map((font) => {\n if (typeof font?.family !== \"string\" || !font.family.trim()) {\n invalid(\"every font needs a family\");\n }\n const sources = typeof font.src === \"string\" ? [{ url: font.src }] : font.src;\n if (!Array.isArray(sources) || sources.length === 0) {\n invalid(`font \"${font.family}\" needs a src`);\n }\n const src = sources.map((source) => {\n if (typeof source?.url !== \"string\" || !source.url.trim()) {\n invalid(`font \"${font.family}\" has a source without a url`);\n }\n if (source.format !== undefined && !FORMATS.has(source.format)) {\n invalid(`font \"${font.family}\" has an unknown format ${JSON.stringify(source.format)}`);\n }\n return { url: source.url.trim(), format: source.format ?? fontFormatOf(source.url) };\n });\n const display = font.display ?? \"swap\";\n if (!DISPLAYS.has(display)) {\n invalid(`display ${JSON.stringify(display)} is not a valid font-display value`);\n }\n const unicodeRange = font.unicodeRange?.trim() || null;\n if (unicodeRange && !UNICODE_RANGE.test(unicodeRange)) {\n invalid(`unicodeRange ${JSON.stringify(font.unicodeRange)} is not a valid unicode-range`);\n }\n return {\n family: font.family.trim(),\n src,\n weight: descriptor(\"weight\", font.weight),\n style: descriptor(\"style\", font.style),\n stretch: descriptor(\"stretch\", font.stretch),\n display,\n unicodeRange,\n preload: font.preload === true,\n };\n });\n}\n\n/**\n * A CSS string literal holding `value`. Quotes, backslashes, control\n * characters and `<` (so `</style>` can't close the element) are escaped.\n */\nexport function cssString(value: string): string {\n // oxlint-disable-next-line no-control-regex -- escaping them is the point\n const escaped = value.replace(/[\\\\\"<>\\u0000-\\u001f\\u007f]/g, (char) =>\n char === \"\\\\\" || char === '\"' ? `\\\\${char}` : `\\\\${char.charCodeAt(0).toString(16)} `,\n );\n return `\"${escaped}\"`;\n}\n\n/** One `@font-face` rule. */\nexport function fontFaceRule(font: NormalizedFont): string {\n const src = font.src\n .map(({ url, format }) => `url(${cssString(url)})${format ? ` format(${cssString(format)})` : \"\"}`)\n .join(\", \");\n const declarations = [\n `font-family: ${cssString(font.family)}`,\n `src: ${src}`,\n font.weight && `font-weight: ${font.weight}`,\n font.style && `font-style: ${font.style}`,\n font.stretch && `font-stretch: ${font.stretch}`,\n `font-display: ${font.display}`,\n font.unicodeRange && `unicode-range: ${font.unicodeRange}`,\n ].filter(Boolean);\n return `@font-face { ${declarations.join(\"; \")}; }`;\n}\n\n/** The `@font-face` rules for `fonts`, an identical font declared twice once. */\nexport function fontFaceRules(fonts: NormalizedFont[] | null | undefined): string[] {\n return [...new Set((fonts ?? []).map(fontFaceRule))];\n}\n\n/** The first file of every font marked `preload`, each url once. */\nexport function fontPreloads(fonts: NormalizedFont[] | null | undefined): FontPreload[] {\n const preloads = new Map<string, FontPreload>();\n for (const font of fonts ?? []) {\n const first = font.preload ? font.src[0] : undefined;\n if (first && !preloads.has(first.url)) {\n preloads.set(first.url, {\n href: first.url,\n type: (first.format && MIME_BY_FORMAT[first.format]) ?? null,\n });\n }\n }\n return [...preloads.values()];\n}\n",
|
|
9
|
-
"import { type MetaFont, type NormalizedFont, normalizeFonts } from \"../client/fonts\";\nimport { configuredAppOrigin } from \"../utils/appOrigin\";\n\nexport type { MetaFont };\n\nexport type OpenGraphParams = {\n title: string;\n description?: string;\n type: string;\n url: string;\n image
|
|
9
|
+
"import { type MetaFont, type NormalizedFont, normalizeFonts } from \"../client/fonts\";\nimport { configuredAppOrigin } from \"../utils/appOrigin\";\n\nexport type { MetaFont };\n\nexport type OpenGraphParams = {\n title: string;\n description?: string;\n type: string;\n url: string;\n /** Rendered as `og:image` only when set. A path is prefixed with the app origin. */\n image?: string;\n imageAlt?: string;\n imageWidth?: number;\n imageHeight?: number;\n twitterImage?: string;\n twitterImageAlt?: string;\n twitterImageWidth?: number;\n twitterImageHeight?: number;\n /**\n * The `twitter:card` type. Defaults to `\"summary_large_image\"` when the page\n * has an image (`twitterImage ?? image`), `\"summary\"` otherwise.\n */\n twitterCard?: \"summary\" | \"summary_large_image\";\n};\n/**\n * Attributes for the document's `<html>` element, handed to the root (or a\n * static view's) layout as its `htmlAttributes` prop.\n */\nexport type HtmlAttributes = {\n /** The document's language, e.g. `\"tr\"`. Defaults to the request's locale. */\n lang?: string;\n /** Text direction. Defaults to the one `lang` is written in. */\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n};\n\n/** One `<link rel=\"alternate\" hreflang>`: the same page in another language. */\nexport type AlternateLink = {\n /** A BCP 47 tag, or `\"x-default\"` for the page to use when none matches. */\n hrefLang: string;\n href: string;\n};\n\nexport class Metadata {\n content: any = {\n title: \"Gemi App\",\n description: null,\n openGraph: null,\n htmlAttributes: null,\n canonical: null,\n alternates: null,\n fonts: null,\n };\n\n /**\n * Whether a handler set anything, as opposed to `content` still being the\n * defaults. A partially rendered response that touched no metadata sends\n * none, so the client keeps what the skipped segments put there.\n */\n touched = false;\n\n render() {\n return {\n title: this.content.title,\n description: this.content.description,\n openGraph: this.content.openGraph,\n htmlAttributes: this.content.htmlAttributes,\n canonical: this.content.canonical,\n alternates: this.content.alternates,\n fonts: this.content.fonts,\n };\n }\n\n /** Merged into what earlier calls set; `undefined` leaves an attribute alone. */\n htmlAttributes(attributes: HtmlAttributes) {\n this.touched = true;\n const defined = Object.fromEntries(\n Object.entries(attributes).filter(([, value]) => value !== undefined),\n );\n this.content.htmlAttributes = { ...this.content.htmlAttributes, ...defined };\n }\n\n canonical(url: string) {\n this.touched = true;\n this.content.canonical = url;\n }\n\n alternates(links: AlternateLink[]) {\n this.touched = true;\n this.content.alternates = links;\n }\n\n /** Added to what earlier calls declared, so a layout and its page can both declare fonts. */\n fonts(fonts: MetaFont[]) {\n const normalized: NormalizedFont[] = normalizeFonts(fonts);\n this.touched = true;\n this.content.fonts = [...(this.content.fonts ?? []), ...normalized];\n }\n\n title(title: string) {\n this.touched = true;\n this.content.title = title;\n }\n\n description(description: string) {\n this.touched = true;\n this.content.description = description;\n }\n\n openGraph({\n title,\n description,\n type,\n url,\n image,\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage = image,\n twitterImageAlt = imageAlt,\n twitterImageWidth = imageWidth,\n twitterImageHeight = imageHeight,\n twitterCard = twitterImage ? \"summary_large_image\" : \"summary\",\n }: OpenGraphParams) {\n this.touched = true;\n const absolute = (src: string | undefined) =>\n src && !src.startsWith(\"http\") ? `${configuredAppOrigin()}${src}` : src;\n this.content.openGraph = Object.fromEntries(\n Object.entries({\n title,\n description,\n type,\n url,\n image: absolute(image),\n imageAlt,\n imageWidth,\n imageHeight,\n twitterImage: absolute(twitterImage),\n twitterImageAlt,\n twitterImageWidth,\n twitterImageHeight,\n twitterCard,\n }).filter(([_, value]) => value !== undefined),\n );\n }\n}\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "8DDA19763EE4F9EC64756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Ba as y}from"./chunk-kk18xqgc.js";import{createElement as k}from"react";function z(i,n){let s=Object.keys(n).sort((p,e)=>e.length-p.length).map((p)=>p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),b=new RegExp(s.join("|"),"g");return i.replace(b,(p)=>n[p])}async function L(i,n,s=[],b){let p=[...s.map((t)=>`${i}/views/${t}.tsx`),b?`${i}/views/${b}.tsx`:`${i}/views/RootLayout.tsx`],e=new Set;for(let t of p){let u=n.moduleGraph.getModulesByFile(t);if(u)for(let l of u)e.add(l)}let g=[],x=[],r={};for(let t of e)if(t)for(let u of t.importedModules){if(u.file.includes("module.css"))r[u.file]=u.ssrTransformResult.map.sourcesContent.join("");if(u.file.includes(".css"))x.push(u.file)}for(let t of x){let u=await n.transformRequest(t+"?direct"),l=t.includes("module.css"),v="";if(l)v=z(r[t],u.default);g.push({isDev:!0,id:t,content:l?v:u.code})}return g.map((t,u)=>{return k("style",{key:u,type:"text/css","data-vite-dev-id":t.id,dangerouslySetInnerHTML:{__html:t.content}})})}async function _(i=[]){return i.map((n,s)=>{return k("style",{key:s,id:n?.id,type:"text/css",dangerouslySetInnerHTML:{__html:n.content}})})}import{existsSync as J}from"fs";import{basename as N}from"path";import{networkInterfaces as O}from"os";var q={name:"gemi",version:"0.
|
|
2
|
+
import{Ba as y}from"./chunk-kk18xqgc.js";import{createElement as k}from"react";function z(i,n){let s=Object.keys(n).sort((p,e)=>e.length-p.length).map((p)=>p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),b=new RegExp(s.join("|"),"g");return i.replace(b,(p)=>n[p])}async function L(i,n,s=[],b){let p=[...s.map((t)=>`${i}/views/${t}.tsx`),b?`${i}/views/${b}.tsx`:`${i}/views/RootLayout.tsx`],e=new Set;for(let t of p){let u=n.moduleGraph.getModulesByFile(t);if(u)for(let l of u)e.add(l)}let g=[],x=[],r={};for(let t of e)if(t)for(let u of t.importedModules){if(u.file.includes("module.css"))r[u.file]=u.ssrTransformResult.map.sourcesContent.join("");if(u.file.includes(".css"))x.push(u.file)}for(let t of x){let u=await n.transformRequest(t+"?direct"),l=t.includes("module.css"),v="";if(l)v=z(r[t],u.default);g.push({isDev:!0,id:t,content:l?v:u.code})}return g.map((t,u)=>{return k("style",{key:u,type:"text/css","data-vite-dev-id":t.id,dangerouslySetInnerHTML:{__html:t.content}})})}async function _(i=[]){return i.map((n,s)=>{return k("style",{key:s,id:n?.id,type:"text/css",dangerouslySetInnerHTML:{__html:n.content}})})}import{existsSync as J}from"fs";import{basename as N}from"path";import{networkInterfaces as O}from"os";var q={name:"gemi",version:"0.144.0",private:!1,license:"MIT",author:"Enes Tufekci <enes@gemijs.dev>",repository:{type:"git",url:"git+https://github.com/nstfkc/gemi.git",directory:"packages/gemi"},bin:{gemi:"./dist/bin/gemi.js","gemi-orm-generator":"./dist/bin/orm-generator.js"},files:["dist/**/*","ide/typescript-plugin/package.json","skills/**/*"],module:!0,exports:{"./http":"./http/index.ts","./client":"./client/index.ts","./ai":"./ai/index.ts","./ai/client":"./ai/client/index.ts","./ai/voice":"./ai/voice/index.ts","./testing":"./testing/index.ts","./app":"./app/index.ts","./facades":"./facades/index.ts","./email":"./email/index.ts","./vite":"./dist/vite/index.mjs","./kernel":"./kernel/index.ts","./services":"./services/index.ts","./i18n":"./i18n/index.ts","./dictionary":"./i18n/dictionaryRuntime.ts","./server":"./server/index.ts","./config":"./config/index.ts","./container":"./container/index.ts","./foundation":"./foundation/index.ts","./database":"./database/index.ts","./orm":"./orm/index.ts","./support":"./support/index.ts","./console/run":"./console/run.ts","./queue/work":"./services/queue/work.ts","./stats/route-table":"./stats/route-table.ts","./ide/typescript-plugin":"./ide/typescript-plugin/index.ts","./bun/preload":"./bun/preload.ts","./bun/plugin":"./bun/plugin.ts","./vitest":"./vitest/index.ts"},scripts:{lint:"oxlint",typecheck:"tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.browser.json && tsc --noEmit -p ide/typescript-plugin/tsconfig.json",build:"NODE_ENV=production bun run build:core && bun run build:bin && bun run build:types && bun run build:client && bun run build:plugin && bun run build:ts-plugin && bun run build:client-types && bun run build:augmentation","build:core":"bun ./scripts/build.ts","build:bin":"bun build --outdir=./dist/bin --target=bun --external=vite --external=react-dom --external=react/jsx-runtime --external=bun --external=sharp --external=@azure/storage-blob --external=typescript --sourcemap ./bin/gemi.ts ./bin/orm-generator.ts && bun ./scripts/prepare-bin.ts","build:client":"rm -rf dist/client dist/testing dist/ai/client dist/ai/voice dist/chunks && vite build -c vite.client.config.mts","build:plugin":"vite build -c vite.plugin.config.mts","build:ts-plugin":"bun ./scripts/build-ts-plugin.ts","build:types":"tsc -p tsconfig.build.json","build:client-types":"tsc -p tsconfig.browser.json",test:"bun --bun x vitest","test:types":"vitest run --typecheck.only","test:live":"bun --bun x vitest run ai/live","test:packaging":"bun --bun x vitest run --config vitest.packaging.config.ts","build:publish":"bun scripts/build-publish.ts",prepublishOnly:"echo 'Do not publish from this directory \u2014 its exports point at TS source. Run: bun run build:publish, then publish from .publish/' && exit 1","build:augmentation":"bun ./scripts/wire-augmentation.ts"},dependencies:{"@aws-sdk/client-s3":"^3.629.0","@aws-sdk/s3-request-presigner":"^3.629.0","ast-types":"^0.14.2",commander:"^12.1.0",history:"^5.3.0","jsx-email":"2.0.0-rc2.1","magic-string":"^0.30.17",open:"^10.1.0","react-error-boundary":"^6.0.0",recast:"^0.23.9",resend:"^6.12.3",satori:"^0.12.2","temporal-polyfill":"^0.2.5","twitter-api-v2":"^1.20.2","urlpattern-polyfill":"^10.0.0",uuid:"^9.0.1"},devDependencies:{"@babel/parser":"^7.25.4","@prisma/generator-helper":"^6.5.0","@repo/typescript-config":"*","@testing-library/react":"^16.3.2","@types/bun":"^1.3.14","@types/eslint":"^8.56.5","@types/node":"^20.11.24","@types/react":"^19.0.2","@types/react-dom":"^19.0.2",eslint:"^8.57.0",jsdom:"^30.0.1",oxlint:"^1.39.0",postgres:"^3.4.5",react:"19.2.3","react-dom":"19.2.3",typescript:"^5.7.3",vitest:"^4.0.0"},peerDependencies:{"@azure/storage-blob":"^12.28.0",react:">=19","react-dom":">=19",sharp:"^0.34.2",typescript:">=5",vite:"^8.0.0",postgres:"^3.4.0"},peerDependenciesMeta:{"@azure/storage-blob":{optional:!0},typescript:{optional:!0},postgres:{optional:!0}}};var Q=[" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551"," \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D"],W=Boolean(process.stdout.isTTY)&&!process.env.NO_COLOR,c=(i,n)=>W?`\x1B[${i}m${n}\x1B[0m`:n,X=(i)=>c("1",i),d=(i)=>c("2",i),j=(i)=>c("36",i),Y=(i)=>c("32",i),Z=(i)=>c("35",i);function $(){return q.version??"?"}function f(i){for(let n of Object.values(O()))for(let s of n??[])if((s.family==="IPv4"||s.family===4)&&!s.internal)return`http://${s.address}:${i}`;return null}function H(i){return y(i).filter((n)=>J(n)).map((n)=>N(n))}function T(i){let{port:n,rootDir:s}=i,b=`http://localhost:${n}`,p=f(n),e=H(s),g=(r,t)=>` ${Y("\u279C")} ${X(r.padEnd(9))}${t}`,x=["",...Q.map((r)=>Z(r)),"",` ${d("gemi")} ${j(`v${$()}`)}`,"",g("Local:",j(b)),g("Network:",p?j(p):d("unavailable")),g("Env:",e.length?e.join(", "):d("none")),""];console.log(x.join(`
|
|
3
3
|
`))}function D(i=process.env.SERVER_IDLE_TIMEOUT){if(i===void 0||i.trim()==="")return 10;let n=Number(i.trim());if(!Number.isInteger(n)||n<0||n>255)throw Error(`SERVER_IDLE_TIMEOUT must be a whole number of seconds from 0 to 255 (0 disables the timeout), got ${JSON.stringify(i)}.`);return n}
|
|
4
4
|
export{L as R,_ as S,T,D as U};
|
|
5
5
|
|
|
6
|
-
//# debugId=
|
|
6
|
+
//# debugId=89348FEDAA87CFD364756E2164756E21
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"/**\n * Bun's default, and what both servers use when `SERVER_IDLE_TIMEOUT` is unset.\n */\nexport const DEFAULT_SERVER_IDLE_TIMEOUT = 10;\n\n/**\n * The `idleTimeout` (seconds) both `gemi dev` and `gemi start` pass to\n * `Bun.serve`, from `SERVER_IDLE_TIMEOUT` (#787).\n *\n * One reader for both servers, so a long-poll that works under `gemi start`\n * also works under `gemi dev`. Before this, only `httpProd` read the variable\n * and the dev server always ran at Bun's 10 seconds.\n *\n * It is the time a connection may stay silent, a response that has not started\n * included, before Bun closes it; `0` disables it. It does not apply to an\n * upgraded websocket (the HMR relay included), which has its own\n * `websocket.idleTimeout`.\n *\n * Unset or blank means the default. Anything that is not a whole number from 0\n * to 255 (Bun's own limits) fails the boot with the variable's name, instead\n * of Bun's \"expects idleTimeout to be an integer\", which does not say where the\n * value came from.\n */\nexport function serverIdleTimeout(raw: string | undefined = process.env.SERVER_IDLE_TIMEOUT): number {\n if (raw === undefined || raw.trim() === \"\") return DEFAULT_SERVER_IDLE_TIMEOUT;\n\n const seconds = Number(raw.trim());\n if (!Number.isInteger(seconds) || seconds < 0 || seconds > 255) {\n throw new Error(\n `SERVER_IDLE_TIMEOUT must be a whole number of seconds from 0 to 255 ` +\n `(0 disables the timeout), got ${JSON.stringify(raw)}.`,\n );\n }\n return seconds;\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "89348FEDAA87CFD364756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{S as k,T as xJ,U as KJ}from"./chunk-
|
|
2
|
+
import{S as k,T as xJ,U as KJ}from"./chunk-t0wfj6hy.js";import{oa as M,sa as F,ta as zJ}from"./chunk-a22h5cby.js";import"./chunk-kk18xqgc.js";import{ae as t,og as jJ,pg as B,xg as VJ,yg as OJ,zg as UJ}from"./chunk-a78b9v7h.js";import"./chunk-ej4kf7m5.js";import"./chunk-5qfzvnyp.js";import{Eh as i,Fh as a,Ih as r}from"./chunk-27xsjq8a.js";import{Ki as GJ}from"./chunk-9k46m1vf.js";import"./chunk-fg2k18d2.js";import"./chunk-ktrm6y5j.js";import"./chunk-9xzg05xg.js";import"./chunk-a37shxb1.js";import"./chunk-68f0jpje.js";import"./chunk-1skdsmjx.js";import"./chunk-yjszzjyj.js";import"./chunk-p81qeav5.js";import"./chunk-t03nda3s.js";import"./chunk-qt6x2r6a.js";import"./chunk-m8yd59gg.js";import"./chunk-1ed75a7b.js";import"./chunk-0839f72f.js";import{al as $J}from"./chunk-rvm5mkwm.js";import"./chunk-s29tgy4y.js";import{ol as YJ}from"./chunk-8ex0y47w.js";import{pl as R}from"./chunk-m6t5a0me.js";import"./chunk-t2nsn0r2.js";import{createHash as H2}from"crypto";import{join as v,resolve as LJ,sep as CJ}from"path";import{Duplex as wJ}from"stream";import{constants as P,createBrotliCompress as kJ,createGzip as vJ}from"zlib";var EJ=["br","gzip"],gJ=1024,yJ=5,uJ=19,fJ=6;function mJ(J){if(J===void 0)return 1;if(!/^\d+(\.\d{0,3})?$/.test(J.trim()))return 1;let $=Number(J.trim());return Number.isFinite($)?Math.min($,1):1}function hJ(J){if(J===null||J===void 0)return null;let $=new Map;for(let Z of J.split(",")){let[X,...Q]=Z.split(";"),j=X.trim().toLowerCase();if(j==="")continue;let H=1;for(let Y of Q){let V=Y.indexOf("=");if(V===-1)continue;if(Y.slice(0,V).trim().toLowerCase()==="q"){H=mJ(Y.slice(V+1));break}}$.set(j,H)}return $}function b(J,$=EJ){let Z=hJ(J);if(!Z)return null;let X=Z.get("*"),Q=null,j=0;for(let H of $){let Y=Z.get(H)??X??0;if(Y>j)Q=H,j=Y}return Q}function pJ(J,$){if(!J)return!1;return J.split(",").some((Z)=>Z.trim().toLowerCase().split("=")[0].trim()===$)}function cJ(J,$){if(J==="HEAD")return!1;if($.status<200||$.status===204||$.status===206||$.status===304)return!1;if($.headers.has("Content-Range"))return!1;let Z=$.headers.get("Content-Type");if(!Z||!/^\s*text\/html\s*(;|$)/i.test(Z))return!1;if(!$.body)return!1;let X=$.headers.get("Content-Encoding");if(X&&X.trim().toLowerCase()!=="identity")return!1;if(pJ($.headers.get("Cache-Control"),"no-transform"))return!1;let Q=$.headers.get("Content-Length");if(Q!==null&&Number(Q)<gJ)return!1;return!0}function dJ(J){let $=J==="br"?kJ({params:{[P.BROTLI_PARAM_QUALITY]:yJ,[P.BROTLI_PARAM_LGWIN]:uJ},flush:P.BROTLI_OPERATION_FLUSH}):vJ({level:fJ,flush:P.Z_SYNC_FLUSH});return wJ.toWeb($)}function lJ(J){let $=J.get("Vary");if(!$){J.set("Vary","Accept-Encoding");return}let Z=$.split(",").map((X)=>X.trim().toLowerCase());if(Z.includes("*")||Z.includes("accept-encoding"))return;J.append("Vary","Accept-Encoding")}function d(J,$){if(!cJ(J.method,$))return $;let Z=new Headers($.headers);lJ(Z);let X=b(J.headers.get("Accept-Encoding"));if(!X)return new Response($.body,{status:$.status,statusText:$.statusText,headers:Z});let Q;try{Q=dJ(X)}catch{return new Response($.body,{status:$.status,statusText:$.statusText,headers:Z})}return Z.set("Content-Encoding",X),Z.delete("Content-Length"),new Response($.body.pipeThrough(Q),{status:$.status,statusText:$.statusText,headers:Z})}import{readdir as sJ,stat as s}from"fs/promises";import{join as eJ}from"path";import{mkdir as L2,readFile as oJ,stat as C2,writeFile as F2}from"fs/promises";import{dirname as _2,join as nJ}from"path";import{promisify as l}from"util";import{brotliCompress as iJ,constants as P2,gzip as aJ}from"zlib";var rJ=".vite/static-assets.json";var o={br:".br",gzip:".gz"},tJ=["br","gzip"],A2=l(iJ),B2=l(aJ);async function n(J){let $;try{$=await oJ(nJ(J,rJ),"utf8")}catch{return null}let Z;try{Z=JSON.parse($)?.files}catch{return null}if(!Z||typeof Z!=="object")return null;let X={files:{}};for(let[Q,j]of Object.entries(Z)){if(!Array.isArray(j))continue;X.files[Q]=tJ.filter((H)=>j.includes(H))}return X}function S(J){let $=J.toString(),Z=new Bun.CryptoHasher("sha1");return Z.update($),Z.digest("hex")}async function e(J){let $=new Set;async function Z(X,Q){let j;try{j=await sJ(X,{withFileTypes:!0})}catch{return}for(let H of j){if(H.name.startsWith("."))continue;if(Q&&H.name==="assets")continue;let Y=eJ(X,H.name),V=H.isDirectory(),O=H.isFile();if(H.isSymbolicLink())try{let K=await s(Y);V=K.isDirectory(),O=K.isFile()}catch{continue}if(O)$.add(Y);else if(V&&!H.isSymbolicLink())await Z(Y,!1)}}return await Z(J,!0),$}var J2="public, max-age=31536000, must-revalidate",$2="public, max-age=31536000, immutable";async function Z2(J,$,Z){if(Z.length===0||J.headers.has("Range"))return null;let X=b(J.headers.get("Accept-Encoding"),Z);if(!X)return null;let Q=$+o[X];try{let j=await s(Q);return j.isFile()?{encoding:X,path:Q,size:j.size}:null}catch{return null}}async function JJ(J,$,Z={}){let X=Bun.file($),Q=Z.encodings??[],j={"Content-Type":X.type||"application/octet-stream","Cache-Control":Z.immutable?$2:J2,"Accept-Ranges":"bytes"};if(Q.length>0)j.Vary="Accept-Encoding";let H=await Z2(J,$,Q);if(H){let O=Bun.file(H.path);return new Response(O.stream(),{headers:{...j,"Content-Encoding":H.encoding,"Content-Length":String(H.size),ETag:`${S(O.lastModified)}-${H.encoding}`}})}let Y=X.size;j.ETag=S(X.lastModified);let V=i(J.headers.get("Range"));if(V){let O=a(V,Y);if(!O)return t(Y);return new Response(X.slice(O.start,O.end+1).stream(),{status:206,headers:{...j,"Content-Range":r(O.start,O.end,Y),"Content-Length":String(O.length)}})}return new Response(X.stream(),{headers:{...j,"Content-Length":String(Y)}})}import{stat as G2}from"fs/promises";var A="app/client.tsx";function ZJ(J,$=M){let Z=J[A]?.file;if(!Z)return;return{module:F(Z,$),preload:C(J,A,$)}}function C(J,$,Z=M){let X=[],Q=new Set,j=(H)=>{if(Q.has(H))return;Q.add(H);let Y=J[H];if(!Y?.file)return;X.push(F(Y.file,Z));for(let V of Y.imports??[])j(V)};return j($),X}function X2(J,$,Z=M){let X=new Set(C(J,$,Z)),Q=[],j=new Set,H=(V)=>{if(j.has(V))return;j.add(V);let O=J[V];if(!O)return;for(let K of O.dynamicImports??[])if(!/(^|\/)node_modules\//.test(K)&&!Q.includes(K))Q.push(K);for(let K of O.imports??[])H(K)};H($);let Y=[];for(let V of Q)for(let O of C(J,V,Z))if(!X.has(O))X.add(O),Y.push(O);return Y}function XJ(J,$){let Z=[],X=new Set,Q=new Set,j=(H)=>{if(Q.has(H))return;Q.add(H);let Y=J[H];if(!Y)return;for(let V of Y.imports??[])j(V);for(let V of Y.css??[])if(!X.has(V))X.add(V),Z.push(V)};return j($),Z}function QJ(J,$=M){let Z=new Map;return(X)=>{if(!Z.has(X)){let Q=`${X}${$J}`,j=J[Q]?.file;Z.set(X,j?{src:F(j,$),preload:C(J,Q,$),dynamicPreload:X2(J,Q,$)}:void 0)}return Z.get(X)}}function WJ(J,$=30000){let Z=JSON.stringify("gemi:chunk-reload"),X=JSON.stringify(`Failed to fetch dynamically imported module: ${J}`);return`var r=!1;try{var s=window.sessionStorage,m=JSON.parse(s.getItem(${Z})||"null");var d=m?Date.now()-m.at:NaN;if(navigator.onLine!==!1&&!(d>=0&&d<${$})){s.setItem(${Z},JSON.stringify({url:window.location.href,at:Date.now()}));r=!0}}catch(e){}if(r)window.location.reload();else throw new Error(${X});export {}`}var Q2=new RegExp(`^${jJ}/.+\\.m?js$`);function W2(J){return Q2.test(J)}function HJ(J){if(W2(J))return new Response(WJ(J),{headers:{"Content-Type":"application/javascript","Cache-Control":"no-store"}});if(B(J))return new Response("Not found",{status:404});return}var j2=`<!DOCTYPE html>
|
|
3
3
|
<html lang="en">
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../client/Head.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAmCnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,QAoD3D;
|
|
1
|
+
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../client/Head.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,OAAO,CAAC;AAmCnD,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,QAoD3D;AAkED,eAAO,MAAM,IAAI,GAAI,wBAGlB;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,4CA6D5C,CAAC"}
|
package/dist/client/index.js
CHANGED
|
@@ -1714,7 +1714,7 @@ function updateMeta(meta, locale) {
|
|
|
1714
1714
|
}
|
|
1715
1715
|
}
|
|
1716
1716
|
var OpenGraph = (props) => {
|
|
1717
|
-
const { title, description, type, url, image, imageAlt, imageWidth, imageHeight, twitterImage, twitterImageAlt, twitterImageWidth, twitterImageHeight } = props;
|
|
1717
|
+
const { title, description, type, url, image, imageAlt, imageWidth, imageHeight, twitterImage, twitterImageAlt, twitterImageWidth, twitterImageHeight, twitterCard = twitterImage ? "summary_large_image" : "summary" } = props;
|
|
1718
1718
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1719
1719
|
/* @__PURE__ */ jsx("meta", {
|
|
1720
1720
|
property: "og:title",
|
|
@@ -1728,7 +1728,7 @@ var OpenGraph = (props) => {
|
|
|
1728
1728
|
property: "og:url",
|
|
1729
1729
|
content: url
|
|
1730
1730
|
}),
|
|
1731
|
-
/* @__PURE__ */ jsx("meta", {
|
|
1731
|
+
image && /* @__PURE__ */ jsx("meta", {
|
|
1732
1732
|
property: "og:image",
|
|
1733
1733
|
content: image
|
|
1734
1734
|
}),
|
|
@@ -1748,13 +1748,14 @@ var OpenGraph = (props) => {
|
|
|
1748
1748
|
property: "og:image:height",
|
|
1749
1749
|
content: String(imageHeight)
|
|
1750
1750
|
}),
|
|
1751
|
-
twitterImage && /* @__PURE__ */
|
|
1751
|
+
twitterImage && /* @__PURE__ */ jsx("meta", {
|
|
1752
1752
|
name: "twitter:image",
|
|
1753
1753
|
content: twitterImage
|
|
1754
|
-
}),
|
|
1754
|
+
}),
|
|
1755
|
+
/* @__PURE__ */ jsx("meta", {
|
|
1755
1756
|
name: "twitter:card",
|
|
1756
|
-
content:
|
|
1757
|
-
})
|
|
1757
|
+
content: twitterCard
|
|
1758
|
+
}),
|
|
1758
1759
|
twitterImageAlt && /* @__PURE__ */ jsx("meta", {
|
|
1759
1760
|
name: "twitter:image:alt",
|
|
1760
1761
|
content: twitterImageAlt
|