@interactive-inc/claude-funnel 0.17.0 → 0.19.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.
@@ -1,6 +1,6 @@
1
1
  import { n as FunnelConnectorAdapter, t as CallInput } from "../connector-adapter-CXB-q_XC.js";
2
2
  import { n as FunnelConnectorListener, r as NotifyFn, t as FunnelLogger } from "../logger-CTlXs7z4.js";
3
- import { a as FunnelProcessRunner, n as ghConnectorSchema, t as GhConnectorConfig } from "../gh-connector-schema-BZFAS-p-.js";
3
+ import { a as FunnelProcessRunner, n as ghConnectorSchema, t as GhConnectorConfig } from "../gh-connector-schema-BNyTaASt.js";
4
4
 
5
5
  //#region lib/connectors/gh-adapter.d.ts
6
6
  type Deps$1 = {
@@ -1,2 +1,2 @@
1
- import { n as FunnelGhListener, r as FunnelGhAdapter, t as ghConnectorSchema } from "../gh-connector-schema-2ml29MBC.js";
1
+ import { n as FunnelGhListener, r as FunnelGhAdapter, t as ghConnectorSchema } from "../gh-connector-schema-CD5HIkrd.js";
2
2
  export { FunnelGhAdapter, FunnelGhListener, ghConnectorSchema };
@@ -541,10 +541,10 @@ Since you have not provided a token or authorize, you might be missing one or mo
541
541
  Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let Z of $.seen.entries()){let K=Z[1];if(x===Z[0]){z(Z);continue}if($.external){let V=$.external.registry.get(Z[0])?.id;if(x!==Z[0]&&V){z(Z);continue}}if($.metadataRegistry.get(Z[0])?.id){z(Z);continue}if(K.cycle){z(Z);continue}if(K.count>1){if($.reused==="ref"){z(Z);continue}}}}function Ux($,x){let Y=$.seen.get(x);if(!Y)throw Error("Unprocessed schema. This is a bug in Zod.");let X=(K)=>{let W=$.seen.get(K);if(W.ref===null)return;let V=W.def??W.schema,w={...V},U=W.ref;if(W.ref=null,U){X(U);let J=$.seen.get(U),q=J.schema;if(q.$ref&&($.target==="draft-07"||$.target==="draft-04"||$.target==="openapi-3.0"))V.allOf=V.allOf??[],V.allOf.push(q);else Object.assign(V,q);if(Object.assign(V,w),K._zod.parent===U)for(let D in V){if(D==="$ref"||D==="allOf")continue;if(!(D in w))delete V[D]}if(q.$ref&&J.def)for(let D in V){if(D==="$ref"||D==="allOf")continue;if(D in J.def&&JSON.stringify(V[D])===JSON.stringify(J.def[D]))delete V[D]}}let H=K._zod.parent;if(H&&H!==U){X(H);let J=$.seen.get(H);if(J?.schema.$ref){if(V.$ref=J.schema.$ref,J.def)for(let q in V){if(q==="$ref"||q==="allOf")continue;if(q in J.def&&JSON.stringify(V[q])===JSON.stringify(J.def[q]))delete V[q]}}}$.override({zodSchema:K,jsonSchema:V,path:W.path??[]})};for(let K of[...$.seen.entries()].reverse())X(K[0]);let Q={};if($.target==="draft-2020-12")Q.$schema="https://json-schema.org/draft/2020-12/schema";else if($.target==="draft-07")Q.$schema="http://json-schema.org/draft-07/schema#";else if($.target==="draft-04")Q.$schema="http://json-schema.org/draft-04/schema#";else if($.target==="openapi-3.0");if($.external?.uri){let K=$.external.registry.get(x)?.id;if(!K)throw Error("Schema is missing an `id` property");Q.$id=$.external.uri(K)}Object.assign(Q,Y.def??Y.schema);let z=$.metadataRegistry.get(x)?.id;if(z!==void 0&&Q.id===z)delete Q.id;let Z=$.external?.defs??{};for(let K of $.seen.entries()){let W=K[1];if(W.def&&W.defId){if(W.def.id===W.defId)delete W.def.id;Z[W.defId]=W.def}}if($.external);else if(Object.keys(Z).length>0)if($.target==="draft-2020-12")Q.$defs=Z;else Q.definitions=Z;try{let K=JSON.parse(JSON.stringify(Q));return Object.defineProperty(K,"~standard",{value:{...x["~standard"],jsonSchema:{input:mX(x,"input",$.processors),output:mX(x,"output",$.processors)}},enumerable:!1,writable:!1}),K}catch(K){throw Error("Error converting schema to JSON.")}}function V$($,x){let Y=x??{seen:new Set};if(Y.seen.has($))return!1;Y.seen.add($);let X=$._zod.def;if(X.type==="transform")return!0;if(X.type==="array")return V$(X.element,Y);if(X.type==="set")return V$(X.valueType,Y);if(X.type==="lazy")return V$(X.getter(),Y);if(X.type==="promise"||X.type==="optional"||X.type==="nonoptional"||X.type==="nullable"||X.type==="readonly"||X.type==="default"||X.type==="prefault")return V$(X.innerType,Y);if(X.type==="intersection")return V$(X.left,Y)||V$(X.right,Y);if(X.type==="record"||X.type==="map")return V$(X.keyType,Y)||V$(X.valueType,Y);if(X.type==="pipe"){if($._zod.traits.has("$ZodCodec"))return!0;return V$(X.in,Y)||V$(X.out,Y)}if(X.type==="object"){for(let Q in X.shape)if(V$(X.shape[Q],Y))return!0;return!1}if(X.type==="union"){for(let Q of X.options)if(V$(Q,Y))return!0;return!1}if(X.type==="tuple"){for(let Q of X.items)if(V$(Q,Y))return!0;if(X.rest&&V$(X.rest,Y))return!0;return!1}return!1}var zI=($,x={})=>(Y)=>{let X=Vx({...Y,processors:x});return m0($,X),wx(X,$),Ux(X,$)},mX=($,x,Y={})=>(X)=>{let{libraryOptions:Q,target:z}=X??{},Z=Vx({...Q??{},target:z,io:x,processors:Y});return m0($,Z),wx(Z,$),Ux(Z,$)};var Rm1={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},ZI=($,x,Y,X)=>{let Q=Y;Q.type="string";let{minimum:z,maximum:Z,format:K,patterns:W,contentEncoding:V}=$._zod.bag;if(typeof z==="number")Q.minLength=z;if(typeof Z==="number")Q.maxLength=Z;if(K){if(Q.format=Rm1[K]??K,Q.format==="")delete Q.format;if(K==="time")delete Q.format}if(V)Q.contentEncoding=V;if(W&&W.size>0){let w=[...W];if(w.length===1)Q.pattern=w[0].source;else if(w.length>1)Q.allOf=[...w.map((U)=>({...x.target==="draft-07"||x.target==="draft-04"||x.target==="openapi-3.0"?{type:"string"}:{},pattern:U.source}))]}},KI=($,x,Y,X)=>{let Q=Y,{minimum:z,maximum:Z,format:K,multipleOf:W,exclusiveMaximum:V,exclusiveMinimum:w}=$._zod.bag;if(typeof K==="string"&&K.includes("int"))Q.type="integer";else Q.type="number";let U=typeof w==="number"&&w>=(z??Number.NEGATIVE_INFINITY),H=typeof V==="number"&&V<=(Z??Number.POSITIVE_INFINITY),J=x.target==="draft-04"||x.target==="openapi-3.0";if(U)if(J)Q.minimum=w,Q.exclusiveMinimum=!0;else Q.exclusiveMinimum=w;else if(typeof z==="number")Q.minimum=z;if(H)if(J)Q.maximum=V,Q.exclusiveMaximum=!0;else Q.exclusiveMaximum=V;else if(typeof Z==="number")Q.maximum=Z;if(typeof W==="number")Q.multipleOf=W},WI=($,x,Y,X)=>{Y.type="boolean"},VI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("BigInt cannot be represented in JSON Schema")},wI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Symbols cannot be represented in JSON Schema")},UI=($,x,Y,X)=>{if(x.target==="openapi-3.0")Y.type="string",Y.nullable=!0,Y.enum=[null];else Y.type="null"},HI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Undefined cannot be represented in JSON Schema")},GI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Void cannot be represented in JSON Schema")},JI=($,x,Y,X)=>{Y.not={}},qI=($,x,Y,X)=>{},DI=($,x,Y,X)=>{},BI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Date cannot be represented in JSON Schema")},FI=($,x,Y,X)=>{let Q=$._zod.def,z=qK(Q.entries);if(z.every((Z)=>typeof Z==="number"))Y.type="number";if(z.every((Z)=>typeof Z==="string"))Y.type="string";Y.enum=z},LI=($,x,Y,X)=>{let Q=$._zod.def,z=[];for(let Z of Q.values)if(Z===void 0){if(x.unrepresentable==="throw")throw Error("Literal `undefined` cannot be represented in JSON Schema")}else if(typeof Z==="bigint")if(x.unrepresentable==="throw")throw Error("BigInt literals cannot be represented in JSON Schema");else z.push(Number(Z));else z.push(Z);if(z.length===0);else if(z.length===1){let Z=z[0];if(Y.type=Z===null?"null":typeof Z,x.target==="draft-04"||x.target==="openapi-3.0")Y.enum=[Z];else Y.const=Z}else{if(z.every((Z)=>typeof Z==="number"))Y.type="number";if(z.every((Z)=>typeof Z==="string"))Y.type="string";if(z.every((Z)=>typeof Z==="boolean"))Y.type="boolean";if(z.every((Z)=>Z===null))Y.type="null";Y.enum=z}},NI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("NaN cannot be represented in JSON Schema")},PI=($,x,Y,X)=>{let Q=Y,z=$._zod.pattern;if(!z)throw Error("Pattern not found in template literal");Q.type="string",Q.pattern=z.source},jI=($,x,Y,X)=>{let Q=Y,z={type:"string",format:"binary",contentEncoding:"binary"},{minimum:Z,maximum:K,mime:W}=$._zod.bag;if(Z!==void 0)z.minLength=Z;if(K!==void 0)z.maxLength=K;if(W)if(W.length===1)z.contentMediaType=W[0],Object.assign(Q,z);else Object.assign(Q,z),Q.anyOf=W.map((V)=>({contentMediaType:V}));else Object.assign(Q,z)},II=($,x,Y,X)=>{Y.type="boolean"},vI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Custom types cannot be represented in JSON Schema")},MI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Function types cannot be represented in JSON Schema")},_I=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Transforms cannot be represented in JSON Schema")},OI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Map cannot be represented in JSON Schema")},bI=($,x,Y,X)=>{if(x.unrepresentable==="throw")throw Error("Set cannot be represented in JSON Schema")},RI=($,x,Y,X)=>{let Q=Y,z=$._zod.def,{minimum:Z,maximum:K}=$._zod.bag;if(typeof Z==="number")Q.minItems=Z;if(typeof K==="number")Q.maxItems=K;Q.type="array",Q.items=m0(z.element,x,{...X,path:[...X.path,"items"]})},AI=($,x,Y,X)=>{let Q=Y,z=$._zod.def;Q.type="object",Q.properties={};let Z=z.shape;for(let V in Z)Q.properties[V]=m0(Z[V],x,{...X,path:[...X.path,"properties",V]});let K=new Set(Object.keys(Z)),W=new Set([...K].filter((V)=>{let w=z.shape[V]._zod;if(x.io==="input")return w.optin===void 0;else return w.optout===void 0}));if(W.size>0)Q.required=Array.from(W);if(z.catchall?._zod.def.type==="never")Q.additionalProperties=!1;else if(!z.catchall){if(x.io==="output")Q.additionalProperties=!1}else if(z.catchall)Q.additionalProperties=m0(z.catchall,x,{...X,path:[...X.path,"additionalProperties"]})},ZU=($,x,Y,X)=>{let Q=$._zod.def,z=Q.inclusive===!1,Z=Q.options.map((K,W)=>m0(K,x,{...X,path:[...X.path,z?"oneOf":"anyOf",W]}));if(z)Y.oneOf=Z;else Y.anyOf=Z},fI=($,x,Y,X)=>{let Q=$._zod.def,z=m0(Q.left,x,{...X,path:[...X.path,"allOf",0]}),Z=m0(Q.right,x,{...X,path:[...X.path,"allOf",1]}),K=(V)=>("allOf"in V)&&Object.keys(V).length===1,W=[...K(z)?z.allOf:[z],...K(Z)?Z.allOf:[Z]];Y.allOf=W},kI=($,x,Y,X)=>{let Q=Y,z=$._zod.def;Q.type="array";let Z=x.target==="draft-2020-12"?"prefixItems":"items",K=x.target==="draft-2020-12"?"items":x.target==="openapi-3.0"?"items":"additionalItems",W=z.items.map((H,J)=>m0(H,x,{...X,path:[...X.path,Z,J]})),V=z.rest?m0(z.rest,x,{...X,path:[...X.path,K,...x.target==="openapi-3.0"?[z.items.length]:[]]}):null;if(x.target==="draft-2020-12"){if(Q.prefixItems=W,V)Q.items=V}else if(x.target==="openapi-3.0"){if(Q.items={anyOf:W},V)Q.items.anyOf.push(V);if(Q.minItems=W.length,!V)Q.maxItems=W.length}else if(Q.items=W,V)Q.additionalItems=V;let{minimum:w,maximum:U}=$._zod.bag;if(typeof w==="number")Q.minItems=w;if(typeof U==="number")Q.maxItems=U},TI=($,x,Y,X)=>{let Q=Y,z=$._zod.def;Q.type="object";let Z=z.keyType,W=Z._zod.bag?.patterns;if(z.mode==="loose"&&W&&W.size>0){let w=m0(z.valueType,x,{...X,path:[...X.path,"patternProperties","*"]});Q.patternProperties={};for(let U of W)Q.patternProperties[U.source]=w}else{if(x.target==="draft-07"||x.target==="draft-2020-12")Q.propertyNames=m0(z.keyType,x,{...X,path:[...X.path,"propertyNames"]});Q.additionalProperties=m0(z.valueType,x,{...X,path:[...X.path,"additionalProperties"]})}let V=Z._zod.values;if(V){let w=[...V].filter((U)=>typeof U==="string"||typeof U==="number");if(w.length>0)Q.required=w}},cI=($,x,Y,X)=>{let Q=$._zod.def,z=m0(Q.innerType,x,X),Z=x.seen.get($);if(x.target==="openapi-3.0")Z.ref=Q.innerType,Y.nullable=!0;else Y.anyOf=[z,{type:"null"}]},SI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType},EI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType,Y.default=JSON.parse(JSON.stringify(Q.defaultValue))},CI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);if(z.ref=Q.innerType,x.io==="input")Y._prefault=JSON.parse(JSON.stringify(Q.defaultValue))},uI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType;let Z;try{Z=Q.catchValue(void 0)}catch{throw Error("Dynamic catch values are not supported in JSON Schema")}Y.default=Z},yI=($,x,Y,X)=>{let Q=$._zod.def,z=Q.in._zod.traits.has("$ZodTransform"),Z=x.io==="input"?z?Q.out:Q.in:Q.out;m0(Z,x,X);let K=x.seen.get($);K.ref=Z},mI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType,Y.readOnly=!0},hI=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType},KU=($,x,Y,X)=>{let Q=$._zod.def;m0(Q.innerType,x,X);let z=x.seen.get($);z.ref=Q.innerType},gI=($,x,Y,X)=>{let Q=$._zod.innerType;m0(Q,x,X);let z=x.seen.get($);z.ref=Q},zU={string:ZI,number:KI,boolean:WI,bigint:VI,symbol:wI,null:UI,undefined:HI,void:GI,never:JI,any:qI,unknown:DI,date:BI,enum:FI,literal:LI,nan:NI,template_literal:PI,file:jI,success:II,custom:vI,function:MI,transform:_I,map:OI,set:bI,array:RI,object:AI,union:ZU,intersection:fI,tuple:kI,record:TI,nullable:cI,nonoptional:SI,default:EI,prefault:CI,catch:uI,pipe:yI,readonly:mI,promise:hI,optional:KU,lazy:gI};function WU($,x){if("_idmap"in $){let X=$,Q=Vx({...x,processors:zU}),z={};for(let W of X._idmap.entries()){let[V,w]=W;m0(w,Q)}let Z={},K={registry:X,uri:x?.uri,defs:z};Q.external=K;for(let W of X._idmap.entries()){let[V,w]=W;wx(Q,w),Z[V]=Ux(Q,w)}if(Object.keys(z).length>0){let W=Q.target==="draft-2020-12"?"$defs":"definitions";Z.__shared={[W]:z}}return{schemas:Z}}let Y=Vx({...x,processors:zU});return m0($,Y),wx(Y,$),Ux(Y,$)}class pI{get metadataRegistry(){return this.ctx.metadataRegistry}get target(){return this.ctx.target}get unrepresentable(){return this.ctx.unrepresentable}get override(){return this.ctx.override}get io(){return this.ctx.io}get counter(){return this.ctx.counter}set counter($){this.ctx.counter=$}get seen(){return this.ctx.seen}constructor($){let x=$?.target??"draft-2020-12";if(x==="draft-4")x="draft-04";if(x==="draft-7")x="draft-07";this.ctx=Vx({processors:zU,target:x,...$?.metadata&&{metadata:$.metadata},...$?.unrepresentable&&{unrepresentable:$.unrepresentable},...$?.override&&{override:$.override},...$?.io&&{io:$.io}})}process($,x={path:[],schemaPath:[]}){return m0($,this.ctx,x)}emit($,x){if(x){if(x.cycles)this.ctx.cycles=x.cycles;if(x.reused)this.ctx.reused=x.reused;if(x.external)this.ctx.external=x.external}wx(this.ctx,$);let Y=Ux(this.ctx,$),{"~standard":X,...Q}=Y;return Q}}var ey={};var EK={};V2(EK,{xor:()=>nm,xid:()=>qm,void:()=>mm,uuidv7:()=>Km,uuidv6:()=>Zm,uuidv4:()=>zm,uuid:()=>Xm,url:()=>Wm,unknown:()=>RY,union:()=>SU,undefined:()=>um,ulid:()=>Jm,uint64:()=>Em,uint32:()=>Tm,tuple:()=>Iv,transform:()=>CU,templateLiteral:()=>Zh,symbol:()=>Cm,superRefine:()=>rv,success:()=>Yh,stringbool:()=>Jh,stringFormat:()=>_m,string:()=>CK,strictObject:()=>im,set:()=>rm,refine:()=>ov,record:()=>vv,readonly:()=>iv,promise:()=>Kh,preprocess:()=>Dh,prefault:()=>Ev,pipe:()=>qU,partialRecord:()=>am,optional:()=>yK,object:()=>pm,number:()=>Kv,nullish:()=>xh,nullable:()=>mK,null:()=>Hv,nonoptional:()=>Cv,never:()=>cU,nativeEnum:()=>tm,nanoid:()=>Um,nan:()=>Qh,meta:()=>Hh,map:()=>om,mac:()=>Fm,looseRecord:()=>sm,looseObject:()=>lm,literal:()=>em,lazy:()=>dv,ksuid:()=>Dm,keyof:()=>gm,jwt:()=>Mm,json:()=>qh,ipv6:()=>Lm,ipv4:()=>Bm,invertCodec:()=>zh,intersection:()=>Pv,int64:()=>Sm,int32:()=>km,int:()=>JU,instanceof:()=>Gh,httpUrl:()=>Vm,hostname:()=>Om,hex:()=>bm,hash:()=>Rm,guid:()=>Qm,function:()=>Wh,float64:()=>fm,float32:()=>Am,file:()=>$h,exactOptional:()=>fv,enum:()=>EU,emoji:()=>wm,email:()=>Ym,e164:()=>vm,discriminatedUnion:()=>dm,describe:()=>Uh,date:()=>hm,custom:()=>wh,cuid2:()=>Gm,cuid:()=>Hm,codec:()=>Xh,cidrv6:()=>Pm,cidrv4:()=>Nm,check:()=>Vh,catch:()=>mv,boolean:()=>Wv,bigint:()=>cm,base64url:()=>Im,base64:()=>jm,array:()=>iK,any:()=>ym,_function:()=>Wh,_default:()=>cv,_ZodString:()=>DU,ZodXor:()=>Fv,ZodXID:()=>IU,ZodVoid:()=>Dv,ZodUnknown:()=>Jv,ZodUnion:()=>nK,ZodUndefined:()=>wv,ZodUUID:()=>I7,ZodURL:()=>gK,ZodULID:()=>jU,ZodType:()=>w0,ZodTuple:()=>jv,ZodTransform:()=>Rv,ZodTemplateLiteral:()=>lv,ZodSymbol:()=>Vv,ZodSuccess:()=>uv,ZodStringFormat:()=>p0,ZodString:()=>iX,ZodSet:()=>_v,ZodRecord:()=>gX,ZodReadonly:()=>pv,ZodPromise:()=>av,ZodPreprocess:()=>gv,ZodPrefault:()=>Sv,ZodPipe:()=>dK,ZodOptional:()=>uU,ZodObject:()=>lK,ZodNumberFormat:()=>AY,ZodNumber:()=>nX,ZodNullable:()=>kv,ZodNull:()=>Uv,ZodNonOptional:()=>yU,ZodNever:()=>qv,ZodNanoID:()=>LU,ZodNaN:()=>hv,ZodMap:()=>Mv,ZodMAC:()=>Zv,ZodLiteral:()=>Ov,ZodLazy:()=>nv,ZodKSUID:()=>vU,ZodJWT:()=>kU,ZodIntersection:()=>Nv,ZodIPv6:()=>_U,ZodIPv4:()=>MU,ZodGUID:()=>uK,ZodFunction:()=>sv,ZodFile:()=>bv,ZodExactOptional:()=>Av,ZodEnum:()=>pX,ZodEmoji:()=>FU,ZodEmail:()=>BU,ZodE164:()=>fU,ZodDiscriminatedUnion:()=>Lv,ZodDefault:()=>Tv,ZodDate:()=>pK,ZodCustomStringFormat:()=>lX,ZodCustom:()=>sK,ZodCodec:()=>aK,ZodCatch:()=>yv,ZodCUID2:()=>PU,ZodCUID:()=>NU,ZodCIDRv6:()=>bU,ZodCIDRv4:()=>OU,ZodBoolean:()=>dX,ZodBigIntFormat:()=>TU,ZodBigInt:()=>aX,ZodBase64URL:()=>AU,ZodBase64:()=>RU,ZodArray:()=>Bv,ZodAny:()=>Gv});var VU={};V2(VU,{uppercase:()=>RX,trim:()=>SX,toUpperCase:()=>CX,toLowerCase:()=>EX,startsWith:()=>fX,slugify:()=>uX,size:()=>_Y,regex:()=>OX,property:()=>XU,positive:()=>$U,overwrite:()=>d9,normalize:()=>cX,nonpositive:()=>YU,nonnegative:()=>QU,negative:()=>xU,multipleOf:()=>Kx,minSize:()=>j7,minLength:()=>U2,mime:()=>TX,maxSize:()=>Wx,maxLength:()=>OY,lte:()=>Q9,lt:()=>N7,lowercase:()=>bX,length:()=>bY,includes:()=>AX,gte:()=>W$,gt:()=>P7,endsWith:()=>kX});var hX={};V2(hX,{time:()=>nI,duration:()=>dI,datetime:()=>iI,date:()=>lI,ZodISOTime:()=>HU,ZodISODuration:()=>GU,ZodISODateTime:()=>wU,ZodISODate:()=>UU});var wU=u("ZodISODateTime",($,x)=>{vN.init($,x),p0.init($,x)});function iI($){return vj(wU,$)}var UU=u("ZodISODate",($,x)=>{MN.init($,x),p0.init($,x)});function lI($){return Mj(UU,$)}var HU=u("ZodISOTime",($,x)=>{_N.init($,x),p0.init($,x)});function nI($){return _j(HU,$)}var GU=u("ZodISODuration",($,x)=>{ON.init($,x),p0.init($,x)});function dI($){return Oj(GU,$)}var $m=($,x)=>{NK.init($,x),$.name="ZodError",Object.defineProperties($,{format:{value:(Y)=>jK($,Y)},flatten:{value:(Y)=>PK($,Y)},addIssue:{value:(Y)=>{$.issues.push(Y),$.message=JSON.stringify($.issues,FX,2)}},addIssues:{value:(Y)=>{$.issues.push(...Y),$.message=JSON.stringify($.issues,FX,2)}},isEmpty:{get(){return $.issues.length===0}}})},fm1=u("ZodError",$m),c$=u("ZodError",$m,{Parent:Error});var aI=PX(c$),sI=jX(c$),oI=IX(c$),rI=vX(c$),tI=Hw(c$),eI=Gw(c$),$v=Jw(c$),xv=qw(c$),Yv=Dw(c$),Qv=Bw(c$),Xv=Fw(c$),zv=Lw(c$);var xm=new WeakMap;function hK($,x,Y){let X=Object.getPrototypeOf($),Q=xm.get(X);if(!Q)Q=new Set,xm.set(X,Q);if(Q.has(x))return;Q.add(x);for(let z in Y){let Z=Y[z];Object.defineProperty(X,z,{configurable:!0,enumerable:!1,get(){let K=Z.bind(this);return Object.defineProperty(this,z,{configurable:!0,writable:!0,enumerable:!0,value:K}),K},set(K){Object.defineProperty(this,z,{configurable:!0,writable:!0,enumerable:!0,value:K})}})}}var w0=u("ZodType",($,x)=>{return Q0.init($,x),Object.assign($["~standard"],{jsonSchema:{input:mX($,"input"),output:mX($,"output")}}),$.toJSONSchema=zI($,{}),$.def=x,$.type=x.type,Object.defineProperty($,"_def",{value:x}),$.parse=(Y,X)=>aI($,Y,X,{callee:$.parse}),$.safeParse=(Y,X)=>oI($,Y,X),$.parseAsync=async(Y,X)=>sI($,Y,X,{callee:$.parseAsync}),$.safeParseAsync=async(Y,X)=>rI($,Y,X),$.spa=$.safeParseAsync,$.encode=(Y,X)=>tI($,Y,X),$.decode=(Y,X)=>eI($,Y,X),$.encodeAsync=async(Y,X)=>$v($,Y,X),$.decodeAsync=async(Y,X)=>xv($,Y,X),$.safeEncode=(Y,X)=>Yv($,Y,X),$.safeDecode=(Y,X)=>Qv($,Y,X),$.safeEncodeAsync=async(Y,X)=>Xv($,Y,X),$.safeDecodeAsync=async(Y,X)=>zv($,Y,X),hK($,"ZodType",{check(...Y){let X=this.def;return this.clone(U1.mergeDefs(X,{checks:[...X.checks??[],...Y.map((Q)=>typeof Q==="function"?{_zod:{check:Q,def:{check:"custom"},onattach:[]}}:Q)]}),{parent:!0})},with(...Y){return this.check(...Y)},clone(Y,X){return Z$(this,Y,X)},brand(){return this},register(Y,X){return Y.add(this,X),this},refine(Y,X){return this.check(ov(Y,X))},superRefine(Y,X){return this.check(rv(Y,X))},overwrite(Y){return this.check(d9(Y))},optional(){return yK(this)},exactOptional(){return fv(this)},nullable(){return mK(this)},nullish(){return yK(mK(this))},nonoptional(Y){return Cv(this,Y)},array(){return iK(this)},or(Y){return SU([this,Y])},and(Y){return Pv(this,Y)},transform(Y){return qU(this,CU(Y))},default(Y){return cv(this,Y)},prefault(Y){return Ev(this,Y)},catch(Y){return mv(this,Y)},pipe(Y){return qU(this,Y)},readonly(){return iv(this)},describe(Y){let X=this.clone();return _8.add(X,{description:Y}),X},meta(...Y){if(Y.length===0)return _8.get(this);let X=this.clone();return _8.add(X,Y[0]),X},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(Y){return Y(this)}}),Object.defineProperty($,"description",{get(){return _8.get($)?.description},configurable:!0}),$}),DU=u("_ZodString",($,x)=>{MY.init($,x),w0.init($,x),$._zod.processJSONSchema=(X,Q,z)=>ZI($,X,Q,z);let Y=$._zod.bag;$.format=Y.format??null,$.minLength=Y.minimum??null,$.maxLength=Y.maximum??null,hK($,"_ZodString",{regex(...X){return this.check(OX(...X))},includes(...X){return this.check(AX(...X))},startsWith(...X){return this.check(fX(...X))},endsWith(...X){return this.check(kX(...X))},min(...X){return this.check(U2(...X))},max(...X){return this.check(OY(...X))},length(...X){return this.check(bY(...X))},nonempty(...X){return this.check(U2(1,...X))},lowercase(X){return this.check(bX(X))},uppercase(X){return this.check(RX(X))},trim(){return this.check(SX())},normalize(...X){return this.check(cX(...X))},toLowerCase(){return this.check(EX())},toUpperCase(){return this.check(CX())},slugify(){return this.check(uX())}})}),iX=u("ZodString",($,x)=>{MY.init($,x),DU.init($,x),$.email=(Y)=>$.check(cw(BU,Y)),$.url=(Y)=>$.check(SK(gK,Y)),$.jwt=(Y)=>$.check(ew(kU,Y)),$.emoji=(Y)=>$.check(yw(FU,Y)),$.guid=(Y)=>$.check(cK(uK,Y)),$.uuid=(Y)=>$.check(Sw(I7,Y)),$.uuidv4=(Y)=>$.check(Ew(I7,Y)),$.uuidv6=(Y)=>$.check(Cw(I7,Y)),$.uuidv7=(Y)=>$.check(uw(I7,Y)),$.nanoid=(Y)=>$.check(mw(LU,Y)),$.guid=(Y)=>$.check(cK(uK,Y)),$.cuid=(Y)=>$.check(hw(NU,Y)),$.cuid2=(Y)=>$.check(gw(PU,Y)),$.ulid=(Y)=>$.check(pw(jU,Y)),$.base64=(Y)=>$.check(ow(RU,Y)),$.base64url=(Y)=>$.check(rw(AU,Y)),$.xid=(Y)=>$.check(iw(IU,Y)),$.ksuid=(Y)=>$.check(lw(vU,Y)),$.ipv4=(Y)=>$.check(nw(MU,Y)),$.ipv6=(Y)=>$.check(dw(_U,Y)),$.cidrv4=(Y)=>$.check(aw(OU,Y)),$.cidrv6=(Y)=>$.check(sw(bU,Y)),$.e164=(Y)=>$.check(tw(fU,Y)),$.datetime=(Y)=>$.check(iI(Y)),$.date=(Y)=>$.check(lI(Y)),$.time=(Y)=>$.check(nI(Y)),$.duration=(Y)=>$.check(dI(Y))});function CK($){return Nj(iX,$)}var p0=u("ZodStringFormat",($,x)=>{g0.init($,x),DU.init($,x)}),BU=u("ZodEmail",($,x)=>{qN.init($,x),p0.init($,x)});function Ym($){return cw(BU,$)}var uK=u("ZodGUID",($,x)=>{GN.init($,x),p0.init($,x)});function Qm($){return cK(uK,$)}var I7=u("ZodUUID",($,x)=>{JN.init($,x),p0.init($,x)});function Xm($){return Sw(I7,$)}function zm($){return Ew(I7,$)}function Zm($){return Cw(I7,$)}function Km($){return uw(I7,$)}var gK=u("ZodURL",($,x)=>{DN.init($,x),p0.init($,x)});function Wm($){return SK(gK,$)}function Vm($){return SK(gK,{protocol:Y9.httpProtocol,hostname:Y9.domain,...U1.normalizeParams($)})}var FU=u("ZodEmoji",($,x)=>{BN.init($,x),p0.init($,x)});function wm($){return yw(FU,$)}var LU=u("ZodNanoID",($,x)=>{FN.init($,x),p0.init($,x)});function Um($){return mw(LU,$)}var NU=u("ZodCUID",($,x)=>{LN.init($,x),p0.init($,x)});function Hm($){return hw(NU,$)}var PU=u("ZodCUID2",($,x)=>{NN.init($,x),p0.init($,x)});function Gm($){return gw(PU,$)}var jU=u("ZodULID",($,x)=>{PN.init($,x),p0.init($,x)});function Jm($){return pw(jU,$)}var IU=u("ZodXID",($,x)=>{jN.init($,x),p0.init($,x)});function qm($){return iw(IU,$)}var vU=u("ZodKSUID",($,x)=>{IN.init($,x),p0.init($,x)});function Dm($){return lw(vU,$)}var MU=u("ZodIPv4",($,x)=>{bN.init($,x),p0.init($,x)});function Bm($){return nw(MU,$)}var Zv=u("ZodMAC",($,x)=>{AN.init($,x),p0.init($,x)});function Fm($){return jj(Zv,$)}var _U=u("ZodIPv6",($,x)=>{RN.init($,x),p0.init($,x)});function Lm($){return dw(_U,$)}var OU=u("ZodCIDRv4",($,x)=>{fN.init($,x),p0.init($,x)});function Nm($){return aw(OU,$)}var bU=u("ZodCIDRv6",($,x)=>{kN.init($,x),p0.init($,x)});function Pm($){return sw(bU,$)}var RU=u("ZodBase64",($,x)=>{cN.init($,x),p0.init($,x)});function jm($){return ow(RU,$)}var AU=u("ZodBase64URL",($,x)=>{SN.init($,x),p0.init($,x)});function Im($){return rw(AU,$)}var fU=u("ZodE164",($,x)=>{EN.init($,x),p0.init($,x)});function vm($){return tw(fU,$)}var kU=u("ZodJWT",($,x)=>{CN.init($,x),p0.init($,x)});function Mm($){return ew(kU,$)}var lX=u("ZodCustomStringFormat",($,x)=>{uN.init($,x),p0.init($,x)});function _m($,x,Y={}){return yX(lX,$,x,Y)}function Om($){return yX(lX,"hostname",Y9.hostname,$)}function bm($){return yX(lX,"hex",Y9.hex,$)}function Rm($,x){let Y=x?.enc??"hex",X=`${$}_${Y}`,Q=Y9[X];if(!Q)throw Error(`Unrecognized hash format: ${X}`);return yX(lX,X,Q,x)}var nX=u("ZodNumber",($,x)=>{bw.init($,x),w0.init($,x),$._zod.processJSONSchema=(X,Q,z)=>KI($,X,Q,z),hK($,"ZodNumber",{gt(X,Q){return this.check(P7(X,Q))},gte(X,Q){return this.check(W$(X,Q))},min(X,Q){return this.check(W$(X,Q))},lt(X,Q){return this.check(N7(X,Q))},lte(X,Q){return this.check(Q9(X,Q))},max(X,Q){return this.check(Q9(X,Q))},int(X){return this.check(JU(X))},safe(X){return this.check(JU(X))},positive(X){return this.check(P7(0,X))},nonnegative(X){return this.check(W$(0,X))},negative(X){return this.check(N7(0,X))},nonpositive(X){return this.check(Q9(0,X))},multipleOf(X,Q){return this.check(Kx(X,Q))},step(X,Q){return this.check(Kx(X,Q))},finite(){return this}});let Y=$._zod.bag;$.minValue=Math.max(Y.minimum??Number.NEGATIVE_INFINITY,Y.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,$.maxValue=Math.min(Y.maximum??Number.POSITIVE_INFINITY,Y.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,$.isInt=(Y.format??"").includes("int")||Number.isSafeInteger(Y.multipleOf??0.5),$.isFinite=!0,$.format=Y.format??null});function Kv($){return bj(nX,$)}var AY=u("ZodNumberFormat",($,x)=>{yN.init($,x),nX.init($,x)});function JU($){return Aj(AY,$)}function Am($){return fj(AY,$)}function fm($){return kj(AY,$)}function km($){return Tj(AY,$)}function Tm($){return cj(AY,$)}var dX=u("ZodBoolean",($,x)=>{_K.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>WI($,Y,X,Q)});function Wv($){return Sj(dX,$)}var aX=u("ZodBigInt",($,x)=>{Rw.init($,x),w0.init($,x),$._zod.processJSONSchema=(X,Q,z)=>VI($,X,Q,z),$.gte=(X,Q)=>$.check(W$(X,Q)),$.min=(X,Q)=>$.check(W$(X,Q)),$.gt=(X,Q)=>$.check(P7(X,Q)),$.gte=(X,Q)=>$.check(W$(X,Q)),$.min=(X,Q)=>$.check(W$(X,Q)),$.lt=(X,Q)=>$.check(N7(X,Q)),$.lte=(X,Q)=>$.check(Q9(X,Q)),$.max=(X,Q)=>$.check(Q9(X,Q)),$.positive=(X)=>$.check(P7(BigInt(0),X)),$.negative=(X)=>$.check(N7(BigInt(0),X)),$.nonpositive=(X)=>$.check(Q9(BigInt(0),X)),$.nonnegative=(X)=>$.check(W$(BigInt(0),X)),$.multipleOf=(X,Q)=>$.check(Kx(X,Q));let Y=$._zod.bag;$.minValue=Y.minimum??null,$.maxValue=Y.maximum??null,$.format=Y.format??null});function cm($){return Cj(aX,$)}var TU=u("ZodBigIntFormat",($,x)=>{mN.init($,x),aX.init($,x)});function Sm($){return yj(TU,$)}function Em($){return mj(TU,$)}var Vv=u("ZodSymbol",($,x)=>{hN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>wI($,Y,X,Q)});function Cm($){return hj(Vv,$)}var wv=u("ZodUndefined",($,x)=>{gN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>HI($,Y,X,Q)});function um($){return gj(wv,$)}var Uv=u("ZodNull",($,x)=>{pN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>UI($,Y,X,Q)});function Hv($){return pj(Uv,$)}var Gv=u("ZodAny",($,x)=>{iN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>qI($,Y,X,Q)});function ym(){return ij(Gv)}var Jv=u("ZodUnknown",($,x)=>{lN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>DI($,Y,X,Q)});function RY(){return lj(Jv)}var qv=u("ZodNever",($,x)=>{nN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>JI($,Y,X,Q)});function cU($){return nj(qv,$)}var Dv=u("ZodVoid",($,x)=>{dN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>GI($,Y,X,Q)});function mm($){return dj(Dv,$)}var pK=u("ZodDate",($,x)=>{aN.init($,x),w0.init($,x),$._zod.processJSONSchema=(X,Q,z)=>BI($,X,Q,z),$.min=(X,Q)=>$.check(W$(X,Q)),$.max=(X,Q)=>$.check(Q9(X,Q));let Y=$._zod.bag;$.minDate=Y.minimum?new Date(Y.minimum):null,$.maxDate=Y.maximum?new Date(Y.maximum):null});function hm($){return aj(pK,$)}var Bv=u("ZodArray",($,x)=>{sN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>RI($,Y,X,Q),$.element=x.element,hK($,"ZodArray",{min(Y,X){return this.check(U2(Y,X))},nonempty(Y){return this.check(U2(1,Y))},max(Y,X){return this.check(OY(Y,X))},length(Y,X){return this.check(bY(Y,X))},unwrap(){return this.element}})});function iK($,x){return rj(Bv,$,x)}function gm($){let x=$._zod.def.shape;return EU(Object.keys(x))}var lK=u("ZodObject",($,x)=>{oN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>AI($,Y,X,Q),U1.defineLazy($,"shape",()=>{return x.shape}),hK($,"ZodObject",{keyof(){return EU(Object.keys(this._zod.def.shape))},catchall(Y){return this.clone({...this._zod.def,catchall:Y})},passthrough(){return this.clone({...this._zod.def,catchall:RY()})},loose(){return this.clone({...this._zod.def,catchall:RY()})},strict(){return this.clone({...this._zod.def,catchall:cU()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(Y){return U1.extend(this,Y)},safeExtend(Y){return U1.safeExtend(this,Y)},merge(Y){return U1.merge(this,Y)},pick(Y){return U1.pick(this,Y)},omit(Y){return U1.omit(this,Y)},partial(...Y){return U1.partial(uU,this,Y[0])},required(...Y){return U1.required(yU,this,Y[0])}})});function pm($,x){let Y={type:"object",shape:$??{},...U1.normalizeParams(x)};return new lK(Y)}function im($,x){return new lK({type:"object",shape:$,catchall:cU(),...U1.normalizeParams(x)})}function lm($,x){return new lK({type:"object",shape:$,catchall:RY(),...U1.normalizeParams(x)})}var nK=u("ZodUnion",($,x)=>{OK.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>ZU($,Y,X,Q),$.options=x.options});function SU($,x){return new nK({type:"union",options:$,...U1.normalizeParams(x)})}var Fv=u("ZodXor",($,x)=>{nK.init($,x),rN.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>ZU($,Y,X,Q),$.options=x.options});function nm($,x){return new Fv({type:"union",options:$,inclusive:!1,...U1.normalizeParams(x)})}var Lv=u("ZodDiscriminatedUnion",($,x)=>{nK.init($,x),tN.init($,x)});function dm($,x,Y){return new Lv({type:"union",options:x,discriminator:$,...U1.normalizeParams(Y)})}var Nv=u("ZodIntersection",($,x)=>{eN.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>fI($,Y,X,Q)});function Pv($,x){return new Nv({type:"intersection",left:$,right:x})}var jv=u("ZodTuple",($,x)=>{Aw.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>kI($,Y,X,Q),$.rest=(Y)=>$.clone({...$._zod.def,rest:Y})});function Iv($,x,Y){let X=x instanceof Q0,Q=X?Y:x;return new jv({type:"tuple",items:$,rest:X?x:null,...U1.normalizeParams(Q)})}var gX=u("ZodRecord",($,x)=>{$P.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>TI($,Y,X,Q),$.keyType=x.keyType,$.valueType=x.valueType});function vv($,x,Y){if(!x||!x._zod)return new gX({type:"record",keyType:CK(),valueType:$,...U1.normalizeParams(x)});return new gX({type:"record",keyType:$,valueType:x,...U1.normalizeParams(Y)})}function am($,x,Y){let X=Z$($);return X._zod.values=void 0,new gX({type:"record",keyType:X,valueType:x,...U1.normalizeParams(Y)})}function sm($,x,Y){return new gX({type:"record",keyType:$,valueType:x,mode:"loose",...U1.normalizeParams(Y)})}var Mv=u("ZodMap",($,x)=>{xP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>OI($,Y,X,Q),$.keyType=x.keyType,$.valueType=x.valueType,$.min=(...Y)=>$.check(j7(...Y)),$.nonempty=(Y)=>$.check(j7(1,Y)),$.max=(...Y)=>$.check(Wx(...Y)),$.size=(...Y)=>$.check(_Y(...Y))});function om($,x,Y){return new Mv({type:"map",keyType:$,valueType:x,...U1.normalizeParams(Y)})}var _v=u("ZodSet",($,x)=>{YP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>bI($,Y,X,Q),$.min=(...Y)=>$.check(j7(...Y)),$.nonempty=(Y)=>$.check(j7(1,Y)),$.max=(...Y)=>$.check(Wx(...Y)),$.size=(...Y)=>$.check(_Y(...Y))});function rm($,x){return new _v({type:"set",valueType:$,...U1.normalizeParams(x)})}var pX=u("ZodEnum",($,x)=>{QP.init($,x),w0.init($,x),$._zod.processJSONSchema=(X,Q,z)=>FI($,X,Q,z),$.enum=x.entries,$.options=Object.values(x.entries);let Y=new Set(Object.keys(x.entries));$.extract=(X,Q)=>{let z={};for(let Z of X)if(Y.has(Z))z[Z]=x.entries[Z];else throw Error(`Key ${Z} not found in enum`);return new pX({...x,checks:[],...U1.normalizeParams(Q),entries:z})},$.exclude=(X,Q)=>{let z={...x.entries};for(let Z of X)if(Y.has(Z))delete z[Z];else throw Error(`Key ${Z} not found in enum`);return new pX({...x,checks:[],...U1.normalizeParams(Q),entries:z})}});function EU($,x){let Y=Array.isArray($)?Object.fromEntries($.map((X)=>[X,X])):$;return new pX({type:"enum",entries:Y,...U1.normalizeParams(x)})}function tm($,x){return new pX({type:"enum",entries:$,...U1.normalizeParams(x)})}var Ov=u("ZodLiteral",($,x)=>{XP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>LI($,Y,X,Q),$.values=new Set(x.values),Object.defineProperty($,"value",{get(){if(x.values.length>1)throw Error("This schema contains multiple valid literal values. Use `.values` instead.");return x.values[0]}})});function em($,x){return new Ov({type:"literal",values:Array.isArray($)?$:[$],...U1.normalizeParams(x)})}var bv=u("ZodFile",($,x)=>{zP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>jI($,Y,X,Q),$.min=(Y,X)=>$.check(j7(Y,X)),$.max=(Y,X)=>$.check(Wx(Y,X)),$.mime=(Y,X)=>$.check(TX(Array.isArray(Y)?Y:[Y],X))});function $h($){return tj(bv,$)}var Rv=u("ZodTransform",($,x)=>{ZP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>_I($,Y,X,Q),$._zod.parse=(Y,X)=>{if(X.direction==="backward")throw new jY($.constructor.name);Y.addIssue=(z)=>{if(typeof z==="string")Y.issues.push(U1.issue(z,Y.value,x));else{let Z=z;if(Z.fatal)Z.continue=!1;Z.code??(Z.code="custom"),Z.input??(Z.input=Y.value),Z.inst??(Z.inst=$),Y.issues.push(U1.issue(Z))}};let Q=x.transform(Y.value,Y);if(Q instanceof Promise)return Q.then((z)=>{return Y.value=z,Y.fallback=!0,Y});return Y.value=Q,Y.fallback=!0,Y}});function CU($){return new Rv({type:"transform",transform:$})}var uU=u("ZodOptional",($,x)=>{fw.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>KU($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function yK($){return new uU({type:"optional",innerType:$})}var Av=u("ZodExactOptional",($,x)=>{KP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>KU($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function fv($){return new Av({type:"optional",innerType:$})}var kv=u("ZodNullable",($,x)=>{WP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>cI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function mK($){return new kv({type:"nullable",innerType:$})}function xh($){return yK(mK($))}var Tv=u("ZodDefault",($,x)=>{VP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>EI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType,$.removeDefault=$.unwrap});function cv($,x){return new Tv({type:"default",innerType:$,get defaultValue(){return typeof x==="function"?x():U1.shallowClone(x)}})}var Sv=u("ZodPrefault",($,x)=>{wP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>CI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function Ev($,x){return new Sv({type:"prefault",innerType:$,get defaultValue(){return typeof x==="function"?x():U1.shallowClone(x)}})}var yU=u("ZodNonOptional",($,x)=>{UP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>SI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function Cv($,x){return new yU({type:"nonoptional",innerType:$,...U1.normalizeParams(x)})}var uv=u("ZodSuccess",($,x)=>{HP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>II($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function Yh($){return new uv({type:"success",innerType:$})}var yv=u("ZodCatch",($,x)=>{GP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>uI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType,$.removeCatch=$.unwrap});function mv($,x){return new yv({type:"catch",innerType:$,catchValue:typeof x==="function"?x:()=>x})}var hv=u("ZodNaN",($,x)=>{JP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>NI($,Y,X,Q)});function Qh($){return oj(hv,$)}var dK=u("ZodPipe",($,x)=>{kw.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>yI($,Y,X,Q),$.in=x.in,$.out=x.out});function qU($,x){return new dK({type:"pipe",in:$,out:x})}var aK=u("ZodCodec",($,x)=>{dK.init($,x),bK.init($,x)});function Xh($,x,Y){return new aK({type:"pipe",in:$,out:x,transform:Y.decode,reverseTransform:Y.encode})}function zh($){let x=$._zod.def;return new aK({type:"pipe",in:x.out,out:x.in,transform:x.reverseTransform,reverseTransform:x.transform})}var gv=u("ZodPreprocess",($,x)=>{dK.init($,x),qP.init($,x)}),pv=u("ZodReadonly",($,x)=>{DP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>mI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function iv($){return new pv({type:"readonly",innerType:$})}var lv=u("ZodTemplateLiteral",($,x)=>{BP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>PI($,Y,X,Q)});function Zh($,x){return new lv({type:"template_literal",parts:$,...U1.normalizeParams(x)})}var nv=u("ZodLazy",($,x)=>{NP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>gI($,Y,X,Q),$.unwrap=()=>$._zod.def.getter()});function dv($){return new nv({type:"lazy",getter:$})}var av=u("ZodPromise",($,x)=>{LP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>hI($,Y,X,Q),$.unwrap=()=>$._zod.def.innerType});function Kh($){return new av({type:"promise",innerType:$})}var sv=u("ZodFunction",($,x)=>{FP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>MI($,Y,X,Q)});function Wh($){return new sv({type:"function",input:Array.isArray($?.input)?Iv($?.input):$?.input??iK(RY()),output:$?.output??RY()})}var sK=u("ZodCustom",($,x)=>{PP.init($,x),w0.init($,x),$._zod.processJSONSchema=(Y,X,Q)=>vI($,Y,X,Q)});function Vh($){let x=new s0({check:"custom"});return x._zod.check=$,x}function wh($,x){return ej(sK,$??(()=>!0),x)}function ov($,x={}){return $I(sK,$,x)}function rv($,x){return xI($,x)}var Uh=YI,Hh=QI;function Gh($,x={}){let Y=new sK({type:"custom",check:"custom",fn:(X)=>X instanceof $,abort:!0,...U1.normalizeParams(x)});return Y._zod.bag.Class=$,Y._zod.check=(X)=>{if(!(X.value instanceof $))X.issues.push({code:"invalid_type",expected:$.name,input:X.value,inst:Y,path:[...Y._zod.def.path??[]]})},Y}var Jh=(...$)=>XI({Codec:aK,Boolean:dX,String:iX},...$);function qh($){let x=dv(()=>{return SU([CK($),Kv(),Wv(),Hv(),iK(x),vv(CK(),x)])});return x}function Dh($,x){return new gv({type:"pipe",in:CU($),out:x})}var Tm1={invalid_type:"invalid_type",too_big:"too_big",too_small:"too_small",invalid_format:"invalid_format",not_multiple_of:"not_multiple_of",unrecognized_keys:"unrecognized_keys",invalid_union:"invalid_union",invalid_key:"invalid_key",invalid_element:"invalid_element",invalid_value:"invalid_value",custom:"custom"};function cm1($){A6({customError:$})}function Sm1(){return A6().customError}var tv;(function($){})(tv||(tv={}));var b1={...EK,...VU,iso:hX},Em1=new Set(["$schema","$ref","$defs","definitions","$id","id","$comment","$anchor","$vocabulary","$dynamicRef","$dynamicAnchor","type","enum","const","anyOf","oneOf","allOf","not","properties","required","additionalProperties","patternProperties","propertyNames","minProperties","maxProperties","items","prefixItems","additionalItems","minItems","maxItems","uniqueItems","contains","minContains","maxContains","minLength","maxLength","pattern","format","minimum","maximum","exclusiveMinimum","exclusiveMaximum","multipleOf","description","default","contentEncoding","contentMediaType","contentSchema","unevaluatedItems","unevaluatedProperties","if","then","else","dependentSchemas","dependentRequired","nullable","readOnly"]);function Cm1($,x){let Y=$.$schema;if(Y==="https://json-schema.org/draft/2020-12/schema")return"draft-2020-12";if(Y==="http://json-schema.org/draft-07/schema#")return"draft-7";if(Y==="http://json-schema.org/draft-04/schema#")return"draft-4";return x??"draft-2020-12"}function um1($,x){if(!$.startsWith("#"))throw Error("External $ref is not supported, only local refs (#/...) are allowed");let Y=$.slice(1).split("/").filter(Boolean);if(Y.length===0)return x.rootSchema;let X=x.version==="draft-2020-12"?"$defs":"definitions";if(Y[0]===X){let Q=Y[1];if(!Q||!x.defs[Q])throw Error(`Reference not found: ${$}`);return x.defs[Q]}throw Error(`Reference not found: ${$}`)}function Bh($,x){if($.not!==void 0){if(typeof $.not==="object"&&Object.keys($.not).length===0)return b1.never();throw Error("not is not supported in Zod (except { not: {} } for never)")}if($.unevaluatedItems!==void 0)throw Error("unevaluatedItems is not supported");if($.unevaluatedProperties!==void 0)throw Error("unevaluatedProperties is not supported");if($.if!==void 0||$.then!==void 0||$.else!==void 0)throw Error("Conditional schemas (if/then/else) are not supported");if($.dependentSchemas!==void 0||$.dependentRequired!==void 0)throw Error("dependentSchemas and dependentRequired are not supported");if($.$ref){let Q=$.$ref;if(x.refs.has(Q))return x.refs.get(Q);if(x.processing.has(Q))return b1.lazy(()=>{if(!x.refs.has(Q))throw Error(`Circular reference not resolved: ${Q}`);return x.refs.get(Q)});x.processing.add(Q);let z=um1(Q,x),Z=l8(z,x);return x.refs.set(Q,Z),x.processing.delete(Q),Z}if($.enum!==void 0){let Q=$.enum;if(x.version==="openapi-3.0"&&$.nullable===!0&&Q.length===1&&Q[0]===null)return b1.null();if(Q.length===0)return b1.never();if(Q.length===1)return b1.literal(Q[0]);if(Q.every((Z)=>typeof Z==="string"))return b1.enum(Q);let z=Q.map((Z)=>b1.literal(Z));if(z.length<2)return z[0];return b1.union([z[0],z[1],...z.slice(2)])}if($.const!==void 0)return b1.literal($.const);let Y=$.type;if(Array.isArray(Y)){let Q=Y.map((z)=>{let Z={...$,type:z};return Bh(Z,x)});if(Q.length===0)return b1.never();if(Q.length===1)return Q[0];return b1.union(Q)}if(!Y)return b1.any();let X;switch(Y){case"string":{let Q=b1.string();if($.format){let z=$.format;if(z==="email")Q=Q.check(b1.email());else if(z==="uri"||z==="uri-reference")Q=Q.check(b1.url());else if(z==="uuid"||z==="guid")Q=Q.check(b1.uuid());else if(z==="date-time")Q=Q.check(b1.iso.datetime());else if(z==="date")Q=Q.check(b1.iso.date());else if(z==="time")Q=Q.check(b1.iso.time());else if(z==="duration")Q=Q.check(b1.iso.duration());else if(z==="ipv4")Q=Q.check(b1.ipv4());else if(z==="ipv6")Q=Q.check(b1.ipv6());else if(z==="mac")Q=Q.check(b1.mac());else if(z==="cidr")Q=Q.check(b1.cidrv4());else if(z==="cidr-v6")Q=Q.check(b1.cidrv6());else if(z==="base64")Q=Q.check(b1.base64());else if(z==="base64url")Q=Q.check(b1.base64url());else if(z==="e164")Q=Q.check(b1.e164());else if(z==="jwt")Q=Q.check(b1.jwt());else if(z==="emoji")Q=Q.check(b1.emoji());else if(z==="nanoid")Q=Q.check(b1.nanoid());else if(z==="cuid")Q=Q.check(b1.cuid());else if(z==="cuid2")Q=Q.check(b1.cuid2());else if(z==="ulid")Q=Q.check(b1.ulid());else if(z==="xid")Q=Q.check(b1.xid());else if(z==="ksuid")Q=Q.check(b1.ksuid())}if(typeof $.minLength==="number")Q=Q.min($.minLength);if(typeof $.maxLength==="number")Q=Q.max($.maxLength);if($.pattern)Q=Q.regex(new RegExp($.pattern));X=Q;break}case"number":case"integer":{let Q=Y==="integer"?b1.number().int():b1.number();if(typeof $.minimum==="number")Q=Q.min($.minimum);if(typeof $.maximum==="number")Q=Q.max($.maximum);if(typeof $.exclusiveMinimum==="number")Q=Q.gt($.exclusiveMinimum);else if($.exclusiveMinimum===!0&&typeof $.minimum==="number")Q=Q.gt($.minimum);if(typeof $.exclusiveMaximum==="number")Q=Q.lt($.exclusiveMaximum);else if($.exclusiveMaximum===!0&&typeof $.maximum==="number")Q=Q.lt($.maximum);if(typeof $.multipleOf==="number")Q=Q.multipleOf($.multipleOf);X=Q;break}case"boolean":{X=b1.boolean();break}case"null":{X=b1.null();break}case"object":{let Q={},z=$.properties||{},Z=new Set($.required||[]);for(let[W,V]of Object.entries(z)){let w=l8(V,x);Q[W]=Z.has(W)?w:w.optional()}if($.propertyNames){let W=l8($.propertyNames,x),V=$.additionalProperties&&typeof $.additionalProperties==="object"?l8($.additionalProperties,x):b1.any();if(Object.keys(Q).length===0){X=b1.record(W,V);break}let w=b1.object(Q).passthrough(),U=b1.looseRecord(W,V);X=b1.intersection(w,U);break}if($.patternProperties){let W=$.patternProperties,V=Object.keys(W),w=[];for(let H of V){let J=l8(W[H],x),q=b1.string().regex(new RegExp(H));w.push(b1.looseRecord(q,J))}let U=[];if(Object.keys(Q).length>0)U.push(b1.object(Q).passthrough());if(U.push(...w),U.length===0)X=b1.object({}).passthrough();else if(U.length===1)X=U[0];else{let H=b1.intersection(U[0],U[1]);for(let J=2;J<U.length;J++)H=b1.intersection(H,U[J]);X=H}break}let K=b1.object(Q);if($.additionalProperties===!1)X=K.strict();else if(typeof $.additionalProperties==="object")X=K.catchall(l8($.additionalProperties,x));else X=K.passthrough();break}case"array":{let{prefixItems:Q,items:z}=$;if(Q&&Array.isArray(Q)){let Z=Q.map((W)=>l8(W,x)),K=z&&typeof z==="object"&&!Array.isArray(z)?l8(z,x):void 0;if(K)X=b1.tuple(Z).rest(K);else X=b1.tuple(Z);if(typeof $.minItems==="number")X=X.check(b1.minLength($.minItems));if(typeof $.maxItems==="number")X=X.check(b1.maxLength($.maxItems))}else if(Array.isArray(z)){let Z=z.map((W)=>l8(W,x)),K=$.additionalItems&&typeof $.additionalItems==="object"?l8($.additionalItems,x):void 0;if(K)X=b1.tuple(Z).rest(K);else X=b1.tuple(Z);if(typeof $.minItems==="number")X=X.check(b1.minLength($.minItems));if(typeof $.maxItems==="number")X=X.check(b1.maxLength($.maxItems))}else if(z!==void 0){let Z=l8(z,x),K=b1.array(Z);if(typeof $.minItems==="number")K=K.min($.minItems);if(typeof $.maxItems==="number")K=K.max($.maxItems);X=K}else X=b1.array(b1.any());break}default:throw Error(`Unsupported type: ${Y}`)}return X}function l8($,x){if(typeof $==="boolean")return $?b1.any():b1.never();let Y=Bh($,x),X=$.type||$.enum!==void 0||$.const!==void 0;if($.anyOf&&Array.isArray($.anyOf)){let K=$.anyOf.map((V)=>l8(V,x)),W=b1.union(K);Y=X?b1.intersection(Y,W):W}if($.oneOf&&Array.isArray($.oneOf)){let K=$.oneOf.map((V)=>l8(V,x)),W=b1.xor(K);Y=X?b1.intersection(Y,W):W}if($.allOf&&Array.isArray($.allOf))if($.allOf.length===0)Y=X?Y:b1.any();else{let K=X?Y:l8($.allOf[0],x),W=X?0:1;for(let V=W;V<$.allOf.length;V++)K=b1.intersection(K,l8($.allOf[V],x));Y=K}if($.nullable===!0&&x.version==="openapi-3.0")Y=b1.nullable(Y);if($.readOnly===!0)Y=b1.readonly(Y);if($.default!==void 0)Y=Y.default($.default);let Q={},z=["$id","id","$comment","$anchor","$vocabulary","$dynamicRef","$dynamicAnchor"];for(let K of z)if(K in $)Q[K]=$[K];let Z=["contentEncoding","contentMediaType","contentSchema"];for(let K of Z)if(K in $)Q[K]=$[K];for(let K of Object.keys($))if(!Em1.has(K))Q[K]=$[K];if(Object.keys(Q).length>0)x.registry.add(Y,Q);if($.description)Y=Y.describe($.description);return Y}function Fh($,x){if(typeof $==="boolean")return $?b1.any():b1.never();let Y;try{Y=JSON.parse(JSON.stringify($))}catch{throw Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas")}let X=Cm1(Y,x?.defaultTarget),Q=Y.$defs||Y.definitions||{},z={version:X,defs:Q,refs:new Map,processing:new Set,rootSchema:Y,registry:x?.registry??_8};return l8(Y,z)}var ev={};V2(ev,{string:()=>ym1,number:()=>mm1,date:()=>pm1,boolean:()=>hm1,bigint:()=>gm1});function ym1($){return Pj(iX,$)}function mm1($){return Rj(nX,$)}function hm1($){return Ej(dX,$)}function gm1($){return uj(aX,$)}function pm1($){return sj(pK,$)}A6(RK());var Lh=m.object({id:m.string(),name:m.string(),type:m.literal("discord"),botToken:m.string().min(10),createdAt:m.string().datetime().optional(),updatedAt:m.string().datetime().optional()});var Nh=m.object({id:m.string(),name:m.string(),type:m.literal("gh"),pollInterval:m.number().int().positive().optional(),createdAt:m.string().datetime().optional(),updatedAt:m.string().datetime().optional()});var im1=m.enum(["latest","all","skip"]),lm1=m.object({id:m.string(),cron:m.string(),prompt:m.string(),enabled:m.boolean().default(!0),catchupPolicy:im1.default("latest")}),Ph=m.object({id:m.string(),name:m.string(),type:m.literal("schedule"),entries:m.array(lm1).default([]),createdAt:m.string().datetime().optional(),updatedAt:m.string().datetime().optional()});var jh=m.object({id:m.string(),name:m.string(),type:m.literal("slack"),botToken:m.string().startsWith("xoxb-"),appToken:m.string().startsWith("xapp-"),createdAt:m.string().datetime().optional(),updatedAt:m.string().datetime().optional()});var Ih=m.discriminatedUnion("type",[jh,Nh,Lh,Ph]);var nm1=m.enum(["fanout","exclusive"]),dm1=m.object({id:m.string(),name:m.string(),delivery:nm1.default("fanout"),options:m.array(m.string()).default([]),env:m.record(m.string(),m.string()).default({}),connectors:m.array(Ih).default([])}),am1=m.object({name:m.string(),path:m.string(),channelId:m.string()}),G2=1,vh=m.object({version:m.literal(G2).default(G2),channels:m.array(dm1).default([]),profiles:m.array(am1).default([])});var O8=Mh(sm1(),".funnel"),rm1=Mh(O8,"settings.json"),tm1=new M8;class $M extends GK{path;fs;constructor($={}){super();this.path=$.path??rm1,this.fs=$.fs??tm1,Object.freeze(this)}read(){if(!this.fs.existsSync(this.path))return{version:G2,channels:[],profiles:[]};let $=this.fs.readFileSync(this.path),x=JSON.parse($);if(this.looksLikeLegacy(x))throw Error(`legacy settings.json detected at ${this.path}. The schema changed (channel.connectors are now nested objects with ids; profile fields renamed). Migration is intentionally not provided. Back up and remove the old file:
542
542
  mv ${this.path} ${this.path}.bak`);if(x&&typeof x==="object"&&"version"in x&&x.version!==G2)throw Error(`unsupported settings.json version (${this.path}): expected ${G2}, got ${String(x.version)}`);let Y=vh.safeParse(x);if(!Y.success)throw Error(`invalid settings.json (${this.path}): ${Y.error.issues.map((X)=>`${X.path.join(".")}: ${X.message}`).join(", ")}`);return Y.data}looksLikeLegacy($){if(!$||typeof $!=="object")return!1;let x=$;if(Array.isArray(x.channels))for(let Y of x.channels){if(!Y||typeof Y!=="object")continue;let X=Y;if(Array.isArray(X.connectors)&&X.connectors.some((Q)=>typeof Q==="string"))return!0;if(!("id"in X)&&"name"in X)return!0}if(Array.isArray(x.connectors))return!0;if(Array.isArray(x.repositories))return!0;if(Array.isArray(x.profiles))for(let Y of x.profiles){if(!Y||typeof Y!=="object")continue;let X=Y;if("repository"in X||"envFiles"in X||"channel"in X&&!("channelId"in X))return!0}return!1}write($){this.fs.mkdirSync(om1(this.path),{recursive:!0});let x={...$,version:G2};this.fs.writeFileSync(this.path,`${JSON.stringify(x,null,2)}
543
543
  `)}}import{join as Ze0}from"path";class fY{}class xM{}class YM extends xM{constructor(){super();Object.freeze(this)}async fetch($){let x=await globalThis.fetch($.url,{method:$.method,headers:$.headers,body:$.body});return{status:x.status,ok:x.ok,text:()=>x.text(),json:()=>x.json()}}}var em1="https://discord.com/api/v10",$h1=new YM;class QM extends fY{token;http;constructor($){super();this.token=$.config.botToken,this.http=$.http??$h1,Object.freeze(this)}async call($){let x=($.method||"GET").toUpperCase(),Y=$.path.startsWith("/")?$.path:`/${$.path}`,X=$.body,Q=X!==null&&typeof X==="object"&&x!=="GET"&&Object.keys(X).length>0,z=await this.http.fetch({method:x,url:`${em1}${Y}`,headers:{Authorization:`Bot ${this.token}`,"Content-Type":"application/json"},body:Q?JSON.stringify($.body):void 0});if(!z.ok)throw Error(`Discord API failed (${z.status}): ${await z.text()}`);if(z.status===204)return null;return await z.json()}}var k2=xL(Hw1(),1);class f2{isAlive(){return!0}}class oA{ownUserId;constructor($){this.ownUserId=$.ownUserId}process($){if($.authorIsBot)return{skip:!0};let x=this.ownUserId?$.mentionedUserIds.includes(this.ownUserId):!1;return{skip:!1,content:JSON.stringify($.raw),meta:{event_type:"discord",channel_id:$.channelId,user_id:$.authorId,mentioned:String(x),guild_id:$.guildId??""}}}}import{appendFileSync as yJ0,mkdirSync as mJ0}from"fs";import{dirname as hJ0,join as gJ0}from"path";class NQ{}var pJ0=gJ0("/tmp/funnel","funnel.log");class I6 extends NQ{file;now;constructor($={}){super();this.file=$.file??pJ0,this.now=$.now??(()=>new Date),Object.freeze(this)}info($,x){this.write("info",$,x)}warn($,x){this.write("warn",$,x)}error($,x){this.write("error",$,x)}write($,x,Y){mJ0(hJ0(this.file),{recursive:!0});let X={time:this.now().toISOString(),level:$,message:x,...Y?{meta:Y}:{}};yJ0(this.file,`${JSON.stringify(X)}
544
- `)}}var iJ0=new I6;class rA extends f2{config;logger;client=null;constructor($){super();this.config=$.config,this.logger=$.logger??iJ0}async start($){let x=new k2.Client({intents:[k2.GatewayIntentBits.Guilds,k2.GatewayIntentBits.GuildMessages,k2.GatewayIntentBits.MessageContent,k2.GatewayIntentBits.DirectMessages],partials:[k2.Partials.Channel]});x.on("messageCreate",async(Y)=>{let X=x.user?.id??"",Q=[...Y.mentions.users.keys()];this.logger.info("discord messageCreate",{author:Y.author.id,authorIsBot:String(Y.author.bot),channelId:Y.channelId,guildId:Y.guildId??"",mentions:Q.join(","),ownUserId:X,mentioned:String(Q.includes(X))});let Z=new oA({ownUserId:X}).process({authorId:Y.author.id,authorIsBot:Y.author.bot,channelId:Y.channelId,guildId:Y.guildId,mentionedUserIds:Q,raw:Y.toJSON()});if(Z.skip){this.logger.info("discord skip",{reason:"bot author"});return}try{await $(Z.content,Z.meta)}catch(K){this.logger.error("discord notify error",{error:K instanceof Error?K.message:String(K)})}}),x.on("ready",(Y)=>{this.logger.info("discord ready",{userId:Y.user.id,tag:Y.user.tag,guilds:String(Y.guilds.cache.size)})}),x.on("error",(Y)=>{this.logger.error("discord client error",{error:Y instanceof Error?Y.message:String(Y)})}),await x.login(this.config.botToken),this.client=x}async stop(){if(!this.client)return;try{await this.client.destroy()}catch($){this.logger.error("discord stop error",{error:$ instanceof Error?$.message:String($)})}finally{this.client=null}}isAlive(){return this.client!==null}}class cW{}var tA=($)=>{if(!$)return;let x={};for(let[Y,X]of Object.entries(process.env))if(typeof X==="string")x[Y]=X;for(let[Y,X]of Object.entries($))x[Y]=X;return x};class L$ extends cW{constructor(){super();Object.freeze(this)}runSync($){let x=Bun.spawnSync($,{stdout:"pipe",stderr:"pipe"});return{exitCode:x.exitCode??0,stdout:x.stdout.toString(),stderr:x.stderr.toString()}}async run($,x={}){let Y=Bun.spawn($,{cwd:x.cwd,env:tA(x.env),stdin:x.input!==void 0?"pipe":"ignore",stdout:"pipe",stderr:"pipe"});if(x.input!==void 0&&Y.stdin)Y.stdin.write(x.input),Y.stdin.end();let X=await Y.exited,Q=await new Response(Y.stdout).text(),z=await new Response(Y.stderr).text();return{exitCode:X,stdout:Q,stderr:z}}async attach($,x={}){return await Bun.spawn($,{cwd:x.cwd,env:tA(x.env),stdio:["inherit","inherit","inherit"]}).exited}detach($,x={}){Bun.spawn($,{env:tA(x.env),stdio:["ignore","ignore","ignore"]}).unref()}kill($,x="SIGTERM"){try{process.kill($,x)}catch{}}}var lJ0=new L$;class eA extends fY{process;constructor($={}){super();this.process=$.process??lJ0,Object.freeze(this)}async call($){let x=["api",$.path];if($.method&&$.method.toLowerCase()!=="get")x.push("-X",$.method.toUpperCase());let Y=$.body&&typeof $.body==="object"&&Object.keys($.body).length>0;if(Y)x.push("--input","-");let X=await this.process.run(["gh",...x],{input:Y?JSON.stringify($.body):void 0});if(X.exitCode!==0)throw Error(`gh api failed: ${X.stderr.trim()||X.stdout.trim()}`);try{return JSON.parse(X.stdout)}catch{return X.stdout}}}var nJ0=m.object({id:m.string(),reason:m.string(),subject:m.object({type:m.string(),url:m.string(),title:m.string()}),repository:m.object({full_name:m.string()}),updated_at:m.string()}),dJ0=m.array(nJ0),aJ0=new L$,sJ0=new I6,oJ0=1e4,rJ0=5000;class $f extends f2{config;process;logger;now;seen=new Map;bootstrapped=!1;since;timer=null;constructor($){super();this.config=$.config,this.process=$.process??aJ0,this.logger=$.logger??sJ0,this.now=$.now??(()=>new Date),this.since=this.now().toISOString()}async start($){await this.pollOnce($);let x=this.config.pollInterval??60;this.timer=setInterval(()=>void this.pollOnce($),x*1000),this.timer.unref()}async stop(){if(!this.timer)return;clearInterval(this.timer),this.timer=null}isAlive(){return this.timer!==null}async pollOnce($){let x=this.now().toISOString(),Y=new URLSearchParams({since:this.since,all:"false"});try{let X=await this.process.run(["gh","api",`/notifications?${Y}`]);if(X.exitCode!==0){this.logger.error("gh poll failed",{stderr:X.stderr});return}let Q=dJ0.safeParse(JSON.parse(X.stdout));if(!Q.success){this.logger.warn("gh response did not match schema",{error:Q.error.message});return}let z=Q.data;for(let Z of z){if(this.seen.get(Z.id)===Z.updated_at)continue;if(this.seen.set(Z.id,Z.updated_at),!this.bootstrapped)continue;let K={event_type:"gh",reason:Z.reason,subject_type:Z.subject.type,subject_url:Z.subject.url,repository:Z.repository.full_name,thread_id:Z.id,updated_at:Z.updated_at};await $(JSON.stringify(Z),K)}if(this.seen.size>oJ0){let Z=this.seen.size-rJ0,K=0;for(let W of this.seen.keys()){if(K>=Z)break;this.seen.delete(W),K++}}this.since=x,this.bootstrapped=!0}catch(X){this.logger.error("gh poll error",{error:X instanceof Error?X.message:String(X)})}}}var SW=($,x,Y)=>{let X=new Set;for(let Q of $.split(",")){let[z,Z]=Q.split("/"),K=Z?Number(Z):1;if(!Number.isFinite(K)||K<=0)throw Error(`invalid cron step: "${Z}"`);let W=x,V=Y;if(z==="*"||z===void 0||z==="")W=x,V=Y;else if(z.includes("-")){let[w,U]=z.split("-"),H=Number(w),J=Number(U);if(!Number.isFinite(H)||!Number.isFinite(J))throw Error(`invalid cron range: "${z}"`);W=H,V=J}else{let w=Number(z);if(!Number.isFinite(w))throw Error(`invalid cron value: "${z}"`);W=w,V=Z?Y:w}if(W<x||V>Y||W>V)throw Error(`cron value out of range: ${z} (must be ${x}-${Y})`);for(let w=W;w<=V;w+=K)X.add(w)}return{min:x,max:Y,values:X}},$q=($,x)=>{let Y=$.trim().split(/\s+/);if(Y.length!==5)throw Error(`cron must have 5 fields (got ${Y.length}): "${$}"`);let[X,Q,z,Z,K]=Y;if(!X||!Q||!z||!Z||!K)throw Error(`cron has empty fields: "${$}"`);let W=[{field:SW(X,0,59),value:x.getMinutes()},{field:SW(Q,0,23),value:x.getHours()},{field:SW(z,1,31),value:x.getDate()},{field:SW(Z,1,12),value:x.getMonth()+1},{field:SW(K,0,6),value:x.getDay()}];for(let{field:V,value:w}of W)if(!V.values.has(w))return!1;return!0};var tJ0=new I6,Gw1=1440;class xf extends f2{config;lastFiredStore;logger;now;onFired;timer=null;stopped=!1;constructor($){super();this.config=$.config,this.lastFiredStore=$.lastFiredStore,this.logger=$.logger??tJ0,this.now=$.now??(()=>new Date),this.onFired=$.onFired??null}async start($){this.stopped=!1;let x=()=>{if(this.stopped)return;let Y=this.now(),X=60000-(Y.getSeconds()*1000+Y.getMilliseconds());this.timer=setTimeout(async()=>{if(this.stopped)return;await this.tick($),x()},X),this.timer.unref()};await this.tick($),x()}async stop(){if(this.stopped=!0,this.timer)clearTimeout(this.timer),this.timer=null}isAlive(){return!this.stopped&&this.timer!==null}async tick($){let x=this.truncateToMinute(this.now()),Y=this.lastFiredStore.load(),X=!1;for(let Q of this.config.entries){if(!Q.enabled)continue;if(await this.fireEntry(Q,x,Y,$))X=!0}if(X)this.lastFiredStore.save(Y)}async fireEntry($,x,Y,X){let Q=Y.get($.id),z=Q?new Date(Q.getTime()+60000):x;if(z.getTime()>x.getTime())return!1;if($.catchupPolicy==="skip"){try{if(!$q($.cron,x))return!1}catch(K){return this.logInvalidCron($,K),!1}return await this.notifyOne($,x,X,!1),Y.set($.id,x),!0}if($.catchupPolicy==="all"){let K=this.findAllMatches($.cron,z,x,$.id);if(K.length===0)return!1;for(let W of K)await this.notifyOne($,W,X,W.getTime()!==x.getTime());return Y.set($.id,K[K.length-1]??x),!0}let Z=this.findMostRecentMatch($.cron,z,x,$.id);if(!Z)return!1;return await this.notifyOne($,Z,X,Z.getTime()!==x.getTime()),Y.set($.id,Z),!0}async notifyOne($,x,Y,X){let Q={event_type:"schedule",schedule_id:$.id,cron:$.cron,fired_at:x.toISOString(),catchup_policy:$.catchupPolicy};if(X)Q.catchup="true";if(await Y($.prompt,Q),this.onFired)try{await this.onFired($,x)}catch(z){this.logger.error("schedule onFired callback failed",{connector:this.config.name,id:$.id,error:z instanceof Error?z.message:String(z)})}}findMostRecentMatch($,x,Y,X){let Q=Math.min(Gw1,Math.floor((Y.getTime()-x.getTime())/60000)+1);for(let z=0;z<Q;z++){let Z=new Date(Y.getTime()-z*60000);try{if($q($,Z))return Z}catch(K){return this.logInvalidCron({id:X,cron:$},K),null}}return null}findAllMatches($,x,Y,X){let Q=Math.min(Gw1,Math.floor((Y.getTime()-x.getTime())/60000)+1),z=[];for(let Z=0;Z<Q;Z++){let K=new Date(x.getTime()+Z*60000);if(K.getTime()>Y.getTime())break;try{if($q($,K))z.push(K)}catch(W){return this.logInvalidCron({id:X,cron:$},W),[]}}return z}logInvalidCron($,x){this.logger.error("invalid cron expression in schedule",{connector:this.config.name,id:$.id,cron:$.cron,error:x instanceof Error?x.message:String(x)})}truncateToMinute($){let x=new Date($.getTime());return x.setSeconds(0,0),x}}import{dirname as eJ0}from"path";var $q0=new M8;class Yf{path;fs;constructor($){this.path=$.path,this.fs=$.fs??$q0,Object.freeze(this)}load(){let $=new Map;if(!this.fs.existsSync(this.path))return $;let x=JSON.parse(this.fs.readFileSync(this.path));if(x===null||typeof x!=="object")return $;for(let[Y,X]of Object.entries(x))if(typeof X==="string")$.set(Y,new Date(X));return $}save($){let x={};for(let[Y,X]of $)x[Y]=X.toISOString();this.fs.mkdirSync(eJ0(this.path),{recursive:!0}),this.fs.writeFileSync(this.path,`${JSON.stringify(x,null,2)}
545
- `)}}var AD1=xL(RD1(),1);var uj0=($)=>{let x={};for(let[Y,X]of Object.entries($))x[Y]=X;return x};class kk extends fY{client;constructor($){super();this.client=$.client??new AD1.WebClient($.config.botToken),Object.freeze(this)}async call($){let x=$.body!==null&&typeof $.body==="object"?uj0($.body):{};return await this.client.apiCall($.path,x)}}var ZF=xL(XS1(),1);var zr0=new Set(["message","app_mention"]),Zr0=new Set([void 0,"thread_broadcast","bot_message","file_share"]);var J7=($,x)=>{let Y=$[x];return typeof Y==="string"?Y:void 0};class SC{ownBotUserId;ownBotId;now;dedup=new Map;constructor($){this.ownBotUserId=$.ownBotUserId,this.ownBotId=$.ownBotId,this.now=$.now??(()=>Date.now())}process($){let x=J7($,"type");if(!x||!zr0.has(x))return{skip:!0};let Y=J7($,"subtype");if(!Zr0.has(Y))return{skip:!0};let X=J7($,"channel")??"",Q=J7($,"event_ts")??J7($,"ts")??"",z=`${X}:${Q}`,Z=this.now();if(this.dedup.has(z))return{skip:!0};this.dedup.set(z,Z);for(let H of this.dedup.keys())if((this.dedup.get(H)??0)<Z-1e4)this.dedup.delete(H);let K=J7($,"user"),W=J7($,"bot_id");if(K===this.ownBotUserId)return{skip:!0};if(W===this.ownBotId)return{skip:!0};let w=(J7($,"text")??"").includes(`<@${this.ownBotUserId}>`),U=J7($,"thread_ts")??J7($,"ts")??"";return{skip:!1,content:JSON.stringify($),meta:{event_type:"slack",channel_id:X,user_id:K??"",mentioned:String(w),thread_ts:U},shouldReact:w,channel:X,timestamp:J7($,"ts")??""}}}var Kr0=m.object({event:m.record(m.string(),m.unknown()).optional()}),Wr0=new I6;class EC extends f2{config;logger;onAppCreated;preprocessEvent;app=null;constructor($){super();this.config=$.config,this.logger=$.logger??Wr0,this.onAppCreated=$.onAppCreated??null,this.preprocessEvent=$.preprocessEvent??null}async start($){let x=new ZF.App({token:this.config.botToken,appToken:this.config.appToken,socketMode:!0,logLevel:ZF.LogLevel.ERROR}),Y=await x.client.auth.test({token:this.config.botToken}),X=new SC({ownBotUserId:Y.user_id??"",ownBotId:Y.bot_id??""}),Q=this.preprocessEvent;if(x.use(async(z)=>{let Z=Kr0.safeParse(z);if(!Z.success||!Z.data.event)return;let K=Z.data.event,W=Q?Q(K):K;if(W===null)return;let V=X.process(W);if(V.skip)return;if(V.shouldReact)try{await x.client.reactions.add({token:this.config.botToken,channel:V.channel,timestamp:V.timestamp,name:"eyes"})}catch{}await $(V.content,V.meta)}),x.error(async(z)=>{this.logger.error("Slack error",{error:z instanceof Error?z.message:String(z)})}),this.onAppCreated)await this.onAppCreated(x);await x.start(),this.app=x}async stop(){if(!this.app)return;try{await this.app.stop()}catch($){this.logger.error("Slack stop error",{error:$ instanceof Error?$.message:String($)})}finally{this.app=null}}isAlive(){return this.app!==null}}import{join as CC}from"path";var Vr0=new M8,wr0=new L$,Ur0=new I6;class uC{fs;process;logger;dir;slackListenerOptions;scheduleListenerOptions;constructor($={}){this.fs=$.fs??Vr0,this.process=$.process??wr0,this.logger=$.logger??Ur0,this.dir=$.dir??O8,this.slackListenerOptions=$.slackListenerOptions??{},this.scheduleListenerOptions=$.scheduleListenerOptions??{},Object.freeze(this)}createListener($,x){if(x.type==="slack")return new EC({config:x,logger:this.logger,onAppCreated:this.slackListenerOptions.onAppCreated,preprocessEvent:this.slackListenerOptions.preprocessEvent});if(x.type==="gh")return new $f({config:x,process:this.process,logger:this.logger});if(x.type==="discord")return new rA({config:x,logger:this.logger});let Y=new Yf({path:CC(this.connectorDir($,x.id),"state.json"),fs:this.fs});return new xf({config:x,lastFiredStore:Y,logger:this.logger,onFired:this.scheduleListenerOptions.onFired})}createAdapter($){if($.type==="slack")return new kk({config:$});if($.type==="gh")return new eA({process:this.process});if($.type==="discord")return new QM({config:$});return null}connectorDir($,x){return CC(this.dir,"channels",$,"connectors",x)}channelDir($){return CC(this.dir,"channels",$)}}function yC($){switch($.type){case"slack":return[$.botToken,$.appToken];case"discord":return[$.botToken];case"gh":case"schedule":return[]}}function Hr0($,x){return $.type===x}function YX($,x,Y){let X=$.connectors.find((Q)=>Q.name===x);if(!X)throw Error(`connector "${x}" not found in channel "${$.name}"`);if(!Hr0(X,Y))throw Error(`connector "${x}" is type "${X.type}", not "${Y}"`);return X}class EV{millis(){return this.now().getTime()}iso(){return this.now().toISOString()}}class QX extends EV{now(){return new Date}}class CV{}class uV extends CV{generate(){return crypto.randomUUID()}}var Gr0=new QX,Jr0=new uV;class mC{store;factory;profileChecker;clock;idGenerator;constructor($){this.store=$.store,this.factory=$.factory,this.profileChecker=$.profileChecker,this.clock=$.clock??Gr0,this.idGenerator=$.idGenerator??Jr0,Object.freeze(this)}list(){return this.store.read().channels}get($){return this.list().find((x)=>x.name===$)??null}getById($){return this.list().find((x)=>x.id===$)??null}add($){let x=this.store.read();if(x.channels.some((X)=>X.name===$.name))throw Error(`channel "${$.name}" already exists`);let Y={id:this.idGenerator.generate(),name:$.name,delivery:$.delivery??"fanout",options:$.options??[],env:$.env??{},connectors:[]};return x.channels.push(Y),this.store.write(x),Y}setDelivery($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.delivery=x,this.store.write(Y)}setOptions($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.options=x,this.store.write(Y)}setEnv($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.env=x,this.store.write(Y)}remove($){let x=this.store.read(),Y=x.channels.findIndex((Q)=>Q.name===$);if(Y<0)throw Error(`channel "${$}" not found`);let X=x.channels[Y];if(X&&this.profileChecker.hasChannelRef(X.id))throw Error(`channel "${$}" is referenced by a profile`);x.channels.splice(Y,1),this.store.write(x)}rename($,x){let Y=this.store.read(),X=Y.channels.find((Q)=>Q.name===$);if(!X)throw Error(`channel "${$}" not found`);if(Y.channels.some((Q)=>Q.name===x))throw Error(`channel "${x}" already exists`);X.name=x,this.store.write(Y)}listConnectors($){return this.requireChannel(this.store.read(),$).connectors}getConnector($,x){let Y=this.get($);if(!Y)return null;return Y.connectors.find((X)=>X.name===x)??null}listAllConnectors(){let $=[];for(let x of this.list())for(let Y of x.connectors)$.push({...Y,channelId:x.id,channelName:x.name});return $}addConnector($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);if(X.connectors.some((z)=>z.name===x.name))throw Error(`connector "${x.name}" already exists in channel "${$}"`);let Q=this.fromInput(x);return this.assertNoTokenCollision(Y,Q),X.connectors.push(Q),this.store.write(Y),Q}fromInput($){let x=this.idGenerator.generate(),Y=this.clock.iso(),X=Y,Q=Y;switch($.type){case"slack":return{id:x,type:"slack",name:$.name,botToken:$.botToken,appToken:$.appToken,createdAt:X,updatedAt:Q};case"gh":return{id:x,type:"gh",name:$.name,...$.pollInterval!==void 0?{pollInterval:$.pollInterval}:{},createdAt:X,updatedAt:Q};case"discord":return{id:x,type:"discord",name:$.name,botToken:$.botToken,createdAt:X,updatedAt:Q};case"schedule":return{id:x,type:"schedule",name:$.name,entries:$.entries??[],createdAt:X,updatedAt:Q}}}removeConnector($,x){let Y=this.store.read(),X=this.requireChannel(Y,$),Q=X.connectors.findIndex((z)=>z.name===x);if(Q<0)throw Error(`connector "${x}" not found in channel "${$}"`);X.connectors.splice(Q,1),this.store.write(Y)}renameConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=Q.connectors.find((Z)=>Z.name===x);if(!z)throw Error(`connector "${x}" not found in channel "${$}"`);if(Q.connectors.some((Z)=>Z.name===Y))throw Error(`connector "${Y}" already exists in channel "${$}"`);z.name=Y,z.updatedAt=this.clock.iso(),this.store.write(X)}updateSlackConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"slack"),Z={...z,botToken:Y.botToken??z.botToken,appToken:Y.appToken??z.appToken,updatedAt:this.clock.iso()};this.assertNoTokenCollision(X,Z),Object.assign(z,Z),this.store.write(X)}updateGhConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"gh");if(Y.pollInterval!==void 0)z.pollInterval=Y.pollInterval;z.updatedAt=this.clock.iso(),this.store.write(X)}updateDiscordConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"discord"),Z={...z,botToken:Y.botToken??z.botToken,updatedAt:this.clock.iso()};this.assertNoTokenCollision(X,Z),Object.assign(z,Z),this.store.write(X)}listScheduleEntries($,x){let Y=this.requireChannel(this.store.read(),$);return YX(Y,x,"schedule").entries}addScheduleEntry($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"schedule"),Z={id:Y.id??this.idGenerator.generate(),cron:Y.cron,prompt:Y.prompt,enabled:Y.enabled??!0,catchupPolicy:Y.catchupPolicy??"latest"};return z.entries.push(Z),z.updatedAt=this.clock.iso(),this.store.write(X),Z}removeScheduleEntry($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"schedule"),Z=z.entries.findIndex((K)=>K.id===Y);if(Z<0)throw Error(`schedule entry "${Y}" not found`);z.entries.splice(Z,1),z.updatedAt=this.clock.iso(),this.store.write(X)}async call($,x,Y){let X=this.getConnector($,x);if(!X)throw Error(`connector "${x}" not found in channel "${$}"`);let Q=this.factory.createAdapter(X);if(!Q)throw Error(`connector type "${X.type}" does not support outbound calls`);return await Q.call(Y)}createListener($,x){let Y=this.get($);if(!Y)return null;let X=Y.connectors.find((Q)=>Q.name===x);if(!X)return null;return{config:X,channelId:Y.id,listener:this.factory.createListener(Y.id,X)}}createAllListeners(){let $=[];for(let x of this.list())for(let Y of x.connectors)$.push({config:Y,channelId:x.id,channelName:x.name,listener:this.factory.createListener(x.id,Y)});return $}requireChannel($,x){let Y=$.channels.find((X)=>X.name===x);if(!Y)throw Error(`channel "${x}" not found`);return Y}assertNoTokenCollision($,x){let Y=yC(x);if(Y.length===0)return;for(let X of $.channels)for(let Q of X.connectors){if(Q.id===x.id)continue;for(let z of yC(Q))if(Y.includes(z))throw Error(`token already in use by connector "${Q.name}" in channel "${X.name}"`)}}}import{join as zS1}from"path";var qr0=new L$,Dr0=new M8,Br0=new I6;class hC{channels;mcp;gateway;process;fs;logger;pidDir;constructor($){this.channels=$.channels,this.mcp=$.mcp,this.gateway=$.gateway,this.process=$.process??qr0,this.fs=$.fs??Dr0,this.logger=$.logger??Br0,this.pidDir=zS1($.dir??O8,"claude"),Object.freeze(this)}async launch($){let x=this.channels.get($.channel)??this.channels.getById($.channel);if(!x)throw Error(`channel "${$.channel}" not found`);if($.profileName&&this.isRunning($.profileName))throw Error(`profile "${$.profileName}" is already running`);let Y=$.cwd??globalThis.process.cwd();if(!this.mcp.findInstalledName(Y))this.mcp.install(Y),this.logger.info("added funnel MCP to .mcp.json",{cwd:Y});if(!this.gateway.isRunning())this.logger.info("starting gateway automatically"),await this.gateway.start();if($.profileName)this.writePidFile($.profileName),this.installCleanup($.profileName);let X=this.buildArgs(x.options,$.userArgs??[],Y),Q=this.buildEnv(x.id,x.env);this.logger.info("claude launch",{channel:$.channel,channelId:x.id,cwd:Y});try{return await this.process.attach(["claude",...X],{cwd:Y,env:Q})}finally{if($.profileName)this.removePidFile($.profileName)}}isRunning($){let x=this.readPid($);if(!x)return!1;return this.isProcessAlive(x)}pidPath($){return zS1(this.pidDir,`${$}.pid`)}readPid($){let x=this.pidPath($);if(!this.fs.existsSync(x))return null;try{let Y=this.fs.readFileSync(x).trim(),X=Number(Y);if(!X||X<=0)return null;return X}catch{return null}}writePidFile($){this.fs.mkdirSync(this.pidDir,{recursive:!0}),this.fs.writeFileSync(this.pidPath($),String(globalThis.process.pid))}removePidFile($){let x=this.pidPath($);if(this.fs.existsSync(x))this.fs.unlink(x)}installCleanup($){globalThis.process.once("exit",()=>this.removePidFile($))}isProcessAlive($){let x=this.process.runSync(["ps","-p",String($),"-o","state="]);if(x.exitCode!==0)return!1;let Y=x.stdout.trim();if(!Y)return!1;return!Y.startsWith("Z")}buildArgs($,x,Y){let X=[...$,...x],Q=this.mcp.findInstalledName(Y);if(Q&&!X.includes("--dangerously-load-development-channels")&&!X.includes("--channels"))X.push("--dangerously-load-development-channels",`server:${Q}`);return X}buildEnv($,x){let Y={};for(let[X,Q]of Object.entries(x))Y[X]=Q;for(let[X,Q]of Object.entries(globalThis.process.env))if(typeof Q==="string")Y[X]=Q;return Y.FUNNEL_CHANNEL_ID=$,Y}}var Fr0=384;class gC extends HK{dirs;files;mtimes;modes;now;constructor($={}){super();this.dirs=new Set($.dirs??[]),this.files=new Map(Object.entries($.files??{})),this.mtimes=new Map(Object.entries($.mtimes??{})),this.modes=new Map(Object.entries($.modes??{})),this.now=$.now??(()=>Date.now())}existsSync($){return this.dirs.has($)||this.files.has($)}readFileSync($){return this.files.get($)??""}writeFileSync($,x){this.files.set($,x),this.touch($)}writeSecretFileSync($,x){this.files.set($,x),this.modes.set($,Fr0),this.touch($)}appendFileSync($,x){let Y=this.files.get($)??"";this.files.set($,Y+x),this.touch($)}unlink($){this.files.delete($),this.mtimes.delete($),this.modes.delete($)}mkdirSync($,x){this.dirs.add($)}readdirSync($){let x=$.endsWith("/")?$:`${$}/`,Y=[];for(let X of this.files.keys()){if(!X.startsWith(x))continue;let Q=X.slice(x.length);if(!Q.includes("/"))Y.push(Q)}return Y}statSync($){let x=this.mtimes.get($);if(x===void 0)throw Error(`not found: ${$}`);return{mtimeMs:x,mode:this.modes.get($)??null}}setMtime($,x){this.mtimes.set($,x)}setMode($,x){this.modes.set($,x)}touch($){if(!this.mtimes.has($))this.mtimes.set($,this.now());else this.mtimes.set($,this.now())}}class pC extends CV{counter=0;prefix;constructor($={}){super();this.prefix=$.prefix??"id"}generate(){return this.counter++,`${this.prefix}-${this.counter}`}}import{join as Or0}from"path";var Lr0=m.object({botToken:m.string().optional(),appToken:m.string().optional()}).optional(),Nr0=m.object({type:m.literal("slack"),name:m.string(),botToken:m.string().optional(),appToken:m.string().optional(),env:Lr0}),Pr0=m.object({botToken:m.string().optional()}).optional(),jr0=m.object({type:m.literal("discord"),name:m.string(),botToken:m.string().optional(),env:Pr0}),Ir0=m.object({type:m.literal("gh"),name:m.string(),pollInterval:m.number().int().positive().optional()}),vr0=m.object({type:m.literal("schedule"),name:m.string()}),Mr0=m.discriminatedUnion("type",[Nr0,jr0,Ir0,vr0]),_r0=m.object({name:m.string(),options:m.array(m.string()).optional(),env:m.record(m.string(),m.string()).optional(),connectors:m.array(Mr0).optional()}),ZS1=m.object({$schema:m.string().optional(),channels:m.array(_r0).min(1)}),KF="funnel.json",KS1=".env.local";var br0=/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/,Rr0=($)=>{if($.length<2)return $;let x=$[0],Y=$[$.length-1];if(x==='"'&&Y==='"')return $.slice(1,-1);if(x==="'"&&Y==="'")return $.slice(1,-1);return $};class iC{fs;constructor($){this.fs=$.fs,Object.freeze(this)}read($){let x=Or0($,KS1);if(!this.fs.existsSync(x))return{};let Y=this.fs.readFileSync(x),X={};for(let Q of Y.split(`
546
- `)){let z=Q.trim();if(z===""||z.startsWith("#"))continue;let Z=z.match(br0);if(!Z)continue;let K=Z[1],W=Z[2];if(!K)continue;X[K]=Rr0(W??"")}return X}}import{join as Ar0}from"path";class lC{fs;constructor($){this.fs=$.fs,Object.freeze(this)}read($){let x=Ar0($,KF);if(!this.fs.existsSync(x))return null;let Y=this.fs.readFileSync(x),X=(()=>{try{return JSON.parse(Y)}catch(z){let Z=z instanceof Error?z.message:String(z);throw Error(`${KF} is not valid JSON: ${Z}`)}})(),Q=ZS1.safeParse(X);if(!Q.success)throw Error(`${KF} is invalid: ${Q.error.message}`);return Q.data}}var fr0=($,x)=>{if($.length!==x.length)return!1;for(let Y=0;Y<$.length;Y++)if($[Y]!==x[Y])return!1;return!0},kr0=($,x)=>{let Y=Object.keys($);if(Y.length!==Object.keys(x).length)return!1;for(let X of Y)if($[X]!==x[X])return!1;return!0};class nC{channels;dotenv;prompter;env;constructor($){this.channels=$.channels,this.dotenv=$.dotenv,this.prompter=$.prompter,this.env=$.env??process.env,Object.freeze(this)}async ensure($,x){let Y=this.channels.get($.name);if(!Y)this.channels.add({name:$.name,options:$.options??[],env:$.env??{}});else{let z=$.options??[],Z=$.env??{};if(!fr0(Y.options,z))this.channels.setOptions($.name,z);if(!kr0(Y.env,Z))this.channels.setEnv($.name,Z)}if($.connectors===void 0)return;let X=this.dotenv.read(x),Q=new Set;for(let z of $.connectors){let Z=await this.ensureConnector($.name,z,X);Q.add(Z)}this.removeExtras($.name,Q)}async ensureConnector($,x,Y){if(x.type==="slack")return await this.ensureSlack($,x,Y);if(x.type==="discord")return await this.ensureDiscord($,x,Y);if(x.type==="gh")return this.ensureGh($,x);return this.ensureSchedule($,x)}async ensureSlack($,x,Y){let X=this.findExistingSlack($,x.name),Q=await this.resolveField({literal:x.botToken,envVar:x.env?.botToken,dotenv:Y,label:`${x.name}.botToken`,existing:X?.botToken}),z=await this.resolveField({literal:x.appToken,envVar:x.env?.appToken,dotenv:Y,label:`${x.name}.appToken`,existing:X?.appToken});if(X){if(X.botToken!==Q||X.appToken!==z)this.channels.updateSlackConnector($,x.name,{botToken:Q,appToken:z});return X.id}let Z=this.findSlackByToken($,[Q,z]);if(Z){if(this.channels.renameConnector($,Z.name,x.name),Z.botToken!==Q||Z.appToken!==z)this.channels.updateSlackConnector($,x.name,{botToken:Q,appToken:z});return Z.id}return this.channels.addConnector($,{type:"slack",name:x.name,botToken:Q,appToken:z}).id}async ensureDiscord($,x,Y){let X=this.findExistingDiscord($,x.name),Q=await this.resolveField({literal:x.botToken,envVar:x.env?.botToken,dotenv:Y,label:`${x.name}.botToken`,existing:X?.botToken});if(X){if(X.botToken!==Q)this.channels.updateDiscordConnector($,x.name,{botToken:Q});return X.id}let z=this.findDiscordByToken($,Q);if(z){if(this.channels.renameConnector($,z.name,x.name),z.botToken!==Q)this.channels.updateDiscordConnector($,x.name,{botToken:Q});return z.id}return this.channels.addConnector($,{type:"discord",name:x.name,botToken:Q}).id}ensureGh($,x){let Y=this.channels.getConnector($,x.name);if(Y&&Y.type!=="gh")throw Error(`connector "${x.name}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "gh"`);if(Y&&Y.type==="gh"){if(x.pollInterval!==void 0&&Y.pollInterval!==x.pollInterval)this.channels.updateGhConnector($,x.name,{pollInterval:x.pollInterval});return Y.id}return this.channels.addConnector($,{type:"gh",name:x.name,...x.pollInterval!==void 0?{pollInterval:x.pollInterval}:{}}).id}ensureSchedule($,x){let Y=this.channels.getConnector($,x.name);if(Y&&Y.type!=="schedule")throw Error(`connector "${x.name}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "schedule"`);if(Y&&Y.type==="schedule")return Y.id;return this.channels.addConnector($,{type:"schedule",name:x.name}).id}findExistingSlack($,x){let Y=this.channels.getConnector($,x);if(!Y)return null;if(Y.type!=="slack")throw Error(`connector "${x}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "slack"`);return Y}findExistingDiscord($,x){let Y=this.channels.getConnector($,x);if(!Y)return null;if(Y.type!=="discord")throw Error(`connector "${x}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "discord"`);return Y}findSlackByToken($,x){let Y=this.channels.get($);if(!Y)return null;for(let X of Y.connectors){if(X.type!=="slack")continue;if(x.includes(X.botToken)||x.includes(X.appToken))return X}return null}findDiscordByToken($,x){let Y=this.channels.get($);if(!Y)return null;for(let X of Y.connectors){if(X.type!=="discord")continue;if(X.botToken===x)return X}return null}removeExtras($,x){let Y=this.channels.get($);if(!Y)return;let X=Y.connectors.filter((Q)=>!x.has(Q.id));for(let Q of X)this.channels.removeConnector($,Q.name)}async resolveField($){if($.literal!==void 0&&$.envVar!==void 0)throw Error(`${$.label} is set both as a literal and as env.${$.label.split(".").pop()}; pick one`);if($.literal!==void 0&&$.literal!=="")return $.literal;if($.envVar!==void 0&&$.envVar!==""){let x=this.env[$.envVar];if(x)return x;let Y=$.dotenv[$.envVar];if(Y)return Y;throw Error(`${$.label} references env var "${$.envVar}" but it is not set in process env or .env.local`)}if($.existing)return $.existing;return await this.prompter.promptSecret($.label)}}class dC extends NQ{file=null;entries=[];info($,x){this.entries.push({level:"info",message:$,meta:x})}warn($,x){this.entries.push({level:"warn",message:$,meta:x})}error($,x){this.entries.push({level:"error",message:$,meta:x})}clear(){this.entries.length=0}}import{join as WS1}from"path";var VS1="funnel",Tr0="funnel",cr0=m.object({command:m.string().optional(),args:m.array(m.string()).optional()}),Sr0=m.object({mcpServers:m.record(m.string(),cr0).optional()}),Er0=new M8;class aC{fs;constructor($={}){this.fs=$.fs??Er0,Object.freeze(this)}install($){if(!this.fs.existsSync($))throw Error(`repository does not exist: ${$}`);let x=this.readConfig($),Y=x.mcpServers??{},Q=this.findServerName(Y)??Tr0;Y[Q]={command:VS1,args:["mcp"]},this.writeConfig($,{...x,mcpServers:Y})}uninstall($){if(!this.fs.existsSync($))return;let x=this.readConfig($),Y=x.mcpServers??{},X=this.findServerName(Y);if(!X)return;let Q={...Y};delete Q[X],this.writeConfig($,{...x,mcpServers:Q})}findInstalledName($){let x=this.readConfig($);return this.findServerName(x.mcpServers??{})}findServerName($){for(let x of Object.entries($)){let Y=x[0];if(x[1]?.command===VS1)return Y}return null}readConfig($){let x=WS1($,".mcp.json");if(!this.fs.existsSync(x))return{};let Y=this.fs.readFileSync(x).trim();if(!Y)return{};let X;try{X=JSON.parse(Y)}catch(z){throw Error(`invalid .mcp.json (${x}): ${z instanceof Error?z.message:String(z)}`)}let Q=Sr0.safeParse(X);if(!Q.success)throw Error(`invalid .mcp.json (${x}): ${Q.error.message}`);return Q.data}writeConfig($,x){let Y=WS1($,".mcp.json");this.fs.writeFileSync(Y,`${JSON.stringify(x,null,2)}
547
- `)}}var wS1={exitCode:0,stdout:"",stderr:""};class sC extends cW{calls=[];killed=[];handler=()=>wS1;syncHandler=()=>wS1;on($){return this.handler=$,this}onSync($){return this.syncHandler=$,this}async run($,x={}){this.calls.push({kind:"run",command:$,options:x});let Y=await this.handler($);return{exitCode:Y.exitCode??0,stdout:Y.stdout??"",stderr:Y.stderr??""}}runSync($){this.calls.push({kind:"runSync",command:$});let x=this.syncHandler($);return{exitCode:x.exitCode??0,stdout:x.stdout??"",stderr:x.stderr??""}}async attach($,x={}){return this.calls.push({kind:"attach",command:$,options:x}),(await this.handler($)).exitCode??0}detach($,x={}){this.calls.push({kind:"detach",command:$,options:x})}kill($,x="SIGTERM"){this.calls.push({kind:"kill",command:[String($),x]}),this.killed.push({pid:$,signal:x})}}class oC{store;constructor($){this.store=$.store,Object.freeze(this)}list(){return this.store.read().profiles}get($){return this.list().find((x)=>x.name===$)??null}getDefault(){return this.list()[0]??null}add($){let x=this.store.read();if(x.profiles.some((Y)=>Y.name===$.name))throw Error(`profile "${$.name}" already exists`);if(!x.channels.some((Y)=>Y.id===$.channelId))throw Error(`channel id "${$.channelId}" not found`);x.profiles.push($),this.store.write(x)}remove($){let x=this.store.read(),Y=x.profiles.findIndex((X)=>X.name===$);if(Y<0)throw Error(`profile "${$}" not found`);x.profiles.splice(Y,1),this.store.write(x)}rename($,x){let Y=this.store.read(),X=Y.profiles.find((Q)=>Q.name===$);if(!X)throw Error(`profile "${$}" not found`);if(Y.profiles.some((Q)=>Q.name===x))throw Error(`profile "${x}" already exists`);X.name=x,this.store.write(Y)}asDefault($){let x=this.store.read(),Y=x.profiles.findIndex((Q)=>Q.name===$);if(Y<0)throw Error(`profile "${$}" not found`);if(Y===0)return;let[X]=x.profiles.splice(Y,1);if(!X)return;x.profiles.unshift(X),this.store.write(x)}hasChannelRef($){return this.store.read().profiles.some((x)=>x.channelId===$)}update($,x){let Y=this.store.read(),X=Y.profiles.find((Q)=>Q.name===$);if(!X)throw Error(`profile "${$}" not found`);if(x.channelId!==void 0){if(!Y.channels.some((Q)=>Q.id===x.channelId))throw Error(`channel id "${x.channelId}" not found`);X.channelId=x.channelId}if(x.path!==void 0)X.path=x.path;this.store.write(Y)}}import{stderr as WF,stdin as e7}from"process";class rC{}var Cr0="*",ur0="\r",US1=`
544
+ `)}}var iJ0=new I6;class rA extends f2{config;logger;client=null;constructor($){super();this.config=$.config,this.logger=$.logger??iJ0}async start($){let x=new k2.Client({intents:[k2.GatewayIntentBits.Guilds,k2.GatewayIntentBits.GuildMessages,k2.GatewayIntentBits.MessageContent,k2.GatewayIntentBits.DirectMessages],partials:[k2.Partials.Channel]});x.on("messageCreate",async(Y)=>{let X=x.user?.id??"",Q=[...Y.mentions.users.keys()];this.logger.info("discord messageCreate",{author:Y.author.id,authorIsBot:String(Y.author.bot),channelId:Y.channelId,guildId:Y.guildId??"",mentions:Q.join(","),ownUserId:X,mentioned:String(Q.includes(X))});let Z=new oA({ownUserId:X}).process({authorId:Y.author.id,authorIsBot:Y.author.bot,channelId:Y.channelId,guildId:Y.guildId,mentionedUserIds:Q,raw:Y.toJSON()});if(Z.skip){this.logger.info("discord skip",{reason:"bot author"});return}try{await $(Z.content,Z.meta)}catch(K){this.logger.error("discord notify error",{error:K instanceof Error?K.message:String(K)})}}),x.on("ready",(Y)=>{this.logger.info("discord ready",{userId:Y.user.id,tag:Y.user.tag,guilds:String(Y.guilds.cache.size)})}),x.on("error",(Y)=>{this.logger.error("discord client error",{error:Y instanceof Error?Y.message:String(Y)})}),await x.login(this.config.botToken),this.client=x}async stop(){if(!this.client)return;try{await this.client.destroy()}catch($){this.logger.error("discord stop error",{error:$ instanceof Error?$.message:String($)})}finally{this.client=null}}isAlive(){return this.client!==null}}class cW{}var tA=($)=>{if(!$)return;let x={};for(let[Y,X]of Object.entries(process.env))if(typeof X==="string")x[Y]=X;for(let[Y,X]of Object.entries($))x[Y]=X;return x};class L$ extends cW{constructor(){super();Object.freeze(this)}runSync($){let x=Bun.spawnSync($,{stdout:"pipe",stderr:"pipe"});return{exitCode:x.exitCode??0,stdout:x.stdout.toString(),stderr:x.stderr.toString()}}async run($,x={}){let Y=Bun.spawn($,{cwd:x.cwd,env:tA(x.env),stdin:x.input!==void 0?"pipe":"ignore",stdout:"pipe",stderr:"pipe"});if(x.input!==void 0&&Y.stdin)Y.stdin.write(x.input),Y.stdin.end();let X=await Y.exited,Q=await new Response(Y.stdout).text(),z=await new Response(Y.stderr).text();return{exitCode:X,stdout:Q,stderr:z}}async attach($,x={}){let Y=Bun.spawn($,{cwd:x.cwd,env:tA(x.env),stdio:["inherit","inherit","inherit"]});if(x.onSpawned)x.onSpawned(Y.pid);return await Y.exited}detach($,x={}){Bun.spawn($,{env:tA(x.env),stdio:["ignore","ignore","ignore"]}).unref()}kill($,x="SIGTERM"){try{process.kill($,x)}catch{}}}var lJ0=new L$;class eA extends fY{process;constructor($={}){super();this.process=$.process??lJ0,Object.freeze(this)}async call($){let x=["api",$.path];if($.method&&$.method.toLowerCase()!=="get")x.push("-X",$.method.toUpperCase());let Y=$.body&&typeof $.body==="object"&&Object.keys($.body).length>0;if(Y)x.push("--input","-");let X=await this.process.run(["gh",...x],{input:Y?JSON.stringify($.body):void 0});if(X.exitCode!==0)throw Error(`gh api failed: ${X.stderr.trim()||X.stdout.trim()}`);try{return JSON.parse(X.stdout)}catch{return X.stdout}}}var nJ0=m.object({id:m.string(),reason:m.string(),subject:m.object({type:m.string(),url:m.string(),title:m.string()}),repository:m.object({full_name:m.string()}),updated_at:m.string()}),dJ0=m.array(nJ0),aJ0=new L$,sJ0=new I6,oJ0=1e4,rJ0=5000;class $f extends f2{config;process;logger;now;seen=new Map;bootstrapped=!1;since;timer=null;constructor($){super();this.config=$.config,this.process=$.process??aJ0,this.logger=$.logger??sJ0,this.now=$.now??(()=>new Date),this.since=this.now().toISOString()}async start($){await this.pollOnce($);let x=this.config.pollInterval??60;this.timer=setInterval(()=>void this.pollOnce($),x*1000),this.timer.unref()}async stop(){if(!this.timer)return;clearInterval(this.timer),this.timer=null}isAlive(){return this.timer!==null}async pollOnce($){let x=this.now().toISOString(),Y=new URLSearchParams({since:this.since,all:"false"});try{let X=await this.process.run(["gh","api",`/notifications?${Y}`]);if(X.exitCode!==0){this.logger.error("gh poll failed",{stderr:X.stderr});return}let Q=dJ0.safeParse(JSON.parse(X.stdout));if(!Q.success){this.logger.warn("gh response did not match schema",{error:Q.error.message});return}let z=Q.data;for(let Z of z){if(this.seen.get(Z.id)===Z.updated_at)continue;if(this.seen.set(Z.id,Z.updated_at),!this.bootstrapped)continue;let K={event_type:"gh",reason:Z.reason,subject_type:Z.subject.type,subject_url:Z.subject.url,repository:Z.repository.full_name,thread_id:Z.id,updated_at:Z.updated_at};await $(JSON.stringify(Z),K)}if(this.seen.size>oJ0){let Z=this.seen.size-rJ0,K=0;for(let W of this.seen.keys()){if(K>=Z)break;this.seen.delete(W),K++}}this.since=x,this.bootstrapped=!0}catch(X){this.logger.error("gh poll error",{error:X instanceof Error?X.message:String(X)})}}}var SW=($,x,Y)=>{let X=new Set;for(let Q of $.split(",")){let[z,Z]=Q.split("/"),K=Z?Number(Z):1;if(!Number.isFinite(K)||K<=0)throw Error(`invalid cron step: "${Z}"`);let W=x,V=Y;if(z==="*"||z===void 0||z==="")W=x,V=Y;else if(z.includes("-")){let[w,U]=z.split("-"),H=Number(w),J=Number(U);if(!Number.isFinite(H)||!Number.isFinite(J))throw Error(`invalid cron range: "${z}"`);W=H,V=J}else{let w=Number(z);if(!Number.isFinite(w))throw Error(`invalid cron value: "${z}"`);W=w,V=Z?Y:w}if(W<x||V>Y||W>V)throw Error(`cron value out of range: ${z} (must be ${x}-${Y})`);for(let w=W;w<=V;w+=K)X.add(w)}return{min:x,max:Y,values:X}},$q=($,x)=>{let Y=$.trim().split(/\s+/);if(Y.length!==5)throw Error(`cron must have 5 fields (got ${Y.length}): "${$}"`);let[X,Q,z,Z,K]=Y;if(!X||!Q||!z||!Z||!K)throw Error(`cron has empty fields: "${$}"`);let W=[{field:SW(X,0,59),value:x.getMinutes()},{field:SW(Q,0,23),value:x.getHours()},{field:SW(z,1,31),value:x.getDate()},{field:SW(Z,1,12),value:x.getMonth()+1},{field:SW(K,0,6),value:x.getDay()}];for(let{field:V,value:w}of W)if(!V.values.has(w))return!1;return!0};var tJ0=new I6,Gw1=1440;class xf extends f2{config;lastFiredStore;logger;now;onFired;timer=null;stopped=!1;constructor($){super();this.config=$.config,this.lastFiredStore=$.lastFiredStore,this.logger=$.logger??tJ0,this.now=$.now??(()=>new Date),this.onFired=$.onFired??null}async start($){this.stopped=!1;let x=()=>{if(this.stopped)return;let Y=this.now(),X=60000-(Y.getSeconds()*1000+Y.getMilliseconds());this.timer=setTimeout(async()=>{if(this.stopped)return;await this.tick($),x()},X),this.timer.unref()};await this.tick($),x()}async stop(){if(this.stopped=!0,this.timer)clearTimeout(this.timer),this.timer=null}isAlive(){return!this.stopped&&this.timer!==null}async tick($){let x=this.truncateToMinute(this.now()),Y=this.lastFiredStore.load(),X=!1;for(let Q of this.config.entries){if(!Q.enabled)continue;if(await this.fireEntry(Q,x,Y,$))X=!0}if(X)this.lastFiredStore.save(Y)}async fireEntry($,x,Y,X){let Q=Y.get($.id),z=Q?new Date(Q.getTime()+60000):x;if(z.getTime()>x.getTime())return!1;if($.catchupPolicy==="skip"){try{if(!$q($.cron,x))return!1}catch(K){return this.logInvalidCron($,K),!1}return await this.notifyOne($,x,X,!1),Y.set($.id,x),!0}if($.catchupPolicy==="all"){let K=this.findAllMatches($.cron,z,x,$.id);if(K.length===0)return!1;for(let W of K)await this.notifyOne($,W,X,W.getTime()!==x.getTime());return Y.set($.id,K[K.length-1]??x),!0}let Z=this.findMostRecentMatch($.cron,z,x,$.id);if(!Z)return!1;return await this.notifyOne($,Z,X,Z.getTime()!==x.getTime()),Y.set($.id,Z),!0}async notifyOne($,x,Y,X){let Q={event_type:"schedule",schedule_id:$.id,cron:$.cron,fired_at:x.toISOString(),catchup_policy:$.catchupPolicy};if(X)Q.catchup="true";if(await Y($.prompt,Q),this.onFired)try{await this.onFired($,x)}catch(z){this.logger.error("schedule onFired callback failed",{connector:this.config.name,id:$.id,error:z instanceof Error?z.message:String(z)})}}findMostRecentMatch($,x,Y,X){let Q=Math.min(Gw1,Math.floor((Y.getTime()-x.getTime())/60000)+1);for(let z=0;z<Q;z++){let Z=new Date(Y.getTime()-z*60000);try{if($q($,Z))return Z}catch(K){return this.logInvalidCron({id:X,cron:$},K),null}}return null}findAllMatches($,x,Y,X){let Q=Math.min(Gw1,Math.floor((Y.getTime()-x.getTime())/60000)+1),z=[];for(let Z=0;Z<Q;Z++){let K=new Date(x.getTime()+Z*60000);if(K.getTime()>Y.getTime())break;try{if($q($,K))z.push(K)}catch(W){return this.logInvalidCron({id:X,cron:$},W),[]}}return z}logInvalidCron($,x){this.logger.error("invalid cron expression in schedule",{connector:this.config.name,id:$.id,cron:$.cron,error:x instanceof Error?x.message:String(x)})}truncateToMinute($){let x=new Date($.getTime());return x.setSeconds(0,0),x}}import{dirname as eJ0}from"path";var $q0=new M8;class Yf{path;fs;constructor($){this.path=$.path,this.fs=$.fs??$q0,Object.freeze(this)}load(){let $=new Map;if(!this.fs.existsSync(this.path))return $;let x=JSON.parse(this.fs.readFileSync(this.path));if(x===null||typeof x!=="object")return $;for(let[Y,X]of Object.entries(x))if(typeof X==="string")$.set(Y,new Date(X));return $}save($){let x={};for(let[Y,X]of $)x[Y]=X.toISOString();this.fs.mkdirSync(eJ0(this.path),{recursive:!0}),this.fs.writeFileSync(this.path,`${JSON.stringify(x,null,2)}
545
+ `)}}var AD1=xL(RD1(),1);var uj0=($)=>{let x={};for(let[Y,X]of Object.entries($))x[Y]=X;return x};class kk extends fY{client;constructor($){super();this.client=$.client??new AD1.WebClient($.config.botToken),Object.freeze(this)}async call($){let x=$.body!==null&&typeof $.body==="object"?uj0($.body):{};return await this.client.apiCall($.path,x)}}var ZF=xL(XS1(),1);var zr0=new Set(["message","app_mention"]),Zr0=new Set([void 0,"thread_broadcast","bot_message","file_share"]);var J7=($,x)=>{let Y=$[x];return typeof Y==="string"?Y:void 0};class SC{ownBotUserId;ownBotId;now;dedup=new Map;constructor($){this.ownBotUserId=$.ownBotUserId,this.ownBotId=$.ownBotId,this.now=$.now??(()=>Date.now())}process($){let x=J7($,"type");if(!x||!zr0.has(x))return{skip:!0};let Y=J7($,"subtype");if(!Zr0.has(Y))return{skip:!0};let X=J7($,"channel")??"",Q=J7($,"event_ts")??J7($,"ts")??"",z=`${X}:${Q}`,Z=this.now();if(this.dedup.has(z))return{skip:!0};this.dedup.set(z,Z);for(let H of this.dedup.keys())if((this.dedup.get(H)??0)<Z-1e4)this.dedup.delete(H);let K=J7($,"user"),W=J7($,"bot_id");if(K===this.ownBotUserId)return{skip:!0};if(W===this.ownBotId)return{skip:!0};let w=(J7($,"text")??"").includes(`<@${this.ownBotUserId}>`),U=J7($,"thread_ts")??J7($,"ts")??"";return{skip:!1,content:JSON.stringify($),meta:{event_type:"slack",channel_id:X,user_id:K??"",mentioned:String(w),thread_ts:U},shouldReact:w,channel:X,timestamp:J7($,"ts")??""}}}var Kr0=m.object({event:m.record(m.string(),m.unknown()).optional()}),Wr0=new I6;class EC extends f2{config;logger;onAppCreated;preprocessEvent;app=null;constructor($){super();this.config=$.config,this.logger=$.logger??Wr0,this.onAppCreated=$.onAppCreated??null,this.preprocessEvent=$.preprocessEvent??null}async start($){let x=new ZF.App({token:this.config.botToken,appToken:this.config.appToken,socketMode:!0,logLevel:ZF.LogLevel.ERROR}),Y=await x.client.auth.test({token:this.config.botToken}),X=new SC({ownBotUserId:Y.user_id??"",ownBotId:Y.bot_id??""}),Q=this.preprocessEvent;if(x.use(async(z)=>{let Z=Kr0.safeParse(z);if(!Z.success||!Z.data.event)return;let K=Z.data.event,W=Q?Q(K):K;if(W===null)return;let V=X.process(W);if(V.skip)return;if(V.shouldReact)try{await x.client.reactions.add({token:this.config.botToken,channel:V.channel,timestamp:V.timestamp,name:"eyes"})}catch{}await $(V.content,V.meta)}),x.error(async(z)=>{this.logger.error("Slack error",{error:z instanceof Error?z.message:String(z)})}),this.onAppCreated)await this.onAppCreated(x);await x.start(),this.app=x}async stop(){if(!this.app)return;try{await this.app.stop()}catch($){this.logger.error("Slack stop error",{error:$ instanceof Error?$.message:String($)})}finally{this.app=null}}isAlive(){return this.app!==null}}import{join as CC}from"path";var Vr0=new M8,wr0=new L$,Ur0=new I6;class uC{fs;process;logger;dir;slackListenerOptions;scheduleListenerOptions;constructor($={}){this.fs=$.fs??Vr0,this.process=$.process??wr0,this.logger=$.logger??Ur0,this.dir=$.dir??O8,this.slackListenerOptions=$.slackListenerOptions??{},this.scheduleListenerOptions=$.scheduleListenerOptions??{},Object.freeze(this)}createListener($,x){if(x.type==="slack")return new EC({config:x,logger:this.logger,onAppCreated:this.slackListenerOptions.onAppCreated,preprocessEvent:this.slackListenerOptions.preprocessEvent});if(x.type==="gh")return new $f({config:x,process:this.process,logger:this.logger});if(x.type==="discord")return new rA({config:x,logger:this.logger});let Y=new Yf({path:CC(this.connectorDir($,x.id),"state.json"),fs:this.fs});return new xf({config:x,lastFiredStore:Y,logger:this.logger,onFired:this.scheduleListenerOptions.onFired})}createAdapter($){if($.type==="slack")return new kk({config:$});if($.type==="gh")return new eA({process:this.process});if($.type==="discord")return new QM({config:$});return null}connectorDir($,x){return CC(this.dir,"channels",$,"connectors",x)}channelDir($){return CC(this.dir,"channels",$)}}function yC($){switch($.type){case"slack":return[$.botToken,$.appToken];case"discord":return[$.botToken];case"gh":case"schedule":return[]}}function Hr0($,x){return $.type===x}function YX($,x,Y){let X=$.connectors.find((Q)=>Q.name===x);if(!X)throw Error(`connector "${x}" not found in channel "${$.name}"`);if(!Hr0(X,Y))throw Error(`connector "${x}" is type "${X.type}", not "${Y}"`);return X}class EV{millis(){return this.now().getTime()}iso(){return this.now().toISOString()}}class QX extends EV{now(){return new Date}}class CV{}class uV extends CV{generate(){return crypto.randomUUID()}}var Gr0=new QX,Jr0=new uV;class mC{store;factory;profileChecker;clock;idGenerator;constructor($){this.store=$.store,this.factory=$.factory,this.profileChecker=$.profileChecker,this.clock=$.clock??Gr0,this.idGenerator=$.idGenerator??Jr0,Object.freeze(this)}list(){return this.store.read().channels}get($){return this.list().find((x)=>x.name===$)??null}getById($){return this.list().find((x)=>x.id===$)??null}add($){let x=this.store.read();if(x.channels.some((X)=>X.name===$.name))throw Error(`channel "${$.name}" already exists`);let Y={id:this.idGenerator.generate(),name:$.name,delivery:$.delivery??"fanout",options:$.options??[],env:$.env??{},connectors:[]};return x.channels.push(Y),this.store.write(x),Y}setDelivery($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.delivery=x,this.store.write(Y)}setOptions($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.options=x,this.store.write(Y)}setEnv($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);X.env=x,this.store.write(Y)}remove($){let x=this.store.read(),Y=x.channels.findIndex((Q)=>Q.name===$);if(Y<0)throw Error(`channel "${$}" not found`);let X=x.channels[Y];if(X&&this.profileChecker.hasChannelRef(X.id))throw Error(`channel "${$}" is referenced by a profile`);x.channels.splice(Y,1),this.store.write(x)}rename($,x){let Y=this.store.read(),X=Y.channels.find((Q)=>Q.name===$);if(!X)throw Error(`channel "${$}" not found`);if(Y.channels.some((Q)=>Q.name===x))throw Error(`channel "${x}" already exists`);X.name=x,this.store.write(Y)}listConnectors($){return this.requireChannel(this.store.read(),$).connectors}getConnector($,x){let Y=this.get($);if(!Y)return null;return Y.connectors.find((X)=>X.name===x)??null}listAllConnectors(){let $=[];for(let x of this.list())for(let Y of x.connectors)$.push({...Y,channelId:x.id,channelName:x.name});return $}addConnector($,x){let Y=this.store.read(),X=this.requireChannel(Y,$);if(X.connectors.some((z)=>z.name===x.name))throw Error(`connector "${x.name}" already exists in channel "${$}"`);let Q=this.fromInput(x);return this.assertNoTokenCollision(Y,Q),X.connectors.push(Q),this.store.write(Y),Q}fromInput($){let x=this.idGenerator.generate(),Y=this.clock.iso(),X=Y,Q=Y;switch($.type){case"slack":return{id:x,type:"slack",name:$.name,botToken:$.botToken,appToken:$.appToken,createdAt:X,updatedAt:Q};case"gh":return{id:x,type:"gh",name:$.name,...$.pollInterval!==void 0?{pollInterval:$.pollInterval}:{},createdAt:X,updatedAt:Q};case"discord":return{id:x,type:"discord",name:$.name,botToken:$.botToken,createdAt:X,updatedAt:Q};case"schedule":return{id:x,type:"schedule",name:$.name,entries:$.entries??[],createdAt:X,updatedAt:Q}}}removeConnector($,x){let Y=this.store.read(),X=this.requireChannel(Y,$),Q=X.connectors.findIndex((z)=>z.name===x);if(Q<0)throw Error(`connector "${x}" not found in channel "${$}"`);X.connectors.splice(Q,1),this.store.write(Y)}renameConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=Q.connectors.find((Z)=>Z.name===x);if(!z)throw Error(`connector "${x}" not found in channel "${$}"`);if(Q.connectors.some((Z)=>Z.name===Y))throw Error(`connector "${Y}" already exists in channel "${$}"`);z.name=Y,z.updatedAt=this.clock.iso(),this.store.write(X)}updateSlackConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"slack"),Z={...z,botToken:Y.botToken??z.botToken,appToken:Y.appToken??z.appToken,updatedAt:this.clock.iso()};this.assertNoTokenCollision(X,Z),Object.assign(z,Z),this.store.write(X)}updateGhConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"gh");if(Y.pollInterval!==void 0)z.pollInterval=Y.pollInterval;z.updatedAt=this.clock.iso(),this.store.write(X)}updateDiscordConnector($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"discord"),Z={...z,botToken:Y.botToken??z.botToken,updatedAt:this.clock.iso()};this.assertNoTokenCollision(X,Z),Object.assign(z,Z),this.store.write(X)}listScheduleEntries($,x){let Y=this.requireChannel(this.store.read(),$);return YX(Y,x,"schedule").entries}addScheduleEntry($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"schedule"),Z={id:Y.id??this.idGenerator.generate(),cron:Y.cron,prompt:Y.prompt,enabled:Y.enabled??!0,catchupPolicy:Y.catchupPolicy??"latest"};return z.entries.push(Z),z.updatedAt=this.clock.iso(),this.store.write(X),Z}removeScheduleEntry($,x,Y){let X=this.store.read(),Q=this.requireChannel(X,$),z=YX(Q,x,"schedule"),Z=z.entries.findIndex((K)=>K.id===Y);if(Z<0)throw Error(`schedule entry "${Y}" not found`);z.entries.splice(Z,1),z.updatedAt=this.clock.iso(),this.store.write(X)}async call($,x,Y){let X=this.getConnector($,x);if(!X)throw Error(`connector "${x}" not found in channel "${$}"`);let Q=this.factory.createAdapter(X);if(!Q)throw Error(`connector type "${X.type}" does not support outbound calls`);return await Q.call(Y)}createListener($,x){let Y=this.get($);if(!Y)return null;let X=Y.connectors.find((Q)=>Q.name===x);if(!X)return null;return{config:X,channelId:Y.id,listener:this.factory.createListener(Y.id,X)}}createAllListeners(){let $=[];for(let x of this.list())for(let Y of x.connectors)$.push({config:Y,channelId:x.id,channelName:x.name,listener:this.factory.createListener(x.id,Y)});return $}requireChannel($,x){let Y=$.channels.find((X)=>X.name===x);if(!Y)throw Error(`channel "${x}" not found`);return Y}assertNoTokenCollision($,x){let Y=yC(x);if(Y.length===0)return;for(let X of $.channels)for(let Q of X.connectors){if(Q.id===x.id)continue;for(let z of yC(Q))if(Y.includes(z))throw Error(`token already in use by connector "${Q.name}" in channel "${X.name}"`)}}}import{join as zS1}from"path";var qr0=new L$,Dr0=new M8,Br0=new I6;class hC{channels;mcp;gateway;process;fs;logger;pidDir;constructor($){this.channels=$.channels,this.mcp=$.mcp,this.gateway=$.gateway,this.process=$.process??qr0,this.fs=$.fs??Dr0,this.logger=$.logger??Br0,this.pidDir=zS1($.dir??O8,"claude"),Object.freeze(this)}async launch($){let x=this.channels.get($.channel)??this.channels.getById($.channel);if(!x)throw Error(`channel "${$.channel}" not found`);if($.profileName&&this.isRunning($.profileName))throw Error(`profile "${$.profileName}" is already running`);let Y=$.cwd??globalThis.process.cwd();if(($.installMcp??!0)&&!this.mcp.findInstalledName(Y))this.mcp.install(Y),this.logger.info("added funnel MCP to .mcp.json",{cwd:Y});if(!this.gateway.isRunning())this.logger.info("starting gateway automatically"),await this.gateway.start();if($.profileName)this.writePidFile($.profileName),this.installCleanup($.profileName);let Q=this.buildArgs(x.options,$.userArgs??[],Y),z=this.buildEnv(x.id,x.env);this.logger.info("claude launch",{channel:$.channel,channelId:x.id,cwd:Y});try{return await this.process.attach(["claude",...Q],{cwd:Y,env:z,onSpawned:$.onSpawned})}finally{if($.profileName)this.removePidFile($.profileName)}}isRunning($){let x=this.readPid($);if(!x)return!1;return this.isProcessAlive(x)}pidPath($){return zS1(this.pidDir,`${$}.pid`)}readPid($){let x=this.pidPath($);if(!this.fs.existsSync(x))return null;try{let Y=this.fs.readFileSync(x).trim(),X=Number(Y);if(!X||X<=0)return null;return X}catch{return null}}writePidFile($){this.fs.mkdirSync(this.pidDir,{recursive:!0}),this.fs.writeFileSync(this.pidPath($),String(globalThis.process.pid))}removePidFile($){let x=this.pidPath($);if(this.fs.existsSync(x))this.fs.unlink(x)}installCleanup($){globalThis.process.once("exit",()=>this.removePidFile($))}isProcessAlive($){let x=this.process.runSync(["ps","-p",String($),"-o","state="]);if(x.exitCode!==0)return!1;let Y=x.stdout.trim();if(!Y)return!1;return!Y.startsWith("Z")}buildArgs($,x,Y){let X=[...$,...x],Q=this.mcp.findInstalledName(Y);if(Q&&!X.includes("--dangerously-load-development-channels")&&!X.includes("--channels"))X.push("--dangerously-load-development-channels",`server:${Q}`);return X}buildEnv($,x){let Y={};for(let[X,Q]of Object.entries(x))Y[X]=Q;for(let[X,Q]of Object.entries(globalThis.process.env))if(typeof Q==="string")Y[X]=Q;return Y.FUNNEL_CHANNEL_ID=$,Y}}var Fr0=384;class gC extends HK{dirs;files;mtimes;modes;now;constructor($={}){super();this.dirs=new Set($.dirs??[]),this.files=new Map(Object.entries($.files??{})),this.mtimes=new Map(Object.entries($.mtimes??{})),this.modes=new Map(Object.entries($.modes??{})),this.now=$.now??(()=>Date.now())}existsSync($){return this.dirs.has($)||this.files.has($)}readFileSync($){return this.files.get($)??""}writeFileSync($,x){this.files.set($,x),this.touch($)}writeSecretFileSync($,x){this.files.set($,x),this.modes.set($,Fr0),this.touch($)}appendFileSync($,x){let Y=this.files.get($)??"";this.files.set($,Y+x),this.touch($)}unlink($){this.files.delete($),this.mtimes.delete($),this.modes.delete($)}mkdirSync($,x){this.dirs.add($)}readdirSync($){let x=$.endsWith("/")?$:`${$}/`,Y=[];for(let X of this.files.keys()){if(!X.startsWith(x))continue;let Q=X.slice(x.length);if(!Q.includes("/"))Y.push(Q)}return Y}statSync($){let x=this.mtimes.get($);if(x===void 0)throw Error(`not found: ${$}`);return{mtimeMs:x,mode:this.modes.get($)??null}}setMtime($,x){this.mtimes.set($,x)}setMode($,x){this.modes.set($,x)}touch($){if(!this.mtimes.has($))this.mtimes.set($,this.now());else this.mtimes.set($,this.now())}}class pC extends CV{counter=0;prefix;constructor($={}){super();this.prefix=$.prefix??"id"}generate(){return this.counter++,`${this.prefix}-${this.counter}`}}import{join as Or0}from"path";var Lr0=m.object({botToken:m.string().optional(),appToken:m.string().optional()}).optional(),Nr0=m.object({type:m.literal("slack"),name:m.string(),botToken:m.string().optional(),appToken:m.string().optional(),env:Lr0}),Pr0=m.object({botToken:m.string().optional()}).optional(),jr0=m.object({type:m.literal("discord"),name:m.string(),botToken:m.string().optional(),env:Pr0}),Ir0=m.object({type:m.literal("gh"),name:m.string(),pollInterval:m.number().int().positive().optional()}),vr0=m.object({type:m.literal("schedule"),name:m.string()}),Mr0=m.discriminatedUnion("type",[Nr0,jr0,Ir0,vr0]),_r0=m.object({name:m.string(),options:m.array(m.string()).optional(),env:m.record(m.string(),m.string()).optional(),connectors:m.array(Mr0).optional()}),ZS1=m.object({$schema:m.string().optional(),channels:m.array(_r0).min(1)}),KF="funnel.json",KS1=".env.local";var br0=/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$/,Rr0=($)=>{if($.length<2)return $;let x=$[0],Y=$[$.length-1];if(x==='"'&&Y==='"')return $.slice(1,-1);if(x==="'"&&Y==="'")return $.slice(1,-1);return $};class iC{fs;constructor($){this.fs=$.fs,Object.freeze(this)}read($){let x=Or0($,KS1);if(!this.fs.existsSync(x))return{};let Y=this.fs.readFileSync(x),X={};for(let Q of Y.split(`
546
+ `)){let z=Q.trim();if(z===""||z.startsWith("#"))continue;let Z=z.match(br0);if(!Z)continue;let K=Z[1],W=Z[2];if(!K)continue;X[K]=Rr0(W??"")}return X}}import{join as Ar0}from"path";class lC{fs;constructor($){this.fs=$.fs,Object.freeze(this)}read($){let x=Ar0($,KF);if(!this.fs.existsSync(x))return null;let Y=this.fs.readFileSync(x),X=(()=>{try{return JSON.parse(Y)}catch(z){let Z=z instanceof Error?z.message:String(z);throw Error(`${KF} is not valid JSON: ${Z}`)}})(),Q=ZS1.safeParse(X);if(!Q.success)throw Error(`${KF} is invalid: ${Q.error.message}`);return Q.data}}var fr0=($,x)=>{if($.length!==x.length)return!1;for(let Y=0;Y<$.length;Y++)if($[Y]!==x[Y])return!1;return!0},kr0=($,x)=>{let Y=Object.keys($);if(Y.length!==Object.keys(x).length)return!1;for(let X of Y)if($[X]!==x[X])return!1;return!0};class nC{channels;dotenv;prompter;env;constructor($){this.channels=$.channels,this.dotenv=$.dotenv,this.prompter=$.prompter,this.env=$.env??process.env,Object.freeze(this)}async ensure($,x){let Y=this.channels.get($.name);if(!Y)this.channels.add({name:$.name,options:$.options??[],env:$.env??{}});else{let K=$.options??[],W=$.env??{};if(!fr0(Y.options,K))this.channels.setOptions($.name,K);if(!kr0(Y.env,W))this.channels.setEnv($.name,W)}if($.connectors===void 0)return{touched:[],removed:[]};let X=this.dotenv.read(x),Q=[],z=new Set;for(let K of $.connectors){let W=await this.ensureConnector($.name,K,X);Q.push({name:W.name,changed:W.changed}),z.add(W.id)}let Z=this.removeExtras($.name,z);return{touched:Q,removed:Z}}async ensureConnector($,x,Y){if(x.type==="slack")return await this.ensureSlack($,x,Y);if(x.type==="discord")return await this.ensureDiscord($,x,Y);if(x.type==="gh")return this.ensureGh($,x);return this.ensureSchedule($,x)}async ensureSlack($,x,Y){let X=this.findExistingSlack($,x.name),Q=await this.resolveField({literal:x.botToken,envVar:x.env?.botToken,dotenv:Y,label:`${x.name}.botToken`,existing:X?.botToken}),z=await this.resolveField({literal:x.appToken,envVar:x.env?.appToken,dotenv:Y,label:`${x.name}.appToken`,existing:X?.appToken});if(X){if(X.botToken!==Q||X.appToken!==z)return this.channels.updateSlackConnector($,x.name,{botToken:Q,appToken:z}),{id:X.id,name:x.name,changed:!0};return{id:X.id,name:x.name,changed:!1}}let Z=this.findSlackByToken($,[Q,z]);if(Z){if(this.channels.renameConnector($,Z.name,x.name),Z.botToken!==Q||Z.appToken!==z)this.channels.updateSlackConnector($,x.name,{botToken:Q,appToken:z});return{id:Z.id,name:x.name,changed:!0}}return{id:this.channels.addConnector($,{type:"slack",name:x.name,botToken:Q,appToken:z}).id,name:x.name,changed:!0}}async ensureDiscord($,x,Y){let X=this.findExistingDiscord($,x.name),Q=await this.resolveField({literal:x.botToken,envVar:x.env?.botToken,dotenv:Y,label:`${x.name}.botToken`,existing:X?.botToken});if(X){if(X.botToken!==Q)return this.channels.updateDiscordConnector($,x.name,{botToken:Q}),{id:X.id,name:x.name,changed:!0};return{id:X.id,name:x.name,changed:!1}}let z=this.findDiscordByToken($,Q);if(z){if(this.channels.renameConnector($,z.name,x.name),z.botToken!==Q)this.channels.updateDiscordConnector($,x.name,{botToken:Q});return{id:z.id,name:x.name,changed:!0}}return{id:this.channels.addConnector($,{type:"discord",name:x.name,botToken:Q}).id,name:x.name,changed:!0}}ensureGh($,x){let Y=this.channels.getConnector($,x.name);if(Y&&Y.type!=="gh")throw Error(`connector "${x.name}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "gh"`);if(Y&&Y.type==="gh"){if(x.pollInterval!==void 0&&Y.pollInterval!==x.pollInterval)return this.channels.updateGhConnector($,x.name,{pollInterval:x.pollInterval}),{id:Y.id,name:x.name,changed:!0};return{id:Y.id,name:x.name,changed:!1}}return{id:this.channels.addConnector($,{type:"gh",name:x.name,...x.pollInterval!==void 0?{pollInterval:x.pollInterval}:{}}).id,name:x.name,changed:!0}}ensureSchedule($,x){let Y=this.channels.getConnector($,x.name);if(Y&&Y.type!=="schedule")throw Error(`connector "${x.name}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "schedule"`);if(Y&&Y.type==="schedule")return{id:Y.id,name:x.name,changed:!1};return{id:this.channels.addConnector($,{type:"schedule",name:x.name}).id,name:x.name,changed:!0}}findExistingSlack($,x){let Y=this.channels.getConnector($,x);if(!Y)return null;if(Y.type!=="slack")throw Error(`connector "${x}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "slack"`);return Y}findExistingDiscord($,x){let Y=this.channels.getConnector($,x);if(!Y)return null;if(Y.type!=="discord")throw Error(`connector "${x}" exists in channel "${$}" with type "${Y.type}", funnel.json declares "discord"`);return Y}findSlackByToken($,x){let Y=this.channels.get($);if(!Y)return null;for(let X of Y.connectors){if(X.type!=="slack")continue;if(x.includes(X.botToken)||x.includes(X.appToken))return X}return null}findDiscordByToken($,x){let Y=this.channels.get($);if(!Y)return null;for(let X of Y.connectors){if(X.type!=="discord")continue;if(X.botToken===x)return X}return null}removeExtras($,x){let Y=this.channels.get($);if(!Y)return[];let X=Y.connectors.filter((Q)=>!x.has(Q.id));for(let Q of X)this.channels.removeConnector($,Q.name);return X.map((Q)=>Q.name)}async resolveField($){if($.literal!==void 0&&$.envVar!==void 0)throw Error(`${$.label} is set both as a literal and as env.${$.label.split(".").pop()}; pick one`);if($.literal!==void 0&&$.literal!=="")return $.literal;if($.envVar!==void 0&&$.envVar!==""){let x=this.env[$.envVar];if(x)return x;let Y=$.dotenv[$.envVar];if(Y)return Y;throw Error(`${$.label} references env var "${$.envVar}" but it is not set in process env or .env.local`)}if($.existing)return $.existing;return await this.prompter.promptSecret($.label)}}class dC extends NQ{file=null;entries=[];info($,x){this.entries.push({level:"info",message:$,meta:x})}warn($,x){this.entries.push({level:"warn",message:$,meta:x})}error($,x){this.entries.push({level:"error",message:$,meta:x})}clear(){this.entries.length=0}}import{join as WS1}from"path";var VS1="funnel",Tr0="funnel",cr0=m.object({command:m.string().optional(),args:m.array(m.string()).optional()}),Sr0=m.object({mcpServers:m.record(m.string(),cr0).optional()}),Er0=new M8;class aC{fs;constructor($={}){this.fs=$.fs??Er0,Object.freeze(this)}install($){if(!this.fs.existsSync($))throw Error(`repository does not exist: ${$}`);let x=this.readConfig($),Y=x.mcpServers??{},Q=this.findServerName(Y)??Tr0;Y[Q]={command:VS1,args:["mcp"]},this.writeConfig($,{...x,mcpServers:Y})}uninstall($){if(!this.fs.existsSync($))return;let x=this.readConfig($),Y=x.mcpServers??{},X=this.findServerName(Y);if(!X)return;let Q={...Y};delete Q[X],this.writeConfig($,{...x,mcpServers:Q})}findInstalledName($){let x=this.readConfig($);return this.findServerName(x.mcpServers??{})}findServerName($){for(let x of Object.entries($)){let Y=x[0];if(x[1]?.command===VS1)return Y}return null}readConfig($){let x=WS1($,".mcp.json");if(!this.fs.existsSync(x))return{};let Y=this.fs.readFileSync(x).trim();if(!Y)return{};let X;try{X=JSON.parse(Y)}catch(z){throw Error(`invalid .mcp.json (${x}): ${z instanceof Error?z.message:String(z)}`)}let Q=Sr0.safeParse(X);if(!Q.success)throw Error(`invalid .mcp.json (${x}): ${Q.error.message}`);return Q.data}writeConfig($,x){let Y=WS1($,".mcp.json");this.fs.writeFileSync(Y,`${JSON.stringify(x,null,2)}
547
+ `)}}var wS1={exitCode:0,stdout:"",stderr:""};class sC extends cW{calls=[];killed=[];handler=()=>wS1;syncHandler=()=>wS1;on($){return this.handler=$,this}onSync($){return this.syncHandler=$,this}async run($,x={}){this.calls.push({kind:"run",command:$,options:x});let Y=await this.handler($);return{exitCode:Y.exitCode??0,stdout:Y.stdout??"",stderr:Y.stderr??""}}runSync($){this.calls.push({kind:"runSync",command:$});let x=this.syncHandler($);return{exitCode:x.exitCode??0,stdout:x.stdout??"",stderr:x.stderr??""}}async attach($,x={}){if(this.calls.push({kind:"attach",command:$,options:x}),x.onSpawned)x.onSpawned(1);return(await this.handler($)).exitCode??0}detach($,x={}){this.calls.push({kind:"detach",command:$,options:x})}kill($,x="SIGTERM"){this.calls.push({kind:"kill",command:[String($),x]}),this.killed.push({pid:$,signal:x})}}class oC{store;constructor($){this.store=$.store,Object.freeze(this)}list(){return this.store.read().profiles}get($){return this.list().find((x)=>x.name===$)??null}getDefault(){return this.list()[0]??null}add($){let x=this.store.read();if(x.profiles.some((Y)=>Y.name===$.name))throw Error(`profile "${$.name}" already exists`);if(!x.channels.some((Y)=>Y.id===$.channelId))throw Error(`channel id "${$.channelId}" not found`);x.profiles.push($),this.store.write(x)}remove($){let x=this.store.read(),Y=x.profiles.findIndex((X)=>X.name===$);if(Y<0)throw Error(`profile "${$}" not found`);x.profiles.splice(Y,1),this.store.write(x)}rename($,x){let Y=this.store.read(),X=Y.profiles.find((Q)=>Q.name===$);if(!X)throw Error(`profile "${$}" not found`);if(Y.profiles.some((Q)=>Q.name===x))throw Error(`profile "${x}" already exists`);X.name=x,this.store.write(Y)}asDefault($){let x=this.store.read(),Y=x.profiles.findIndex((Q)=>Q.name===$);if(Y<0)throw Error(`profile "${$}" not found`);if(Y===0)return;let[X]=x.profiles.splice(Y,1);if(!X)return;x.profiles.unshift(X),this.store.write(x)}hasChannelRef($){return this.store.read().profiles.some((x)=>x.channelId===$)}update($,x){let Y=this.store.read(),X=Y.profiles.find((Q)=>Q.name===$);if(!X)throw Error(`profile "${$}" not found`);if(x.channelId!==void 0){if(!Y.channels.some((Q)=>Q.id===x.channelId))throw Error(`channel id "${x.channelId}" not found`);X.channelId=x.channelId}if(x.path!==void 0)X.path=x.path;this.store.write(Y)}}import{stderr as WF,stdin as e7}from"process";class rC{}var Cr0="*",ur0="\r",US1=`
548
548
  `,yr0=String.fromCharCode(8),mr0=String.fromCharCode(127),hr0=String.fromCharCode(3),gr0=String.fromCharCode(4);class tC extends rC{async promptSecret($){if(!e7.isTTY)throw Error(`cannot prompt for "${$}": stdin is not a TTY. Set the matching env var or run \`fnl channels <ch> connectors add ...\` first.`);WF.write(`${$}: `);let x=e7.isRaw;e7.setRawMode(!0),e7.resume();try{return await this.readSecret()}finally{e7.setRawMode(x),e7.pause(),WF.write(US1)}}readSecret(){return new Promise(($,x)=>{let Y="",X=(Q)=>{for(let z of Q){let Z=String.fromCharCode(z);if(Z===US1||Z===ur0){e7.off("data",X),$(Y);return}if(Z===hr0){e7.off("data",X),x(Error("prompt cancelled"));return}if(Z===gr0){if(e7.off("data",X),Y.length===0)x(Error("prompt cancelled"));else $(Y);return}if(Z===yr0||Z===mr0){if(Y.length>0)Y=Y.slice(0,-1),WF.write("\b \b");continue}Y+=Z,WF.write(Cr0)}};e7.on("data",X)})}}var pr0=($={})=>({version:G2,channels:[],profiles:[],...$});class eC extends GK{state;constructor($){super();this.state=pr0($)}read(){return this.state}write($){this.state=$}}class $u extends EV{current;constructor($={}){super();this.current=$.start??new Date(0)}now(){return new Date(this.current.getTime())}set($){this.current=$}advance($){this.current=new Date(this.current.getTime()+$)}}var HS1=m.object({content:m.string().min(1),meta:m.record(m.string(),m.string()).optional(),connector:m.string().min(1).optional()}),GS1=m.object({ok:m.literal(!0),offset:m.number().int().nonnegative()});var ir0={state:"offline"};class xu{port;isDaemonRunning;getToken;constructor($){this.port=$.port,this.isDaemonRunning=$.isDaemonRunning,this.getToken=$.getToken??(()=>null),Object.freeze(this)}async publish($,x){if(!this.isDaemonRunning())return ir0;try{let Y=`http://localhost:${this.port}/channels/${encodeURIComponent($)}/publish`,X=await fetch(Y,{method:"POST",headers:{...this.authHeaders(),"content-type":"application/json"},body:JSON.stringify(x)});if(!X.ok)return{state:"error",reason:await X.text()||`HTTP ${X.status}`};let Q=GS1.safeParse(await X.json());if(!Q.success)return{state:"error",reason:"malformed daemon response"};return{state:"ok",offset:Q.data.offset}}catch(Y){return{state:"error",reason:Y instanceof Error?Y.message:String(Y)}}}authHeaders(){let $=this.getToken();return $?{authorization:`Bearer ${$}`}:{}}}import{join as Qu}from"path";import{existsSync as lr0}from"fs";import{dirname as nr0,resolve as Yu}from"path";import{fileURLToPath as dr0}from"url";var JS1=()=>{let $=nr0(dr0(import.meta.url)),x=[Yu($,"./daemon.ts"),Yu($,"./daemon.js"),Yu($,"./gateway/daemon.js")];for(let Y of x)if(lr0(Y))return Y;throw Error(`daemon script not found (looked in ${x.join(", ")})`)};var ar0=9742,sr0="/tmp/funnel",or0=5000,rr0=2000,qS1=100,tr0=200,er0=new L$,$t0=new M8,xt0=new QX,Yt0=($)=>new Promise((x)=>{setTimeout(x,$)});class Xu{process;fs;clock;dir;pidFile;logDir;gatewayLog;tmpDir;port;sleep;constructor($={}){this.process=$.process??er0,this.fs=$.fs??$t0,this.clock=$.clock??xt0,this.dir=$.dir??O8,this.tmpDir=$.tmpDir??sr0,this.pidFile=Qu(this.dir,"gateway.pid"),this.logDir=Qu(this.tmpDir,"events"),this.gatewayLog=Qu(this.tmpDir,"gateway.log"),this.port=$.port??ar0,this.sleep=$.sleep??Yt0,Object.freeze(this)}isRunning(){let $=this.readPid();if(!$)return!1;return this.isProcessAlive($)}getStatus(){let $=this.readPid(),x=$!==null&&this.isProcessAlive($);return{running:x,pid:x?$:null,port:this.port}}async start($={}){if(this.isRunning())return!0;this.fs.mkdirSync(this.tmpDir,{recursive:!0});let x=JS1(),Y=this.buildStartCommand(x,$);this.process.detach(["bash","-c",Y]);let X=this.clock.millis()+or0;while(this.clock.millis()<X){if(this.isRunning())return!0;await this.sleep(qS1)}return this.isRunning()}buildStartCommand($,x={}){let X=x.caffeinate!==!1&&globalThis.process.platform==="darwin"?"caffeinate -i ":"",Q=`funnel-gateway[${this.dir}]`;return`nohup ${X}bun ${$} ${Q} >> ${this.gatewayLog} 2>&1 &`}async stop(){let $=this.readPid();if(!$)return!0;if(!this.isProcessAlive($))return this.removePid(),!0;try{this.process.kill($,"SIGTERM")}catch{return!1}let x=this.clock.millis()+rr0;while(this.clock.millis()<x){if(!this.isProcessAlive($))return this.removePid(),!0;await this.sleep(qS1)}try{this.process.kill($,"SIGKILL")}catch{}return await this.sleep(tr0),this.removePid(),!this.isProcessAlive($)}async restart($={}){let x=this.isRunning();if($.onlyIfRunning&&!x)return{ok:!0,wasRunning:!1,stopped:!1,started:!1};let Y=x?await this.stop():!0;if(!Y)return{ok:!1,wasRunning:x,stopped:!1,started:!1};let X=await this.start({caffeinate:$.caffeinate});return{ok:X,wasRunning:x,stopped:Y,started:X}}getLogDir(){return this.logDir}getGatewayLog(){return this.gatewayLog}getPort(){return this.port}readPid(){if(!this.fs.existsSync(this.pidFile))return null;try{let $=this.fs.readFileSync(this.pidFile).trim(),x=Number($);if(!x||x<=0)return null;return x}catch{return null}}removePid(){this.fs.unlink(this.pidFile)}isProcessAlive($){let x=this.process.runSync(["ps","-p",String($),"-o","state="]);if(x.exitCode!==0)return!1;let Y=x.stdout.trim();if(!Y)return!1;return!Y.startsWith("Z")}}import{existsSync as dt0,mkdirSync as at0}from"fs";import{join as xE1}from"path";import{timingSafeEqual as Qt0}from"crypto";var VF=($)=>{return async(x,Y)=>{let z=(x.req.header("authorization")??"").match(/^Bearer\s+(.+)$/i)?.[1]??"";if(!wF(z,$.expected))return x.text("unauthorized",401);return await Y()}},wF=($,x)=>{let Y=Buffer.from($,"utf-8"),X=Buffer.from(x,"utf-8"),Q=Math.max(Y.length,X.length,1),z=Buffer.alloc(Q),Z=Buffer.alloc(Q);return Y.copy(z),X.copy(Z),Qt0(z,Z)&&Y.length===X.length};var zu=($,x,Y)=>{return(X,Q)=>{let z=-1;return Z(0);async function Z(K){if(K<=z)throw Error("next() called multiple times");z=K;let W,V=!1,w;if($[K])w=$[K][0][0],X.req.routeIndex=K;else w=K===$.length&&Q||void 0;if(w)try{W=await w(X,()=>Z(K+1))}catch(U){if(U instanceof Error&&x)X.error=U,W=await x(U,X),V=!0;else throw U}else if(X.finalized===!1&&Y)W=await Y(X);if(W&&(X.finalized===!1||V))X.res=W;return X}}};var QK=class extends Error{res;status;constructor($=500,x){super(x?.message,{cause:x?.cause});this.res=x?.res,this.status=$}getResponse(){if(this.res)return new Response(this.res.body,{status:this.status,headers:this.res.headers});return new Response(this.message,{status:this.status})}};var DS1=Symbol();var BS1=async($,x=Object.create(null))=>{let{all:Y=!1,dot:X=!1}=x,z=($ instanceof UF?$.raw.headers:$.headers).get("Content-Type");if(z?.startsWith("multipart/form-data")||z?.startsWith("application/x-www-form-urlencoded"))return Xt0($,{all:Y,dot:X});return{}};async function Xt0($,x){let Y=await $.formData();if(Y)return zt0(Y,x);return{}}function zt0($,x){let Y=Object.create(null);if($.forEach((X,Q)=>{if(!(x.all||Q.endsWith("[]")))Y[Q]=X;else Zt0(Y,Q,X)}),x.dot)Object.entries(Y).forEach(([X,Q])=>{if(X.includes("."))Kt0(Y,X,Q),delete Y[X]});return Y}var Zt0=($,x,Y)=>{if($[x]!==void 0)if(Array.isArray($[x]))$[x].push(Y);else $[x]=[$[x],Y];else if(!x.endsWith("[]"))$[x]=Y;else $[x]=[Y]},Kt0=($,x,Y)=>{if(/(?:^|\.)__proto__\./.test(x))return;let X=$,Q=x.split(".");Q.forEach((z,Z)=>{if(Z===Q.length-1)X[z]=Y;else{if(!X[z]||typeof X[z]!=="object"||Array.isArray(X[z])||X[z]instanceof File)X[z]=Object.create(null);X=X[z]}})};var Ku=($)=>{let x=$.split("/");if(x[0]==="")x.shift();return x},FS1=($)=>{let{groups:x,path:Y}=Wt0($),X=Ku(Y);return Vt0(X,x)},Wt0=($)=>{let x=[];return $=$.replace(/\{[^}]+\}/g,(Y,X)=>{let Q=`@${X}`;return x.push([Q,Y]),Q}),{groups:x,path:$}},Vt0=($,x)=>{for(let Y=x.length-1;Y>=0;Y--){let[X]=x[Y];for(let Q=$.length-1;Q>=0;Q--)if($[Q].includes(X)){$[Q]=$[Q].replace(X,x[Y][1]);break}}return $},HF={},LS1=($,x)=>{if($==="*")return"*";let Y=$.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);if(Y){let X=`${$}#${x}`;if(!HF[X])if(Y[2])HF[X]=x&&x[0]!==":"&&x[0]!=="*"?[X,Y[1],new RegExp(`^${Y[2]}(?=/${x})`)]:[$,Y[1],new RegExp(`^${Y[2]}$`)];else HF[X]=[$,Y[1],!0];return HF[X]}return null},XK=($,x)=>{try{return x($)}catch{return $.replace(/(?:%[0-9A-Fa-f]{2})+/g,(Y)=>{try{return x(Y)}catch{return Y}})}},wt0=($)=>XK($,decodeURI),Wu=($)=>{let x=$.url,Y=x.indexOf("/",x.indexOf(":")+4),X=Y;for(;X<x.length;X++){let Q=x.charCodeAt(X);if(Q===37){let z=x.indexOf("?",X),Z=x.indexOf("#",X),K=z===-1?Z===-1?void 0:Z:Z===-1?z:Math.min(z,Z),W=x.slice(Y,K);return wt0(W.includes("%25")?W.replace(/%25/g,"%2525"):W)}else if(Q===63||Q===35)break}return x.slice(Y,X)};var NS1=($)=>{let x=Wu($);return x.length>1&&x.at(-1)==="/"?x.slice(0,-1):x},XX=($,x,...Y)=>{if(Y.length)x=XX(x,...Y);return`${$?.[0]==="/"?"":"/"}${$}${x==="/"?"":`${$?.at(-1)==="/"?"":"/"}${x?.[0]==="/"?x.slice(1):x}`}`},GF=($)=>{if($.charCodeAt($.length-1)!==63||!$.includes(":"))return null;let x=$.split("/"),Y=[],X="";return x.forEach((Q)=>{if(Q!==""&&!/\:/.test(Q))X+="/"+Q;else if(/\:/.test(Q))if(/\?/.test(Q)){if(Y.length===0&&X==="")Y.push("/");else Y.push(X);let z=Q.replace("?","");X+="/"+z,Y.push(X)}else X+="/"+Q}),Y.filter((Q,z,Z)=>Z.indexOf(Q)===z)},Zu=($)=>{if(!/[%+]/.test($))return $;if($.indexOf("+")!==-1)$=$.replace(/\+/g," ");return $.indexOf("%")!==-1?XK($,yV):$},PS1=($,x,Y)=>{let X;if(!Y&&x&&!/[%+]/.test(x)){let Z=$.indexOf("?",8);if(Z===-1)return;if(!$.startsWith(x,Z+1))Z=$.indexOf(`&${x}`,Z+1);while(Z!==-1){let K=$.charCodeAt(Z+x.length+1);if(K===61){let W=Z+x.length+2,V=$.indexOf("&",W);return Zu($.slice(W,V===-1?void 0:V))}else if(K==38||isNaN(K))return"";Z=$.indexOf(`&${x}`,Z+1)}if(X=/[%+]/.test($),!X)return}let Q={};X??=/[%+]/.test($);let z=$.indexOf("?",8);while(z!==-1){let Z=$.indexOf("&",z+1),K=$.indexOf("=",z);if(K>Z&&Z!==-1)K=-1;let W=$.slice(z+1,K===-1?Z===-1?void 0:Z:K);if(X)W=Zu(W);if(z=Z,W==="")continue;let V;if(K===-1)V="";else if(V=$.slice(K+1,Z===-1?void 0:Z),X)V=Zu(V);if(Y){if(!(Q[W]&&Array.isArray(Q[W])))Q[W]=[];Q[W].push(V)}else Q[W]??=V}return x?Q[x]:Q},jS1=PS1,IS1=($,x)=>{return PS1($,x,!0)},yV=decodeURIComponent;var vS1=($)=>XK($,yV),UF=class{raw;#$;#x;routeIndex=0;path;bodyCache={};constructor($,x="/",Y=[[]]){this.raw=$,this.path=x,this.#x=Y,this.#$={}}param($){return $?this.#Y($):this.#z()}#Y($){let x=this.#x[0][this.routeIndex][1][$],Y=this.#X(x);return Y&&/\%/.test(Y)?vS1(Y):Y}#z(){let $={},x=Object.keys(this.#x[0][this.routeIndex][1]);for(let Y of x){let X=this.#X(this.#x[0][this.routeIndex][1][Y]);if(X!==void 0)$[Y]=/\%/.test(X)?vS1(X):X}return $}#X($){return this.#x[1]?this.#x[1][$]:$}query($){return jS1(this.url,$)}queries($){return IS1(this.url,$)}header($){if($)return this.raw.headers.get($)??void 0;let x={};return this.raw.headers.forEach((Y,X)=>{x[X]=Y}),x}async parseBody($){return BS1(this,$)}#Q=($)=>{let{bodyCache:x,raw:Y}=this,X=x[$];if(X)return X;let Q=Object.keys(x)[0];if(Q)return x[Q].then((z)=>{if(Q==="json")z=JSON.stringify(z);return new Response(z)[$]()});return x[$]=Y[$]()};json(){return this.#Q("text").then(($)=>JSON.parse($))}text(){return this.#Q("text")}arrayBuffer(){return this.#Q("arrayBuffer")}bytes(){return this.#Q("arrayBuffer").then(($)=>new Uint8Array($))}blob(){return this.#Q("blob")}formData(){return this.#Q("formData")}addValidatedData($,x){this.#$[$]=x}valid($){return this.#$[$]}get url(){return this.raw.url}get method(){return this.raw.method}get[DS1](){return this.#x}get matchedRoutes(){return this.#x[0].map(([[,$]])=>$)}get routePath(){return this.#x[0].map(([[,$]])=>$)[this.routeIndex].path}};var MS1={Stringify:1,BeforeStream:2,Stream:3},Ut0=($,x)=>{let Y=new String($);return Y.isEscaped=!0,Y.callbacks=x,Y};var Vu=async($,x,Y,X,Q)=>{if(typeof $==="object"&&!($ instanceof String)){if(!($ instanceof Promise))$=$.toString();if($ instanceof Promise)$=await $}let z=$.callbacks;if(!z?.length)return Promise.resolve($);if(Q)Q[0]+=$;else Q=[$];let Z=Promise.all(z.map((K)=>K({phase:x,buffer:Q,context:X}))).then((K)=>Promise.all(K.filter(Boolean).map((W)=>Vu(W,x,!1,X,Q))).then(()=>Q[0]));if(Y)return Ut0(await Z,z);else return Z};var Ht0="text/plain; charset=UTF-8",wu=($,x)=>{return{"Content-Type":$,...x}},mV=($,x)=>new Response($,x),_S1=class{#$;#x;env={};#Y;finalized=!1;error;#z;#X;#Q;#w;#W;#V;#K;#U;#H;constructor($,x){if(this.#$=$,x)this.#X=x.executionCtx,this.env=x.env,this.#V=x.notFoundHandler,this.#H=x.path,this.#U=x.matchResult}get req(){return this.#x??=new UF(this.#$,this.#H,this.#U),this.#x}get event(){if(this.#X&&"respondWith"in this.#X)return this.#X;else throw Error("This context has no FetchEvent")}get executionCtx(){if(this.#X)return this.#X;else throw Error("This context has no ExecutionContext")}get res(){return this.#Q||=mV(null,{headers:this.#K??=new Headers})}set res($){if(this.#Q&&$){$=mV($.body,$);for(let[x,Y]of this.#Q.headers.entries()){if(x==="content-type")continue;if(x==="set-cookie"){let X=this.#Q.headers.getSetCookie();$.headers.delete("set-cookie");for(let Q of X)$.headers.append("set-cookie",Q)}else $.headers.set(x,Y)}}this.#Q=$,this.finalized=!0}render=(...$)=>{return this.#W??=(x)=>this.html(x),this.#W(...$)};setLayout=($)=>this.#w=$;getLayout=()=>this.#w;setRenderer=($)=>{this.#W=$};header=($,x,Y)=>{if(this.finalized)this.#Q=mV(this.#Q.body,this.#Q);let X=this.#Q?this.#Q.headers:this.#K??=new Headers;if(x===void 0)X.delete($);else if(Y?.append)X.append($,x);else X.set($,x)};status=($)=>{this.#z=$};set=($,x)=>{this.#Y??=new Map,this.#Y.set($,x)};get=($)=>{return this.#Y?this.#Y.get($):void 0};get var(){if(!this.#Y)return{};return Object.fromEntries(this.#Y)}#Z($,x,Y){let X=this.#Q?new Headers(this.#Q.headers):this.#K??new Headers;if(typeof x==="object"&&"headers"in x){let z=x.headers instanceof Headers?x.headers:new Headers(x.headers);for(let[Z,K]of z)if(Z.toLowerCase()==="set-cookie")X.append(Z,K);else X.set(Z,K)}if(Y)for(let[z,Z]of Object.entries(Y))if(typeof Z==="string")X.set(z,Z);else{X.delete(z);for(let K of Z)X.append(z,K)}let Q=typeof x==="number"?x:x?.status??this.#z;return mV($,{status:Q,headers:X})}newResponse=(...$)=>this.#Z(...$);body=($,x,Y)=>this.#Z($,x,Y);text=($,x,Y)=>{return!this.#K&&!this.#z&&!x&&!Y&&!this.finalized?new Response($):this.#Z($,x,wu(Ht0,Y))};json=($,x,Y)=>{return this.#Z(JSON.stringify($),x,wu("application/json",Y))};html=($,x,Y)=>{let X=(Q)=>this.#Z(Q,x,wu("text/html; charset=UTF-8",Y));return typeof $==="object"?Vu($,MS1.Stringify,!1,{}).then(X):X($)};redirect=($,x)=>{let Y=String($);return this.header("Location",!/[^\x00-\xFF]/.test(Y)?Y:encodeURI(Y)),this.newResponse(null,x??302)};notFound=()=>{return this.#V??=()=>mV(),this.#V(this)}};var t0="ALL",OS1="all",bS1=["get","post","put","delete","options","patch"],JF="Can not add a route since the matcher is already built.",qF=class extends Error{};var RS1="__COMPOSED_HANDLER";var Gt0=($)=>{return $.text("404 Not Found",404)},AS1=($,x)=>{if("getResponse"in $){let Y=$.getResponse();return x.newResponse(Y.body,Y)}return console.error($),x.text("Internal Server Error",500)},fS1=class ${get;post;put;delete;options;patch;all;on;use;router;getPath;_basePath="/";#$="/";routes=[];constructor(x={}){[...bS1,OS1].forEach((z)=>{this[z]=(Z,...K)=>{if(typeof Z==="string")this.#$=Z;else this.#z(z,this.#$,Z);return K.forEach((W)=>{this.#z(z,this.#$,W)}),this}}),this.on=(z,Z,...K)=>{for(let W of[Z].flat()){this.#$=W;for(let V of[z].flat())K.map((w)=>{this.#z(V.toUpperCase(),this.#$,w)})}return this},this.use=(z,...Z)=>{if(typeof z==="string")this.#$=z;else this.#$="*",Z.unshift(z);return Z.forEach((K)=>{this.#z(t0,this.#$,K)}),this};let{strict:X,...Q}=x;Object.assign(this,Q),this.getPath=X??!0?x.getPath??Wu:NS1}#x(){let x=new $({router:this.router,getPath:this.getPath});return x.errorHandler=this.errorHandler,x.#Y=this.#Y,x.routes=this.routes,x}#Y=Gt0;errorHandler=AS1;route(x,Y){let X=this.basePath(x);return Y.routes.map((Q)=>{let z;if(Y.errorHandler===AS1)z=Q.handler;else z=async(Z,K)=>(await zu([],Y.errorHandler)(Z,()=>Q.handler(Z,K))).res,z[RS1]=Q.handler;X.#z(Q.method,Q.path,z)}),this}basePath(x){let Y=this.#x();return Y._basePath=XX(this._basePath,x),Y}onError=(x)=>{return this.errorHandler=x,this};notFound=(x)=>{return this.#Y=x,this};mount(x,Y,X){let Q,z;if(X)if(typeof X==="function")z=X;else if(z=X.optionHandler,X.replaceRequest===!1)Q=(W)=>W;else Q=X.replaceRequest;let Z=z?(W)=>{let V=z(W);return Array.isArray(V)?V:[V]}:(W)=>{let V=void 0;try{V=W.executionCtx}catch{}return[W.env,V]};Q||=(()=>{let W=XX(this._basePath,x),V=W==="/"?0:W.length;return(w)=>{let U=new URL(w.url);return U.pathname=U.pathname.slice(V)||"/",new Request(U,w)}})();let K=async(W,V)=>{let w=await Y(Q(W.req.raw),...Z(W));if(w)return w;await V()};return this.#z(t0,XX(x,"*"),K),this}#z(x,Y,X){x=x.toUpperCase(),Y=XX(this._basePath,Y);let Q={basePath:this._basePath,path:Y,method:x,handler:X};this.router.add(x,Y,[X,Q]),this.routes.push(Q)}#X(x,Y){if(x instanceof Error)return this.errorHandler(x,Y);throw x}#Q(x,Y,X,Q){if(Q==="HEAD")return(async()=>new Response(null,await this.#Q(x,Y,X,"GET")))();let z=this.getPath(x,{env:X}),Z=this.router.match(Q,z),K=new _S1(x,{path:z,matchResult:Z,env:X,executionCtx:Y,notFoundHandler:this.#Y});if(Z[0].length===1){let V;try{V=Z[0][0][0][0](K,async()=>{K.res=await this.#Y(K)})}catch(w){return this.#X(w,K)}return V instanceof Promise?V.then((w)=>w||(K.finalized?K.res:this.#Y(K))).catch((w)=>this.#X(w,K)):V??this.#Y(K)}let W=zu(Z[0],this.errorHandler,this.#Y);return(async()=>{try{let V=await W(K);if(!V.finalized)throw Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");return V.res}catch(V){return this.#X(V,K)}})()}fetch=(x,...Y)=>{return this.#Q(x,Y[1],Y[0],x.method)};request=(x,Y,X,Q)=>{if(x instanceof Request)return this.fetch(Y?new Request(x,Y):x,X,Q);return x=x.toString(),this.fetch(new Request(/^https?:\/\//.test(x)?x:`http://localhost${XX("/",x)}`,Y),X,Q)};fire=()=>{addEventListener("fetch",(x)=>{x.respondWith(this.#Q(x.request,x,void 0,x.request.method))})}};var hV=[];function DF($,x){let Y=this.buildAllMatchers(),X=(Q,z)=>{let Z=Y[Q]||Y[t0],K=Z[2][z];if(K)return K;let W=z.match(Z[0]);if(!W)return[[],hV];let V=W.indexOf("",1);return[Z[1][V],W]};return this.match=X,X($,x)}var BF="[^/]+",gV=".*",pV="(?:|/.*)",zX=Symbol(),Jt0=new Set(".\\+*[^]$()");function qt0($,x){if($.length===1)return x.length===1?$<x?-1:1:-1;if(x.length===1)return 1;if($===gV||$===pV)return 1;else if(x===gV||x===pV)return-1;if($===BF)return 1;else if(x===BF)return-1;return $.length===x.length?$<x?-1:1:x.length-$.length}var kS1=class ${#$;#x;#Y=Object.create(null);insert(x,Y,X,Q,z){if(x.length===0){if(this.#$!==void 0)throw zX;if(z)return;this.#$=Y;return}let[Z,...K]=x,W=Z==="*"?K.length===0?["","",gV]:["","",BF]:Z==="/*"?["","",pV]:Z.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/),V;if(W){let w=W[1],U=W[2]||BF;if(w&&W[2]){if(U===".*")throw zX;if(U=U.replace(/^\((?!\?:)(?=[^)]+\)$)/,"(?:"),/\((?!\?:)/.test(U))throw zX}if(V=this.#Y[U],!V){if(Object.keys(this.#Y).some((H)=>H!==gV&&H!==pV))throw zX;if(z)return;if(V=this.#Y[U]=new $,w!=="")V.#x=Q.varIndex++}if(!z&&w!=="")X.push([w,V.#x])}else if(V=this.#Y[Z],!V){if(Object.keys(this.#Y).some((w)=>w.length>1&&w!==gV&&w!==pV))throw zX;if(z)return;V=this.#Y[Z]=new $}V.insert(K,Y,X,Q,z)}buildRegExpStr(){let Y=Object.keys(this.#Y).sort(qt0).map((X)=>{let Q=this.#Y[X];return(typeof Q.#x==="number"?`(${X})@${Q.#x}`:Jt0.has(X)?`\\${X}`:X)+Q.buildRegExpStr()});if(typeof this.#$==="number")Y.unshift(`#${this.#$}`);if(Y.length===0)return"";if(Y.length===1)return Y[0];return"(?:"+Y.join("|")+")"}};var TS1=class{#$={varIndex:0};#x=new kS1;insert($,x,Y){let X=[],Q=[];for(let Z=0;;){let K=!1;if($=$.replace(/\{[^}]+\}/g,(W)=>{let V=`@\\${Z}`;return Q[Z]=[V,W],Z++,K=!0,V}),!K)break}let z=$.match(/(?::[^\/]+)|(?:\/\*$)|./g)||[];for(let Z=Q.length-1;Z>=0;Z--){let[K]=Q[Z];for(let W=z.length-1;W>=0;W--)if(z[W].indexOf(K)!==-1){z[W]=z[W].replace(K,Q[Z][1]);break}}return this.#x.insert(z,x,X,this.#$,Y),X}buildRegExp(){let $=this.#x.buildRegExpStr();if($==="")return[/^$/,[],[]];let x=0,Y=[],X=[];return $=$.replace(/#(\d+)|@(\d+)|\.\*\$/g,(Q,z,Z)=>{if(z!==void 0)return Y[++x]=Number(z),"$()";if(Z!==void 0)return X[Number(Z)]=++x,"";return""}),[new RegExp(`^${$}`),Y,X]}};var Dt0=[/^$/,[],Object.create(null)],cS1=Object.create(null);function SS1($){return cS1[$]??=new RegExp($==="*"?"":`^${$.replace(/\/\*$|([.\\+*[^\]$()])/g,(x,Y)=>Y?`\\${Y}`:"(?:|/.*)")}$`)}function Bt0(){cS1=Object.create(null)}function Ft0($){let x=new TS1,Y=[];if($.length===0)return Dt0;let X=$.map((V)=>[!/\*|\/:/.test(V[0]),...V]).sort(([V,w],[U,H])=>V?1:U?-1:w.length-H.length),Q=Object.create(null);for(let V=0,w=-1,U=X.length;V<U;V++){let[H,J,q]=X[V];if(H)Q[J]=[q.map(([D])=>[D,Object.create(null)]),hV];else w++;let B;try{B=x.insert(J,w,H)}catch(D){throw D===zX?new qF(J):D}if(H)continue;Y[w]=q.map(([D,F])=>{let P=Object.create(null);F-=1;for(;F>=0;F--){let[N,b]=B[F];P[N]=b}return[D,P]})}let[z,Z,K]=x.buildRegExp();for(let V=0,w=Y.length;V<w;V++)for(let U=0,H=Y[V].length;U<H;U++){let J=Y[V][U]?.[1];if(!J)continue;let q=Object.keys(J);for(let B=0,D=q.length;B<D;B++)J[q[B]]=K[J[q[B]]]}let W=[];for(let V in Z)W[V]=Y[Z[V]];return[z,W,Q]}function zK($,x){if(!$)return;for(let Y of Object.keys($).sort((X,Q)=>Q.length-X.length))if(SS1(Y).test(x))return[...$[Y]];return}var FF=class{name="RegExpRouter";#$;#x;constructor(){this.#$={[t0]:Object.create(null)},this.#x={[t0]:Object.create(null)}}add($,x,Y){let X=this.#$,Q=this.#x;if(!X||!Q)throw Error(JF);if(!X[$])[X,Q].forEach((K)=>{K[$]=Object.create(null),Object.keys(K[t0]).forEach((W)=>{K[$][W]=[...K[t0][W]]})});if(x==="/*")x="*";let z=(x.match(/\/:/g)||[]).length;if(/\*$/.test(x)){let K=SS1(x);if($===t0)Object.keys(X).forEach((W)=>{X[W][x]||=zK(X[W],x)||zK(X[t0],x)||[]});else X[$][x]||=zK(X[$],x)||zK(X[t0],x)||[];Object.keys(X).forEach((W)=>{if($===t0||$===W)Object.keys(X[W]).forEach((V)=>{K.test(V)&&X[W][V].push([Y,z])})}),Object.keys(Q).forEach((W)=>{if($===t0||$===W)Object.keys(Q[W]).forEach((V)=>K.test(V)&&Q[W][V].push([Y,z]))});return}let Z=GF(x)||[x];for(let K=0,W=Z.length;K<W;K++){let V=Z[K];Object.keys(Q).forEach((w)=>{if($===t0||$===w)Q[w][V]||=[...zK(X[w],V)||zK(X[t0],V)||[]],Q[w][V].push([Y,z-W+K+1])})}}match=DF;buildAllMatchers(){let $=Object.create(null);return Object.keys(this.#x).concat(Object.keys(this.#$)).forEach((x)=>{$[x]||=this.#Y(x)}),this.#$=this.#x=void 0,Bt0(),$}#Y($){let x=[],Y=$===t0;if([this.#$,this.#x].forEach((X)=>{let Q=X[$]?Object.keys(X[$]).map((z)=>[z,X[$][z]]):[];if(Q.length!==0)Y||=!0,x.push(...Q);else if($!==t0)x.push(...Object.keys(X[t0]).map((z)=>[z,X[t0][z]]))}),!Y)return null;else return Ft0(x)}};var Lt0=class{name="PreparedRegExpRouter";#$;#x;constructor($,x){this.#$=$,this.#x=x}#Y($,x){let Y=this.#$[$];Y[1].forEach((X)=>X&&X.push(x)),Object.values(Y[2]).forEach((X)=>X[0].push(x))}#z($,x,Y,X,Q){let z=this.#$[$];if(!Q)z[2][x][0].push([Y,{}]);else X.forEach((Z)=>{if(typeof Z==="number")z[1][Z].push([Y,Q]);else z[2][Z||x][0].push([Y,Q])})}add($,x,Y){if(!this.#$[$]){let Q=this.#$[t0],z={};for(let Z in Q[2])z[Z]=[Q[2][Z][0].slice(),hV];this.#$[$]=[Q[0],Q[1].map((Z)=>Array.isArray(Z)?Z.slice():0),z]}if(x==="/*"||x==="*"){let Q=[Y,{}];if($===t0)for(let z in this.#$)this.#Y(z,Q);else this.#Y($,Q);return}let X=this.#x[x];if(!X)throw Error(`Path ${x} is not registered`);for(let[Q,z]of X)if($===t0)for(let Z in this.#$)this.#z(Z,x,Y,Q,z);else this.#z($,x,Y,Q,z)}buildAllMatchers(){return this.#$}match=DF};var Uu=class{name="SmartRouter";#$=[];#x=[];constructor($){this.#$=$.routers}add($,x,Y){if(!this.#x)throw Error(JF);this.#x.push([$,x,Y])}match($,x){if(!this.#x)throw Error("Fatal error");let Y=this.#$,X=this.#x,Q=Y.length,z=0,Z;for(;z<Q;z++){let K=Y[z];try{for(let W=0,V=X.length;W<V;W++)K.add(...X[W]);Z=K.match($,x)}catch(W){if(W instanceof qF)continue;throw W}this.match=K.match.bind(K),this.#$=[K],this.#x=void 0;break}if(z===Q)throw Error("Fatal error");return this.name=`SmartRouter + ${this.activeRouter.name}`,Z}get activeRouter(){if(this.#x||this.#$.length!==1)throw Error("No active router has been determined yet.");return this.#$[0]}};var iV=Object.create(null),Nt0=($)=>{for(let x in $)return!0;return!1},ES1=class ${#$;#x;#Y;#z=0;#X=iV;constructor(x,Y,X){if(this.#x=X||Object.create(null),this.#$=[],x&&Y){let Q=Object.create(null);Q[x]={handler:Y,possibleKeys:[],score:0},this.#$=[Q]}this.#Y=[]}insert(x,Y,X){this.#z=++this.#z;let Q=this,z=FS1(Y),Z=[];for(let K=0,W=z.length;K<W;K++){let V=z[K],w=z[K+1],U=LS1(V,w),H=Array.isArray(U)?U[0]:V;if(H in Q.#x){if(Q=Q.#x[H],U)Z.push(U[1]);continue}if(Q.#x[H]=new $,U)Q.#Y.push(U),Z.push(U[1]);Q=Q.#x[H]}return Q.#$.push({[x]:{handler:X,possibleKeys:Z.filter((K,W,V)=>V.indexOf(K)===W),score:this.#z}}),Q}#Q(x,Y,X,Q,z){for(let Z=0,K=Y.#$.length;Z<K;Z++){let W=Y.#$[Z],V=W[X]||W[t0],w={};if(V!==void 0){if(V.params=Object.create(null),x.push(V),Q!==iV||z&&z!==iV)for(let U=0,H=V.possibleKeys.length;U<H;U++){let J=V.possibleKeys[U],q=w[V.score];V.params[J]=z?.[J]&&!q?z[J]:Q[J]??z?.[J],w[V.score]=!0}}}}search(x,Y){let X=[];this.#X=iV;let z=[this],Z=Ku(Y),K=[],W=Z.length,V=null;for(let w=0;w<W;w++){let U=Z[w],H=w===W-1,J=[];for(let B=0,D=z.length;B<D;B++){let F=z[B],P=F.#x[U];if(P)if(P.#X=F.#X,H){if(P.#x["*"])this.#Q(X,P.#x["*"],x,F.#X);this.#Q(X,P,x,F.#X)}else J.push(P);for(let N=0,b=F.#Y.length;N<b;N++){let C=F.#Y[N],l=F.#X===iV?{}:{...F.#X};if(C==="*"){let X1=F.#x["*"];if(X1)this.#Q(X,X1,x,F.#X),X1.#X=l,J.push(X1);continue}let[H1,F1,g]=C;if(!U&&!(g instanceof RegExp))continue;let a=F.#x[H1];if(g instanceof RegExp){if(V===null){V=Array(W);let _1=Y[0]==="/"?1:0;for(let N1=0;N1<W;N1++)V[N1]=_1,_1+=Z[N1].length+1}let X1=Y.substring(V[w]),V1=g.exec(X1);if(V1){if(l[F1]=V1[0],this.#Q(X,a,x,F.#X,l),Nt0(a.#x)){a.#X=l;let _1=V1[0].match(/\//)?.length??0;(K[_1]||=[]).push(a)}continue}}if(g===!0||g.test(U))if(l[F1]=U,H){if(this.#Q(X,a,x,l,F.#X),a.#x["*"])this.#Q(X,a.#x["*"],x,l,F.#X)}else a.#X=l,J.push(a)}}let q=K.shift();z=q?J.concat(q):J}if(X.length>1)X.sort((w,U)=>{return w.score-U.score});return[X.map(({handler:w,params:U})=>[w,U])]}};var Hu=class{name="TrieRouter";#$;constructor(){this.#$=new ES1}add($,x,Y){let X=GF(x);if(X){for(let Q=0,z=X.length;Q<z;Q++)this.#$.insert($,X[Q],Y);return}this.#$.insert($,x,Y)}match($,x){return this.#$.search($,x)}};var CS1=class extends fS1{constructor($={}){super($);this.router=$.router??new Uu({routers:[new FF,new Hu]})}};var Pt0=class{initApp;#$;constructor($){this.initApp=$?.initApp,this.#$=$?.defaultAppOptions}createApp=($)=>{let x=new CS1($&&this.#$?{...this.#$,...$}:$??this.#$);if(this.initApp)this.initApp(x);return x};createMiddleware=($)=>$;createHandlers=(...$)=>{return $.filter((x)=>x!==void 0)}},uS1=($)=>new Pt0($);var z8=uS1();class Gu extends NQ{file=null;info(){}warn(){}error(){}}var yS1=($)=>{let x=Buffer.byteLength($.content,"utf-8");if($.meta)for(let[Y,X]of Object.entries($.meta))x+=Buffer.byteLength(Y,"utf-8")+Buffer.byteLength(X,"utf-8");return x},jt0=1048576,It0=200,vt0=4194304,Mt0=new Gu;class Ju{clients=new Map;subscribers=new Set;logger;maxBufferedBytes;now;replayBufferSize;replayBufferMaxBytes;replayBuffer=[];persistentReplay;exclusiveCursor=new Map;replayBufferBytes=0;eventsBroadcast=0;droppedSlowClients=0;lastBroadcastAt=null;latestOffset=0;constructor($={}){this.logger=$.logger??Mt0,this.maxBufferedBytes=$.maxBufferedBytes??jt0,this.now=$.now??(()=>Date.now()),this.replayBufferSize=Math.max(0,$.replayBufferSize??It0),this.replayBufferMaxBytes=Math.max(0,$.replayBufferMaxBytes??vt0),this.persistentReplay=$.persistentReplay??null}getMetrics(){return{clients:this.clients.size,subscribers:this.subscribers.size,eventsBroadcast:this.eventsBroadcast,droppedSlowClients:this.droppedSlowClients,lastBroadcastAt:this.lastBroadcastAt?new Date(this.lastBroadcastAt).toISOString():null,latestOffset:this.latestOffset,oldestReplayableOffset:this.replayBuffer[0]?.offset??null}}replaySince($,x){let Y=this.replayBuffer[0]?.offset,X=this.persistentReplay&&(Y===void 0||$<Y-1),Q=this.replayBuffer.filter((W)=>W.offset>$&&this.matchesClient(W,x));if(!X)return Q;let z=this.persistentReplay?this.persistentReplay.loadSince($).filter((W)=>this.matchesClient(W,x)):[],Z=Y??Number.POSITIVE_INFINITY;return[...z.filter((W)=>W.offset<Z),...Q]}matchesClient($,x){if(x.tapAll)return!0;let Y=$.meta?.channelId;if(Y&&Y!==x.channel)return!1;let X=$.meta?.connector;if(!X)return!0;return x.connectors.includes(X)}pickRecipients($){let x=new Map,Y=[];for(let[X,Q]of this.clients){if(!this.matchesClient($,Q))continue;if(Q.tapAll){Y.push(X);continue}if(Q.delivery==="exclusive"){let z=x.get(Q.channel)??[];z.push(X),x.set(Q.channel,z);continue}Y.push(X)}for(let[X,Q]of x){if(Q.length===0)continue;let z=this.exclusiveCursor.get(X)??0,Z=Q[z%Q.length];if(Z)Y.push(Z);this.exclusiveCursor.set(X,z+1)}return Y}addClient($,x){this.clients.set($,x)}removeClient($){this.clients.delete($)}getClientCount(){return this.clients.size}listChannels(){return[...this.clients.values()].map(($)=>({...$}))}subscribe($){return this.subscribers.add($),()=>{this.subscribers.delete($)}}broadcast($,x){this.latestOffset+=1;let Y={content:$,meta:x,offset:this.latestOffset},X=JSON.stringify(Y),Q=x?.connector;if(this.eventsBroadcast+=1,this.lastBroadcastAt=this.now(),this.replayBufferSize>0){let Z=yS1(Y);this.replayBuffer.push(Y),this.replayBufferBytes+=Z;while((this.replayBuffer.length>this.replayBufferSize||this.replayBufferBytes>this.replayBufferMaxBytes)&&this.replayBuffer.length>0){let K=this.replayBuffer.shift();if(K)this.replayBufferBytes-=yS1(K)}}let z=this.pickRecipients(Y);for(let Z of z){let K=Z.getBufferedAmount();if(K>this.maxBufferedBytes){let W=this.clients.get(Z);this.logger.warn("dropping slow WS client (backpressure)",{channel:W?.channel,buffered:K,max:this.maxBufferedBytes});try{Z.close(1009,"backpressure")}catch{}this.clients.delete(Z),this.droppedSlowClients+=1;continue}Z.send(X)}for(let Z of this.subscribers)try{Z(Y)}catch(K){this.logger.error("broadcast subscriber threw",{error:K instanceof Error?K.message:String(K)})}return Y}seedLatestOffset($){if($>this.latestOffset)this.latestOffset=$}}import{Database as _t0}from"bun:sqlite";var Ot0=/^[a-z_][a-z0-9_]*$/,bt0=new Set(["seq","ts","type","event"]),mS1=[["CREATE TABLE IF NOT EXISTS leuco_log (seq INTEGER PRIMARY KEY, ts INTEGER NOT NULL, type TEXT, event TEXT NOT NULL)","CREATE INDEX IF NOT EXISTS idx_leuco_log_ts ON leuco_log (ts)","CREATE INDEX IF NOT EXISTS idx_leuco_log_type ON leuco_log (type)"]];class qu{db;maxRows;maxAgeMs;now;indexes;extractIndexes;insertStmt;insertWithSeqStmt;maxSeqStmt;countStmt;trimRowsStmt;trimAgeStmt;constructor($){if(this.db=new _t0($.path),this.db.run("PRAGMA journal_mode = WAL"),this.migrate(),this.maxRows=$.maxRows??null,this.maxAgeMs=$.maxAgeMs??null,this.now=$.now??(()=>Date.now()),this.indexes=$.indexes??[],this.indexes.length>0)Rt0(this.indexes),this.extractIndexes=$.extractIndexes??null,this.syncIndexColumns();else this.extractIndexes=null;let x=["ts","type","event",...this.indexes],Y=x.map(()=>"?").join(", ");this.insertStmt=this.db.prepare(`INSERT INTO leuco_log (${x.join(", ")}) VALUES (${Y})`);let X=["seq",...x],Q=X.map(()=>"?").join(", ");this.insertWithSeqStmt=this.db.prepare(`INSERT INTO leuco_log (${X.join(", ")}) VALUES (${Q})`),this.maxSeqStmt=this.db.prepare("SELECT COALESCE(MAX(seq), 0) AS max FROM leuco_log"),this.countStmt=this.db.prepare("SELECT COUNT(*) AS n FROM leuco_log"),this.trimRowsStmt=this.db.prepare("DELETE FROM leuco_log WHERE seq <= (SELECT seq FROM leuco_log ORDER BY seq DESC LIMIT 1 OFFSET ?)"),this.trimAgeStmt=this.db.prepare("DELETE FROM leuco_log WHERE ts < ?")}insert($){try{let x=this.buildInsertParams($.ts,$.event),Y=this.insertStmt.run(...x),X=Number(Y.lastInsertRowid);return this.trim(),{seq:X,ts:$.ts,event:$.event}}catch(x){return x instanceof Error?x:Error(String(x))}}insertMany($){if($.length===0)return[];try{let x=[];return this.db.transaction((X)=>{for(let Q of X){let z=this.buildInsertParams(Q.ts,Q.event),Z=this.insertStmt.run(...z);x.push({seq:Number(Z.lastInsertRowid),ts:Q.ts,event:Q.event})}})($),this.trim(),x}catch(x){return x instanceof Error?x:Error(String(x))}}write($){try{let x=[$.seq,...this.buildInsertParams($.ts,$.event)];this.insertWithSeqStmt.run(...x),this.trim()}catch(x){return x instanceof Error?x:Error(String(x))}}getMaxSeq(){let $=this.maxSeqStmt.get();return $?$.max:0}getRecords($={}){let x=["seq > ?"],Y=[$.sinceSeq??0];if(typeof $.type==="string")x.push("type = ?"),Y.push($.type);if($.where)this.appendWhereConditions($.where,x,Y);let X=$.limit??1000;Y.push(X);let Q=`SELECT seq, ts, type, event FROM leuco_log WHERE ${x.join(" AND ")} ORDER BY seq ASC LIMIT ?`;return this.db.prepare(Q).all(...Y).map(ft0)}getSchemaVersion(){return this.db.prepare("PRAGMA user_version").get()?.user_version??0}close(){this.db.close()}buildInsertParams($,x){let Y=At0(x),X=JSON.stringify(x);if(this.indexes.length===0)return[$,Y,X];let Q=this.extractIndexes?this.extractIndexes(x):null,z=this.indexes.map((Z)=>Q?.[Z]??null);return[$,Y,X,...z]}appendWhereConditions($,x,Y){let X=$;for(let Q of this.indexes){let z=X[Q];if(z===void 0)continue;if(z===null)x.push(`${Q} IS NULL`);else x.push(`${Q} = ?`),Y.push(z)}}trim(){if(this.maxRows!==null){let $=this.countStmt.get();if($&&$.n>this.maxRows)this.trimRowsStmt.run(this.maxRows)}if(this.maxAgeMs!==null)this.trimAgeStmt.run(this.now()-this.maxAgeMs)}syncIndexColumns(){let $=new Set(this.db.prepare("PRAGMA table_info(leuco_log)").all().map((x)=>x.name));for(let x of this.indexes){if(!$.has(x))this.db.run(`ALTER TABLE leuco_log ADD COLUMN ${x} TEXT`);this.db.run(`CREATE INDEX IF NOT EXISTS idx_leuco_log_${x} ON leuco_log (${x})`)}}migrate(){let x=this.db.prepare("PRAGMA user_version").get()?.user_version??0;if(x>=mS1.length)return;let Y=mS1.slice(x),X=x;for(let Q of Y)X+=1,this.db.transaction(()=>{for(let Z of Q)this.db.run(Z);this.db.run(`PRAGMA user_version = ${X}`)})()}}function Rt0($){for(let x of $){if(!Ot0.test(x))throw Error(`invalid index column name: ${x}`);if(bt0.has(x))throw Error(`reserved index column name: ${x}`)}}function At0($){if(typeof $!=="object"||$===null)return null;if(!("type"in $))return null;let x=$.type;return typeof x==="string"?x:null}function ft0($){return{seq:$.seq,ts:$.ts,event:JSON.parse($.event)}}var hS1=2000,HB6=m.object({type:m.string(),content:m.string(),channel_id:m.string().nullable(),connector_id:m.string().nullable(),meta:m.record(m.string(),m.string()).nullable()});class Du{sink;now;constructor($){this.now=$.now??(()=>Date.now()),this.sink=new qu({path:$.path,indexes:["channel_id","connector_id"],extractIndexes:(x)=>({channel_id:x.channel_id,connector_id:x.connector_id}),now:this.now,...$.maxRows!==void 0?{maxRows:$.maxRows}:{},...$.maxAgeMs!==void 0?{maxAgeMs:$.maxAgeMs}:{}})}record($){let x={type:$.meta?.event_type??"unknown",content:kt0($.content),channel_id:$.channelId,connector_id:$.connectorId,meta:$.meta};this.sink.write({seq:$.offset,ts:this.now(),event:x})}loadSince($){let x=this.sink.getRecords({sinceSeq:$}),Y=[];for(let X of x)Y.push({content:X.event.content,meta:X.event.meta??void 0,offset:X.seq});return Y}loadForChannel($){let x={channel_id:$.channelId};if($.connectorId!==void 0)x.connector_id=$.connectorId;let Y=this.sink.getRecords({where:x,...$.sinceSeq!==void 0?{sinceSeq:$.sinceSeq}:{},...$.limit!==void 0?{limit:$.limit}:{}}),X=[];for(let Q of Y)X.push({content:Q.event.content,meta:Q.event.meta??void 0,offset:Q.seq});return X}findMaxOffset(){return this.sink.getMaxSeq()}close(){this.sink.close()}}function kt0($){if($.length<=hS1)return $;return`${$.slice(0,hS1)}...`}var Tt0=new I6,ct0=30000,St0=60000,Et0=($)=>new Promise((x)=>{setTimeout(x,$)});class ZX{channels;notify;logger;running=new Map;failureCounts=new Map;stats=new Map;healthCheckIntervalMs;maxBackoffMs;sleep;now;healthCheckTimer=null;healthCheckInFlight=!1;constructor($){this.channels=$.channels,this.notify=$.notify,this.logger=$.logger??Tt0,this.healthCheckIntervalMs=$.healthCheckIntervalMs??ct0,this.maxBackoffMs=$.maxBackoffMs??St0,this.sleep=$.sleep??Et0,this.now=$.now??(()=>Date.now())}static keyOf($,x){return`${$}/${x}`}isRunning($,x){return this.running.has(ZX.keyOf($,x))}list(){return[...this.running.entries()].map(([$,x])=>{let Y=this.stats.get($);return{channelName:x.channelName,channelId:x.channelId,name:x.config.name,type:x.config.type,alive:x.listener.isAlive(),events:Y?.events??0,errors:Y?.errors??0,failureCount:this.failureCounts.get($)??0,lastEventAt:Y?.lastEventAt??null}})}async start($,x){let Y=ZX.keyOf($,x);if(this.running.has(Y))return{ok:!0,reason:"already running"};let X=this.channels.createListener($,x);if(!X)return{ok:!1,reason:`connector "${x}" not found in channel "${$}"`};let Q=async(z,Z)=>{try{await this.notify($,x,z,Z),this.recordEvent(Y)}catch(K){throw this.recordError(Y),K}};try{return await X.listener.start(Q),this.running.set(Y,{config:X.config,channelName:$,channelId:X.channelId,listener:X.listener}),this.ensureStats(Y),this.logger.info(`${X.config.type} listener started`,{channel:$,connector:x}),{ok:!0}}catch(z){return this.logger.error(`${X.config.type} listener failed to start`,{channel:$,connector:x,error:z instanceof Error?z.message:String(z)}),{ok:!1,reason:z instanceof Error?z.message:String(z)}}}async stop($,x){let Y=ZX.keyOf($,x),X=this.running.get(Y);if(!X)return{ok:!0,reason:"not running"};try{return await X.listener.stop(),this.running.delete(Y),this.failureCounts.delete(Y),this.logger.info(`${X.config.type} listener stopped`,{channel:$,connector:x}),{ok:!0}}catch(Q){return this.logger.error(`${X.config.type} listener failed to stop`,{channel:$,connector:x,error:Q instanceof Error?Q.message:String(Q)}),{ok:!1,reason:Q instanceof Error?Q.message:String(Q)}}}async restart($,x){let Y=await this.stop($,x);if(!Y.ok)return Y;return await this.start($,x)}async startAll(){let $=this.channels.listAllConnectors();for(let x of $)await this.start(x.channelName,x.name);this.startHealthCheck()}async stopAll(){this.stopHealthCheck();for(let[,$]of[...this.running.entries()])await this.stop($.channelName,$.config.name)}ensureStats($){let x=this.stats.get($);if(x)return x;let Y={events:0,errors:0,failureCount:0,lastEventAt:null};return this.stats.set($,Y),Y}recordEvent($){let x=this.ensureStats($);x.events+=1,x.lastEventAt=new Date(this.now()).toISOString()}recordError($){this.ensureStats($).errors+=1}startHealthCheck(){if(this.healthCheckTimer)return;this.healthCheckTimer=setInterval(()=>{this.runHealthCheck()},this.healthCheckIntervalMs),this.healthCheckTimer.unref()}stopHealthCheck(){if(!this.healthCheckTimer)return;clearInterval(this.healthCheckTimer),this.healthCheckTimer=null}async runHealthCheck(){if(this.healthCheckInFlight)return;this.healthCheckInFlight=!0;try{for(let[$,x]of[...this.running.entries()]){if(x.listener.isAlive()){this.failureCounts.delete($);continue}await this.recoverDead(x.channelName,x.config.name,x.config.type)}}finally{this.healthCheckInFlight=!1}}async recoverDead($,x,Y){let X=ZX.keyOf($,x),Q=this.failureCounts.get(X)??0,z=Math.min(1000*2**Q,this.maxBackoffMs);if(this.logger.warn(`${Y} listener unhealthy, restarting`,{channel:$,connector:x,attempt:Q+1,backoffMs:z}),await this.stop($,x),await this.sleep(z),(await this.start($,x)).ok)this.failureCounts.delete(X),this.logger.info(`${Y} listener recovered`,{channel:$,connector:x});else this.failureCounts.set(X,Q+1)}}var Ct0=new L$,ut0=new I6,yt0=($)=>`funnel-gateway[${$}]`,gS1=async($)=>{let x=$.process??Ct0,Y=$.logger??ut0,X=await x.run(["ps","-e","-o","pid=,args="]);if(X.exitCode!==0)return[];let Q=yt0($.dir),z=[];for(let Z of X.stdout.split(`
549
549
  `)){let K=Z.trim();if(!K)continue;let W=/^(\d+)\s+(.+)$/.exec(K);if(!W)continue;let V=Number(W[1]),w=W[2];if(!Number.isInteger(V)||V<=0)continue;if(V===$.selfPid)continue;if(!w.includes(Q))continue;x.kill(V,"SIGTERM"),z.push(V),Y.info("killed competing Slack gateway process",{pid:V,args:w.slice(0,160)})}return z};var mt0=/^[\w!#$%&'*.^`|~+-]+$/,ht0=/^[ !#-:<-[\]-~]*$/,pS1=($)=>{let x=0,Y=$.length;while(x<Y){let X=$.charCodeAt(x);if(X!==32&&X!==9)break;x++}while(Y>x){let X=$.charCodeAt(Y-1);if(X!==32&&X!==9)break;Y--}return x===0&&Y===$.length?$:$.slice(x,Y)},Bu=($,x)=>{if(x&&$.indexOf(x)===-1)return{};let Y=$.split(";"),X=Object.create(null);for(let Q of Y){let z=Q.indexOf("=");if(z===-1)continue;let Z=pS1(Q.substring(0,z));if(x&&x!==Z||!mt0.test(Z)||Z in X)continue;let K=pS1(Q.substring(z+1));if(K.startsWith('"')&&K.endsWith('"'))K=K.slice(1,-1);if(ht0.test(K)){if(X[Z]=K.indexOf("%")!==-1?XK(K,yV):K,x)break}}return X};var iS1=($,x,Y)=>{let X=$.req.raw.headers.get("Cookie");if(typeof x==="string"){if(!X)return;let z=x;if(Y==="secure")z="__Secure-"+x;else if(Y==="host")z="__Host-"+x;return Bu(X,z)[z]}if(!X)return{};return Bu(X)};var lS1=($,x)=>{return new Response($,{headers:{"Content-Type":x}}).formData()};var gt0=/^application\/([a-z-\.]+\+)?json(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/,pt0=/^multipart\/form-data(;\s?boundary=[a-zA-Z0-9'"()+_,\-./:=?]+)?$/,it0=/^application\/x-www-form-urlencoded(;\s*[a-zA-Z0-9\-]+\=([^;]+))*$/,Fu=($,x)=>{return async(Y,X)=>{let Q={},z=Y.req.header("Content-Type");switch($){case"json":if(!z||!gt0.test(z))break;try{Q=await Y.req.json()}catch{throw new QK(400,{message:"Malformed JSON in request body"})}break;case"form":{if(!z||!(pt0.test(z)||it0.test(z)))break;let K;if(Y.req.bodyCache.formData)K=await Y.req.bodyCache.formData;else try{let V=await Y.req.arrayBuffer();K=await lS1(V,z),Y.req.bodyCache.formData=K}catch(V){let w="Malformed FormData request.";throw w+=V instanceof Error?` ${V.message}`:` ${String(V)}`,new QK(400,{message:w})}let W=Object.create(null);K.forEach((V,w)=>{if(w.endsWith("[]"))(W[w]??=[]).push(V);else if(Array.isArray(W[w]))W[w].push(V);else if(Object.hasOwn(W,w))W[w]=[W[w],V];else W[w]=V}),Q=W;break}case"query":Q=Object.fromEntries(Object.entries(Y.req.queries()).map(([K,W])=>{return W.length===1?[K,W[0]]:[K,W]}));break;case"param":Q=Y.req.param();break;case"header":Q=Y.req.header();break;case"cookie":Q=iS1(Y);break}let Z=await x(Q,Y);if(Z instanceof Response)return Z;return Y.req.addValidatedData($,Z),await X()}};function lt0($,x,Y,X){return Fu($,async(Q,z)=>{let Z=Q;if($==="header"&&"_def"in x||$==="header"&&"_zod"in x){let W=Object.keys("in"in x?x.in.shape:x.shape),V=Object.fromEntries(W.map((w)=>[w.toLowerCase(),w]));Z=Object.fromEntries(Object.entries(Q).map(([w,U])=>[V[w]||w,U]))}let K=X&&X.validationFunction?await X.validationFunction(x,Z):await x.safeParseAsync(Z);if(Y){let W=await Y({data:Z,...K,target:$},z);if(W){if(W instanceof Response)return W;if("response"in W)return W.response}}if(!K.success)return z.json(K,400);return K.data})}var LF=lt0;var $2=($)=>LF("param",$,(x,Y)=>{if(x.success)return;let X=x.error.issues[0],Q=X?`${X.path.join(".")}: ${X.message}`:"invalid request";return Y.json({ok:!1,reason:Q},400)});var nt0=m.object({method:m.string().min(1),path:m.string().min(1),body:m.unknown().optional()}),nS1=z8.createHandlers($2(m.object({channel:m.string().min(1),connector:m.string().min(1)})),async($)=>{let x=$.req.valid("param"),Y=await $.req.json().catch(()=>null),X=nt0.safeParse(Y);if(!X.success)throw new QK(400,{message:X.error.issues[0]?.message??"invalid body"});let Q=await $.var.deps.channels.call(x.channel,x.connector,{method:X.data.method,path:X.data.path,body:X.data.body??{}});return $.json({ok:!0,result:Q})});var dS1=z8.createHandlers($2(m.object({channel:m.string().min(1)})),LF("json",HS1,($,x)=>{if($.success)return;let Y=$.error.issues[0],X=Y?`${Y.path.join(".")}: ${Y.message}`:"invalid body";return x.json({ok:!1,reason:X},400)}),($)=>{let x=$.req.valid("param"),Y=$.req.valid("json"),Q={ok:!0,offset:$.var.deps.emit({channel:x.channel,connector:Y.connector,content:Y.content,meta:Y.meta}).offset};return $.json(Q)});var aS1=z8.createHandlers(($)=>{let x=$.var.deps;return $.json({ok:!0,pid:x.selfPid,clients:x.broadcaster.getClientCount(),listeners:x.supervisor.list()})});var sS1=z8.createHandlers(($)=>{return $.json({listeners:$.var.deps.supervisor.list()})});var oS1=z8.createHandlers($2(m.object({channel:m.string().min(1),connector:m.string().min(1)})),async($)=>{let x=$.req.valid("param"),Y=await $.var.deps.supervisor.restart(x.channel,x.connector);return $.json(Y,Y.ok?200:400)});var rS1=z8.createHandlers($2(m.object({channel:m.string().min(1),connector:m.string().min(1)})),async($)=>{let x=$.req.valid("param"),Y=await $.var.deps.supervisor.start(x.channel,x.connector);return $.json(Y,Y.ok?200:400)});var tS1=z8.createHandlers($2(m.object({channel:m.string().min(1),connector:m.string().min(1)})),async($)=>{let x=$.req.valid("param"),Y=await $.var.deps.supervisor.stop(x.channel,x.connector);return $.json(Y,Y.ok?200:400)});var eS1=z8.createHandlers(($)=>{let x=$.var.deps;return $.json({ok:!0,pid:x.selfPid,uptimeMs:x.uptimeMs(),clients:x.broadcaster.listChannels(),listeners:x.supervisor.list(),broadcaster:x.broadcaster.getMetrics()})});var $E1=z8.createApp().get("/health",...aS1).get("/status",...eS1).get("/listeners",...sS1).post("/listeners/:channel/:connector/start",...rS1).delete("/listeners/:channel/:connector",...tS1).post("/listeners/:channel/:connector/restart",...oS1).post("/channels/:channel/connectors/:connector/call",...nS1).post("/channels/:channel/publish",...dS1);var st0=9742,ot0="/tmp/funnel/events",YE1="events.db",rt0=new I6;class Lu{channels;settings;port;logDir;process;logger;selfPid;dir;killCompetingSlack;token;broadcaster;eventStore;supervisor;nowMs;extraRoutes;startedAt=null;server=null;constructor($){this.channels=$.channels,this.settings=$.settings,this.port=$.port??st0,this.logDir=$.logDir??ot0,this.process=$.process,this.logger=$.logger??rt0,this.selfPid=$.selfPid??globalThis.process.pid,this.dir=$.dir??O8,this.killCompetingSlack=$.killCompetingSlack??!0,this.token=$.token??"",this.extraRoutes=$.extraRoutes??null;let x=$.clock;if(this.nowMs=x?()=>x.millis():()=>Date.now(),!dt0(this.logDir))at0(this.logDir,{recursive:!0});this.eventStore=new Du({path:xE1(this.logDir,YE1),now:this.nowMs}),this.broadcaster=new Ju({logger:this.logger,now:this.nowMs,persistentReplay:this.eventStore}),this.broadcaster.seedLatestOffset(this.eventStore.findMaxOffset()),this.supervisor=new ZX({channels:this.channels,logger:this.logger,notify:async(Y,X,Q,z)=>{this.emit({channel:Y,connector:X,content:Q,meta:z})},now:this.nowMs})}async start(){if(this.server)return this.server;let $=this.buildApp();return this.startedAt=this.nowMs(),this.server=Bun.serve({port:this.port,development:!1,fetch:(x,Y)=>this.handleFetch(x,Y,$),websocket:{open:(x)=>this.handleWsOpen(x),close:(x)=>this.handleWsClose(x),message(){}}}),this.logServerStarted(),await this.bootListeners(),this.server}async stop(){if(await this.supervisor.stopAll(),this.server)this.server.stop(),this.server=null}getStatus(){return{clients:this.broadcaster.getClientCount(),channels:this.broadcaster.listChannels()}}getBroadcaster(){return this.broadcaster}getSupervisor(){return this.supervisor}getEventStore(){return this.eventStore}handleFetch($,x,Y){let X=new URL($.url);if(X.pathname==="/ws"&&$.headers.get("upgrade")==="websocket"){if(this.token&&!this.tokenMatchesUpgrade($))return new Response("unauthorized",{status:401});let Q=X.searchParams.get("tap")==="all",z=Q?"":X.searchParams.get("channel")??"",Z=!Q&&z?this.resolveChannel(z):null,K=Q?"":Z?.id??z,W=Q?null:Z?.name??null,V=Z?.connectors??[],w=Z?.delivery??"fanout",U=X.searchParams.get("since"),H=U===null?Number.NaN:Number.parseInt(U,10),J=Number.isFinite(H)&&H>=0?H:void 0;if(x.upgrade($,{data:{channel:K,channelName:W,connectors:V,tapAll:Q,delivery:w,since:J}}))return;return new Response("WebSocket upgrade failed",{status:400})}return Y.fetch($)}handleWsOpen($){if(typeof $.data.since==="number"){let x=this.broadcaster.replaySince($.data.since,$.data);for(let Y of x)$.send(JSON.stringify(Y))}if(this.broadcaster.addClient($,$.data),$.data.channelName){let x={event_type:"system",action:"channel_connect",channel:$.data.channelName,channelId:$.data.channel,connectors:$.data.connectors.join(","),total:String(this.broadcaster.getClientCount())};this.logger.info("channel connected",x)}else this.logger.info("tap-all client connected",{event_type:"system",action:"tap_connect",total:String(this.broadcaster.getClientCount())})}handleWsClose($){if(this.broadcaster.removeClient($),$.data.channelName)this.logger.info("channel disconnected",{event_type:"system",action:"channel_disconnect",channel:$.data.channelName,channelId:$.data.channel,total:String(this.broadcaster.getClientCount())});else this.logger.info("tap-all client disconnected",{event_type:"system",action:"tap_disconnect",total:String(this.broadcaster.getClientCount())})}logServerStarted(){this.logger.info("gateway started",{event_type:"system",action:"gateway_start",port:String(this.port),pid:String(this.selfPid)}),this.logger.info("funnel gateway listening",{url:`http://localhost:${this.port}`,websocket:`ws://localhost:${this.port}/ws`,health:`http://localhost:${this.port}/health`})}buildApp(){let $=z8.createApp();if($.use((Y,X)=>{return Y.set("deps",{selfPid:this.selfPid,broadcaster:this.broadcaster,supervisor:this.supervisor,channels:this.channels,uptimeMs:()=>this.startedAt?this.nowMs()-this.startedAt:0,emit:(Q)=>this.emit(Q)}),X()}),this.token)$.use("/listeners/*",VF({expected:this.token})),$.use("/status",VF({expected:this.token})),$.use("/channels/*",VF({expected:this.token}));return(this.extraRoutes?$.route("/",this.extraRoutes):$).route("/",$E1)}tokenMatchesUpgrade($){let x=($.headers.get("sec-websocket-protocol")??"").split(",").map((Q)=>Q.trim()).filter((Q)=>Q.length>0);for(let Q of x)if(Q.startsWith("funnel.token.")&&wF(Q.slice(13),this.token))return!0;let X=($.headers.get("authorization")??"").match(/^Bearer\s+(.+)$/i);if(X&&wF(X[1]??"",this.token))return!0;return!1}resolveChannel($){let Y=this.settings.read()?.channels.find((X)=>X.id===$||X.name===$);if(!Y)return null;return{id:Y.id,name:Y.name,connectors:Y.connectors.map((X)=>X.name),delivery:Y.delivery}}async bootListeners(){let $=this.channels.listAllConnectors();if(this.killCompetingSlack&&$.some((x)=>x.type==="slack")){let x=await gS1({selfPid:this.selfPid,dir:this.dir,process:this.process,logger:this.logger});if(x.length>0)this.logger.info("killed competing Slack gateway processes",{event_type:"system",action:"kill_competing",pids:x.join(",")})}await this.supervisor.startAll();for(let x of this.supervisor.list())this.logger.info(`${x.type} listener started: ${x.name}`,{event_type:"system",action:`${x.type}_connect`,channel:x.channelName,connector:x.name});this.logger.info(`event store: ${xE1(this.logDir,YE1)}`),this.logger.info("funnel gateway running")}emit($){let x=this.lookupChannelId($.channel),Y=x&&$.connector?this.lookupConnectorId(x,$.connector):null,X={...$.meta,channel:$.channel};if($.connector)X.connector=$.connector;if(x)X.channelId=x;if(Y)X.connectorId=Y;let Q=this.broadcaster.broadcast($.content,X);return this.eventStore.record({content:$.content,channelId:x??null,connectorId:Y??null,meta:X,offset:Q.offset}),{offset:Q.offset}}lookupChannelId($){return this.settings.read().channels.find((Y)=>Y.name===$)?.id??null}lookupConnectorId($,x){return this.settings.read().channels.find((Q)=>Q.id===$)?.connectors.find((Q)=>Q.name===x)?.id??null}}import{homedir as tt0}from"os";import{dirname as et0,join as QE1}from"path";var XE1="gateway.token",$e0=32,xe0=new M8,Ye0=()=>{let $=new Uint8Array($e0);return crypto.getRandomValues($),[...$].map((x)=>x.toString(16).padStart(2,"0")).join("")};class Nu{fs;path;generate;constructor($={}){this.fs=$.fs??xe0,this.path=QE1($.dir??O8,XE1),this.generate=$.generate??Ye0,Object.freeze(this)}read(){if(!this.fs.existsSync(this.path))return null;let $=this.fs.readFileSync(this.path).trim();return $.length>0?$:null}ensure(){let $=this.read();if($)return $;let x=this.generate();return this.fs.mkdirSync(et0(this.path),{recursive:!0}),this.fs.writeSecretFileSync(this.path,`${x}
550
550
  `),x}getPath(){return this.path}}var hF6=QE1(tt0(),".funnel",XE1);var Qe0=m.object({channelName:m.string(),channelId:m.string(),name:m.string(),type:m.string(),alive:m.boolean()}),Xe0=m.object({listeners:m.array(Qe0)}),ze0=m.object({reason:m.string().optional()}),Pu={state:"offline"};class ju{port;isDaemonRunning;getToken;constructor($){this.port=$.port,this.isDaemonRunning=$.isDaemonRunning,this.getToken=$.getToken??(()=>null),Object.freeze(this)}async list(){if(!this.isDaemonRunning())return{state:"offline"};try{let $=await fetch(`http://localhost:${this.port}/listeners`,{headers:this.authHeaders()});if(!$.ok)return{state:"error",reason:`HTTP ${$.status}`};let x=Xe0.safeParse(await $.json());if(!x.success)return{state:"error",reason:"malformed daemon response"};return{state:"ok",listeners:x.data.listeners}}catch($){return{state:"error",reason:$ instanceof Error?$.message:String($)}}}async start($,x){if(!this.isDaemonRunning())return Pu;return await this.call("POST",`/listeners/${this.path($,x)}/start`)}async stop($,x){if(!this.isDaemonRunning())return Pu;return await this.call("DELETE",`/listeners/${this.path($,x)}`)}async restart($,x){if(!this.isDaemonRunning())return Pu;return await this.call("POST",`/listeners/${this.path($,x)}/restart`)}path($,x){return`${encodeURIComponent($)}/${encodeURIComponent(x)}`}authHeaders(){let $=this.getToken();return $?{authorization:`Bearer ${$}`}:{}}async call($,x){try{let Y=await fetch(`http://localhost:${this.port}${x}`,{method:$,headers:this.authHeaders()});if(!Y.ok){let X=ze0.safeParse(await Y.json().catch(()=>null));return{state:"error",reason:(X.success?X.data.reason:void 0)??`HTTP ${Y.status}`}}return{state:"ok"}}catch(Y){return{state:"error",reason:Y instanceof Error?Y.message:String(Y)}}}}var Ke0="/tmp/funnel",We0="/sandbox/.funnel",Ve0="/sandbox/tmp";class NF{props;memos={};constructor($={}){this.props=$;Object.freeze(this)}static inMemory($={}){return new NF({store:$.store??new eC,fs:$.fs??new gC,process:$.process??new sC,logger:$.logger??new dC,clock:$.clock??new $u,idGenerator:$.idGenerator??new pC,dir:$.dir??We0,tmpDir:$.tmpDir??Ve0})}get paths(){let $=this.props.dir??O8,x=this.props.tmpDir??Ke0;return{dir:$,tmpDir:x,settings:Ze0($,"settings.json")}}get fs(){if(!this.memos.fs)this.memos.fs=this.props.fs??new M8;return this.memos.fs}get process(){if(!this.memos.process)this.memos.process=this.props.process??new L$;return this.memos.process}get logger(){if(!this.memos.logger)this.memos.logger=this.props.logger??new I6;return this.memos.logger}get clock(){if(!this.memos.clock)this.memos.clock=this.props.clock??new QX;return this.memos.clock}get idGenerator(){if(!this.memos.idGenerator)this.memos.idGenerator=this.props.idGenerator??new uV;return this.memos.idGenerator}get store(){if(!this.memos.store)this.memos.store=this.props.store??new $M({path:this.paths.settings,fs:this.fs});return this.memos.store}get factory(){if(!this.memos.factory)this.memos.factory=new uC({fs:this.fs,process:this.process,logger:this.logger,dir:this.paths.dir,slackListenerOptions:this.props.slackListenerOptions,scheduleListenerOptions:this.props.scheduleListenerOptions});return this.memos.factory}get channels(){if(!this.memos.channels)this.memos.channels=new mC({store:this.store,factory:this.factory,profileChecker:this.profiles,clock:this.clock,idGenerator:this.idGenerator});return this.memos.channels}get profiles(){if(!this.memos.profiles)this.memos.profiles=new oC({store:this.store});return this.memos.profiles}get localConfig(){if(!this.memos.localConfig)this.memos.localConfig=new lC({fs:this.fs});return this.memos.localConfig}get dotenv(){if(!this.memos.dotenv)this.memos.dotenv=new iC({fs:this.fs});return this.memos.dotenv}get tokenPrompter(){if(!this.memos.tokenPrompter)this.memos.tokenPrompter=this.props.tokenPrompter??new tC;return this.memos.tokenPrompter}get localConfigSync(){if(!this.memos.localConfigSync)this.memos.localConfigSync=new nC({channels:this.channels,dotenv:this.dotenv,prompter:this.tokenPrompter});return this.memos.localConfigSync}get mcp(){if(!this.memos.mcp)this.memos.mcp=new aC({fs:this.fs});return this.memos.mcp}get claude(){if(!this.memos.claude)this.memos.claude=new hC({channels:this.channels,mcp:this.mcp,gateway:this.gateway,fs:this.fs,process:this.process,logger:this.logger,dir:this.paths.dir});return this.memos.claude}get gateway(){if(!this.memos.gateway)this.memos.gateway=new Xu({fs:this.fs,process:this.process,clock:this.clock,dir:this.paths.dir,tmpDir:this.paths.tmpDir});return this.memos.gateway}get gatewayToken(){if(!this.memos.gatewayToken)this.memos.gatewayToken=new Nu({fs:this.fs,dir:this.paths.dir});return this.memos.gatewayToken}get publisher(){if(!this.memos.publisher){let $=this.gateway,x=this.gatewayToken;this.memos.publisher=new xu({port:$.getPort(),isDaemonRunning:()=>$.isRunning(),getToken:()=>x.read()})}return this.memos.publisher}get listeners(){if(!this.memos.listeners){let $=this.gateway,x=this.gatewayToken;this.memos.listeners=new ju({port:$.getPort(),isDaemonRunning:()=>$.isRunning(),getToken:()=>x.read()})}return this.memos.listeners}gatewayServer($={}){return new Lu({channels:this.channels,settings:this.store,port:$.port,logDir:$.logDir,process:this.process,clock:this.clock,logger:this.logger,dir:this.paths.dir,killCompetingSlack:$.killCompetingSlack,token:$.token??this.gatewayToken.ensure(),extraRoutes:$.extraRoutes})}}var De0=Number(process.env.FUNNEL_PORT)||9742,PF=qe0(O8,"gateway.pid"),Be0="/tmp/funnel/events";process.title=`funnel-gateway[${O8}]`;var zE1=new I6;Ue0(O8,{recursive:!0});if(we0(PF)){let $=Number(He0(PF,"utf-8").trim());if($>0){let x=Bun.spawnSync(["ps","-p",String($),"-o","state="],{stdout:"pipe",stderr:"pipe"});if(x.exitCode===0&&x.stdout.toString().trim())zE1.error("funnel gateway already running",{pid:$}),process.exit(1)}}Je0(PF,String(process.pid));process.on("exit",()=>{try{Ge0(PF)}catch{}});process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var Fe0=new NF({logger:zE1}),Le0=Fe0.gatewayServer({port:De0,logDir:Be0});await Le0.start();
@@ -14,6 +14,9 @@ type RunResult = {
14
14
  type AttachOptions = {
15
15
  cwd?: string;
16
16
  env?: Record<string, string>;
17
+ /** Invoked synchronously after the child process has been spawned, with its PID.
18
+ * Useful for hosts that need to register the spawned process before it exits. */
19
+ onSpawned?: (pid: number) => void;
17
20
  };
18
21
  type DetachOptions = {
19
22
  env?: Record<string, string>;
@@ -52,7 +52,7 @@ var NodeFunnelProcessRunner = class extends FunnelProcessRunner {
52
52
  };
53
53
  }
54
54
  async attach(command, options = {}) {
55
- return await Bun.spawn(command, {
55
+ const proc = Bun.spawn(command, {
56
56
  cwd: options.cwd,
57
57
  env: toEnv(options.env),
58
58
  stdio: [
@@ -60,7 +60,9 @@ var NodeFunnelProcessRunner = class extends FunnelProcessRunner {
60
60
  "inherit",
61
61
  "inherit"
62
62
  ]
63
- }).exited;
63
+ });
64
+ if (options.onSpawned) options.onSpawned(proc.pid);
65
+ return await proc.exited;
64
66
  }
65
67
  detach(command, options = {}) {
66
68
  Bun.spawn(command, {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { n as FunnelConnectorAdapter, t as CallInput } from "./connector-adapter-CXB-q_XC.js";
2
2
  import { n as discordConnectorSchema, t as DiscordConnectorConfig } from "./discord-connector-schema-Dww2I4zH.js";
3
3
  import { n as FunnelConnectorListener, r as NotifyFn, t as FunnelLogger } from "./logger-CTlXs7z4.js";
4
- import { a as FunnelProcessRunner, i as DetachOptions, n as ghConnectorSchema, o as RunOptions, r as AttachOptions, s as RunResult, t as GhConnectorConfig } from "./gh-connector-schema-BZFAS-p-.js";
4
+ import { a as FunnelProcessRunner, i as DetachOptions, n as ghConnectorSchema, o as RunOptions, r as AttachOptions, s as RunResult, t as GhConnectorConfig } from "./gh-connector-schema-BNyTaASt.js";
5
5
  import { a as FunnelFileSystem, c as ScheduleEntry, d as scheduleEntrySchema, i as FileStat, l as scheduleCatchupPolicySchema, n as ScheduleOnFired, o as ScheduleCatchupPolicy, s as ScheduleConnectorConfig, u as scheduleConnectorSchema } from "./schedule-listener-BPodvbld.js";
6
6
  import { a as SlackProcessed, c as SlackRawEvent, i as FunnelSlackEventProcessor, l as SlackConnectorConfig, n as SlackOnAppCreated, o as SlackProcessedEmit, r as SlackPreprocessEvent, s as SlackProcessedSkip, u as slackConnectorSchema } from "./slack-listener-CHj6uMY-.js";
7
7
  import { z } from "zod";
@@ -398,6 +398,14 @@ type LaunchOptions = {
398
398
  cwd?: string;
399
399
  userArgs?: string[];
400
400
  profileName?: string;
401
+ /** Invoked synchronously after the child claude process has been spawned, with its PID.
402
+ * Useful for hosts that need to register the spawned process before it exits
403
+ * (e.g. multi-session registries that track per-claude liveness). */
404
+ onSpawned?: (pid: number) => void;
405
+ /** Whether to install the funnel MCP entry into `.mcp.json` (default: true).
406
+ * Set to false when the host already provides its own MCP server entry and
407
+ * does not need the funnel binary as an MCP endpoint. */
408
+ installMcp?: boolean;
401
409
  };
402
410
  type Deps$12 = {
403
411
  channels: FunnelChannels;
@@ -577,6 +585,14 @@ type Deps$9 = {
577
585
  prompter: FunnelTokenPrompter;
578
586
  env?: NodeJS.ProcessEnv;
579
587
  };
588
+ type ConnectorSyncOutcome = {
589
+ name: string;
590
+ changed: boolean;
591
+ };
592
+ type LocalConfigSyncResult = {
593
+ touched: ConnectorSyncOutcome[];
594
+ removed: string[];
595
+ };
580
596
  /**
581
597
  * Reconciles a single funnel.json channel spec with `~/.funnel/settings.json`.
582
598
  * The spec is the source of truth for the channel it declares:
@@ -592,6 +608,9 @@ type Deps$9 = {
592
608
  * absent field means "do not manage connectors from here" and leaves
593
609
  * everything in `~/.funnel` alone. Other channels in funnel.json (not
594
610
  * passed to this call) are untouched.
611
+ *
612
+ * Returns the per-connector change set so callers (e.g. the claude launcher)
613
+ * can drive listener hot-reload on the gateway after settings are written.
595
614
  */
596
615
  declare class FunnelLocalConfigSync {
597
616
  private readonly channels;
@@ -599,7 +618,7 @@ declare class FunnelLocalConfigSync {
599
618
  private readonly prompter;
600
619
  private readonly env;
601
620
  constructor(deps: Deps$9);
602
- ensure(channel: ChannelSpec, cwd: string): Promise<void>;
621
+ ensure(channel: ChannelSpec, cwd: string): Promise<LocalConfigSyncResult>;
603
622
  private ensureConnector;
604
623
  private ensureSlack;
605
624
  private ensureDiscord;
@@ -4191,4 +4210,4 @@ ${string}`;
4191
4210
  //#region lib/tui/tui.d.ts
4192
4211
  declare function launchTui(funnel: Funnel): Promise<void>;
4193
4212
  //#endregion
4194
- export { AttachOptions, BroadcastEvent, BroadcastSubscriber, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ChannelSpec, ConnectorConfig, ConnectorSpec, ConnectorType, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiscordConnectorConfig, Env, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelDotenvReader, FunnelEvent, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, type GatewayEmitInput, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GhConnectorConfig, LOCAL_CONFIG_FILENAME, LOCAL_ENV_FILENAME, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LocalConfig, LogEntry, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, ProfileConfig, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, launchTui, localConfigSchema, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };
4213
+ export { AttachOptions, BroadcastEvent, BroadcastSubscriber, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelServerOptions, ChannelSpec, ConnectorConfig, ConnectorSpec, ConnectorSyncOutcome, ConnectorType, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiscordConnectorConfig, Env, FUNNEL_DIR, FUNNEL_MCP_COMMAND, FUNNEL_MCP_NAME, FileStat, Funnel, FunnelBroadcaster, FunnelChannelPublisher, FunnelChannels, FunnelClaude, FunnelClock, FunnelConnectorFactory, FunnelConnectorListener, FunnelDotenvReader, FunnelEvent, FunnelEventStore, FunnelFileSystem, FunnelGateway, FunnelGatewayServer, FunnelGatewayToken, FunnelIdGenerator, FunnelListenerSupervisor, FunnelListenersClient, FunnelLocalConfig, FunnelLocalConfigSync, FunnelLogger, FunnelMcp, FunnelProcessRunner, FunnelProfiles, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenPrompter, type GatewayEmitInput, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GhConnectorConfig, LOCAL_CONFIG_FILENAME, LOCAL_ENV_FILENAME, LaunchOptions, ListListenersResult, ListenerEntry, ListenerOpResult, LocalConfig, LocalConfigSyncResult, LogEntry, MemoryFunnelClock, MemoryFunnelFileSystem, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, ProfileConfig, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleListenerOptions, Settings, SlackConnectorConfig, SlackListenerOptions, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, channelConfigSchema, channelDeliveryModeSchema, channelSpecSchema, app as cliApp, connectorConfigSchema, connectorSpecSchema, createCliApp, createSettings, discordConnectorSchema, factory, funnelEventSchema, funnelJsonSchema, ghConnectorSchema, launchTui, localConfigSchema, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryToCliArgs, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, startChannelServer, toRequest };