@frontmcp/utils 1.10.15 → 1.11.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/browser/async-context/browser-async-context.mjs +177 -0
- package/browser/async-context/index.mjs +15 -0
- package/browser/async-context/overlap-error.mjs +10 -0
- package/browser/class-brand/class-brand.mjs +27 -0
- package/browser/class-brand/index.mjs +6 -0
- package/browser/content/content.mjs +151 -0
- package/browser/content/index.mjs +8 -0
- package/browser/crypto/browser.mjs +103 -0
- package/browser/crypto/encrypted-blob.mjs +119 -0
- package/browser/crypto/hmac-signing.mjs +70 -0
- package/browser/crypto/index.mjs +281 -0
- package/browser/crypto/jwt-alg.mjs +40 -0
- package/browser/crypto/key-persistence/factory.mjs +134 -0
- package/browser/crypto/key-persistence/index.mjs +26 -0
- package/browser/crypto/key-persistence/key-persistence.mjs +185 -0
- package/browser/crypto/key-persistence/schemas.mjs +82 -0
- package/browser/crypto/pkce/index.mjs +25 -0
- package/browser/crypto/pkce/pkce.mjs +59 -0
- package/browser/crypto/runtime.mjs +17 -0
- package/browser/crypto/secret-persistence/index.mjs +29 -0
- package/browser/crypto/secret-persistence/persistence.mjs +181 -0
- package/browser/crypto/secret-persistence/schema.mjs +40 -0
- package/browser/crypto/web-rsa.mjs +36 -0
- package/browser/env/browser-env.mjs +56 -0
- package/browser/env/browser-runtime-context.mjs +85 -0
- package/browser/env/build-target.mjs +25 -0
- package/browser/env/edge-scope.mjs +17 -0
- package/browser/env/index.mjs +47 -0
- package/browser/env/provider.mjs +46 -0
- package/browser/escape/escape.mjs +43 -0
- package/browser/escape/index.mjs +9 -0
- package/browser/event-emitter/browser-event-emitter.mjs +49 -0
- package/browser/event-emitter/index.mjs +5 -0
- package/browser/fs/fs.mjs +227 -0
- package/browser/fs/index.mjs +65 -0
- package/browser/http/cookie.mjs +85 -0
- package/browser/http/http.mjs +18 -0
- package/browser/http/index.mjs +11 -0
- package/browser/index.mjs +526 -0
- package/browser/llm/index.mjs +5 -0
- package/browser/llm/llm-tool-handlers.mjs +55 -0
- package/browser/machine-id/index.mjs +7 -0
- package/browser/machine-id/machine-id.mjs +108 -0
- package/browser/naming/index.mjs +10 -0
- package/browser/naming/naming.mjs +68 -0
- package/browser/net/index.mjs +10 -0
- package/browser/net/ip-address.mjs +128 -0
- package/browser/net/redirect.mjs +7 -0
- package/browser/path/browser-path.mjs +47 -0
- package/browser/path/index.mjs +24 -0
- package/browser/path/path.mjs +13 -0
- package/browser/process/child-process.mjs +23 -0
- package/browser/process/index.mjs +15 -0
- package/browser/process/owned-process.mjs +175 -0
- package/browser/process/process-tree.mjs +149 -0
- package/browser/process/process-watch.mjs +48 -0
- package/browser/redaction/index.mjs +6 -0
- package/browser/redaction/redaction.mjs +74 -0
- package/browser/regex/index.mjs +3 -0
- package/browser/regex/patterns.mjs +167 -0
- package/browser/regex/safe-regex.mjs +93 -0
- package/browser/serialization/index.mjs +5 -0
- package/browser/serialization/serialization.mjs +22 -0
- package/browser/stdio-bridge/errors.mjs +27 -0
- package/browser/stdio-bridge/index.mjs +24 -0
- package/browser/stdio-bridge/list-changed.mjs +21 -0
- package/browser/stdio-bridge/state-machine.mjs +211 -0
- package/browser/stdio-bridge/stdio-framer.mjs +91 -0
- package/browser/stdio-bridge/upstream-client.mjs +189 -0
- package/browser/storage/adapters/base.mjs +139 -0
- package/browser/storage/adapters/cloudflare-kv.mjs +149 -0
- package/browser/storage/adapters/filesystem.mjs +279 -0
- package/browser/storage/adapters/index.mjs +23 -0
- package/browser/storage/adapters/indexeddb.mjs +198 -0
- package/browser/storage/adapters/localstorage.mjs +222 -0
- package/browser/storage/adapters/memory.mjs +350 -0
- package/browser/storage/adapters/redis.mjs +497 -0
- package/browser/storage/adapters/upstash.mjs +299 -0
- package/browser/storage/adapters/vercel-kv.mjs +226 -0
- package/browser/storage/change-feed.mjs +189 -0
- package/browser/storage/encrypted-typed-storage.mjs +329 -0
- package/browser/storage/errors.mjs +92 -0
- package/browser/storage/factory.mjs +155 -0
- package/browser/storage/index.mjs +96 -0
- package/browser/storage/namespace.mjs +186 -0
- package/browser/storage/redis-error-listener.mjs +32 -0
- package/browser/storage/redis-url.mjs +66 -0
- package/browser/storage/typed-storage.mjs +171 -0
- package/browser/storage/utils/compare-and-delete.mjs +9 -0
- package/browser/storage/utils/index.mjs +24 -0
- package/browser/storage/utils/pattern.mjs +68 -0
- package/browser/storage/utils/ttl.mjs +48 -0
- package/browser/uri/index.mjs +19 -0
- package/browser/uri/uri-template.mjs +86 -0
- package/browser/uri/uri-validation.mjs +18 -0
- package/content/content.d.ts +8 -0
- package/content/index.d.ts +1 -1
- package/crypto/browser.d.ts +1 -13
- package/crypto/browser.js +1 -1
- package/crypto/node.js +1 -1
- package/crypto/web-rsa.d.ts +13 -0
- package/env/browser-runtime-context.js +1 -1
- package/env/runtime-context.js +1 -1
- package/esm/crypto/browser.mjs +1 -1
- package/esm/crypto/node.mjs +1 -1
- package/esm/env/browser-runtime-context.mjs +1 -1
- package/esm/env/runtime-context.mjs +1 -1
- package/esm/index.mjs +1 -1
- package/fs/fs.d.ts +45 -4
- package/fs/index.d.ts +1 -1
- package/index.d.ts +10 -4
- package/index.js +1 -1
- package/package.json +24 -8
- package/process/child-process.d.ts +2 -0
- package/process/index.d.ts +6 -0
- package/process/owned-process.d.ts +59 -0
- package/process/process-tree.d.ts +78 -0
- package/process/process-watch.d.ts +41 -0
- package/redaction/index.d.ts +2 -0
- package/redaction/redaction.d.ts +24 -0
- package/stdio-bridge/errors.d.ts +23 -0
- package/stdio-bridge/index.d.ts +9 -0
- package/stdio-bridge/list-changed.d.ts +3 -0
- package/stdio-bridge/state-machine.d.ts +61 -0
- package/stdio-bridge/stdio-framer.d.ts +49 -0
- package/stdio-bridge/types.d.ts +10 -0
- package/stdio-bridge/upstream-client.d.ts +66 -0
- package/storage/adapters/base.d.ts +2 -0
- package/storage/adapters/memory.d.ts +1 -0
- package/storage/adapters/redis.d.ts +3 -0
- package/storage/change-feed.d.ts +47 -0
- package/storage/factory.d.ts +6 -0
- package/storage/index.d.ts +3 -1
- package/storage/namespace.d.ts +2 -0
- package/storage/types.d.ts +46 -1
- package/storage/utils/compare-and-delete.d.ts +2 -0
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);function isNode(){return typeof process!=="undefined"&&!!process.versions?.node}function isBrowser(){return typeof globalThis!=="undefined"&&typeof globalThis.crypto!=="undefined"&&typeof globalThis.crypto.getRandomValues==="function"}function assertNode(feature){if(!isNode()){throw new Error(`${feature} is not supported in the browser. Requires Node.js.`)}}var init_runtime=__esm({"libs/utils/src/crypto/runtime.ts"(){"use strict"}});function getFsp(){if(!_fsp){assertNode("File system operations");_fsp=require("fs").promises}return _fsp}function getFs(){if(!_fs){assertNode("File system operations");_fs=require("fs")}return _fs}function getSpawn(){if(!_spawn){assertNode("Child process operations");_spawn=require("child_process").spawn}return _spawn}function getSpawnFn(){return getSpawn()}async function readFile(p,encoding="utf8"){const fsp=getFsp();return fsp.readFile(p,encoding)}function readFileSync(p,encoding="utf8"){const fs=getFs();return fs.readFileSync(p,encoding)}async function readFileBuffer(p){const fsp=getFsp();return fsp.readFile(p)}async function writeFile(p,content,options){const fsp=getFsp();await fsp.writeFile(p,content,{encoding:"utf8",mode:options?.mode})}async function mkdir(p,options){const fsp=getFsp();await fsp.mkdir(p,options)}function ensureDirSync(p){const fs=getFs();fs.mkdirSync(p,{recursive:true})}async function rename(oldPath,newPath){const fsp=getFsp();await fsp.rename(oldPath,newPath)}async function unlink(p){const fsp=getFsp();await fsp.unlink(p)}async function fileExists(p){try{const fsp=getFsp();await fsp.access(p,F_OK);return true}catch{return false}}function fileExistsSync(p){return getFs().existsSync(p)}async function readJSON(jsonPath){try{const fsp=getFsp();const buf=await fsp.readFile(jsonPath,"utf8");return JSON.parse(buf)}catch{return null}}async function writeJSON(p,obj){const fsp=getFsp();await fsp.writeFile(p,JSON.stringify(obj,null,2)+"\n","utf8")}async function ensureDir(p){const fsp=getFsp();await fsp.mkdir(p,{recursive:true})}async function stat(p){const fsp=getFsp();return fsp.stat(p)}async function symlink(target,linkPath,type){const fsp=getFsp();await fsp.symlink(target,linkPath,type)}async function realpath(p){const fsp=getFsp();return fsp.realpath(p)}async function copyFile(src,dest){const fsp=getFsp();await fsp.copyFile(src,dest)}async function cp(src,dest,options){const fsp=getFsp();await fsp.cp(src,dest,options)}async function readdir(p){const fsp=getFsp();return fsp.readdir(p)}function readdirSync(p){const fs=getFs();return fs.readdirSync(p)}async function rm(p,options){const fsp=getFsp();await fsp.rm(p,options)}async function isDirEmpty(dir){try{const fsp=getFsp();const items=await fsp.readdir(dir);return items.length===0}catch(e){if(e?.code==="ENOENT")return true;throw e}}async function mkdtemp(prefix){const fsp=getFsp();return fsp.mkdtemp(prefix)}async function access(p,mode){const fsp=getFsp();await fsp.access(p,mode??F_OK)}function runCmd(cmd,args,opts={}){const spawn=getSpawn();return new Promise((resolve2,reject)=>{const child=spawn(cmd,args,{stdio:"inherit",shell:false,...opts});child.on("close",code=>code===0?resolve2():reject(new Error(`${cmd} exited with code ${code}`)));child.on("error",reject)})}function watchFile(p,onChange,options){const fs=getFs();const watcher=fs.watch(p,{persistent:false,recursive:options?.recursive===true},(eventType,filename)=>{onChange(eventType,filename)});return{close(){watcher.close()},onError(handler){watcher.on("error",handler)}}}var _fsp,_fs,_spawn,F_OK;var init_fs=__esm({"libs/utils/src/fs/fs.ts"(){"use strict";init_runtime();_fsp=null;_fs=null;_spawn=null;F_OK=0}});var init_fs2=__esm({"libs/utils/src/fs/index.ts"(){"use strict";init_fs()}});function jwtAlgToNodeAlg(jwtAlg){const nodeAlg=JWT_ALG_TO_NODE_DIGEST[jwtAlg];if(!nodeAlg){throw new Error(`Unsupported JWT algorithm: ${jwtAlg}`)}return nodeAlg}function isRsaPssAlg(jwtAlg){return jwtAlg.startsWith("PS")}function jwtAlgToWebCryptoAlg(jwtAlg){const webAlg=JWT_ALG_TO_WEB_CRYPTO[jwtAlg];if(!webAlg){throw new Error(`Unsupported JWT algorithm for WebCrypto: ${jwtAlg}`)}return webAlg}var JWT_ALG_TO_NODE_DIGEST,JWT_ALG_TO_WEB_CRYPTO;var init_jwt_alg=__esm({"libs/utils/src/crypto/jwt-alg.ts"(){"use strict";JWT_ALG_TO_NODE_DIGEST={RS256:"RSA-SHA256",RS384:"RSA-SHA384",RS512:"RSA-SHA512",PS256:"RSA-SHA256",PS384:"RSA-SHA384",PS512:"RSA-SHA512"};JWT_ALG_TO_WEB_CRYPTO={RS256:"SHA-256",RS384:"SHA-384",RS512:"SHA-512",PS256:"SHA-256",PS384:"SHA-384",PS512:"SHA-512"}}});function encryptValue(data,key){if(key.length!==32){throw new EncryptedBlobError(`Encryption key must be 32 bytes (AES-256), got ${key.length} bytes`)}let jsonString;try{jsonString=JSON.stringify(data)}catch(error){throw new EncryptedBlobError(`Failed to serialize data: ${error.message}`)}const plaintext=textEncoder.encode(jsonString);const iv=randomBytes(12);const{ciphertext,tag}=encryptAesGcm(key,plaintext,iv);return{alg:"A256GCM",iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}function decryptValue(blob,key){if(key.length!==32){throw new EncryptedBlobError(`Decryption key must be 32 bytes (AES-256), got ${key.length} bytes`)}if(blob.alg!=="A256GCM"){throw new EncryptedBlobError(`Unsupported algorithm: ${blob.alg}, expected A256GCM`)}let iv;let tag;let ciphertext;try{iv=base64urlDecode(blob.iv);tag=base64urlDecode(blob.tag);ciphertext=base64urlDecode(blob.data)}catch(error){throw new EncryptedBlobError(`Failed to decode blob fields: ${error.message}`)}let decrypted;try{decrypted=decryptAesGcm(key,ciphertext,iv,tag)}catch(error){throw new EncryptedBlobError(`Decryption failed: ${error.message}`)}try{return JSON.parse(textDecoder.decode(decrypted))}catch(error){throw new EncryptedBlobError(`Failed to parse decrypted data: ${error.message}`)}}function tryDecryptValue(blob,key){try{return decryptValue(blob,key)}catch{return null}}function serializeBlob(blob){return JSON.stringify(blob)}function deserializeBlob(str){let parsed;try{parsed=JSON.parse(str)}catch(error){throw new EncryptedBlobError(`Failed to parse blob JSON: ${error.message}`)}if(!isValidEncryptedBlob(parsed)){throw new EncryptedBlobError("Invalid encrypted blob structure")}return parsed}function tryDeserializeBlob(str){try{return deserializeBlob(str)}catch{return null}}function isValidEncryptedBlob(value){return typeof value==="object"&&value!==null&&"alg"in value&&"iv"in value&&"tag"in value&&"data"in value&&value.alg==="A256GCM"&&typeof value.iv==="string"&&typeof value.tag==="string"&&typeof value.data==="string"}function encryptAndSerialize(data,key){const blob=encryptValue(data,key);return serializeBlob(blob)}function deserializeAndDecrypt(str,key){const blob=deserializeBlob(str);return decryptValue(blob,key)}function tryDeserializeAndDecrypt(str,key){try{return deserializeAndDecrypt(str,key)}catch{return null}}var textEncoder,textDecoder,EncryptedBlobError;var init_encrypted_blob=__esm({"libs/utils/src/crypto/encrypted-blob.ts"(){"use strict";init_crypto();textEncoder=new TextEncoder;textDecoder=new TextDecoder;EncryptedBlobError=class extends Error{constructor(message){super(message);this.name="EncryptedBlobError"}}}});function generateCodeVerifier(length=DEFAULT_CODE_VERIFIER_LENGTH){if(length<MIN_CODE_VERIFIER_LENGTH||length>MAX_CODE_VERIFIER_LENGTH){throw new PkceError(`Code verifier length must be between ${MIN_CODE_VERIFIER_LENGTH} and ${MAX_CODE_VERIFIER_LENGTH} characters (got ${length})`)}const bytesNeeded=Math.ceil(length*6/8);const bytes=randomBytes(bytesNeeded);return base64urlEncode(bytes).slice(0,length)}function generateCodeChallenge(codeVerifier){const verifierBytes=new TextEncoder().encode(codeVerifier);const hash=sha256(verifierBytes);return base64urlEncode(hash)}function verifyCodeChallenge(codeVerifier,codeChallenge){const computedChallenge=generateCodeChallenge(codeVerifier);return computedChallenge===codeChallenge}function generatePkcePair(length=DEFAULT_CODE_VERIFIER_LENGTH){const codeVerifier=generateCodeVerifier(length);const codeChallenge=generateCodeChallenge(codeVerifier);return{codeVerifier,codeChallenge}}function isValidCodeVerifier(value){if(value.length<MIN_CODE_VERIFIER_LENGTH||value.length>MAX_CODE_VERIFIER_LENGTH){return false}return/^[A-Za-z0-9\-._~]+$/.test(value)}function isValidCodeChallenge(value){if(value.length!==43){return false}return/^[A-Za-z0-9\-_]+$/.test(value)}var MIN_CODE_VERIFIER_LENGTH,MAX_CODE_VERIFIER_LENGTH,DEFAULT_CODE_VERIFIER_LENGTH,PkceError;var init_pkce=__esm({"libs/utils/src/crypto/pkce/pkce.ts"(){"use strict";init_crypto();MIN_CODE_VERIFIER_LENGTH=43;MAX_CODE_VERIFIER_LENGTH=128;DEFAULT_CODE_VERIFIER_LENGTH=64;PkceError=class extends Error{constructor(message){super(message);this.name="PkceError"}}}});var init_pkce2=__esm({"libs/utils/src/crypto/pkce/index.ts"(){"use strict";init_pkce()}});function validateSecretData(data){const result=secretDataSchema.safeParse(data);if(!result.success){return{valid:false,error:result.error.issues[0]?.message??"Invalid secret structure"}}const parsed=result.data;const now=Date.now();if(parsed.createdAt>now+MAX_CLOCK_DRIFT_MS){return{valid:false,error:"createdAt is in the future"}}if(parsed.createdAt<now-MAX_SECRET_AGE_MS){return{valid:false,error:"createdAt is too old"}}return{valid:true}}function parseSecretData(data){const validation=validateSecretData(data);if(!validation.valid){return null}return data}var import_lazy_zod,secretDataSchema,MAX_CLOCK_DRIFT_MS,MAX_SECRET_AGE_MS;var init_schema=__esm({"libs/utils/src/crypto/secret-persistence/schema.ts"(){"use strict";import_lazy_zod=require("@frontmcp/lazy-zod");secretDataSchema=import_lazy_zod.z.object({secret:import_lazy_zod.z.string().base64url().length(43),createdAt:import_lazy_zod.z.number().positive().int(),version:import_lazy_zod.z.number().positive().int()}).strict();MAX_CLOCK_DRIFT_MS=6e4;MAX_SECRET_AGE_MS=100*365*24*60*60*1e3}});function getPath(){return require("path")}function isSecretPersistenceEnabled(options){const isProduction3=(0,import_env.getEnv)("NODE_ENV")==="production";if(isProduction3){return options?.forceEnable===true}return true}function resolveSecretPath(options){const p=getPath();if(options?.secretPath){if(p.isAbsolute(options.secretPath)){return options.secretPath}return p.resolve((0,import_env.getCwd)(),options.secretPath)}const name=options?.name??"default";const defaultPath=`${DEFAULT_SECRET_DIR}/${name}-secret.json`;return p.resolve((0,import_env.getCwd)(),defaultPath)}function getLogger(options){if(options?.enableLogging===false){return{warn:noop,error:noop}}return options?.logger??{warn:console.warn,error:console.error}}function getLogPrefix(options){const name=options?.name??"Secret";return`[${name}Persistence]`}async function loadSecret(options){if(!isSecretPersistenceEnabled(options)){return null}const secretPath=resolveSecretPath(options);const logger=getLogger(options);const prefix=getLogPrefix(options);try{const content=await readFile(secretPath);const data=JSON.parse(content);const validation=validateSecretData(data);if(!validation.valid){logger.warn(`${prefix} Invalid secret file format at ${secretPath}: ${validation.error}, will regenerate`);return null}return data}catch(error){if(error.code==="ENOENT"){return null}logger.warn(`${prefix} Failed to load secret from ${secretPath}: ${error.message}`);return null}}async function saveSecret(secretData,options){if(!isSecretPersistenceEnabled(options)){return true}const secretPath=resolveSecretPath(options);const dir=getPath().dirname(secretPath);const tempPath=`${secretPath}.tmp.${Date.now()}.${base64urlEncode(randomBytes(8))}`;const logger=getLogger(options);const prefix=getLogPrefix(options);try{await mkdir(dir,{recursive:true,mode:448});const content=JSON.stringify(secretData,null,2);await writeFile(tempPath,content,{mode:384});await rename(tempPath,secretPath);return true}catch(error){logger.error(`${prefix} Failed to save secret to ${secretPath}: ${error.message}`);try{await unlink(tempPath)}catch{}return false}}async function deleteSecret(options){const secretPath=resolveSecretPath(options);const logger=getLogger(options);const prefix=getLogPrefix(options);try{await unlink(secretPath);return true}catch(error){if(error.code==="ENOENT"){return true}logger.warn(`${prefix} Failed to delete secret at ${secretPath}: ${error.message}`);return false}}function generateSecret(bytes=DEFAULT_SECRET_BYTES){return base64urlEncode(randomBytes(bytes))}function createSecretData(options){const secretBytes=options?.secretBytes??DEFAULT_SECRET_BYTES;return{secret:generateSecret(secretBytes),createdAt:Date.now(),version:1}}async function getOrCreateSecret(options){const cacheKey=resolveSecretPath(options);const cached=secretCache.get(cacheKey);if(cached){return cached}const existing=generationPromises.get(cacheKey);if(existing){return existing}const promise=(async()=>{try{const loaded=await loadSecret(options);if(loaded){secretCache.set(cacheKey,loaded.secret);return loaded.secret}const secretData=createSecretData(options);if(isSecretPersistenceEnabled(options)){await saveSecret(secretData,options)}secretCache.set(cacheKey,secretData.secret);return secretData.secret}finally{generationPromises.delete(cacheKey)}})();generationPromises.set(cacheKey,promise);return promise}function clearCachedSecret(options){if(options){const cacheKey=resolveSecretPath(options);secretCache.delete(cacheKey)}else{secretCache.clear()}}function isSecretCached(options){const cacheKey=resolveSecretPath(options);return secretCache.has(cacheKey)}var import_env,DEFAULT_SECRET_BYTES,DEFAULT_SECRET_DIR,noop,secretCache,generationPromises;var init_persistence=__esm({"libs/utils/src/crypto/secret-persistence/persistence.ts"(){"use strict";init_fs2();init_crypto();init_schema();import_env=require("#env");DEFAULT_SECRET_BYTES=32;DEFAULT_SECRET_DIR=".frontmcp";noop=()=>{};secretCache=new Map;generationPromises=new Map}});var init_secret_persistence=__esm({"libs/utils/src/crypto/secret-persistence/index.ts"(){"use strict";init_schema();init_persistence()}});function computeSignature(data,secret){const encoder=new TextEncoder;const keyBytes=encoder.encode(secret);const dataBytes=encoder.encode(data);const hmac2=hmacSha256(keyBytes,dataBytes);return base64urlEncode(hmac2)}function signData(data,config){const jsonData=JSON.stringify(data);const sig=computeSignature(jsonData,config.secret);const signed={data,sig,v:1};return JSON.stringify(signed)}function verifyData(signedJson,config){try{const parsed=JSON.parse(signedJson);if(!parsed||typeof parsed!=="object"||!("sig"in parsed)){return null}const signed=parsed;if(signed.v!==1){return null}const jsonData=JSON.stringify(signed.data);const expectedSig=computeSignature(jsonData,config.secret);const sigBytes=base64urlDecode(signed.sig);const expectedBytes=base64urlDecode(expectedSig);if(sigBytes.length!==expectedBytes.length){return null}if(!timingSafeEqual(sigBytes,expectedBytes)){return null}return signed.data}catch{return null}}function isSignedData(json){try{const parsed=JSON.parse(json);return parsed&&typeof parsed==="object"&&"sig"in parsed&&"v"in parsed}catch{return false}}function verifyOrParseData(json,config){if(isSignedData(json)){return verifyData(json,config)}try{return JSON.parse(json)}catch{return null}}var init_hmac_signing=__esm({"libs/utils/src/crypto/hmac-signing.ts"(){"use strict";init_crypto();init_crypto();init_crypto()}});function validateKeyData(data){const result=anyKeyDataSchema.safeParse(data);if(!result.success){return{valid:false,error:result.error.issues[0]?.message??"Invalid key structure"}}const parsed=result.data;const now=Date.now();if(parsed.createdAt>now+MAX_CLOCK_DRIFT_MS2){return{valid:false,error:"createdAt is in the future"}}if(parsed.createdAt<now-MAX_KEY_AGE_MS){return{valid:false,error:"createdAt is too old"}}return{valid:true,data:parsed}}function parseKeyData(data){const validation=validateKeyData(data);if(!validation.valid){return null}return validation.data}function isSecretKeyData(data){return data.type==="secret"}function isAsymmetricKeyData(data){return data.type==="asymmetric"}var import_lazy_zod2,MAX_CLOCK_DRIFT_MS2,MAX_KEY_AGE_MS,asymmetricAlgSchema,baseKeyDataSchema,jsonWebKeySchema,secretKeyDataSchema,asymmetricKeyDataSchema,anyKeyDataSchema;var init_schemas=__esm({"libs/utils/src/crypto/key-persistence/schemas.ts"(){"use strict";import_lazy_zod2=require("@frontmcp/lazy-zod");MAX_CLOCK_DRIFT_MS2=6e4;MAX_KEY_AGE_MS=100*365*24*60*60*1e3;asymmetricAlgSchema=import_lazy_zod2.z.enum(["RS256","RS384","RS512","ES256","ES384","ES512"]);baseKeyDataSchema=import_lazy_zod2.z.object({kid:import_lazy_zod2.z.string().min(1),createdAt:import_lazy_zod2.z.number().positive().int(),version:import_lazy_zod2.z.number().positive().int()});jsonWebKeySchema=import_lazy_zod2.z.object({kty:import_lazy_zod2.z.string().optional(),use:import_lazy_zod2.z.string().optional(),alg:import_lazy_zod2.z.string().optional(),kid:import_lazy_zod2.z.string().optional(),n:import_lazy_zod2.z.string().optional(),e:import_lazy_zod2.z.string().optional(),d:import_lazy_zod2.z.string().optional(),p:import_lazy_zod2.z.string().optional(),q:import_lazy_zod2.z.string().optional(),dp:import_lazy_zod2.z.string().optional(),dq:import_lazy_zod2.z.string().optional(),qi:import_lazy_zod2.z.string().optional(),x:import_lazy_zod2.z.string().optional(),y:import_lazy_zod2.z.string().optional(),crv:import_lazy_zod2.z.string().optional()}).passthrough();secretKeyDataSchema=baseKeyDataSchema.extend({type:import_lazy_zod2.z.literal("secret"),secret:import_lazy_zod2.z.string().min(1),bytes:import_lazy_zod2.z.number().positive().int()});asymmetricKeyDataSchema=baseKeyDataSchema.extend({type:import_lazy_zod2.z.literal("asymmetric"),alg:asymmetricAlgSchema,privateKey:jsonWebKeySchema,publicJwk:import_lazy_zod2.z.object({keys:import_lazy_zod2.z.array(jsonWebKeySchema).min(1)})});anyKeyDataSchema=import_lazy_zod2.z.discriminatedUnion("type",[secretKeyDataSchema,asymmetricKeyDataSchema])}});var KeyPersistence;var init_key_persistence=__esm({"libs/utils/src/crypto/key-persistence/key-persistence.ts"(){"use strict";init_crypto();init_schemas();KeyPersistence=class{storage;cache=new Map;enableCache;throwOnInvalid;constructor(options){this.storage=options.storage;this.enableCache=options.enableCache??true;this.throwOnInvalid=options.throwOnInvalid??false}async get(kid){if(this.enableCache){const cached=this.cache.get(kid);if(cached)return cached}const raw=await this.storage.get(kid);if(!raw)return null;let parsed;try{parsed=JSON.parse(raw)}catch{if(this.throwOnInvalid){throw new Error(`Invalid JSON for key "${kid}"`)}return null}const validation=validateKeyData(parsed);if(!validation.valid){if(this.throwOnInvalid){throw new Error(`Invalid key data for "${kid}": ${validation.error}`)}return null}const key=validation.data;if(this.enableCache){this.cache.set(kid,key)}return key}async getSecret(kid){const key=await this.get(kid);if(!key||!isSecretKeyData(key))return null;return key}async getAsymmetric(kid){const key=await this.get(kid);if(!key||!isAsymmetricKeyData(key))return null;return key}async set(key){const validation=validateKeyData(key);if(!validation.valid){throw new Error(`Invalid key data: ${validation.error}`)}await this.storage.set(key.kid,JSON.stringify(key,null,2));if(this.enableCache){this.cache.set(key.kid,key)}}async delete(kid){this.cache.delete(kid);return this.storage.delete(kid)}async has(kid){if(this.enableCache&&this.cache.has(kid)){return true}return this.storage.exists(kid)}async list(){return this.storage.keys()}async getOrCreateSecret(kid,options){const existing=await this.getSecret(kid);if(existing){return existing}const bytes=options?.bytes??32;const secret={type:"secret",kid,secret:base64urlEncode(randomBytes(bytes)),bytes,createdAt:Date.now(),version:1};await this.set(secret);return secret}clearCache(){this.cache.clear()}clearCacheFor(kid){this.cache.delete(kid)}isCached(kid){return this.cache.has(kid)}getAdapter(){return this.storage}}}});var StorageError,StorageConnectionError,StorageOperationError,StorageNotSupportedError,StorageConfigError,StorageTTLError,StoragePatternError,StorageNotConnectedError,EncryptedStorageError;var init_errors=__esm({"libs/utils/src/storage/errors.ts"(){"use strict";StorageError=class extends Error{cause;constructor(message,cause){super(message);this.cause=cause;this.name="StorageError";Object.setPrototypeOf(this,new.target.prototype);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}};StorageConnectionError=class extends StorageError{constructor(message,cause,backend){const fullMessage=cause?`${message}: ${cause.message}`:message;super(fullMessage,cause);this.backend=backend;this.name="StorageConnectionError"}backend};StorageOperationError=class extends StorageError{constructor(operation,key,message,cause){super(`${operation} failed for key "${key}": ${message}`,cause);this.operation=operation;this.key=key;this.name="StorageOperationError"}operation;key};StorageNotSupportedError=class extends StorageError{constructor(operation,backend,suggestion){const msg=suggestion?`${operation} is not supported by ${backend}. ${suggestion}`:`${operation} is not supported by ${backend}`;super(msg);this.operation=operation;this.backend=backend;this.name="StorageNotSupportedError"}operation;backend};StorageConfigError=class extends StorageError{constructor(backend,message){super(`Invalid ${backend} configuration: ${message}`);this.backend=backend;this.name="StorageConfigError"}backend};StorageTTLError=class extends StorageError{constructor(ttl,message){super(message??`Invalid TTL value: ${ttl}. TTL must be a positive integer.`);this.ttl=ttl;this.name="StorageTTLError"}ttl};StoragePatternError=class extends StorageError{constructor(pattern,message){super(`Invalid pattern "${pattern}": ${message}`);this.pattern=pattern;this.name="StoragePatternError"}pattern};StorageNotConnectedError=class extends StorageError{constructor(backend){super(`Storage backend "${backend}" is not connected. Call connect() first.`);this.backend=backend;this.name="StorageNotConnectedError"}backend};EncryptedStorageError=class extends StorageError{constructor(message){super(message);this.name="EncryptedStorageError"}}}});function globToRegex(pattern){if(pattern.length>MAX_PATTERN_LENGTH){throw new StoragePatternError(pattern.substring(0,50)+"...",`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`)}const wildcardCount=(pattern.match(/[*?]/g)||[]).length;if(wildcardCount>MAX_WILDCARDS){throw new StoragePatternError(pattern,`Pattern has too many wildcards (max: ${MAX_WILDCARDS})`)}if(pattern===""||pattern==="*"){return/^.*$/}let regexStr="^";let prevChar="";for(let i=0;i<pattern.length;i++){const char=pattern[i];switch(char){case"*":if(prevChar!=="*"){regexStr+=".*"}break;case"?":regexStr+=".";break;default:regexStr+=char.replace(REGEX_SPECIAL_CHARS,"\\$&")}prevChar=char}regexStr+="$";try{return new RegExp(regexStr)}catch{throw new StoragePatternError(pattern,"Failed to compile pattern to regex")}}function matchesPattern(key,pattern){const regex=globToRegex(pattern);return regex.test(key)}function validatePattern(pattern){try{globToRegex(pattern);return{valid:true}}catch(e){return{valid:false,error:e instanceof Error?e.message:"Invalid pattern"}}}function escapeGlob(literal){return literal.replace(/[*?\\]/g,"\\$&")}var MAX_PATTERN_LENGTH,MAX_WILDCARDS,REGEX_SPECIAL_CHARS;var init_pattern=__esm({"libs/utils/src/storage/utils/pattern.ts"(){"use strict";init_errors();MAX_PATTERN_LENGTH=500;MAX_WILDCARDS=20;REGEX_SPECIAL_CHARS=/[.+^${}()|[\]\\]/g}});function validateTTL(ttlSeconds){if(typeof ttlSeconds!=="number"){throw new StorageTTLError(ttlSeconds,`TTL must be a number, got ${typeof ttlSeconds}`)}if(!Number.isFinite(ttlSeconds)){throw new StorageTTLError(ttlSeconds,"TTL must be a finite number")}if(!Number.isInteger(ttlSeconds)){throw new StorageTTLError(ttlSeconds,`TTL must be an integer, got ${ttlSeconds}`)}if(ttlSeconds<=0){throw new StorageTTLError(ttlSeconds,`TTL must be positive, got ${ttlSeconds}`)}if(ttlSeconds>MAX_TTL_SECONDS){throw new StorageTTLError(ttlSeconds,`TTL exceeds maximum of ${MAX_TTL_SECONDS} seconds`)}}function validateOptionalTTL(ttlSeconds){if(ttlSeconds!==void 0){validateTTL(ttlSeconds)}}function ttlToExpiresAt(ttlSeconds){return Date.now()+ttlSeconds*1e3}function expiresAtToTTL(expiresAt){const remaining=Math.ceil((expiresAt-Date.now())/1e3);return Math.max(0,remaining)}function isExpired(expiresAt){if(expiresAt===void 0)return false;return Date.now()>=expiresAt}function normalizeTTL(ttl,unit){return unit==="milliseconds"?Math.ceil(ttl/1e3):ttl}var MAX_TTL_SECONDS;var init_ttl=__esm({"libs/utils/src/storage/utils/ttl.ts"(){"use strict";init_errors();MAX_TTL_SECONDS=31536e5}});var BaseStorageAdapter;var init_base=__esm({"libs/utils/src/storage/adapters/base.ts"(){"use strict";init_errors();init_ttl();BaseStorageAdapter=class{connected=false;ensureConnected(){if(!this.connected){throw new StorageNotConnectedError(this.backendName)}}async set(key,value,options){this.ensureConnected();this.validateSetOptions(options);return this.doSet(key,value,options)}async mget(keys){this.ensureConnected();return Promise.all(keys.map(k=>this.get(k)))}async mset(entries){this.ensureConnected();for(const entry of entries){this.validateSetOptions(entry.options)}await Promise.all(entries.map(e=>this.doSet(e.key,e.value,e.options)))}async mdelete(keys){this.ensureConnected();const results=await Promise.all(keys.map(k=>this.delete(k)));return results.filter(Boolean).length}async count(pattern="*"){const matchedKeys=await this.keys(pattern);return matchedKeys.length}async deleteIfEquals(_key,_expectedValue){throw new StorageNotSupportedError("deleteIfEquals",this.backendName,"Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-delete.")}async expireIfEquals(_key,_expectedValue,_ttlSeconds){throw new StorageNotSupportedError("expireIfEquals",this.backendName,"Use the memory, Redis, Upstash or Vercel KV adapter for an atomic compare-and-expire.")}supportsPubSub(){return false}async publish(_channel,_message){throw new StorageNotSupportedError("publish",this.backendName,this.getPubSubSuggestion())}async subscribe(_channel,_handler){throw new StorageNotSupportedError("subscribe",this.backendName,this.getPubSubSuggestion())}getPubSubSuggestion(){return"Use Redis or Upstash adapter for pub/sub support."}validateSetOptions(options){if(!options)return;validateOptionalTTL(options.ttlSeconds);if(options.ifNotExists&&options.ifExists){throw new Error("ifNotExists and ifExists are mutually exclusive")}}}}});var import_event_emitter,DEFAULT_SWEEP_INTERVAL_SECONDS,MAX_TIMEOUT_MS,MemoryStorageAdapter;var init_memory=__esm({"libs/utils/src/storage/adapters/memory.ts"(){"use strict";import_event_emitter=require("#event-emitter");init_errors();init_pattern();init_ttl();init_base();DEFAULT_SWEEP_INTERVAL_SECONDS=60;MAX_TIMEOUT_MS=2147483647;MemoryStorageAdapter=class extends BaseStorageAdapter{backendName="memory";store=new Map;emitter=new import_event_emitter.EventEmitter;sweepInterval;options;accessOrder=[];constructor(options={}){super();this.options={enableSweeper:options.enableSweeper??true,sweepIntervalSeconds:options.sweepIntervalSeconds??DEFAULT_SWEEP_INTERVAL_SECONDS,maxEntries:options.maxEntries??0};this.emitter.setMaxListeners(1e3)}async connect(){if(this.connected)return;this.connected=true;if(this.options.enableSweeper&&this.options.sweepIntervalSeconds>0){this.startSweeper()}}async disconnect(){if(!this.connected)return;this.stopSweeper();this.clearAllTimeouts();this.store.clear();this.accessOrder=[];this.emitter.removeAllListeners();this.connected=false}async ping(){return this.connected}async get(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return null;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return null}this.touchLRU(key);return entry.value}async doSet(key,value,options){const existingEntry=this.store.get(key);const exists=existingEntry!==void 0&&!isExpired(existingEntry.expiresAt);if(options?.ifNotExists&&exists){return}if(options?.ifExists&&!exists){return}this.clearEntryTimeout(key);const entry={value};if(options?.ttlSeconds){entry.expiresAt=ttlToExpiresAt(options.ttlSeconds);const ttlMs=options.ttlSeconds*1e3;if(ttlMs<MAX_TIMEOUT_MS){entry.timeout=setTimeout(()=>{this.deleteEntry(key)},ttlMs);if(entry.timeout.unref){entry.timeout.unref()}}}if(this.options.maxEntries>0&&!this.store.has(key)){while(this.store.size>=this.options.maxEntries){this.evictOldest()}}this.store.set(key,entry);this.touchLRU(key)}async delete(key){this.ensureConnected();return this.deleteEntry(key)}async deleteIfEquals(key,expectedValue){this.ensureConnected();const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)||entry.value!==expectedValue)return false;return this.deleteEntry(key)}async expireIfEquals(key,expectedValue,ttlSeconds){this.ensureConnected();const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)||entry.value!==expectedValue)return false;return this.expire(key,ttlSeconds)}async exists(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return false;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return false}return true}async expire(key,ttlSeconds){this.ensureConnected();validateTTL(ttlSeconds);const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)){return false}this.clearEntryTimeout(key);entry.expiresAt=ttlToExpiresAt(ttlSeconds);const ttlMs=ttlSeconds*1e3;if(ttlMs<MAX_TIMEOUT_MS){entry.timeout=setTimeout(()=>{this.deleteEntry(key)},ttlMs);if(entry.timeout.unref){entry.timeout.unref()}}return true}async ttl(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return null;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return null}if(entry.expiresAt===void 0){return-1}return expiresAtToTTL(entry.expiresAt)}async keys(pattern="*"){this.ensureConnected();const regex=globToRegex(pattern);const result=[];for(const[key,entry]of this.store){if(isExpired(entry.expiresAt)){this.deleteEntry(key);continue}if(regex.test(key)){result.push(key)}}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const entry=this.store.get(key);let currentValue=0;if(entry&&!isExpired(entry.expiresAt)){const parsed=parseInt(entry.value,10);if(isNaN(parsed)){throw new StorageOperationError("incrBy",key,"Value is not an integer")}currentValue=parsed}const newValue=currentValue+amount;const newEntry={value:String(newValue)};if(entry?.expiresAt&&!isExpired(entry.expiresAt)){newEntry.expiresAt=entry.expiresAt;const remainingMs=entry.expiresAt-Date.now();if(remainingMs>0&&remainingMs<MAX_TIMEOUT_MS){this.clearEntryTimeout(key);newEntry.timeout=setTimeout(()=>{this.deleteEntry(key)},remainingMs);if(newEntry.timeout.unref){newEntry.timeout.unref()}}}this.store.set(key,newEntry);this.touchLRU(key);return newValue}supportsPubSub(){return true}async publish(channel,message){this.ensureConnected();return this.emitter.listenerCount(channel)>0?(this.emitter.emit(channel,message,channel),this.emitter.listenerCount(channel)):0}async subscribe(channel,handler){this.ensureConnected();const wrappedHandler=(message,ch)=>{handler(message,ch)};this.emitter.on(channel,wrappedHandler);return async()=>{this.emitter.off(channel,wrappedHandler)}}deleteEntry(key){const entry=this.store.get(key);if(!entry)return false;this.clearEntryTimeout(key);this.store.delete(key);this.removeLRU(key);return true}clearEntryTimeout(key){const entry=this.store.get(key);if(entry?.timeout){clearTimeout(entry.timeout);entry.timeout=void 0}}clearAllTimeouts(){for(const[key]of this.store){this.clearEntryTimeout(key)}}touchLRU(key){if(this.options.maxEntries<=0)return;const idx=this.accessOrder.indexOf(key);if(idx!==-1){this.accessOrder.splice(idx,1)}this.accessOrder.push(key)}removeLRU(key){if(this.options.maxEntries<=0)return;const idx=this.accessOrder.indexOf(key);if(idx!==-1){this.accessOrder.splice(idx,1)}}evictOldest(){if(this.accessOrder.length===0)return;const oldestKey=this.accessOrder.shift();if(oldestKey){this.deleteEntry(oldestKey)}}startSweeper(){this.sweepInterval=setInterval(()=>{this.sweep()},this.options.sweepIntervalSeconds*1e3);if(this.sweepInterval.unref){this.sweepInterval.unref()}}stopSweeper(){if(this.sweepInterval){clearInterval(this.sweepInterval);this.sweepInterval=void 0}}sweep(){const now=Date.now();for(const[key,entry]of this.store){if(entry.expiresAt&&now>=entry.expiresAt){this.deleteEntry(key)}}}getStats(){return{size:this.store.size,maxEntries:this.options.maxEntries,sweeperActive:this.sweepInterval!==void 0}}}}});var filesystem_exports={};__export(filesystem_exports,{FileSystemStorageAdapter:()=>FileSystemStorageAdapter});var FileSystemStorageAdapter;var init_filesystem=__esm({"libs/utils/src/storage/adapters/filesystem.ts"(){"use strict";init_base();init_errors();init_pattern();init_fs2();init_crypto();FileSystemStorageAdapter=class extends BaseStorageAdapter{backendName="filesystem";baseDir;extension;dirMode;fileMode;constructor(options){super();this.baseDir=options.baseDir;this.extension=options.extension??".json";this.dirMode=options.dirMode??448;this.fileMode=options.fileMode??384}async connect(){if(this.connected)return;await ensureDir(this.baseDir);try{await mkdir(this.baseDir,{recursive:true,mode:this.dirMode})}catch{}this.connected=true}async disconnect(){if(!this.connected)return;this.connected=false}async ping(){if(!this.connected)return false;try{return await fileExists(this.baseDir)}catch{return false}}async get(key){this.ensureConnected();const filePath=this.keyToPath(key);try{const entry=await readJSON(filePath);if(!entry)return null;if(entry.expiresAt&&Date.now()>=entry.expiresAt){await this.deleteFile(filePath);return null}return entry.value}catch(e){const error=e;if(error.code==="ENOENT"){return null}throw e}}async doSet(key,value,options){const filePath=this.keyToPath(key);const existingEntry=await this.readEntry(filePath);const exists=existingEntry!==null&&!this.isExpired(existingEntry);if(options?.ifNotExists&&exists){return}if(options?.ifExists&&!exists){return}const entry={value};if(options?.ttlSeconds){entry.expiresAt=Date.now()+options.ttlSeconds*1e3}await this.atomicWrite(filePath,entry)}async delete(key){this.ensureConnected();const filePath=this.keyToPath(key);return this.deleteFile(filePath)}async exists(key){this.ensureConnected();const filePath=this.keyToPath(key);try{const entry=await this.readEntry(filePath);if(!entry)return false;if(this.isExpired(entry)){await this.deleteFile(filePath);return false}return true}catch{return false}}async expire(key,ttlSeconds){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(!entry||this.isExpired(entry)){return false}entry.expiresAt=Date.now()+ttlSeconds*1e3;await this.atomicWrite(filePath,entry);return true}async ttl(key){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(!entry)return null;if(this.isExpired(entry)){await this.deleteFile(filePath);return null}if(entry.expiresAt===void 0){return-1}return Math.max(0,Math.ceil((entry.expiresAt-Date.now())/1e3))}async keys(pattern="*"){this.ensureConnected();const regex=globToRegex(pattern);const result=[];try{const files=await readdir(this.baseDir);for(const file of files){if(!file.endsWith(this.extension))continue;const key=this.pathToKey(file);if(!regex.test(key))continue;const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(entry&&!this.isExpired(entry)){result.push(key)}else if(entry&&this.isExpired(entry)){await this.deleteFile(filePath)}}}catch(e){const error=e;if(error.code==="ENOENT"){return[]}throw e}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);let currentValue=0;if(entry&&!this.isExpired(entry)){const parsed=parseInt(entry.value,10);if(isNaN(parsed)){throw new StorageOperationError("incrBy",key,"Value is not an integer")}currentValue=parsed}const newValue=currentValue+amount;const newEntry={value:String(newValue)};if(entry?.expiresAt&&!this.isExpired(entry)){newEntry.expiresAt=entry.expiresAt}await this.atomicWrite(filePath,newEntry);return newValue}keyToPath(key){const safeKey=this.encodeKey(key);return`${this.baseDir}/${safeKey}${this.extension}`}pathToKey(filename){const safeKey=filename.slice(0,-this.extension.length);return this.decodeKey(safeKey)}encodeKey(key){return encodeURIComponent(key).replace(/\./g,"%2E")}decodeKey(encoded){return decodeURIComponent(encoded)}async readEntry(filePath){try{return await readJSON(filePath)}catch{return null}}isExpired(entry){return entry.expiresAt!==void 0&&Date.now()>=entry.expiresAt}async deleteFile(filePath){try{await unlink(filePath);return true}catch(e){const error=e;if(error.code==="ENOENT"){return false}throw e}}async atomicWrite(filePath,entry){const tempSuffix=bytesToHex(randomBytes(8));const tempPath=`${filePath}.${tempSuffix}.tmp`;try{const content=JSON.stringify(entry,null,2);await writeFile(tempPath,content,{mode:this.fileMode});await rename(tempPath,filePath)}catch(e){try{await unlink(tempPath)}catch{}throw e}}getPubSubSuggestion(){return"FileSystem adapter does not support pub/sub. Use Redis or Memory adapter for pub/sub support."}}}});var indexeddb_exports={};__export(indexeddb_exports,{IndexedDBStorageAdapter:()=>IndexedDBStorageAdapter});var IndexedDBStorageAdapter;var init_indexeddb=__esm({"libs/utils/src/storage/adapters/indexeddb.ts"(){"use strict";init_base();init_pattern();IndexedDBStorageAdapter=class extends BaseStorageAdapter{backendName="indexeddb";dbName;storeName;prefix;db=null;constructor(options){super();this.dbName=options?.dbName??"frontmcp";this.storeName=options?.storeName??"kv";this.prefix=options?.prefix??"frontmcp:"}assertAvailable(){if(typeof indexedDB==="undefined"){throw new Error("IndexedDB is not available in this environment")}}key(k){return`${this.prefix}${k}`}stripPrefix(fullKey){return fullKey.slice(this.prefix.length)}async connect(){this.assertAvailable();if(this.db){this.connected=true;return}this.db=await new Promise((resolve2,reject)=>{const request=indexedDB.open(this.dbName,1);request.onupgradeneeded=()=>{const db=request.result;if(!db.objectStoreNames.contains(this.storeName)){db.createObjectStore(this.storeName,{keyPath:"k"})}};request.onsuccess=()=>resolve2(request.result);request.onerror=()=>reject(request.error)});this.connected=true}async disconnect(){if(this.db){this.db.close();this.db=null}this.connected=false}async ping(){return this.db!==null&&this.connected}getStore(mode){if(!this.db){throw new Error("IndexedDB adapter is not connected. Call connect() first.")}const tx=this.db.transaction(this.storeName,mode);return tx.objectStore(this.storeName)}idbRequest(request){return new Promise((resolve2,reject)=>{request.onsuccess=()=>resolve2(request.result);request.onerror=()=>reject(request.error)})}idbTransaction(store){return new Promise((resolve2,reject)=>{const tx=store.transaction;tx.oncomplete=()=>resolve2();tx.onerror=()=>reject(tx.error)})}async get(key){this.ensureConnected();const store=this.getStore("readonly");const entry=await this.idbRequest(store.get(this.key(key)));if(!entry)return null;if(entry.e&&entry.e<Date.now()){const writeStore=this.getStore("readwrite");writeStore.delete(this.key(key));return null}return entry.v}async doSet(key,value,options){if(options?.ifNotExists){const existing=await this.get(key);if(existing!==null)return}if(options?.ifExists){const existing=await this.get(key);if(existing===null)return}const entry={k:this.key(key),v:value};if(options?.ttlSeconds){entry.e=Date.now()+options.ttlSeconds*1e3}const store=this.getStore("readwrite");await this.idbRequest(store.put(entry))}async delete(key){this.ensureConnected();const existing=await this.get(key);if(existing===null)return false;const store=this.getStore("readwrite");await this.idbRequest(store.delete(this.key(key)));return true}async exists(key){return await this.get(key)!==null}async expire(key,ttlSeconds){this.ensureConnected();const value=await this.get(key);if(value===null)return false;await this.doSet(key,value,{ttlSeconds});return true}async ttl(key){this.ensureConnected();const store=this.getStore("readonly");const entry=await this.idbRequest(store.get(this.key(key)));if(!entry)return null;if(entry.e){const remaining=Math.ceil((entry.e-Date.now())/1e3);return remaining>0?remaining:null}return-1}async keys(pattern){this.ensureConnected();const store=this.getStore("readonly");const allKeys=await this.idbRequest(store.getAllKeys());const now=Date.now();const result=[];for(const fullKey of allKeys){const keyStr=String(fullKey);if(!keyStr.startsWith(this.prefix))continue;const key=this.stripPrefix(keyStr);if(pattern&&pattern!=="*"&&!this.matchPattern(key,pattern))continue;const entry=await this.idbRequest(store.get(keyStr));if(entry&&(!entry.e||entry.e>=now)){result.push(key)}}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const current=await this.get(key);const value=current!==null?parseInt(current,10)+amount:amount;if(Number.isNaN(value)){throw new Error(`Value at "${key}" is not an integer`)}await this.doSet(key,String(value));return value}matchPattern(key,pattern){return matchesPattern(key,pattern)}}}});var localstorage_exports={};__export(localstorage_exports,{LocalStorageAdapter:()=>LocalStorageAdapter});var LocalStorageAdapter;var init_localstorage=__esm({"libs/utils/src/storage/adapters/localstorage.ts"(){"use strict";init_base();init_crypto();init_pattern();LocalStorageAdapter=class extends BaseStorageAdapter{backendName="localstorage";prefix;encryptionKey;allowPlaintext;encoder=new TextEncoder;decoder=new TextDecoder;constructor(options){super();this.prefix=options?.prefix??"frontmcp:";this.allowPlaintext=options?.allowPlaintext??true;if(options?.encryptionKey){if(options.encryptionKey.length!==32){throw new Error(`encryptionKey must be exactly 32 bytes, got ${options.encryptionKey.length}`)}this.encryptionKey=options.encryptionKey}}assertAvailable(){if(typeof localStorage==="undefined"){throw new Error("localStorage is not available in this environment")}}key(k){return`${this.prefix}${k}`}stripPrefix(fullKey){return fullKey.slice(this.prefix.length)}async connect(){this.assertAvailable();const probeKey=this.key("__probe__");try{localStorage.setItem(probeKey,"1");const read=localStorage.getItem(probeKey);if(read!=="1"){throw new Error("localStorage probe: read-back mismatch")}}catch(err){throw new Error(`localStorage is not writable: ${err instanceof Error?err.message:String(err)}`)}finally{try{localStorage.removeItem(probeKey)}catch{}}this.connected=true}async disconnect(){this.connected=false}async ping(){const probeKey=this.key("__probe__");try{this.assertAvailable();localStorage.setItem(probeKey,"1");return localStorage.getItem(probeKey)==="1"}catch{return false}finally{try{localStorage.removeItem(probeKey)}catch{}}}async get(key){const raw=localStorage.getItem(this.key(key));if(raw===null)return null;try{const entry=JSON.parse(raw);if(entry.e&&entry.e<Date.now()){localStorage.removeItem(this.key(key));return null}if(entry._enc){if(!this.encryptionKey)return null;const iv=base64urlDecode(entry._enc.iv);const tag=base64urlDecode(entry._enc.tag);const ciphertext=base64urlDecode(entry._enc.data);const plainBytes=decryptAesGcm(this.encryptionKey,ciphertext,iv,tag);return this.decoder.decode(plainBytes)}return entry.v}catch{return null}}async set(key,value,options){if(options?.ifNotExists){const existing=await this.get(key);if(existing!==null)return}if(options?.ifExists){const existing=await this.get(key);if(existing===null)return}await this.doSet(key,value,options)}async doSet(key,value,options){const entry={v:""};if(options?.ttlSeconds){entry.e=Date.now()+options.ttlSeconds*1e3}if(this.encryptionKey){const iv=randomBytes(12);const plainBytes=this.encoder.encode(value);const{ciphertext,tag}=encryptAesGcm(this.encryptionKey,plainBytes,iv);entry._enc={alg:"A256GCM",iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}else{if(!this.allowPlaintext){throw new Error("Plaintext storage is disabled. Provide an encryptionKey or set allowPlaintext: true.")}entry.v=value}localStorage.setItem(this.key(key),JSON.stringify(entry))}async delete(key){const existed=await this.get(key)!==null;localStorage.removeItem(this.key(key));return existed}async exists(key){return await this.get(key)!==null}async mget(keys){return Promise.all(keys.map(k=>this.get(k)))}async mset(entries){for(const entry of entries){await this.set(entry.key,entry.value,entry.options)}}async mdelete(keys){let count=0;for(const key of keys){if(await this.delete(key))count++}return count}async expire(key,ttlSeconds){const value=await this.get(key);if(value===null)return false;await this.set(key,value,{ttlSeconds});return true}async ttl(key){const raw=localStorage.getItem(this.key(key));if(raw===null)return null;try{const entry=JSON.parse(raw);if(!entry.e)return-1;const remaining=Math.ceil((entry.e-Date.now())/1e3);return remaining>0?remaining:null}catch{return null}}async keys(pattern){const result=[];const candidates=[];for(let i=0;i<localStorage.length;i++){const fullKey=localStorage.key(i);if(fullKey&&fullKey.startsWith(this.prefix)){candidates.push(this.stripPrefix(fullKey))}}for(const key of candidates){if(!pattern||pattern==="*"||this.matchPattern(key,pattern)){if(await this.get(key)!==null){result.push(key)}}}return result}async count(pattern){return(await this.keys(pattern)).length}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){if(!Number.isInteger(amount)){throw new Error(`amount must be an integer, got ${amount}`)}const current=await this.get(key);if(current!==null&&!/^-?\d+$/.test(current)){throw new Error(`Value at "${key}" is not an integer`)}const value=current!==null?parseInt(current,10)+amount:amount;await this.set(key,String(value));return value}async publish(){throw new Error("LocalStorage adapter does not support pub/sub")}async subscribe(_channel,_handler){throw new Error("LocalStorage adapter does not support pub/sub")}supportsPubSub(){return false}matchPattern(key,pattern){return matchesPattern(key,pattern)}}}});function getOrCreateInstallationSalt(){if(typeof localStorage==="undefined"){throw new Error("localStorage unavailable: cannot derive installation salt")}const existing=localStorage.getItem(INSTALL_SALT_KEY);if(existing){try{return base64urlDecode(existing)}catch{}}const legacy=localStorage.getItem(LEGACY_SALT_KEY);if(legacy){try{const salt2=base64urlDecode(legacy);localStorage.setItem(INSTALL_SALT_KEY,base64urlEncode(salt2));localStorage.removeItem(LEGACY_SALT_KEY);return salt2}catch{localStorage.removeItem(LEGACY_SALT_KEY)}}const salt=randomBytes(32);localStorage.setItem(INSTALL_SALT_KEY,base64urlEncode(salt));return salt}function deriveLocalStorageKey(userKey){if(userKey)return userKey;const salt=getOrCreateInstallationSalt();const origin=typeof location!=="undefined"?location.origin:"unknown";const info=new TextEncoder().encode(origin);return import_crypto_provider.cryptoProvider.hkdfSha256(LS_HKDF_IKM,salt,info,32)}async function createKeyPersistence(options){const type=options?.type??"auto";const baseDir=options?.baseDir??DEFAULT_BASE_DIR;let adapter;if(type==="memory"){adapter=new MemoryStorageAdapter}else if(type==="filesystem"){const{FileSystemStorageAdapter:FileSystemStorageAdapter2}=await Promise.resolve().then(()=>(init_filesystem(),filesystem_exports));adapter=new FileSystemStorageAdapter2({baseDir})}else if(type==="indexeddb"){const{IndexedDBStorageAdapter:IndexedDBStorageAdapter2}=await Promise.resolve().then(()=>(init_indexeddb(),indexeddb_exports));adapter=new IndexedDBStorageAdapter2({prefix:"frontmcp:keys:"})}else if(type==="localstorage"){const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)})}else{let connected=false;if(isNode()){try{const{FileSystemStorageAdapter:FileSystemStorageAdapter2}=await Promise.resolve().then(()=>(init_filesystem(),filesystem_exports));adapter=new FileSystemStorageAdapter2({baseDir});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else if(isBrowser()&&typeof indexedDB!=="undefined"){try{const{IndexedDBStorageAdapter:IndexedDBStorageAdapter2}=await Promise.resolve().then(()=>(init_indexeddb(),indexeddb_exports));adapter=new IndexedDBStorageAdapter2({prefix:"frontmcp:keys:"});await adapter.connect();connected=true}catch{if(typeof localStorage!=="undefined"){try{const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else{adapter=new MemoryStorageAdapter}}}else if(isBrowser()&&typeof localStorage!=="undefined"){try{const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else{adapter=new MemoryStorageAdapter}if(!connected){await adapter.connect()}}if(type!=="auto"){await adapter.connect()}return new KeyPersistence({storage:adapter,throwOnInvalid:options?.throwOnInvalid??false,enableCache:options?.enableCache??true})}function createKeyPersistenceWithStorage(storage,options){return new KeyPersistence({storage,throwOnInvalid:options?.throwOnInvalid??false,enableCache:options?.enableCache??true})}var import_crypto_provider,DEFAULT_BASE_DIR,LS_HKDF_IKM,INSTALL_SALT_KEY,LEGACY_SALT_KEY;var init_factory=__esm({"libs/utils/src/crypto/key-persistence/factory.ts"(){"use strict";init_runtime();import_crypto_provider=require("#crypto-provider");init_memory();init_key_persistence();init_crypto();DEFAULT_BASE_DIR=".frontmcp/keys";LS_HKDF_IKM=new TextEncoder().encode("frontmcp:localstorage:v1");INSTALL_SALT_KEY="__frontmcp_internal__:install_salt";LEGACY_SALT_KEY="frontmcp:_install_salt"}});var init_key_persistence2=__esm({"libs/utils/src/crypto/key-persistence/index.ts"(){"use strict";init_schemas();init_key_persistence();init_factory()}});var browser_exports={};__export(browser_exports,{browserCrypto:()=>browserCrypto,cryptoProvider:()=>browserCrypto,generateRsaKeyPair:()=>generateRsaKeyPair,isRsaPssAlg:()=>isRsaPssAlg,jwtAlgToWebCryptoAlg:()=>jwtAlgToWebCryptoAlg,pemToPublicJwk:()=>pemToPublicJwk,rsaSignBase64Url:()=>rsaSignBase64Url,rsaVerify:()=>rsaVerify,rsaVerifyBrowser:()=>rsaVerifyBrowser,rsaVerifySync:()=>rsaVerifySync});function toBytes(data){if(typeof data==="string"){return new TextEncoder().encode(data)}return data}function toHex(bytes){return Array.from(bytes).map(b=>b.toString(16).padStart(2,"0")).join("")}function generateUUID(){if(typeof crypto!=="undefined"&&typeof crypto.randomUUID==="function"){return crypto.randomUUID()}const bytes=(0,import_utils.randomBytes)(16);bytes[6]=bytes[6]&15|64;bytes[8]=bytes[8]&63|128;const hex=toHex(bytes);return`${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`}function constantTimeEqual(a,b){if(a.length!==b.length)return false;let result=0;for(let i=0;i<a.length;i++){result|=a[i]^b[i]}return result===0}function nodeOnly(name){throw new Error(`${name} is only available in Node.js runtimes`)}function rsaVerify(){return nodeOnly("rsaVerify")}function rsaSignBase64Url(){return nodeOnly("rsaSignBase64Url")}function rsaVerifySync(){return nodeOnly("rsaVerifySync")}function pemToPublicJwk(){return nodeOnly("pemToPublicJwk")}function generateRsaKeyPair(){return nodeOnly("generateRsaKeyPair")}async function rsaVerifyBrowser(jwtAlg,data,publicJwk,signature){if(typeof globalThis.crypto?.subtle==="undefined"){throw new Error("WebCrypto API (crypto.subtle) is not available in this environment")}const webAlg=jwtAlgToWebCryptoAlg(jwtAlg);const isPss=isRsaPssAlg(jwtAlg);const algorithm={name:isPss?"RSA-PSS":"RSASSA-PKCS1-v1_5",hash:{name:webAlg}};const key=await globalThis.crypto.subtle.importKey("jwk",publicJwk,algorithm,false,["verify"]);const verifyAlgorithm=isPss?{name:"RSA-PSS",saltLength:getSaltLength(jwtAlg)}:{name:"RSASSA-PKCS1-v1_5"};const sigBuf=new Uint8Array(signature).buffer;const dataBuf=new Uint8Array(data).buffer;return globalThis.crypto.subtle.verify(verifyAlgorithm,key,sigBuf,dataBuf)}function getSaltLength(jwtAlg){switch(jwtAlg){case"PS256":return 32;case"PS384":return 48;case"PS512":return 64;default:return 32}}var import_aes,import_hkdf,import_hmac,import_sha2,import_utils,browserCrypto;var init_browser=__esm({"libs/utils/src/crypto/browser.ts"(){"use strict";import_aes=require("@noble/ciphers/aes.js");import_hkdf=require("@noble/hashes/hkdf.js");import_hmac=require("@noble/hashes/hmac.js");import_sha2=require("@noble/hashes/sha2.js");import_utils=require("@noble/hashes/utils.js");init_jwt_alg();init_jwt_alg();browserCrypto={randomUUID(){return generateUUID()},randomBytes(length){return(0,import_utils.randomBytes)(length)},sha256(data){return(0,import_sha2.sha256)(toBytes(data))},sha256Hex(data){return toHex((0,import_sha2.sha256)(toBytes(data)))},hmacSha256(key,data){return(0,import_hmac.hmac)(import_sha2.sha256,key,data)},hkdfSha256(ikm,salt,info,length){const effectiveSalt=salt.length>0?salt:new Uint8Array(32);return(0,import_hkdf.hkdf)(import_sha2.sha256,ikm,effectiveSalt,info,length)},encryptAesGcm(key,plaintext,iv){const cipher=(0,import_aes.gcm)(key,iv);const sealed=cipher.encrypt(plaintext);const ciphertext=sealed.slice(0,-16);const tag=sealed.slice(-16);return{ciphertext,tag}},decryptAesGcm(key,ciphertext,iv,tag){const cipher=(0,import_aes.gcm)(key,iv);const sealed=new Uint8Array(ciphertext.length+tag.length);sealed.set(ciphertext);sealed.set(tag,ciphertext.length);return cipher.decrypt(sealed)},timingSafeEqual(a,b){return constantTimeEqual(a,b)}}}});function getCrypto(){return platformCrypto.cryptoProvider}function rsaVerify3(jwtAlg,data,publicJwk,signature){if(isNode()){return Promise.resolve(platformCrypto.rsaVerify(jwtAlg,data,publicJwk,signature))}const{rsaVerifyBrowser:rsaVerifyBrowser2}=(init_browser(),__toCommonJS(browser_exports));return rsaVerifyBrowser2(jwtAlg,data,publicJwk,signature)}function rsaSignBase64Url3(jwtAlg,data,privateJwk){if(!isNode()){throw new Error("rsaSignBase64Url is only available in Node.js runtimes")}return platformCrypto.rsaSignBase64Url(jwtAlg,data,privateJwk)}function rsaVerifySync3(jwtAlg,data,publicJwk,signature){if(!isNode()){throw new Error("rsaVerifySync is only available in Node.js runtimes; use the async rsaVerify in browsers")}return platformCrypto.rsaVerifySync(jwtAlg,data,publicJwk,signature)}function pemToPublicJwk3(pem){if(!isNode()){throw new Error("pemToPublicJwk is only available in Node.js runtimes")}return platformCrypto.pemToPublicJwk(pem)}function generateRsaKeyPair3(modulusLength,alg){if(!isNode()){throw new Error("generateRsaKeyPair is only available in Node.js runtimes")}return platformCrypto.generateRsaKeyPair(modulusLength,alg)}function randomUUID(){return getCrypto().randomUUID()}function randomBytes(length){if(!Number.isInteger(length)||length<=0){throw new Error(`randomBytes length must be a positive integer, got ${length}`)}return getCrypto().randomBytes(length)}function sha256(data){return getCrypto().sha256(data)}function sha256Hex(data){return getCrypto().sha256Hex(data)}function hmacSha256(key,data){return getCrypto().hmacSha256(key,data)}function hkdfSha256(ikm,salt,info,length){if(!Number.isInteger(length)||length<=0){throw new Error(`HKDF length must be a positive integer, got ${length}`)}if(length>HKDF_SHA256_MAX_LENGTH){throw new Error(`HKDF-SHA256 length cannot exceed ${HKDF_SHA256_MAX_LENGTH} bytes, got ${length}`)}return getCrypto().hkdfSha256(ikm,salt,info,length)}function encryptAesGcm(key,plaintext,iv){if(key.length!==32){throw new Error(`AES-256-GCM requires a 32-byte key, got ${key.length} bytes`)}if(iv.length!==12){throw new Error(`AES-GCM requires a 12-byte IV, got ${iv.length} bytes`)}return getCrypto().encryptAesGcm(key,plaintext,iv)}function decryptAesGcm(key,ciphertext,iv,tag){if(key.length!==32){throw new Error(`AES-256-GCM requires a 32-byte key, got ${key.length} bytes`)}if(iv.length!==12){throw new Error(`AES-GCM requires a 12-byte IV, got ${iv.length} bytes`)}if(tag.length!==16){throw new Error(`AES-GCM requires a 16-byte authentication tag, got ${tag.length} bytes`)}return getCrypto().decryptAesGcm(key,ciphertext,iv,tag)}function timingSafeEqual(a,b){if(a.length!==b.length){throw new Error(`timingSafeEqual requires equal-length arrays, got ${a.length} and ${b.length} bytes`)}return getCrypto().timingSafeEqual(a,b)}function bytesToHex(data){return Array.from(data).map(b=>b.toString(16).padStart(2,"0")).join("")}function base64urlEncode(data){let base64;if(typeof Buffer!=="undefined"){base64=Buffer.from(data).toString("base64")}else{const binString=Array.from(data,byte=>String.fromCodePoint(byte)).join("");base64=btoa(binString)}const result=base64.replace(/\+/g,"-").replace(/\//g,"_");let end=result.length;while(end>0&&result[end-1]==="="){end--}return result.slice(0,end)}function base64urlDecode(data){let base64=data.replace(/-/g,"+").replace(/_/g,"/");const pad=base64.length%4;if(pad){base64+="=".repeat(4-pad)}if(typeof Buffer!=="undefined"){return new Uint8Array(Buffer.from(base64,"base64"))}else{const binString=atob(base64);return Uint8Array.from(binString,c=>c.codePointAt(0)??0)}}function base64Encode(data){if(typeof Buffer!=="undefined"){return Buffer.from(data).toString("base64")}else{const binString=Array.from(data,byte=>String.fromCodePoint(byte)).join("");return btoa(binString)}}function base64Decode(data){if(typeof Buffer!=="undefined"){return new Uint8Array(Buffer.from(data,"base64"))}else{const binString=atob(data);return Uint8Array.from(binString,c=>c.codePointAt(0)??0)}}function sha256Base64url(data){return base64urlEncode(sha256(data))}var platformCrypto,HKDF_SHA256_MAX_LENGTH;var init_crypto=__esm({"libs/utils/src/crypto/index.ts"(){"use strict";platformCrypto=__toESM(require("#crypto-provider"));init_runtime();init_jwt_alg();init_runtime();init_encrypted_blob();init_pkce2();init_secret_persistence();init_hmac_signing();init_key_persistence2();HKDF_SHA256_MAX_LENGTH=255*32}});function attachRedisErrorListener(client,options={}){const label=options.label??"redis";const intervalMs=options.intervalMs??DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;let lastLoggedAt=0;let suppressed=0;const listener=error=>{const now=Date.now();if(lastLoggedAt!==0&&now-lastLoggedAt<intervalMs){suppressed++;return}const extra=suppressed>0?` (${suppressed} similar error(s) suppressed)`:"";suppressed=0;lastLoggedAt=now;const message=`[${label}] Redis connection error: ${error?.message??String(error)}${extra}`;if(options.logger){options.logger.warn(message)}else{console.warn(message)}};client.on("error",listener);return()=>{client.removeListener("error",listener)}}var DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;var init_redis_error_listener=__esm({"libs/utils/src/storage/redis-error-listener.ts"(){"use strict";DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS=3e4}});function decodeOrRaw(encoded){try{return decodeURIComponent(encoded)}catch{return encoded}}function integerOrUndefined(text){const value=Number.parseInt(text??"",10);return Number.isNaN(value)?void 0:value}function readRedisUrl(rawUrl){let url;try{url=new URL(rawUrl)}catch{return void 0}if(url.protocol!=="redis:"&&url.protocol!=="rediss:")return void 0;const query=Object.fromEntries(url.searchParams);const{host,port,username,password,db,...otherOptions}=query;const queryOptions={};for(const[name,value=""]of Object.entries(otherOptions)){queryOptions[name]=name==="family"?integerOrUndefined(value)??value:value}return{host:url.hostname.replace(/^\[(.*)\]$/,"$1")||host,port:integerOrUndefined(url.port||port),username:decodeOrRaw(url.username)||username||void 0,password:decodeOrRaw(url.password)||password||void 0,db:integerOrUndefined(url.pathname.replace(/^\/+/,"")||db),tls:url.protocol==="rediss:",queryOptions}}function mergeRedisUrlFields(rawUrl,fields){const connection=readRedisUrl(rawUrl);if(!connection)return void 0;const fillIns={};const conflicts=[];if(fields.host!==void 0&&fields.host!==connection.host)conflicts.push("host");if(fields.port!==void 0){if(connection.port===void 0)fillIns.port=fields.port;else if(fields.port!==connection.port)conflicts.push("port")}if(fields.password!==void 0){if(connection.password===void 0)fillIns.password=fields.password;else if(fields.password!==connection.password)conflicts.push("password")}if(fields.db!==void 0){if(connection.db===void 0)fillIns.db=fields.db;else if(fields.db!==connection.db)conflicts.push("db")}if(fields.tls===true&&!connection.tls)fillIns.tls=true;if(fields.tls===false&&connection.tls)conflicts.push("tls");return{connection,fillIns,conflicts}}function describeRedisUrlConflicts(conflicts){return`redis ${conflicts.join(", ")} contradict${conflicts.length===1?"s":""} redis.url. Fields beside a url only fill in what the URL leaves out (port, password, db, tls); put the value in the URL or drop the field.`}var init_redis_url=__esm({"libs/utils/src/storage/redis-url.ts"(){"use strict"}});var init_utils=__esm({"libs/utils/src/storage/utils/index.ts"(){"use strict";init_ttl()}});var COMPARE_AND_DELETE_SCRIPT,COMPARE_AND_EXPIRE_SCRIPT;var init_compare_and_delete=__esm({"libs/utils/src/storage/utils/compare-and-delete.ts"(){"use strict";COMPARE_AND_DELETE_SCRIPT=`if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;COMPARE_AND_EXPIRE_SCRIPT=`if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('EXPIRE', KEYS[1], ARGV[2]) end return 0`}});var redis_exports={};__export(redis_exports,{RedisStorageAdapter:()=>RedisStorageAdapter,createRedisClient:()=>createRedisClient});function getRedisClass(){try{return require("ioredis").default||require("ioredis")}catch(error){const msg=error instanceof Error?error.message:String(error);if(msg.includes("Dynamic require")||msg.includes("require is not defined")){throw new Error(`Failed to load ioredis: ${msg}. This typically happens with ESM bundlers (esbuild, Vite). Ensure your bundler externalizes ioredis or use CJS mode.`,{cause:error})}throw new Error("ioredis is required for Redis storage adapter. Install it with: npm install ioredis",{cause:error})}}function resolveUrlOptions(connectionUrl,options){const{url:configUrl,...siblingFields}={url:void 0,...options.config};if(options.url&&configUrl&&configUrl!==options.url){throw new StorageConfigError("redis","redis.url and redis.config.url name different servers; set one of them.")}return urlConnectionOptions(connectionUrl,siblingFields)}function urlConnectionOptions(url,fields){const merge=mergeRedisUrlFields(url,fields);if(!merge)return void 0;if(merge.conflicts.length>0){throw new StorageConfigError("redis",describeRedisUrlConflicts(merge.conflicts))}const{queryOptions,tls,...stated}=merge.connection;return{...queryOptions,...stated,...toFillInOptions(merge.fillIns),...tls?{tls:{}}:{}}}function toFillInOptions({port,password,db,tls}){return{...port!==void 0?{port}:{},...password!==void 0?{password}:{},...db!==void 0?{db}:{},...tls?{tls:{}}:{}}}function createRedisClient(options){const urlOptions=options.url?urlConnectionOptions(options.url,options):void 0;const RedisClass=getRedisClass();const baseOptions={lazyConnect:false,maxRetriesPerRequest:3};let client;if(urlOptions){client=new RedisClass({...baseOptions,...urlOptions})}else if(options.url){client=new RedisClass(options.url,baseOptions)}else{client=new RedisClass({...baseOptions,host:options.host??"localhost",port:options.port??6379,password:options.password,db:options.db??0,tls:options.tls?{}:void 0})}attachRedisErrorListener(client,{label:options.label??"redis",logger:options.logger});return client}var RedisStorageAdapter;var init_redis=__esm({"libs/utils/src/storage/adapters/redis.ts"(){"use strict";init_errors();init_redis_error_listener();init_redis_url();init_utils();init_compare_and_delete();init_base();RedisStorageAdapter=class extends BaseStorageAdapter{backendName="redis";client;subscriber;options;ownsClient;detachErrorListener;connecting;keyPrefix;subscriptionHandlers=new Map;connectionUrl;urlOptions;constructor(options={}){super();const hasClient=options.client!==void 0;const hasConfig=options.config!==void 0||options.url!==void 0;if(hasClient&&hasConfig){throw new StorageConfigError("redis",'Cannot specify both "client" and "config"/"url". Use one or the other.')}if(!hasClient&&!hasConfig){const envUrl=process.env["REDIS_URL"]||process.env["REDIS_HOST"];if(envUrl){options={...options,url:envUrl}}else{throw new StorageConfigError("redis",'Either "client", "config", "url", or REDIS_URL environment variable must be provided.')}}this.options=options;this.ownsClient=!hasClient;this.keyPrefix=options.keyPrefix??"";const configUrl=options.config?.url;this.connectionUrl=options.url??(typeof configUrl==="string"?configUrl:void 0);this.urlOptions=this.connectionUrl?resolveUrlOptions(this.connectionUrl,options):void 0}async connect(){if(this.connected)return;this.connecting??=this.openConnection().finally(()=>{this.connecting=void 0});return this.connecting}async openConnection(){let socketError;const recordSocketError=error=>{socketError=error};let client;try{if(this.options.client){client=this.options.client}else{client=this.newClient();client.on("error",recordSocketError)}await client.ping();this.client=client;this.connected=true;if(this.ownsClient){client.removeListener("error",recordSocketError);this.detachErrorListener=attachRedisErrorListener(client,{label:"RedisStorage"})}}catch(e){if(this.ownsClient&&client){try{client.disconnect()}catch{}}const cause=socketError??(e instanceof Error?e:void 0);throw new StorageConnectionError("Failed to connect to Redis",cause,"redis")}}async disconnect(){if(!this.connected)return;if(this.subscriber){await this.subscriber.quit();this.subscriber=void 0}if(this.ownsClient&&this.client){await this.client.quit()}this.detachErrorListener?.();this.detachErrorListener=void 0;this.client=void 0;this.connected=false;this.subscriptionHandlers.clear()}async ping(){if(!this.client)return false;try{const result=await this.client.ping();return result==="PONG"}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Redis client not connected",void 0,"redis")}return this.client}getConnectedSubscriber(){if(!this.subscriber){throw new StorageConnectionError("Redis subscriber not created",void 0,"redis")}return this.subscriber}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);if(options?.ttlSeconds){if(options.ifNotExists){await client.set(prefixedKey,value,"EX",options.ttlSeconds,"NX")}else if(options.ifExists){await client.set(prefixedKey,value,"EX",options.ttlSeconds,"XX")}else{await client.set(prefixedKey,value,"EX",options.ttlSeconds)}}else if(options?.ifNotExists){await client.set(prefixedKey,value,"NX")}else if(options?.ifExists){await client.set(prefixedKey,value,"XX")}else{await client.set(prefixedKey,value)}}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,1,this.prefixKey(key),expectedValue);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,1,this.prefixKey(key),expectedValue,String(ttlSeconds));return extended===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mset(entries){if(entries.length===0)return;for(const entry of entries){this.validateSetOptions(entry.options)}const pipeline=this.getConnectedClient().pipeline();for(const entry of entries){const prefixedKey=this.prefixKey(entry.key);if(entry.options?.ttlSeconds){if(entry.options.ifNotExists){pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds,"NX")}else if(entry.options.ifExists){pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds,"XX")}else{pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds)}}else if(entry.options?.ifNotExists){pipeline.set(prefixedKey,entry.value,"NX")}else if(entry.options?.ifExists){pipeline.set(prefixedKey,entry.value,"XX")}else{pipeline.set(prefixedKey,entry.value)}}await pipeline.exec()}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);const result=[];let cursor="0";do{const[nextCursor,keys]=await client.scan(cursor,"MATCH",prefixedPattern,"COUNT",100);cursor=nextCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!=="0");return result}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return true}async publish(channel,message){const prefixedChannel=this.prefixKey(channel);return this.getConnectedClient().publish(prefixedChannel,message)}async subscribe(channel,handler){this.ensureConnected();const prefixedChannel=this.prefixKey(channel);if(!this.subscriber){await this.createSubscriber()}const subscriber=this.getConnectedSubscriber();if(!this.subscriptionHandlers.has(prefixedChannel)){this.subscriptionHandlers.set(prefixedChannel,new Set);await subscriber.subscribe(prefixedChannel)}const handlers=this.subscriptionHandlers.get(prefixedChannel);if(handlers){handlers.add(handler)}return async()=>{const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){handlers2.delete(handler);if(handlers2.size===0){this.subscriptionHandlers.delete(prefixedChannel);await this.subscriber?.unsubscribe(prefixedChannel)}}}}buildRedisOptions(){if(this.connectionUrl){return{lazyConnect:false,maxRetriesPerRequest:3,...this.urlOptions}}const config=this.options.config;if(!config||typeof config.url==="string"||config.host===void 0){throw new StorageConfigError("redis","Redis config is required when URL is not provided")}return{host:config.host,port:config.port??6379,password:config.password,db:config.db??0,tls:config.tls?{}:void 0,lazyConnect:false,maxRetriesPerRequest:3}}newClient(){const RedisClass=getRedisClass();if(this.connectionUrl&&!this.urlOptions){return new RedisClass(this.connectionUrl,this.buildRedisOptions())}return new RedisClass(this.buildRedisOptions())}async createSubscriber(){let subscriber;if(this.connectionUrl||this.options.config){subscriber=this.newClient()}else if(this.options.client){subscriber=this.options.client.duplicate()}else{throw new StorageConfigError("redis","Cannot create subscriber without url, config, or client")}attachRedisErrorListener(subscriber,{label:"RedisStorage:subscriber"});subscriber.on("message",(channel,message)=>{const handlers=this.subscriptionHandlers.get(channel);if(handlers){const unprefixedChannel=this.unprefixKey(channel);for(const handler of handlers){try{handler(message,unprefixedChannel)}catch{}}}});this.subscriber=subscriber}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}getClient(){return this.client}}}});var vercel_kv_exports={};__export(vercel_kv_exports,{VercelKvStorageAdapter:()=>VercelKvStorageAdapter,createVercelKvClient:()=>createVercelKvClient});async function loadVercelKv(){try{const mod=await import("@vercel/kv");const resolved=typeof mod.createClient==="function"?mod:mod.default;if(!resolved||typeof resolved.createClient!=="function")throw new Error("createClient missing");return resolved}catch{throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv")}}async function createVercelKvClient(connection={}){const url=connection.url??process.env["KV_REST_API_URL"];const token=connection.token??process.env["KV_REST_API_TOKEN"];if(!url||!token){throw new StorageConfigError("vercel-kv","Pass url and token, or set KV_REST_API_URL and KV_REST_API_TOKEN.")}const{createClient}=await loadVercelKv();return createClient({url,token,cache:void 0,automaticDeserialization:false})}var VercelKvStorageAdapter;var init_vercel_kv=__esm({"libs/utils/src/storage/adapters/vercel-kv.ts"(){"use strict";init_errors();init_compare_and_delete();init_ttl();init_base();VercelKvStorageAdapter=class extends BaseStorageAdapter{backendName="vercel-kv";client;options;keyPrefix;constructor(options={}){super();const url=options.url??process.env["KV_REST_API_URL"];const token=options.token??process.env["KV_REST_API_TOKEN"];if(!url||!token){throw new StorageConfigError("vercel-kv","KV_REST_API_URL and KV_REST_API_TOKEN must be provided via options or environment variables.")}this.options={...options,url,token};this.keyPrefix=options.keyPrefix??""}async connect(){if(this.connected)return;try{this.client=await createVercelKvClient({url:this.options.url,token:this.options.token});await this.client.exists("__healthcheck__");this.connected=true}catch(e){throw new StorageConnectionError("Failed to connect to Vercel KV",e instanceof Error?e:void 0,"vercel-kv")}}async disconnect(){this.client=void 0;this.connected=false}async ping(){if(!this.client)return false;try{await this.client.exists("__healthcheck__");return true}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Vercel KV client not connected",void 0,"vercel-kv")}return this.client}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);const setOptions={};if(options?.ttlSeconds){setOptions.ex=options.ttlSeconds}if(options?.ifNotExists){setOptions.nx=true}else if(options?.ifExists){setOptions.xx=true}await client.set(prefixedKey,value,Object.keys(setOptions).length>0?setOptions:void 0)}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,[this.prefixKey(key)],[expectedValue]);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,[this.prefixKey(key)],[expectedValue,String(ttlSeconds)]);return extended===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);try{const result=[];let cursor=0;do{const[nextCursor,keys]=await client.scan(cursor,{match:prefixedPattern,count:100});const parsedCursor=typeof nextCursor==="string"?parseInt(nextCursor,10):nextCursor;cursor=Number.isNaN(parsedCursor)?0:parsedCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!==0);return result}catch{const allKeys=await client.keys(prefixedPattern);return allKeys.map(k=>this.unprefixKey(k))}}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return false}getPubSubSuggestion(){return"Vercel KV is REST-based and does not support pub/sub. Use Upstash adapter for pub/sub support."}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}}}});var upstash_exports={};__export(upstash_exports,{UpstashStorageAdapter:()=>UpstashStorageAdapter});async function loadUpstashRedis(){try{const mod=await import("@upstash/redis");const resolved=typeof mod.Redis==="function"?mod:mod.default;if(!resolved||typeof resolved.Redis!=="function")throw new Error("Redis missing");return resolved}catch{throw new Error("@upstash/redis is required for Upstash storage adapter. Install it with: npm install @upstash/redis")}}var PUBSUB_POLL_INTERVAL_MS,UpstashStorageAdapter;var init_upstash=__esm({"libs/utils/src/storage/adapters/upstash.ts"(){"use strict";init_errors();init_compare_and_delete();init_ttl();init_base();PUBSUB_POLL_INTERVAL_MS=100;UpstashStorageAdapter=class extends BaseStorageAdapter{backendName="upstash";client;options;keyPrefix;pubSubEnabled;subscriptionHandlers=new Map;pollingIntervals=new Map;constructor(options={}){super();const url=options.url??process.env["UPSTASH_REDIS_REST_URL"];const token=options.token??process.env["UPSTASH_REDIS_REST_TOKEN"];if(!url||!token){throw new StorageConfigError("upstash","UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN must be provided via options or environment variables.")}this.options={...options,url,token};this.keyPrefix=options.keyPrefix??"";this.pubSubEnabled=options.enablePubSub??false}async connect(){if(this.connected)return;try{const{Redis}=await loadUpstashRedis();const url=this.options.url;const token=this.options.token;if(!url||!token){throw new StorageConfigError("upstash","URL and token are required")}this.client=new Redis({url,token,automaticDeserialization:false});await this.client.exists("__healthcheck__");this.connected=true}catch(e){throw new StorageConnectionError("Failed to connect to Upstash Redis",e instanceof Error?e:void 0,"upstash")}}async disconnect(){if(!this.connected)return;for(const interval of this.pollingIntervals.values()){clearInterval(interval)}this.pollingIntervals.clear();this.subscriptionHandlers.clear();this.client=void 0;this.connected=false}async ping(){if(!this.client)return false;try{await this.client.exists("__healthcheck__");return true}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Upstash client not connected",void 0,"upstash")}return this.client}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);const setOptions={};if(options?.ttlSeconds){setOptions.ex=options.ttlSeconds}if(options?.ifNotExists){setOptions.nx=true}else if(options?.ifExists){setOptions.xx=true}await client.set(prefixedKey,value,Object.keys(setOptions).length>0?setOptions:void 0)}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,[this.prefixKey(key)],[expectedValue]);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,[this.prefixKey(key)],[expectedValue,String(ttlSeconds)]);return extended===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);const result=[];let cursor=0;do{const[nextCursor,keys]=await client.scan(cursor,{match:prefixedPattern,count:100});const parsedCursor=typeof nextCursor==="string"?parseInt(nextCursor,10):nextCursor;cursor=Number.isNaN(parsedCursor)?0:parsedCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!==0);return result}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return this.pubSubEnabled}async publish(channel,message){if(!this.pubSubEnabled){return super.publish(channel,message)}const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);const listKey=`${prefixedChannel}:queue`;await this.getConnectedClient().lpush(listKey,message);return 1}async subscribe(channel,handler){const client=this.getConnectedClient();if(!this.pubSubEnabled){return super.subscribe(channel,handler)}const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);if(!this.subscriptionHandlers.has(prefixedChannel)){this.subscriptionHandlers.set(prefixedChannel,new Set);const listKey=`${prefixedChannel}:queue`;const interval=setInterval(async()=>{try{const message=await client.rpop(listKey);if(message){const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){for(const h of handlers2){try{h(message,channel)}catch{}}}}}catch{}},PUBSUB_POLL_INTERVAL_MS);if(interval.unref){interval.unref()}this.pollingIntervals.set(prefixedChannel,interval)}const handlers=this.subscriptionHandlers.get(prefixedChannel);if(handlers){handlers.add(handler)}return async()=>{const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){handlers2.delete(handler);if(handlers2.size===0){this.subscriptionHandlers.delete(prefixedChannel);const interval=this.pollingIntervals.get(prefixedChannel);if(interval){clearInterval(interval);this.pollingIntervals.delete(prefixedChannel)}}}}}async publishToQueue(channel,message){const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);const listKey=`${prefixedChannel}:queue`;await this.getConnectedClient().lpush(listKey,message)}getPubSubSuggestion(){return"Enable pub/sub by setting enablePubSub: true in the adapter options."}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}}}});var cloudflare_kv_exports={};__export(cloudflare_kv_exports,{CloudflareKvStorageAdapter:()=>CloudflareKvStorageAdapter});function literalPrefix(pattern){const star=pattern.indexOf("*");const q=pattern.indexOf("?");const idx=star===-1?q:q===-1?star:Math.min(star,q);return idx===-1?pattern:pattern.slice(0,idx)}var CF_KV_MIN_TTL_SECONDS,CloudflareKvStorageAdapter;var init_cloudflare_kv=__esm({"libs/utils/src/storage/adapters/cloudflare-kv.ts"(){"use strict";init_errors();init_pattern();init_ttl();init_base();CF_KV_MIN_TTL_SECONDS=60;CloudflareKvStorageAdapter=class extends BaseStorageAdapter{backendName="cloudflare-kv";kv;keyPrefix;constructor(options){super();if(!options?.namespace){throw new Error("CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`).")}this.kv=options.namespace;this.keyPrefix=options.keyPrefix??""}async connect(){this.connected=true}async disconnect(){this.connected=false}async ping(){if(!this.connected)return false;try{await this.kv.list({limit:1});return true}catch{return false}}async get(key){this.ensureConnected();return this.kv.get(this.prefixKey(key),"text")}async doSet(key,value,options){if(options?.ifNotExists||options?.ifExists){throw new StorageNotSupportedError("conditional set (ifNotExists/ifExists)",this.backendName,"Cloudflare KV has no compare-and-set; use a Durable Object for atomic conditional writes.")}const putOptions=options?.ttlSeconds!==void 0?{expirationTtl:this.toExpirationTtl(options.ttlSeconds,key)}:void 0;await this.kv.put(this.prefixKey(key),value,putOptions)}async delete(key){this.ensureConnected();const existed=await this.exists(key);await this.kv.delete(this.prefixKey(key));return existed}async exists(key){this.ensureConnected();return await this.kv.get(this.prefixKey(key),"text")!==null}async expire(key,ttlSeconds){this.ensureConnected();const ttl=this.toExpirationTtl(ttlSeconds,key);const value=await this.kv.get(this.prefixKey(key),"text");if(value===null)return false;await this.kv.put(this.prefixKey(key),value,{expirationTtl:ttl});return true}async ttl(_key){throw new StorageNotSupportedError("ttl",this.backendName,"Cloudflare KV does not expose a key's remaining TTL. Track expiry alongside the value if you need it.")}async keys(pattern="*"){this.ensureConnected();const prefixedPattern=this.prefixKey(pattern);const listPrefix=literalPrefix(prefixedPattern);const out=[];let cursor;do{const page=await this.kv.list({prefix:listPrefix||void 0,cursor});for(const{name}of page.keys){if(matchesPattern(name,prefixedPattern))out.push(this.unprefixKey(name))}cursor=page.list_complete?void 0:page.cursor}while(cursor);return out}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(_key,_amount){throw new StorageNotSupportedError("incr/decr/incrBy",this.backendName,"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters.")}async deleteIfEquals(_key,_expectedValue){throw new StorageNotSupportedError("deleteIfEquals",this.backendName,"Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete.")}getPubSubSuggestion(){return"Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out."}toExpirationTtl(ttlSeconds,key){validateTTL(ttlSeconds);if(ttlSeconds<CF_KV_MIN_TTL_SECONDS){throw new StorageOperationError("set",key,`cloudflare-kv: expirationTtl must be >= ${CF_KV_MIN_TTL_SECONDS}s (Cloudflare KV minimum); got ${ttlSeconds}s.`)}return ttlSeconds}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){return this.keyPrefix&&key.startsWith(this.keyPrefix)?key.slice(this.keyPrefix.length):key}}}});var index_exports={};__export(index_exports,{AsyncContextOverlapError:()=>import_async_context.AsyncContextOverlapError,AsyncLocalStorage:()=>import_async_context.AsyncLocalStorage,BaseStorageAdapter:()=>BaseStorageAdapter,DEFAULT_CODE_VERIFIER_LENGTH:()=>DEFAULT_CODE_VERIFIER_LENGTH,DEFAULT_MAX_INPUT_LENGTH:()=>DEFAULT_MAX_INPUT_LENGTH,DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS:()=>DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS,EncryptedBlobError:()=>EncryptedBlobError,EncryptedStorageError:()=>EncryptedStorageError,EncryptedTypedStorage:()=>EncryptedTypedStorage,EventEmitter:()=>import_event_emitter2.EventEmitter,FileSystemStorageAdapter:()=>FileSystemStorageAdapter,KeyPersistence:()=>KeyPersistence,MAX_CODE_VERIFIER_LENGTH:()=>MAX_CODE_VERIFIER_LENGTH,MAX_TTL_SECONDS:()=>MAX_TTL_SECONDS,MIN_CODE_VERIFIER_LENGTH:()=>MIN_CODE_VERIFIER_LENGTH,MemoryStorageAdapter:()=>MemoryStorageAdapter,NAMESPACE_SEPARATOR:()=>NAMESPACE_SEPARATOR,NamespacedStorageImpl:()=>NamespacedStorageImpl,PkceError:()=>PkceError,REDOS_THRESHOLDS:()=>import_redos.REDOS_THRESHOLDS,RedisStorageAdapter:()=>RedisStorageAdapter,StorageConfigError:()=>StorageConfigError,StorageConnectionError:()=>StorageConnectionError,StorageError:()=>StorageError,StorageNotConnectedError:()=>StorageNotConnectedError,StorageNotSupportedError:()=>StorageNotSupportedError,StorageOperationError:()=>StorageOperationError,StoragePatternError:()=>StoragePatternError,StorageTTLError:()=>StorageTTLError,TypedStorage:()=>TypedStorage,UpstashStorageAdapter:()=>UpstashStorageAdapter,VercelKvStorageAdapter:()=>VercelKvStorageAdapter,access:()=>access,analyzePattern:()=>analyzePattern,anyKeyDataSchema:()=>anyKeyDataSchema,assertNode:()=>assertNode,asymmetricAlgSchema:()=>asymmetricAlgSchema,asymmetricKeyDataSchema:()=>asymmetricKeyDataSchema,attachRedisErrorListener:()=>attachRedisErrorListener,awaitOutsideRequest:()=>import_async_context.awaitOutsideRequest,base64Decode:()=>base64Decode,base64Encode:()=>base64Encode,base64urlDecode:()=>base64urlDecode,base64urlEncode:()=>base64urlEncode,basename:()=>import_path2.basename,brandClass:()=>brandClass,buildPrefix:()=>buildPrefix,buildSetCookie:()=>buildSetCookie,bytesToHex:()=>bytesToHex,checkEntryAvailability:()=>import_runtime_context.checkEntryAvailability,classifyIpAddress:()=>classifyIpAddress,clearCachedSecret:()=>clearCachedSecret,collapseChar:()=>collapseChar,collapseWhitespace:()=>collapseWhitespace,copyFile:()=>copyFile,cp:()=>cp,createKeyPersistence:()=>createKeyPersistence,createKeyPersistenceWithStorage:()=>createKeyPersistenceWithStorage,createMemoryStorage:()=>createMemoryStorage,createNamespacedStorage:()=>createNamespacedStorage,createRedisClient:()=>createRedisClient,createRootStorage:()=>createRootStorage,createSafeRegExp:()=>createSafeRegExp,createSecretData:()=>createSecretData,createStorage:()=>createStorage,createVercelKvClient:()=>createVercelKvClient,decryptAesGcm:()=>decryptAesGcm,decryptValue:()=>decryptValue,deleteSecret:()=>deleteSecret,describeRedisUrlConflicts:()=>describeRedisUrlConflicts,deserializeAndDecrypt:()=>deserializeAndDecrypt,deserializeBlob:()=>deserializeBlob,detectRuntimeContext:()=>import_runtime_context.detectRuntimeContext,dirname:()=>import_path2.dirname,encryptAesGcm:()=>encryptAesGcm,encryptAndSerialize:()=>encryptAndSerialize,encryptValue:()=>encryptValue,ensureDir:()=>ensureDir,ensureDirSync:()=>ensureDirSync,ensureMaxLen:()=>ensureMaxLen,entryAvailabilitySchema:()=>import_runtime_context.entryAvailabilitySchema,escapeGlob:()=>escapeGlob,escapeHtml:()=>escapeHtml,escapeHtmlAttr:()=>escapeHtmlAttr,escapeJsString:()=>escapeJsString,escapeScriptClose:()=>escapeScriptClose,expandIpv6:()=>expandIpv6,expandTemplate:()=>expandTemplate,expandUriTemplate:()=>expandUriTemplate,expiresAtToTTL:()=>expiresAtToTTL,extname:()=>import_path2.extname,extractBracedParams:()=>extractBracedParams,extractEmbeddedIpv4:()=>extractEmbeddedIpv4,extractTemplateParams:()=>extractTemplateParams,extractUriScheme:()=>extractUriScheme,fileExists:()=>fileExists,fileExistsSync:()=>fileExistsSync,findNonFiniteNumber:()=>findNonFiniteNumber,generateCodeChallenge:()=>generateCodeChallenge,generateCodeVerifier:()=>generateCodeVerifier,generatePkcePair:()=>generatePkcePair,generateRsaKeyPair:()=>generateRsaKeyPair3,generateSecret:()=>generateSecret,getAsyncContextMode:()=>import_async_context.getAsyncContextMode,getCookie:()=>getCookie,getCrypto:()=>getCrypto,getCwd:()=>import_env2.getCwd,getDetectedStorageType:()=>getDetectedStorageType,getEnv:()=>import_env2.getEnv,getEnvFlag:()=>import_env2.getEnvFlag,getHostname:()=>getHostname,getMachineId:()=>getMachineId,getNodeEnv:()=>import_env2.getNodeEnv,getOrCreateSecret:()=>getOrCreateSecret,getRuntimeContext:()=>import_runtime_context.getRuntimeContext,getSpawnFn:()=>getSpawnFn,globToRegex:()=>globToRegex,hasTemplatePlaceholders:()=>hasTemplatePlaceholders,hkdfSha256:()=>hkdfSha256,hmacSha256:()=>hmacSha256,idFromString:()=>idFromString,inferMimeType:()=>inferMimeType,isAbsolute:()=>import_path2.isAbsolute,isAsymmetricKeyData:()=>isAsymmetricKeyData,isBrandedInstance:()=>isBrandedInstance,isBrowser:()=>isBrowser,isDebug:()=>import_env2.isDebug,isDevelopment:()=>import_env2.isDevelopment,isDirEmpty:()=>isDirEmpty,isEdgeRuntime:()=>import_env2.isEdgeRuntime,isEntryAvailable:()=>import_runtime_context.isEntryAvailable,isExpired:()=>isExpired,isInputLengthSafe:()=>isInputLengthSafe,isLocalhost:()=>isLocalhost,isNode:()=>isNode,isPatternSafe:()=>isPatternSafe,isProduction:()=>import_env2.isProduction,isRedirectResponse:()=>isRedirectResponse,isRsaPssAlg:()=>isRsaPssAlg,isSecretCached:()=>isSecretCached,isSecretKeyData:()=>isSecretKeyData,isSecretPersistenceEnabled:()=>isSecretPersistenceEnabled,isSecureRequest:()=>isSecureRequest,isServerless:()=>import_env2.isServerless,isSignedData:()=>isSignedData,isUriTemplate:()=>isUriTemplate,isValidCodeChallenge:()=>isValidCodeChallenge,isValidCodeVerifier:()=>isValidCodeVerifier,isValidEncryptedBlob:()=>isValidEncryptedBlob,isValidMcpUri:()=>isValidMcpUri,isValidMcpUriTemplate:()=>isValidMcpUriTemplate,joinPath:()=>joinPath,jwtAlgToNodeAlg:()=>jwtAlgToNodeAlg,loadSecret:()=>loadSecret,matchUriTemplate:()=>matchUriTemplate,matchesPattern:()=>matchesPattern,mergeRedisUrlFields:()=>mergeRedisUrlFields,mkdir:()=>mkdir,mkdtemp:()=>mkdtemp,normalizeTTL:()=>normalizeTTL,parseCookies:()=>parseCookies,parseIpv4:()=>parseIpv4,parseKeyData:()=>parseKeyData,parseSecretData:()=>parseSecretData,parseUriTemplate:()=>parseUriTemplate,pathJoin:()=>import_path2.join,pathResolve:()=>import_path2.resolve,pathToFileURL:()=>import_path2.pathToFileURL,pemToPublicJwk:()=>pemToPublicJwk3,processPlatformToolCalls:()=>processPlatformToolCalls,randomBytes:()=>randomBytes,randomUUID:()=>randomUUID,readFile:()=>readFile,readFileBuffer:()=>readFileBuffer,readFileSync:()=>readFileSync,readJSON:()=>readJSON,readdir:()=>readdir,readdirSync:()=>readdirSync,realpath:()=>realpath,rename:()=>rename,resetRuntimeContext:()=>import_runtime_context.resetRuntimeContext,resolveSecretPath:()=>resolveSecretPath,rm:()=>rm,rsaSignBase64Url:()=>rsaSignBase64Url3,rsaVerify:()=>rsaVerify3,rsaVerifySync:()=>rsaVerifySync3,runCmd:()=>runCmd,runRequestExclusive:()=>import_async_context.runRequestExclusive,safeExec:()=>safeExec,safeJsonForScript:()=>safeJsonForScript,safeMatch:()=>safeMatch,safeReplace:()=>safeReplace,safeStringify:()=>safeStringify,safeTest:()=>safeTest,sanitizeToJson:()=>sanitizeToJson,saveSecret:()=>saveSecret,secretDataSchema:()=>secretDataSchema,secretKeyDataSchema:()=>secretKeyDataSchema,sep:()=>import_path2.sep,sepFor:()=>sepFor,serializeBlob:()=>serializeBlob,setEnv:()=>import_env2.setEnv,setMachineIdOverride:()=>setMachineIdOverride,sha256:()=>sha256,sha256Base64url:()=>sha256Base64url,sha256Hex:()=>sha256Hex,shortHash:()=>shortHash,signData:()=>signData,splitWords:()=>splitWords,stat:()=>stat,supportsAnsi:()=>import_env2.supportsAnsi,symlink:()=>symlink,timingSafeEqual:()=>timingSafeEqual,toCase:()=>toCase,trimBoth:()=>trimBoth,trimChars:()=>trimChars,trimLeading:()=>trimLeading,trimSlashes:()=>trimSlashes,trimTrailing:()=>trimTrailing,tryDecryptValue:()=>tryDecryptValue,tryDeserializeAndDecrypt:()=>tryDeserializeAndDecrypt,tryDeserializeBlob:()=>tryDeserializeBlob,ttlToExpiresAt:()=>ttlToExpiresAt,unlink:()=>unlink,validateBaseUrl:()=>validateBaseUrl,validateKeyData:()=>validateKeyData,validateOptionalTTL:()=>validateOptionalTTL,validatePattern:()=>validatePattern,validateSecretData:()=>validateSecretData,validateTTL:()=>validateTTL,verifyCodeChallenge:()=>verifyCodeChallenge,verifyData:()=>verifyData,verifyOrParseData:()=>verifyOrParseData,watchFile:()=>watchFile,writeFile:()=>writeFile,writeJSON:()=>writeJSON});module.exports=__toCommonJS(index_exports);var import_redos=require("@enclave-vm/ast/redos");var DEFAULT_MAX_INPUT_LENGTH=5e4;function analyzePattern(pattern,level="polynomial"){const patternStr=typeof pattern==="string"?pattern:pattern.source;try{new RegExp(patternStr)}catch{return{safe:false,score:100,vulnerabilityType:"invalid_syntax",explanation:"Pattern has invalid regex syntax"}}try{const result=(0,import_redos.analyzeForReDoS)(patternStr,level);return{safe:!result.vulnerable,score:result.score,vulnerabilityType:result.vulnerabilityType,explanation:result.explanation}}catch{return{safe:false,score:100,vulnerabilityType:"analysis_failed",explanation:"Pattern analysis failed - treating as potentially unsafe"}}}function isPatternSafe(pattern,level="polynomial"){return analyzePattern(pattern,level).safe}function createSafeRegExp(pattern,flags,options={}){const{level="polynomial",throwOnVulnerable=false}=options;const analysis=analyzePattern(pattern,level);if(!analysis.safe){if(throwOnVulnerable){throw new Error(`Vulnerable regex pattern detected: ${analysis.explanation||analysis.vulnerabilityType}`)}return null}try{return new RegExp(pattern,flags)}catch{return null}}function safeTest(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return pattern.test(input)}function safeMatch(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return input.match(pattern)}function safeReplace(input,pattern,replacement,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return input}return input.replace(pattern,replacement)}function safeExec(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return pattern.exec(input)}function isInputLengthSafe(input,maxLength=DEFAULT_MAX_INPUT_LENGTH){return input.length<=maxLength}function trimLeading(input,char){if(!input||char.length!==1){return input??""}let start=0;while(start<input.length&&input[start]===char){start++}return start===0?input:input.slice(start)}function trimTrailing(input,char){if(!input||char.length!==1){return input??""}let end=input.length;while(end>0&&input[end-1]===char){end--}return end===input.length?input:input.slice(0,end)}function trimBoth(input,char){return trimTrailing(trimLeading(input,char),char)}function trimChars(input,chars){if(!input||chars.size===0){return input??""}let start=0;while(start<input.length&&chars.has(input[start])){start++}let end=input.length;while(end>start&&chars.has(input[end-1])){end--}return input.slice(start,end)}function extractBracedParams(template,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!template||template.length>maxLength){return[]}const params=[];let i=0;while(i<template.length){const openBrace=template.indexOf("{",i);if(openBrace===-1){break}const closeBrace=template.indexOf("}",openBrace+1);if(closeBrace===-1){break}const nestedOpen=template.indexOf("{",openBrace+1);if(nestedOpen!==-1&&nestedOpen<closeBrace){i=nestedOpen+1;continue}const paramName=template.slice(openBrace+1,closeBrace).trim();if(paramName&&!paramName.includes("{")&&!paramName.includes("}")){params.push(paramName)}i=closeBrace+1}return params}function expandTemplate(template,values,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!template||template.length>maxLength){return template??""}let result="";let i=0;while(i<template.length){const openBrace=template.indexOf("{",i);if(openBrace===-1){result+=template.slice(i);break}result+=template.slice(i,openBrace);const closeBrace=template.indexOf("}",openBrace+1);if(closeBrace===-1){result+=template.slice(openBrace);break}const nestedOpen=template.indexOf("{",openBrace+1);if(nestedOpen!==-1&&nestedOpen<closeBrace){result+="{";i=openBrace+1;continue}const paramName=template.slice(openBrace+1,closeBrace).trim();if(paramName in values){result+=values[paramName]}else{result+=template.slice(openBrace,closeBrace+1)}i=closeBrace+1}return result}function hasTemplatePlaceholders(str,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!str||str.length>maxLength){return false}const openBrace=str.indexOf("{");if(openBrace===-1){return false}const closeBrace=str.indexOf("}",openBrace+1);return closeBrace>openBrace+1}function collapseChar(input,char){if(!input||char.length!==1){return input??""}let result="";let lastWasChar=false;for(let i=0;i<input.length;i++){const c=input[i];if(c===char){if(!lastWasChar){result+=c;lastWasChar=true}}else{result+=c;lastWasChar=false}}return result}function collapseWhitespace(input,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!input){return""}if(input.length>maxLength){return input}let result="";let lastWasWhitespace=false;for(let i=0;i<input.length;i++){const c=input[i];const isWhitespace=c===" "||c===" "||c==="\n"||c==="\r"||c==="\f"||c==="\v";if(isWhitespace){if(!lastWasWhitespace){result+=" ";lastWasWhitespace=true}}else{result+=c;lastWasWhitespace=false}}return result}function splitWords(input){const parts=[];let buff="";for(let i=0;i<input.length;i++){const ch=input[i];const isAlphaNum=/[A-Za-z0-9]/.test(ch);if(!isAlphaNum){if(buff){parts.push(buff);buff=""}continue}if(buff&&/[a-z]/.test(buff[buff.length-1])&&/[A-Z]/.test(ch)){parts.push(buff);buff=ch}else{buff+=ch}}if(buff)parts.push(buff);return parts}function toCase(words,kind){const safe=words.filter(Boolean);switch(kind){case"snake":return safe.map(w=>w.toLowerCase()).join("_");case"kebab":return safe.map(w=>w.toLowerCase()).join("-");case"dot":return safe.map(w=>w.toLowerCase()).join(".");case"camel":if(safe.length===0)return"";return safe[0].toLowerCase()+safe.slice(1).map(w=>w.charAt(0).toUpperCase()+w.slice(1).toLowerCase()).join("")}}function sepFor(kind){return kind==="snake"?"_":kind==="kebab"?"-":kind==="dot"?".":""}function shortHash(s){let h=5381;for(let i=0;i<s.length;i++)h=(h<<5)+h+s.charCodeAt(i);return(h>>>0).toString(16).slice(-6).padStart(6,"0")}function ensureMaxLen(name,max){if(name.length<=max)return name;const hash=shortHash(name);const lastSep=Math.max(name.lastIndexOf("_"),name.lastIndexOf("-"),name.lastIndexOf("."),name.lastIndexOf("/"));const tail=lastSep>0?name.slice(lastSep+1):name.slice(-Math.max(3,Math.min(16,Math.floor(max/4))));const budget=Math.max(1,max-(1+hash.length+1+tail.length));const prefix=name.slice(0,budget);return`${prefix}-${hash}-${tail}`.slice(0,max)}function idFromString(name){const cleaned=name.replace(/[^A-Za-z0-9_-]+/g,"-");return trimBoth(cleaned,"-").slice(0,64)}var RFC_3986_SCHEME_PATTERN=/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//;var SCHEME_EXTRACT_PATTERN=/^([a-zA-Z][a-zA-Z0-9+.-]*):/;function isValidMcpUri(uri){return RFC_3986_SCHEME_PATTERN.test(uri)}function extractUriScheme(uri){const match=uri.match(SCHEME_EXTRACT_PATTERN);return match?match[1].toLowerCase():null}function isValidMcpUriTemplate(uriTemplate){return RFC_3986_SCHEME_PATTERN.test(uriTemplate)}function parseUriTemplate(template){if(template.length>1e3){throw new Error("URI template too long (max 1000 characters)")}const paramCount=(template.match(/\{[^{}]+\}/g)||[]).length;if(paramCount>50){throw new Error("URI template has too many parameters (max 50)")}const paramNames=[];const placeholder=/\{([^{}]+)\}/g;let regexStr="";let lastIndex=0;for(let m=placeholder.exec(template);m!==null;m=placeholder.exec(template)){regexStr+=escapeRegex(template.slice(lastIndex,m.index));const raw=m[1];const reserved=raw.startsWith("+");paramNames.push(reserved?raw.slice(1):raw);regexStr+=reserved?"(.+?)":"([^/]+)";lastIndex=m.index+m[0].length}regexStr+=escapeRegex(template.slice(lastIndex));return{pattern:new RegExp(`^${regexStr}$`),paramNames}}function escapeRegex(literal){return literal.replace(/[.*+?^${}()|[\]\\]/g,c=>`\\${c}`)}function matchUriTemplate(template,uri){const{pattern,paramNames}=parseUriTemplate(template);const match=uri.match(pattern);if(!match)return null;const params={};paramNames.forEach((name,index)=>{params[name]=decodeURIComponent(match[index+1])});return params}function expandUriTemplate(template,params){return template.replace(/\{([^{}]+)\}/g,(_,raw)=>{const reserved=raw.startsWith("+");const paramName=reserved?raw.slice(1):raw;const value=params[paramName];if(value===void 0){throw new Error(`Missing parameter '${paramName}' for URI template '${template}'`)}return reserved?encodeReserved(value):encodeURIComponent(value)})}function encodeReserved(value){const decoded=safeDecode(value);return decoded.replace(/[^A-Za-z0-9\-._~:/?#[\]@!$&'()*+,;=]/g,c=>encodeURIComponent(c))}function safeDecode(value){try{return decodeURIComponent(value)}catch{return value.replace(/%[0-9A-Fa-f]{2}/g,triplet=>{try{return decodeURIComponent(triplet)}catch{return triplet}})}}function extractTemplateParams(template){const params=[];template.replace(/\{([^{}]+)\}/g,(_,raw)=>{params.push(raw.startsWith("+")?raw.slice(1):raw);return""});return params}function isUriTemplate(uri){return/\{[^{}]+\}/.test(uri)}function trimSlashes(s){return trimBoth(s??"","/")}function joinPath(...parts){const cleaned=parts.map(p=>trimSlashes(p)).filter(Boolean);return cleaned.length?`/${cleaned.join("/")}`:""}var import_path2=require("#path");function sanitizeToJson(value){const ancestors=new WeakSet;function withinAncestors(container,build){if(ancestors.has(container)){return void 0}ancestors.add(container);try{return build()}finally{ancestors.delete(container)}}function sanitize(val){if(typeof val==="function"||typeof val==="symbol"){return void 0}if(typeof val==="bigint"){return val.toString()}if(val instanceof Date){return val.toISOString()}if(val instanceof Error){return{name:val.name,message:val.message,stack:val.stack}}if(val instanceof Map){return withinAncestors(val,()=>{const obj={};for(const[k,v]of val.entries()){obj[String(k)]=sanitize(v)}return obj})}if(val instanceof Set){return withinAncestors(val,()=>Array.from(val).map(sanitize))}if(Array.isArray(val)){return withinAncestors(val,()=>val.map(sanitize))}if(val&&typeof val==="object"){return withinAncestors(val,()=>{const sanitized={};for(const[key,value2]of Object.entries(val)){const clean=sanitize(value2);if(clean!==void 0){sanitized[key]=clean}}return sanitized})}return val}return sanitize(value)}function findNonFiniteNumber(value){const seen=new WeakSet;function walk(val,path){if(typeof val==="number"&&!Number.isFinite(val)){return{path,value:val}}if(val&&typeof val==="object"){if(seen.has(val))return void 0;seen.add(val);if(Array.isArray(val)){for(let i=0;i<val.length;i++){const found=walk(val[i],`${path}[${i}]`);if(found)return found}return void 0}for(const[k,v]of Object.entries(val)){const found=walk(v,path?`${path}.${k}`:k);if(found)return found}}return void 0}return walk(value,"")}var MIME_TYPES={json:"application/json",xml:"application/xml",html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",ts:"application/typescript",txt:"text/plain",md:"text/markdown",yaml:"application/yaml",yml:"application/yaml",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",pdf:"application/pdf"};function inferMimeType(uri,content){const ext=uri.split(".").pop()?.toLowerCase();if(ext&&MIME_TYPES[ext]){return MIME_TYPES[ext]}if(typeof content==="string"){if(content.trim().startsWith("{")||content.trim().startsWith("[")){return"application/json"}if(content.trim().startsWith("<")){return content.includes("<!DOCTYPE html")||content.includes("<html")?"text/html":"application/xml"}}return"text/plain"}function validateBaseUrl(url){try{const parsed=new URL(url);if(!["http:","https:"].includes(parsed.protocol)){throw new Error(`Unsupported protocol: ${parsed.protocol}. Only http: and https: are supported.`)}return parsed}catch(err){if(err instanceof Error&&err.message.includes("Unsupported protocol")){throw err}throw new Error(`Invalid base URL: ${url}`)}}init_runtime();var LOCALHOST_PATTERNS=new Set(["localhost","127.0.0.1","::1","0.0.0.0"]);function isLocalhost(host){if(!host)return false;if(host.startsWith("[")){const closeBracket=host.indexOf("]");if(closeBracket>0){return LOCALHOST_PATTERNS.has(host.slice(1,closeBracket))}}if(LOCALHOST_PATTERNS.has(host))return true;const lastColon=host.lastIndexOf(":");if(lastColon>0){const hostname=host.slice(0,lastColon);return LOCALHOST_PATTERNS.has(hostname)}return false}function isSecureRequest(req){if(!req)return false;if(req.protocol==="https")return true;const forwarded=req.headers?.["x-forwarded-proto"];const forwardedStr=(Array.isArray(forwarded)?forwarded[0]:forwarded)?.split(",")[0]?.trim()?.toLowerCase();if(forwardedStr==="https")return true;if(req.socket?.encrypted)return true;return false}function buildSetCookie(options,req){if(!isNode())return null;const{name,value,path="/",maxAge=86400,httpOnly=true,sameSite="Strict",domain}=options;let secure;if(options.secure!==void 0){secure=options.secure}else{const host=req?.headers?.["host"];const hostStr=Array.isArray(host)?host[0]:host;if(isLocalhost(hostStr)){secure=false}else if(req){secure=isSecureRequest(req)}else{secure=process.env["NODE_ENV"]==="production"}}if(sameSite==="None"&&!secure){secure=true}const parts=[`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];parts.push(`Path=${path}`);parts.push(`Max-Age=${maxAge}`);if(httpOnly)parts.push("HttpOnly");if(secure)parts.push("Secure");parts.push(`SameSite=${sameSite}`);if(domain)parts.push(`Domain=${domain}`);return parts.join("; ")}function parseCookies(cookieHeader){const cookies={};if(!cookieHeader)return cookies;const pairs=cookieHeader.split(";");for(const pair of pairs){const eqIdx=pair.indexOf("=");if(eqIdx<0)continue;try{const name=decodeURIComponent(pair.slice(0,eqIdx).trim());const value=decodeURIComponent(pair.slice(eqIdx+1).trim());if(name)cookies[name]=value}catch{continue}}return cookies}function getCookie(cookieHeader,name){if(!cookieHeader)return void 0;return parseCookies(cookieHeader)[name]}var IPV4_OCTET_PATTERN=/^(0|[1-9]\d{0,2})$/;var IPV6_GROUP_PATTERN=/^[0-9a-f]{1,4}$/;var IPV4_BLOCKS=compileBlocks([["0.0.0.0/8","this-network"],["10.0.0.0/8","private"],["100.64.0.0/10","carrier-grade-nat"],["127.0.0.0/8","loopback"],["169.254.0.0/16","link-local"],["172.16.0.0/12","private"],["192.0.0.0/24","ietf-protocol"],["192.168.0.0/16","private"],["198.18.0.0/15","benchmarking"],["224.0.0.0/4","multicast"],["255.255.255.255/32","reserved"],["240.0.0.0/4","reserved"]],parseIpv4);var IPV6_BLOCKS=compileBlocks([["::/128","unspecified"],["::1/128","loopback"],["fd00:ec2::254/128","cloud-metadata"],["fc00::/7","private"],["fe80::/10","link-local"],["fec0::/10","site-local"],["64:ff9b:1::/48","local-use-nat64"],["ff00::/8","multicast"]],expandIpv6);var IPV4_EMBEDDINGS=compileBlocks([["::ffff:0:0/96",6],["::ffff:0:0:0/96",6],["::/96",6],["64:ff9b::/96",6],["2002::/16",1]],expandIpv6);function parseIpv4(address){const parts=address.split(".");if(parts.length!==4||!parts.every(part=>IPV4_OCTET_PATTERN.test(part)))return void 0;const octets=parts.map(Number);return octets.every(octet=>octet<=255)?octets:void 0}function expandIpv6(address){const zoneIndex=address.indexOf("%");let text=(zoneIndex===-1?address:address.slice(0,zoneIndex)).toLowerCase();const lastColonIndex=text.lastIndexOf(":");const trailingSegment=text.slice(lastColonIndex+1);if(lastColonIndex!==-1&&trailingSegment.includes(".")){const octets=parseIpv4(trailingSegment);if(!octets)return void 0;const highGroup=(octets[0]<<8|octets[1]).toString(16);const lowGroup=(octets[2]<<8|octets[3]).toString(16);text=`${text.slice(0,lastColonIndex+1)}${highGroup}:${lowGroup}`}const halves=text.split("::");if(halves.length>2)return void 0;const head=parseIpv6Groups(halves[0]);if(!head)return void 0;if(halves.length===1)return head.length===8?head:void 0;const tail=parseIpv6Groups(halves[1]);if(!tail||head.length+tail.length>7)return void 0;return[...head,...new Array(8-head.length-tail.length).fill(0),...tail]}function extractEmbeddedIpv4(groups){const octets=findEmbeddedIpv4Octets(groups);return octets?octets.join("."):void 0}function classifyIpAddress(address){const isBracketed=address.startsWith("[")&&address.endsWith("]");const octets=isBracketed?void 0:parseIpv4(address);if(octets)return classifyIpv4(octets);const groups=expandIpv6(isBracketed?address.slice(1,-1):address);if(!groups)return void 0;const block=IPV6_BLOCKS.find(candidate=>matchesBlock(groups,candidate,16));if(block)return{family:6,range:block.value,cidr:block.cidr};const embeddedOctets=findEmbeddedIpv4Octets(groups);if(!embeddedOctets)return{family:6,range:"public"};return{...classifyIpv4(embeddedOctets),family:6,embeddedIpv4:embeddedOctets.join(".")}}function classifyIpv4(octets){const block=IPV4_BLOCKS.find(candidate=>matchesBlock(octets,candidate,8));return block?{family:4,range:block.value,cidr:block.cidr}:{family:4,range:"public"}}function findEmbeddedIpv4Octets(groups){const embedding=IPV4_EMBEDDINGS.find(block=>matchesBlock(groups,block,16));if(!embedding)return void 0;const highGroup=groups[embedding.value];const lowGroup=groups[embedding.value+1];return[highGroup>>8,highGroup&255,lowGroup>>8,lowGroup&255]}function parseIpv6Groups(part){if(part==="")return[];const groups=part.split(":");if(!groups.every(group=>IPV6_GROUP_PATTERN.test(group)))return void 0;return groups.map(group=>parseInt(group,16))}function matchesBlock(words,block,bitsPerWord){let remainingBits=block.prefixLength;for(let index=0;remainingBits>0;index++){const comparedBits=Math.min(bitsPerWord,remainingBits);const ignoredBits=bitsPerWord-comparedBits;if(words[index]>>ignoredBits!==block.network[index]>>ignoredBits)return false;remainingBits-=comparedBits}return true}function compileBlocks(entries,parseNetwork){return entries.map(([cidr,value])=>{const[networkText,prefixText]=cidr.split("/");const network=parseNetwork(networkText);if(!network)throw new Error(`Invalid network in address block "${cidr}"`);return{cidr,network,prefixLength:Number(prefixText),value}})}function isRedirectResponse(response){return response.type==="opaqueredirect"||response.status>=300&&response.status<400}init_fs2();function escapeHtml(str){if(str===null||str===void 0){return""}const s=String(str);return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function escapeHtmlAttr(str){return str.replace(/&/g,"&").replace(/"/g,""")}function escapeJsString(str){return str.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function escapeScriptClose(jsonString){return jsonString.replace(/<\//g,"<\\/")}function safeJsonForScript(value){if(value===void 0){return"null"}try{const jsonString=JSON.stringify(value,(_key,val)=>{if(typeof val==="bigint"){return val.toString()}return val});if(jsonString===void 0){return"null"}return escapeScriptClose(jsonString)}catch{return'{"error":"Value could not be serialized"}'}}var CLASS_BRAND=Symbol.for("@frontmcp/class-brand");var ordinaryHasInstance=Function.prototype[Symbol.hasInstance];function ownBrandOf(klass){if(typeof klass!=="function"||!Object.prototype.hasOwnProperty.call(klass,CLASS_BRAND))return void 0;return klass[CLASS_BRAND]}function classOfPrototype(proto){return Object.getOwnPropertyDescriptor(proto,"constructor")?.value}function brandClass(klass,brand){Object.defineProperty(klass,CLASS_BRAND,{value:brand,enumerable:false,writable:false,configurable:false})}function isBrandedInstance(klass,value){if(ordinaryHasInstance.call(klass,value))return true;if(typeof value!=="object"||value===null)return false;const brand=ownBrandOf(klass);if(brand===void 0)return false;for(let proto=Object.getPrototypeOf(value);proto!==null;proto=Object.getPrototypeOf(proto)){if(ownBrandOf(classOfPrototype(proto))===brand)return true}return false}function safeStringify(value,space){const seen=new WeakSet;try{return JSON.stringify(value,(_key,val)=>{if(typeof val==="object"&&val!==null){if(seen.has(val))return"[Circular]";seen.add(val)}return val},space)}catch{return JSON.stringify({error:"Output could not be serialized"})}}init_crypto();var import_async_context=require("#async-context");var import_event_emitter2=require("#event-emitter");var import_env2=require("#env");var import_runtime_context=require("#runtime-context");var import_env3=require("#env");var import_runtime_context2=require("#runtime-context");init_memory();init_errors();init_errors();var NAMESPACE_SEPARATOR=":";function buildPrefix(name,id){if(id){return`${name}${NAMESPACE_SEPARATOR}${id}${NAMESPACE_SEPARATOR}`}return`${name}${NAMESPACE_SEPARATOR}`}var NamespacedStorageImpl=class _NamespacedStorageImpl{constructor(adapter,prefix="",root=adapter){this.adapter=adapter;this.prefix=prefix;this.root=root}adapter;prefix;root;prefixKey(key){return this.prefix+key}unprefixKey(key){if(this.prefix&&key.startsWith(this.prefix)){return key.slice(this.prefix.length)}return key}prefixPattern(pattern){return this.prefix+pattern}prefixChannel(channel){return this.prefix+channel}namespace(name,id){const newPrefix=this.prefix+buildPrefix(name,id);return new _NamespacedStorageImpl(this.adapter,newPrefix,this.root)}async connect(){return this.adapter.connect()}async disconnect(){return this.adapter.disconnect()}async ping(){return this.adapter.ping()}async get(key){return this.adapter.get(this.prefixKey(key))}async set(key,value,options){return this.adapter.set(this.prefixKey(key),value,options)}async delete(key){return this.adapter.delete(this.prefixKey(key))}async exists(key){return this.adapter.exists(this.prefixKey(key))}async mget(keys){const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.adapter.mget(prefixedKeys)}async mset(entries){const prefixedEntries=entries.map(e=>({...e,key:this.prefixKey(e.key)}));return this.adapter.mset(prefixedEntries)}async mdelete(keys){const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.adapter.mdelete(prefixedKeys)}async expire(key,ttlSeconds){return this.adapter.expire(this.prefixKey(key),ttlSeconds)}async ttl(key){return this.adapter.ttl(this.prefixKey(key))}async keys(pattern="*"){const prefixedPattern=this.prefixPattern(pattern);const keys=await this.adapter.keys(prefixedPattern);return keys.map(k=>this.unprefixKey(k))}async count(pattern="*"){const prefixedPattern=this.prefixPattern(pattern);return this.adapter.count(prefixedPattern)}async incr(key){return this.adapter.incr(this.prefixKey(key))}async decr(key){return this.adapter.decr(this.prefixKey(key))}async incrBy(key,amount){return this.adapter.incrBy(this.prefixKey(key),amount)}async deleteIfEquals(key,expectedValue){if(!this.adapter.deleteIfEquals){throw new StorageNotSupportedError("deleteIfEquals","this storage adapter")}return this.adapter.deleteIfEquals(this.prefixKey(key),expectedValue)}async expireIfEquals(key,expectedValue,ttlSeconds){if(!this.adapter.expireIfEquals){throw new StorageNotSupportedError("expireIfEquals","this storage adapter")}return this.adapter.expireIfEquals(this.prefixKey(key),expectedValue,ttlSeconds)}async publish(channel,message){return this.adapter.publish(this.prefixChannel(channel),message)}async subscribe(channel,handler){const prefixedChannel=this.prefixChannel(channel);const wrappedHandler=(message,ch)=>{const unprefixedChannel=ch.startsWith(this.prefix)?ch.slice(this.prefix.length):ch;handler(message,unprefixedChannel)};return this.adapter.subscribe(prefixedChannel,wrappedHandler)}supportsPubSub(){return this.adapter.supportsPubSub()}};function createRootStorage(adapter){return new NamespacedStorageImpl(adapter,"",adapter)}function createNamespacedStorage(adapter,prefix){const normalizedPrefix=prefix&&!prefix.endsWith(NAMESPACE_SEPARATOR)?prefix+NAMESPACE_SEPARATOR:prefix;return new NamespacedStorageImpl(adapter,normalizedPrefix,adapter)}var noDistributedStorageWarned=false;function warnNoDistributedStorage(){if(noDistributedStorageWarned||(0,import_runtime_context2.getRuntimeContext)().runtime==="browser")return;noDistributedStorageWarned=true;console.warn("[storage] Warning: No distributed storage backend detected in production. Using in-memory storage. Set REDIS_URL, UPSTASH_REDIS_REST_URL, or KV_REST_API_URL.")}function detectStorageType(){if((0,import_env3.getEnv)("UPSTASH_REDIS_REST_URL")&&(0,import_env3.getEnv)("UPSTASH_REDIS_REST_TOKEN")){return"upstash"}if((0,import_env3.getEnv)("KV_REST_API_URL")&&(0,import_env3.getEnv)("KV_REST_API_TOKEN")){return"vercel-kv"}if((0,import_env3.getEnv)("REDIS_URL")||(0,import_env3.getEnv)("REDIS_HOST")){return"redis"}return"memory"}async function createAdapter(type,config){switch(type){case"memory":{return new MemoryStorageAdapter(config.memory)}case"redis":{const{RedisStorageAdapter:RedisStorageAdapter2}=await Promise.resolve().then(()=>(init_redis(),redis_exports));return new RedisStorageAdapter2(config.redis)}case"vercel-kv":{const{VercelKvStorageAdapter:VercelKvStorageAdapter2}=await Promise.resolve().then(()=>(init_vercel_kv(),vercel_kv_exports));return new VercelKvStorageAdapter2(config.vercelKv)}case"upstash":{const{UpstashStorageAdapter:UpstashStorageAdapter2}=await Promise.resolve().then(()=>(init_upstash(),upstash_exports));return new UpstashStorageAdapter2(config.upstash)}case"cloudflare-kv":{if(!config.cloudflareKv){throw new StorageConfigError("cloudflare-kv","cloudflare-kv requires `cloudflareKv: { namespace }` (the KV binding can't be auto-detected)")}const{CloudflareKvStorageAdapter:CloudflareKvStorageAdapter2}=await Promise.resolve().then(()=>(init_cloudflare_kv(),cloudflare_kv_exports));return new CloudflareKvStorageAdapter2(config.cloudflareKv)}case"auto":throw new StorageConfigError("auto","Auto type should be resolved before calling createAdapter");default:throw new StorageConfigError("unknown",`Unknown storage type: ${type}`)}}async function createStorage(config={}){let type=config.type??"auto";const fallback=config.fallback??((0,import_env3.isProduction)()?"error":"memory");if(type==="auto"){type=detectStorageType();if(type==="memory"&&(0,import_env3.isProduction)())warnNoDistributedStorage()}let adapter;try{adapter=await createAdapter(type,config)}catch(e){if(fallback==="memory"&&type!=="memory"){console.warn(`[storage] Warning: Failed to create ${type} adapter, falling back to memory. Error: ${e instanceof Error?e.message:String(e)}`);adapter=new MemoryStorageAdapter(config.memory)}else{throw e}}try{await adapter.connect()}catch(e){if(fallback==="memory"&&type!=="memory"){console.warn(`[storage] Warning: Failed to connect to ${type}, falling back to memory. Error: ${e instanceof Error?e.message:String(e)}`);adapter=new MemoryStorageAdapter(config.memory);await adapter.connect()}else{throw e}}if(config.prefix){return createNamespacedStorage(adapter,config.prefix)}return createRootStorage(adapter)}function createMemoryStorage(config={}){const adapter=new MemoryStorageAdapter(config);if(config.prefix){return createNamespacedStorage(adapter,config.prefix)}return createRootStorage(adapter)}function getDetectedStorageType(){return detectStorageType()}init_redis_error_listener();init_redis_url();init_errors();var TypedStorage=class{storage;serialize;deserialize;schema;throwOnInvalid;constructor(storage,options={}){this.storage=storage;this.serialize=options.serialize??JSON.stringify;this.deserialize=options.deserialize??JSON.parse;this.schema=options.schema;this.throwOnInvalid=options.throwOnInvalid??false}async get(key){const raw=await this.storage.get(key);if(raw===null){return null}return this.parseValue(raw,key)}async set(key,value,options){const serialized=this.serialize(value);await this.storage.set(key,serialized,options)}async delete(key){return this.storage.delete(key)}async exists(key){return this.storage.exists(key)}async mget(keys){if(keys.length===0){return[]}const rawValues=await this.storage.mget(keys);return rawValues.map((raw,index)=>{if(raw===null){return null}return this.parseValue(raw,keys[index])})}async mset(entries){if(entries.length===0){return}const rawEntries=entries.map(entry=>({key:entry.key,value:this.serialize(entry.value),options:entry.options}));await this.storage.mset(rawEntries)}async mdelete(keys){return this.storage.mdelete(keys)}async expire(key,ttlSeconds){return this.storage.expire(key,ttlSeconds)}async ttl(key){return this.storage.ttl(key)}async keys(pattern){return this.storage.keys(pattern)}async count(pattern){return this.storage.count(pattern)}get raw(){return this.storage}parseValue(raw,key){try{const parsed=this.deserialize(raw);if(this.schema){const result=this.schema.safeParse(parsed);if(!result.success){if(this.throwOnInvalid){throw new Error(`TypedStorage validation failed for key "${key}": ${result.error.message}`)}return null}return result.data}return parsed}catch(error){if(this.throwOnInvalid){throw error}return null}}};init_crypto();init_errors();var textEncoder2=new TextEncoder;var textDecoder2=new TextDecoder;var EncryptedTypedStorage=class{storage;activeKey;keyMap;schema;throwOnError;onKeyRotationNeeded;clientBinding;constructor(storage,options){if(!options.keys||options.keys.length===0){throw new EncryptedStorageError("At least one encryption key is required")}for(const k of options.keys){if(k.key.length!==32){throw new EncryptedStorageError(`Encryption key "${k.kid}" must be 32 bytes (AES-256), got ${k.key.length} bytes`)}}this.storage=storage;this.activeKey=options.keys[0];this.keyMap=new Map(options.keys.map(k=>[k.kid,k.key]));this.schema=options.schema;this.throwOnError=options.throwOnError??false;this.onKeyRotationNeeded=options.onKeyRotationNeeded;this.clientBinding=options.clientBinding}async get(key){const raw=await this.storage.get(key);if(raw===null){return null}return this.decryptAndParse(raw,key)}async set(key,value,options){const encrypted=this.encryptValue(value);const serialized=JSON.stringify(encrypted);await this.storage.set(key,serialized,options)}async delete(key){return this.storage.delete(key)}async exists(key){return this.storage.exists(key)}async mget(keys){if(keys.length===0){return[]}const rawValues=await this.storage.mget(keys);return rawValues.map((raw,index)=>{if(raw===null){return null}return this.decryptAndParse(raw,keys[index])})}async mset(entries){if(entries.length===0){return}const rawEntries=entries.map(entry=>({key:entry.key,value:JSON.stringify(this.encryptValue(entry.value)),options:entry.options}));await this.storage.mset(rawEntries)}async mdelete(keys){return this.storage.mdelete(keys)}async expire(key,ttlSeconds){return this.storage.expire(key,ttlSeconds)}async ttl(key){return this.storage.ttl(key)}async keys(pattern){return this.storage.keys(pattern)}async count(pattern){return this.storage.count(pattern)}async reencrypt(key,options){const value=await this.get(key);if(value===null){return false}await this.set(key,value,options);return true}rotateKey(newKey){if(newKey.key.length!==32){throw new EncryptedStorageError(`New encryption key must be 32 bytes (AES-256), got ${newKey.key.length} bytes`)}if(!this.keyMap.has(newKey.kid)){this.keyMap.set(newKey.kid,newKey.key)}this.activeKey=newKey}get activeKeyId(){return this.activeKey.kid}get keyIds(){return Array.from(this.keyMap.keys())}get raw(){return this.storage}get hasClientBinding(){return this.clientBinding!==void 0}deriveKey(serverKey){if(!this.clientBinding){return serverKey}const clientSecret=typeof this.clientBinding.secret==="string"?textEncoder2.encode(this.clientBinding.secret):this.clientBinding.secret;const ikm=new Uint8Array(serverKey.length+clientSecret.length);ikm.set(serverKey,0);ikm.set(clientSecret,serverKey.length);const salt=this.clientBinding.salt??new Uint8Array(0);const info=textEncoder2.encode(this.clientBinding.info??"frontmcp-client-bound-v1");return hkdfSha256(ikm,salt,info,32)}encryptValue(value){let jsonString;try{jsonString=JSON.stringify(value)}catch(error){throw new EncryptedStorageError(`Failed to serialize value: ${error.message}`)}const plaintext=textEncoder2.encode(jsonString);const iv=randomBytes(12);const encryptionKey=this.deriveKey(this.activeKey.key);const{ciphertext,tag}=encryptAesGcm(encryptionKey,plaintext,iv);return{alg:"A256GCM",kid:this.activeKey.kid,iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}decryptAndParse(raw,storageKey){let blob;try{blob=JSON.parse(raw)}catch(_error){if(this.throwOnError){throw new EncryptedStorageError(`Failed to parse stored blob for key "${storageKey}"`)}return null}if(!this.isValidBlob(blob)){if(this.throwOnError){throw new EncryptedStorageError(`Invalid encrypted blob structure for key "${storageKey}"`)}return null}const serverKey=this.keyMap.get(blob.kid);if(!serverKey){if(this.throwOnError){throw new EncryptedStorageError(`Unknown encryption key "${blob.kid}" for key "${storageKey}". Known keys: ${Array.from(this.keyMap.keys()).join(", ")}`)}return null}const decryptionKey=this.deriveKey(serverKey);let decrypted;try{const iv=base64urlDecode(blob.iv);const tag=base64urlDecode(blob.tag);const ciphertext=base64urlDecode(blob.data);const plaintext=decryptAesGcm(decryptionKey,ciphertext,iv,tag);decrypted=JSON.parse(textDecoder2.decode(plaintext))}catch(error){if(this.throwOnError){throw new EncryptedStorageError(`Decryption failed for key "${storageKey}": ${error.message}`)}return null}if(this.schema){const result=this.schema.safeParse(decrypted);if(!result.success){if(this.throwOnError){throw new EncryptedStorageError(`Schema validation failed for key "${storageKey}": ${result.error.message}`)}return null}decrypted=result.data}if(blob.kid!==this.activeKey.kid&&this.onKeyRotationNeeded){this.onKeyRotationNeeded(storageKey,blob.kid,this.activeKey.kid)}return decrypted}isValidBlob(blob){return typeof blob==="object"&&blob!==null&&"alg"in blob&&"kid"in blob&&"iv"in blob&&"tag"in blob&&"data"in blob&&blob.alg==="A256GCM"&&typeof blob.kid==="string"&&typeof blob.iv==="string"&&typeof blob.tag==="string"&&typeof blob.data==="string"}};init_base();init_memory();init_redis();init_vercel_kv();init_upstash();init_filesystem();init_pattern();init_ttl();async function processPlatformToolCalls(platform,calls,callTool){switch(platform){case"openai":return processOpenAI(calls,callTool);case"claude":return processClaude(calls,callTool);case"vercel-ai":return processVercel(calls,callTool);default:throw new Error(`Unsupported platform: ${platform}`)}}async function processOpenAI(toolCalls,callTool){return Promise.all(toolCalls.map(async tc=>{let args;try{args=JSON.parse(tc.function.arguments)}catch{return{role:"tool",tool_call_id:tc.id,content:JSON.stringify({error:`Invalid JSON in tool call arguments for "${tc.function.name}"`})}}const result=await callTool(tc.function.name,args);return{role:"tool",tool_call_id:tc.id,content:typeof result==="string"?result:JSON.stringify(result)}}))}async function processClaude(toolUseBlocks,callTool){return Promise.all(toolUseBlocks.map(async block=>{const result=await callTool(block.name,block.input);const content=Array.isArray(result)?result.map(c=>c.text??"").join("\n"):typeof result==="string"?result:JSON.stringify(result);return{type:"tool_result",tool_use_id:block.id,content}}))}async function processVercel(info,callTool){const args=info.args!=null&&typeof info.args==="object"&&!Array.isArray(info.args)?info.args:void 0;return callTool(info.toolName,args)}init_crypto();init_runtime();function getEnvDirect(key){return typeof process!=="undefined"?process.env[key]:void 0}function isProductionDirect(){return getEnvDirect("NODE_ENV")==="production"}var DEFAULT_MACHINE_ID_PATH=".frontmcp/machine-id";function isDevPersistenceEnabled(){if(isBrowser())return false;return!isProductionDirect()}function resolveMachineIdPath(){if(isBrowser())return DEFAULT_MACHINE_ID_PATH;const path=require("path");const machineIdPath=getEnvDirect("MACHINE_ID_PATH")??DEFAULT_MACHINE_ID_PATH;const cwd=typeof process!=="undefined"?process.cwd():".";return path.isAbsolute(machineIdPath)?machineIdPath:path.resolve(cwd,machineIdPath)}function loadMachineIdSync(){if(!isDevPersistenceEnabled())return null;const machineIdPath=resolveMachineIdPath();try{const fs=require("fs");const content=fs.readFileSync(machineIdPath,"utf8").trim();if(/^[0-9a-f-]{32,36}$/i.test(content))return content;console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);return null}catch(error){if(error.code!=="ENOENT"){console.warn(`[MachineId] Failed to load from ${machineIdPath}: ${error.message}`)}return null}}function saveMachineIdAsync(machineId){if(!isDevPersistenceEnabled())return;const machineIdPath=resolveMachineIdPath();const path=require("path");const dir=path.dirname(machineIdPath);(async()=>{try{const fsp=require("fs").promises;await fsp.mkdir(dir,{recursive:true,mode:448});await fsp.writeFile(machineIdPath,machineId,{mode:384})}catch(error){console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`)}})()}function getHostname(){if(!isNode())return void 0;try{return require("os").hostname()}catch{return void 0}}function computeMachineId(){const envMachineId=getEnvDirect("MACHINE_ID");if(envMachineId)return envMachineId;const deploymentMode=getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");if(deploymentMode==="distributed"){const hostname=getEnvDirect("HOSTNAME");if(hostname)return hostname;if(isNode()){const os=require("os");return os.hostname()}}if(deploymentMode==="serverless"){return randomUUID()}const loadedId=loadMachineIdSync();if(loadedId)return loadedId;const newId=randomUUID();saveMachineIdAsync(newId);return newId}var cachedMachineId;var machineIdOverride;function getMachineId(){if(machineIdOverride!==void 0)return machineIdOverride;if(cachedMachineId===void 0){cachedMachineId=computeMachineId()}return cachedMachineId}function setMachineIdOverride(id){machineIdOverride=id}0&&(module.exports={AsyncContextOverlapError,AsyncLocalStorage,BaseStorageAdapter,DEFAULT_CODE_VERIFIER_LENGTH,DEFAULT_MAX_INPUT_LENGTH,DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS,EncryptedBlobError,EncryptedStorageError,EncryptedTypedStorage,EventEmitter,FileSystemStorageAdapter,KeyPersistence,MAX_CODE_VERIFIER_LENGTH,MAX_TTL_SECONDS,MIN_CODE_VERIFIER_LENGTH,MemoryStorageAdapter,NAMESPACE_SEPARATOR,NamespacedStorageImpl,PkceError,REDOS_THRESHOLDS,RedisStorageAdapter,StorageConfigError,StorageConnectionError,StorageError,StorageNotConnectedError,StorageNotSupportedError,StorageOperationError,StoragePatternError,StorageTTLError,TypedStorage,UpstashStorageAdapter,VercelKvStorageAdapter,access,analyzePattern,anyKeyDataSchema,assertNode,asymmetricAlgSchema,asymmetricKeyDataSchema,attachRedisErrorListener,awaitOutsideRequest,base64Decode,base64Encode,base64urlDecode,base64urlEncode,basename,brandClass,buildPrefix,buildSetCookie,bytesToHex,checkEntryAvailability,classifyIpAddress,clearCachedSecret,collapseChar,collapseWhitespace,copyFile,cp,createKeyPersistence,createKeyPersistenceWithStorage,createMemoryStorage,createNamespacedStorage,createRedisClient,createRootStorage,createSafeRegExp,createSecretData,createStorage,createVercelKvClient,decryptAesGcm,decryptValue,deleteSecret,describeRedisUrlConflicts,deserializeAndDecrypt,deserializeBlob,detectRuntimeContext,dirname,encryptAesGcm,encryptAndSerialize,encryptValue,ensureDir,ensureDirSync,ensureMaxLen,entryAvailabilitySchema,escapeGlob,escapeHtml,escapeHtmlAttr,escapeJsString,escapeScriptClose,expandIpv6,expandTemplate,expandUriTemplate,expiresAtToTTL,extname,extractBracedParams,extractEmbeddedIpv4,extractTemplateParams,extractUriScheme,fileExists,fileExistsSync,findNonFiniteNumber,generateCodeChallenge,generateCodeVerifier,generatePkcePair,generateRsaKeyPair,generateSecret,getAsyncContextMode,getCookie,getCrypto,getCwd,getDetectedStorageType,getEnv,getEnvFlag,getHostname,getMachineId,getNodeEnv,getOrCreateSecret,getRuntimeContext,getSpawnFn,globToRegex,hasTemplatePlaceholders,hkdfSha256,hmacSha256,idFromString,inferMimeType,isAbsolute,isAsymmetricKeyData,isBrandedInstance,isBrowser,isDebug,isDevelopment,isDirEmpty,isEdgeRuntime,isEntryAvailable,isExpired,isInputLengthSafe,isLocalhost,isNode,isPatternSafe,isProduction,isRedirectResponse,isRsaPssAlg,isSecretCached,isSecretKeyData,isSecretPersistenceEnabled,isSecureRequest,isServerless,isSignedData,isUriTemplate,isValidCodeChallenge,isValidCodeVerifier,isValidEncryptedBlob,isValidMcpUri,isValidMcpUriTemplate,joinPath,jwtAlgToNodeAlg,loadSecret,matchUriTemplate,matchesPattern,mergeRedisUrlFields,mkdir,mkdtemp,normalizeTTL,parseCookies,parseIpv4,parseKeyData,parseSecretData,parseUriTemplate,pathJoin,pathResolve,pathToFileURL,pemToPublicJwk,processPlatformToolCalls,randomBytes,randomUUID,readFile,readFileBuffer,readFileSync,readJSON,readdir,readdirSync,realpath,rename,resetRuntimeContext,resolveSecretPath,rm,rsaSignBase64Url,rsaVerify,rsaVerifySync,runCmd,runRequestExclusive,safeExec,safeJsonForScript,safeMatch,safeReplace,safeStringify,safeTest,sanitizeToJson,saveSecret,secretDataSchema,secretKeyDataSchema,sep,sepFor,serializeBlob,setEnv,setMachineIdOverride,sha256,sha256Base64url,sha256Hex,shortHash,signData,splitWords,stat,supportsAnsi,symlink,timingSafeEqual,toCase,trimBoth,trimChars,trimLeading,trimSlashes,trimTrailing,tryDecryptValue,tryDeserializeAndDecrypt,tryDeserializeBlob,ttlToExpiresAt,unlink,validateBaseUrl,validateKeyData,validateOptionalTTL,validatePattern,validateSecretData,validateTTL,verifyCodeChallenge,verifyData,verifyOrParseData,watchFile,writeFile,writeJSON});
|
|
1
|
+
"use strict";var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf;var __hasOwnProp=Object.prototype.hasOwnProperty;var __esm=(fn,res,err)=>function __init(){if(err)throw err[0];try{return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res}catch(e){throw err=[e],e}};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true})};var __copyProps=(to,from,except,desc)=>{if(from&&typeof from==="object"||typeof from==="function"){for(let key of __getOwnPropNames(from))if(!__hasOwnProp.call(to,key)&&key!==except)__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:true}):target,mod));var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:true}),mod);function isNode(){return typeof process!=="undefined"&&!!process.versions?.node}function isBrowser(){return typeof globalThis!=="undefined"&&typeof globalThis.crypto!=="undefined"&&typeof globalThis.crypto.getRandomValues==="function"}function assertNode(feature){if(!isNode()){throw new Error(`${feature} is not supported in the browser. Requires Node.js.`)}}var init_runtime=__esm({"libs/utils/src/crypto/runtime.ts"(){"use strict"}});function getFsp(){if(!_fsp){assertNode("File system operations");_fsp=require("fs").promises}return _fsp}function getFs(){if(!_fs){assertNode("File system operations");_fs=require("fs")}return _fs}function getSpawn(){if(!_spawn){assertNode("Child process operations");_spawn=require("child_process").spawn}return _spawn}function getSpawnFn(){return getSpawn()}async function readFile(p,encoding="utf8"){const fsp=getFsp();return fsp.readFile(p,encoding)}function readFileSync(p,encoding="utf8"){const fs=getFs();return fs.readFileSync(p,encoding)}async function readFileBuffer(p){const fsp=getFsp();return fsp.readFile(p)}async function writeFile(p,content,options){const fsp=getFsp();await fsp.writeFile(p,content,{encoding:"utf8",mode:options?.mode,flag:options?.flag})}async function appendFile(p,content,options){const fsp=getFsp();await fsp.appendFile(p,content,{encoding:"utf8",mode:options?.mode})}async function mkdir(p,options){const fsp=getFsp();await fsp.mkdir(p,options)}function ensureDirSync(p){const fs=getFs();fs.mkdirSync(p,{recursive:true})}async function rename(oldPath,newPath){const fsp=getFsp();await fsp.rename(oldPath,newPath)}async function unlink(p){const fsp=getFsp();await fsp.unlink(p)}async function fileExists(p){try{const fsp=getFsp();await fsp.access(p,F_OK);return true}catch{return false}}function fileExistsSync(p){return getFs().existsSync(p)}function isMissingSync(p){try{getFs().statSync(p);return false}catch(error){const code=error.code;return code==="ENOENT"||code==="ENOTDIR"}}async function readJSON(jsonPath){try{const fsp=getFsp();const buf=await fsp.readFile(jsonPath,"utf8");return JSON.parse(buf)}catch{return null}}async function writeJSON(p,obj){const fsp=getFsp();await fsp.writeFile(p,JSON.stringify(obj,null,2)+"\n","utf8")}async function ensureDir(p){const fsp=getFsp();await fsp.mkdir(p,{recursive:true})}async function stat(p){const fsp=getFsp();return fsp.stat(p)}async function lstat(p){const fsp=getFsp();return fsp.lstat(p)}async function chmod(p,mode){const fsp=getFsp();await fsp.chmod(p,mode)}async function symlink(target,linkPath,type){const fsp=getFsp();await fsp.symlink(target,linkPath,type)}async function realpath(p){const fsp=getFsp();return fsp.realpath(p)}async function copyFile(src,dest){const fsp=getFsp();await fsp.copyFile(src,dest)}async function cp(src,dest,options){const fsp=getFsp();await fsp.cp(src,dest,options)}async function readdir(p){const fsp=getFsp();return fsp.readdir(p)}function readdirSync(p){const fs=getFs();return fs.readdirSync(p)}async function rm(p,options){const fsp=getFsp();await fsp.rm(p,options)}async function isDirEmpty(dir){try{const fsp=getFsp();const items=await fsp.readdir(dir);return items.length===0}catch(e){if(e?.code==="ENOENT")return true;throw e}}async function mkdtemp(prefix){const fsp=getFsp();return fsp.mkdtemp(prefix)}async function access(p,mode){const fsp=getFsp();await fsp.access(p,mode??F_OK)}function runCmd(cmd,args,opts={}){const spawn=getSpawn();return new Promise((resolve2,reject)=>{const child=spawn(cmd,args,{stdio:"inherit",shell:false,...opts});child.on("close",code=>code===0?resolve2():reject(new Error(`${cmd} exited with code ${code}`)));child.on("error",reject)})}function watchFile(p,onChange,options){const fs=getFs();const watcher=fs.watch(p,{persistent:false,recursive:options?.recursive===true},(eventType,filename)=>{onChange(eventType,filename)});return{close(){watcher.close()},onError(handler){watcher.on("error",handler)}}}var _fsp,_fs,_spawn,F_OK;var init_fs=__esm({"libs/utils/src/fs/fs.ts"(){"use strict";init_runtime();_fsp=null;_fs=null;_spawn=null;F_OK=0}});var init_fs2=__esm({"libs/utils/src/fs/index.ts"(){"use strict";init_fs()}});function jwtAlgToNodeAlg(jwtAlg){const nodeAlg=JWT_ALG_TO_NODE_DIGEST[jwtAlg];if(!nodeAlg){throw new Error(`Unsupported JWT algorithm: ${jwtAlg}`)}return nodeAlg}function isRsaPssAlg(jwtAlg){return jwtAlg.startsWith("PS")}function jwtAlgToWebCryptoAlg(jwtAlg){const webAlg=JWT_ALG_TO_WEB_CRYPTO[jwtAlg];if(!webAlg){throw new Error(`Unsupported JWT algorithm for WebCrypto: ${jwtAlg}`)}return webAlg}var JWT_ALG_TO_NODE_DIGEST,JWT_ALG_TO_WEB_CRYPTO;var init_jwt_alg=__esm({"libs/utils/src/crypto/jwt-alg.ts"(){"use strict";JWT_ALG_TO_NODE_DIGEST={RS256:"RSA-SHA256",RS384:"RSA-SHA384",RS512:"RSA-SHA512",PS256:"RSA-SHA256",PS384:"RSA-SHA384",PS512:"RSA-SHA512"};JWT_ALG_TO_WEB_CRYPTO={RS256:"SHA-256",RS384:"SHA-384",RS512:"SHA-512",PS256:"SHA-256",PS384:"SHA-384",PS512:"SHA-512"}}});async function rsaVerifyBrowser(jwtAlg,data,publicJwk,signature){if(typeof globalThis.crypto?.subtle==="undefined"){throw new Error("WebCrypto API (crypto.subtle) is not available in this environment")}const webAlg=jwtAlgToWebCryptoAlg(jwtAlg);const isPss=isRsaPssAlg(jwtAlg);const algorithm={name:isPss?"RSA-PSS":"RSASSA-PKCS1-v1_5",hash:{name:webAlg}};const key=await globalThis.crypto.subtle.importKey("jwk",publicJwk,algorithm,false,["verify"]);const verifyAlgorithm=isPss?{name:"RSA-PSS",saltLength:getSaltLength(jwtAlg)}:{name:"RSASSA-PKCS1-v1_5"};const sigBuf=new Uint8Array(signature).buffer;const dataBuf=new Uint8Array(data).buffer;return globalThis.crypto.subtle.verify(verifyAlgorithm,key,sigBuf,dataBuf)}function getSaltLength(jwtAlg){switch(jwtAlg){case"PS256":return 32;case"PS384":return 48;case"PS512":return 64;default:return 32}}var init_web_rsa=__esm({"libs/utils/src/crypto/web-rsa.ts"(){"use strict";init_jwt_alg()}});function encryptValue(data,key){if(key.length!==32){throw new EncryptedBlobError(`Encryption key must be 32 bytes (AES-256), got ${key.length} bytes`)}let jsonString;try{jsonString=JSON.stringify(data)}catch(error){throw new EncryptedBlobError(`Failed to serialize data: ${error.message}`)}const plaintext=textEncoder.encode(jsonString);const iv=randomBytes(12);const{ciphertext,tag}=encryptAesGcm(key,plaintext,iv);return{alg:"A256GCM",iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}function decryptValue(blob,key){if(key.length!==32){throw new EncryptedBlobError(`Decryption key must be 32 bytes (AES-256), got ${key.length} bytes`)}if(blob.alg!=="A256GCM"){throw new EncryptedBlobError(`Unsupported algorithm: ${blob.alg}, expected A256GCM`)}let iv;let tag;let ciphertext;try{iv=base64urlDecode(blob.iv);tag=base64urlDecode(blob.tag);ciphertext=base64urlDecode(blob.data)}catch(error){throw new EncryptedBlobError(`Failed to decode blob fields: ${error.message}`)}let decrypted;try{decrypted=decryptAesGcm(key,ciphertext,iv,tag)}catch(error){throw new EncryptedBlobError(`Decryption failed: ${error.message}`)}try{return JSON.parse(textDecoder.decode(decrypted))}catch(error){throw new EncryptedBlobError(`Failed to parse decrypted data: ${error.message}`)}}function tryDecryptValue(blob,key){try{return decryptValue(blob,key)}catch{return null}}function serializeBlob(blob){return JSON.stringify(blob)}function deserializeBlob(str){let parsed;try{parsed=JSON.parse(str)}catch(error){throw new EncryptedBlobError(`Failed to parse blob JSON: ${error.message}`)}if(!isValidEncryptedBlob(parsed)){throw new EncryptedBlobError("Invalid encrypted blob structure")}return parsed}function tryDeserializeBlob(str){try{return deserializeBlob(str)}catch{return null}}function isValidEncryptedBlob(value){return typeof value==="object"&&value!==null&&"alg"in value&&"iv"in value&&"tag"in value&&"data"in value&&value.alg==="A256GCM"&&typeof value.iv==="string"&&typeof value.tag==="string"&&typeof value.data==="string"}function encryptAndSerialize(data,key){const blob=encryptValue(data,key);return serializeBlob(blob)}function deserializeAndDecrypt(str,key){const blob=deserializeBlob(str);return decryptValue(blob,key)}function tryDeserializeAndDecrypt(str,key){try{return deserializeAndDecrypt(str,key)}catch{return null}}var textEncoder,textDecoder,EncryptedBlobError;var init_encrypted_blob=__esm({"libs/utils/src/crypto/encrypted-blob.ts"(){"use strict";init_crypto();textEncoder=new TextEncoder;textDecoder=new TextDecoder;EncryptedBlobError=class extends Error{constructor(message){super(message);this.name="EncryptedBlobError"}}}});function generateCodeVerifier(length=DEFAULT_CODE_VERIFIER_LENGTH){if(length<MIN_CODE_VERIFIER_LENGTH||length>MAX_CODE_VERIFIER_LENGTH){throw new PkceError(`Code verifier length must be between ${MIN_CODE_VERIFIER_LENGTH} and ${MAX_CODE_VERIFIER_LENGTH} characters (got ${length})`)}const bytesNeeded=Math.ceil(length*6/8);const bytes=randomBytes(bytesNeeded);return base64urlEncode(bytes).slice(0,length)}function generateCodeChallenge(codeVerifier){const verifierBytes=new TextEncoder().encode(codeVerifier);const hash=sha256(verifierBytes);return base64urlEncode(hash)}function verifyCodeChallenge(codeVerifier,codeChallenge){const computedChallenge=generateCodeChallenge(codeVerifier);return computedChallenge===codeChallenge}function generatePkcePair(length=DEFAULT_CODE_VERIFIER_LENGTH){const codeVerifier=generateCodeVerifier(length);const codeChallenge=generateCodeChallenge(codeVerifier);return{codeVerifier,codeChallenge}}function isValidCodeVerifier(value){if(value.length<MIN_CODE_VERIFIER_LENGTH||value.length>MAX_CODE_VERIFIER_LENGTH){return false}return/^[A-Za-z0-9\-._~]+$/.test(value)}function isValidCodeChallenge(value){if(value.length!==43){return false}return/^[A-Za-z0-9\-_]+$/.test(value)}var MIN_CODE_VERIFIER_LENGTH,MAX_CODE_VERIFIER_LENGTH,DEFAULT_CODE_VERIFIER_LENGTH,PkceError;var init_pkce=__esm({"libs/utils/src/crypto/pkce/pkce.ts"(){"use strict";init_crypto();MIN_CODE_VERIFIER_LENGTH=43;MAX_CODE_VERIFIER_LENGTH=128;DEFAULT_CODE_VERIFIER_LENGTH=64;PkceError=class extends Error{constructor(message){super(message);this.name="PkceError"}}}});var init_pkce2=__esm({"libs/utils/src/crypto/pkce/index.ts"(){"use strict";init_pkce()}});function validateSecretData(data){const result=secretDataSchema.safeParse(data);if(!result.success){return{valid:false,error:result.error.issues[0]?.message??"Invalid secret structure"}}const parsed=result.data;const now=Date.now();if(parsed.createdAt>now+MAX_CLOCK_DRIFT_MS){return{valid:false,error:"createdAt is in the future"}}if(parsed.createdAt<now-MAX_SECRET_AGE_MS){return{valid:false,error:"createdAt is too old"}}return{valid:true}}function parseSecretData(data){const validation=validateSecretData(data);if(!validation.valid){return null}return data}var import_lazy_zod,secretDataSchema,MAX_CLOCK_DRIFT_MS,MAX_SECRET_AGE_MS;var init_schema=__esm({"libs/utils/src/crypto/secret-persistence/schema.ts"(){"use strict";import_lazy_zod=require("@frontmcp/lazy-zod");secretDataSchema=import_lazy_zod.internalZ.object({secret:import_lazy_zod.internalZ.string().base64url().length(43),createdAt:import_lazy_zod.internalZ.number().positive().int(),version:import_lazy_zod.internalZ.number().positive().int()}).strict();MAX_CLOCK_DRIFT_MS=6e4;MAX_SECRET_AGE_MS=100*365*24*60*60*1e3}});function getPath(){return require("path")}function isSecretPersistenceEnabled(options){const isProduction3=(0,import_env.getEnv)("NODE_ENV")==="production";if(isProduction3){return options?.forceEnable===true}return true}function resolveSecretPath(options){const p=getPath();if(options?.secretPath){if(p.isAbsolute(options.secretPath)){return options.secretPath}return p.resolve((0,import_env.getCwd)(),options.secretPath)}const name=options?.name??"default";const defaultPath=`${DEFAULT_SECRET_DIR}/${name}-secret.json`;return p.resolve((0,import_env.getCwd)(),defaultPath)}function getLogger(options){if(options?.enableLogging===false){return{warn:noop,error:noop}}return options?.logger??{warn:console.warn,error:console.error}}function getLogPrefix(options){const name=options?.name??"Secret";return`[${name}Persistence]`}async function loadSecret(options){if(!isSecretPersistenceEnabled(options)){return null}const secretPath=resolveSecretPath(options);const logger=getLogger(options);const prefix=getLogPrefix(options);try{const content=await readFile(secretPath);const data=JSON.parse(content);const validation=validateSecretData(data);if(!validation.valid){logger.warn(`${prefix} Invalid secret file format at ${secretPath}: ${validation.error}, will regenerate`);return null}return data}catch(error){if(error.code==="ENOENT"){return null}logger.warn(`${prefix} Failed to load secret from ${secretPath}: ${error.message}`);return null}}async function saveSecret(secretData,options){if(!isSecretPersistenceEnabled(options)){return true}const secretPath=resolveSecretPath(options);const dir=getPath().dirname(secretPath);const tempPath=`${secretPath}.tmp.${Date.now()}.${base64urlEncode(randomBytes(8))}`;const logger=getLogger(options);const prefix=getLogPrefix(options);try{await mkdir(dir,{recursive:true,mode:448});const content=JSON.stringify(secretData,null,2);await writeFile(tempPath,content,{mode:384});await rename(tempPath,secretPath);return true}catch(error){logger.error(`${prefix} Failed to save secret to ${secretPath}: ${error.message}`);try{await unlink(tempPath)}catch{}return false}}async function deleteSecret(options){const secretPath=resolveSecretPath(options);const logger=getLogger(options);const prefix=getLogPrefix(options);try{await unlink(secretPath);return true}catch(error){if(error.code==="ENOENT"){return true}logger.warn(`${prefix} Failed to delete secret at ${secretPath}: ${error.message}`);return false}}function generateSecret(bytes=DEFAULT_SECRET_BYTES){return base64urlEncode(randomBytes(bytes))}function createSecretData(options){const secretBytes=options?.secretBytes??DEFAULT_SECRET_BYTES;return{secret:generateSecret(secretBytes),createdAt:Date.now(),version:1}}async function getOrCreateSecret(options){const cacheKey=resolveSecretPath(options);const cached=secretCache.get(cacheKey);if(cached){return cached}const existing=generationPromises.get(cacheKey);if(existing){return existing}const promise=(async()=>{try{const loaded=await loadSecret(options);if(loaded){secretCache.set(cacheKey,loaded.secret);return loaded.secret}const secretData=createSecretData(options);if(isSecretPersistenceEnabled(options)){await saveSecret(secretData,options)}secretCache.set(cacheKey,secretData.secret);return secretData.secret}finally{generationPromises.delete(cacheKey)}})();generationPromises.set(cacheKey,promise);return promise}function clearCachedSecret(options){if(options){const cacheKey=resolveSecretPath(options);secretCache.delete(cacheKey)}else{secretCache.clear()}}function isSecretCached(options){const cacheKey=resolveSecretPath(options);return secretCache.has(cacheKey)}var import_env,DEFAULT_SECRET_BYTES,DEFAULT_SECRET_DIR,noop,secretCache,generationPromises;var init_persistence=__esm({"libs/utils/src/crypto/secret-persistence/persistence.ts"(){"use strict";init_fs2();init_crypto();init_schema();import_env=require("#env");DEFAULT_SECRET_BYTES=32;DEFAULT_SECRET_DIR=".frontmcp";noop=()=>{};secretCache=new Map;generationPromises=new Map}});var init_secret_persistence=__esm({"libs/utils/src/crypto/secret-persistence/index.ts"(){"use strict";init_schema();init_persistence()}});function computeSignature(data,secret){const encoder=new TextEncoder;const keyBytes=encoder.encode(secret);const dataBytes=encoder.encode(data);const hmac=hmacSha256(keyBytes,dataBytes);return base64urlEncode(hmac)}function signData(data,config){const jsonData=JSON.stringify(data);const sig=computeSignature(jsonData,config.secret);const signed={data,sig,v:1};return JSON.stringify(signed)}function verifyData(signedJson,config){try{const parsed=JSON.parse(signedJson);if(!parsed||typeof parsed!=="object"||!("sig"in parsed)){return null}const signed=parsed;if(signed.v!==1){return null}const jsonData=JSON.stringify(signed.data);const expectedSig=computeSignature(jsonData,config.secret);const sigBytes=base64urlDecode(signed.sig);const expectedBytes=base64urlDecode(expectedSig);if(sigBytes.length!==expectedBytes.length){return null}if(!timingSafeEqual(sigBytes,expectedBytes)){return null}return signed.data}catch{return null}}function isSignedData(json){try{const parsed=JSON.parse(json);return parsed&&typeof parsed==="object"&&"sig"in parsed&&"v"in parsed}catch{return false}}function verifyOrParseData(json,config){if(isSignedData(json)){return verifyData(json,config)}try{return JSON.parse(json)}catch{return null}}var init_hmac_signing=__esm({"libs/utils/src/crypto/hmac-signing.ts"(){"use strict";init_crypto();init_crypto();init_crypto()}});function validateKeyData(data){const result=anyKeyDataSchema.safeParse(data);if(!result.success){return{valid:false,error:result.error.issues[0]?.message??"Invalid key structure"}}const parsed=result.data;const now=Date.now();if(parsed.createdAt>now+MAX_CLOCK_DRIFT_MS2){return{valid:false,error:"createdAt is in the future"}}if(parsed.createdAt<now-MAX_KEY_AGE_MS){return{valid:false,error:"createdAt is too old"}}return{valid:true,data:parsed}}function parseKeyData(data){const validation=validateKeyData(data);if(!validation.valid){return null}return validation.data}function isSecretKeyData(data){return data.type==="secret"}function isAsymmetricKeyData(data){return data.type==="asymmetric"}var import_lazy_zod2,MAX_CLOCK_DRIFT_MS2,MAX_KEY_AGE_MS,asymmetricAlgSchema,baseKeyDataSchema,jsonWebKeySchema,secretKeyDataSchema,asymmetricKeyDataSchema,anyKeyDataSchema;var init_schemas=__esm({"libs/utils/src/crypto/key-persistence/schemas.ts"(){"use strict";import_lazy_zod2=require("@frontmcp/lazy-zod");MAX_CLOCK_DRIFT_MS2=6e4;MAX_KEY_AGE_MS=100*365*24*60*60*1e3;asymmetricAlgSchema=import_lazy_zod2.internalZ.enum(["RS256","RS384","RS512","ES256","ES384","ES512"]);baseKeyDataSchema=import_lazy_zod2.internalZ.object({kid:import_lazy_zod2.internalZ.string().min(1),createdAt:import_lazy_zod2.internalZ.number().positive().int(),version:import_lazy_zod2.internalZ.number().positive().int()});jsonWebKeySchema=import_lazy_zod2.internalZ.object({kty:import_lazy_zod2.internalZ.string().optional(),use:import_lazy_zod2.internalZ.string().optional(),alg:import_lazy_zod2.internalZ.string().optional(),kid:import_lazy_zod2.internalZ.string().optional(),n:import_lazy_zod2.internalZ.string().optional(),e:import_lazy_zod2.internalZ.string().optional(),d:import_lazy_zod2.internalZ.string().optional(),p:import_lazy_zod2.internalZ.string().optional(),q:import_lazy_zod2.internalZ.string().optional(),dp:import_lazy_zod2.internalZ.string().optional(),dq:import_lazy_zod2.internalZ.string().optional(),qi:import_lazy_zod2.internalZ.string().optional(),x:import_lazy_zod2.internalZ.string().optional(),y:import_lazy_zod2.internalZ.string().optional(),crv:import_lazy_zod2.internalZ.string().optional()}).passthrough();secretKeyDataSchema=baseKeyDataSchema.extend({type:import_lazy_zod2.internalZ.literal("secret"),secret:import_lazy_zod2.internalZ.string().min(1),bytes:import_lazy_zod2.internalZ.number().positive().int()});asymmetricKeyDataSchema=baseKeyDataSchema.extend({type:import_lazy_zod2.internalZ.literal("asymmetric"),alg:asymmetricAlgSchema,privateKey:jsonWebKeySchema,publicJwk:import_lazy_zod2.internalZ.object({keys:import_lazy_zod2.internalZ.array(jsonWebKeySchema).min(1)})});anyKeyDataSchema=import_lazy_zod2.internalZ.discriminatedUnion("type",[secretKeyDataSchema,asymmetricKeyDataSchema])}});var KeyPersistence;var init_key_persistence=__esm({"libs/utils/src/crypto/key-persistence/key-persistence.ts"(){"use strict";init_crypto();init_schemas();KeyPersistence=class{storage;cache=new Map;enableCache;throwOnInvalid;constructor(options){this.storage=options.storage;this.enableCache=options.enableCache??true;this.throwOnInvalid=options.throwOnInvalid??false}async get(kid){if(this.enableCache){const cached=this.cache.get(kid);if(cached)return cached}const raw=await this.storage.get(kid);if(!raw)return null;let parsed;try{parsed=JSON.parse(raw)}catch{if(this.throwOnInvalid){throw new Error(`Invalid JSON for key "${kid}"`)}return null}const validation=validateKeyData(parsed);if(!validation.valid){if(this.throwOnInvalid){throw new Error(`Invalid key data for "${kid}": ${validation.error}`)}return null}const key=validation.data;if(this.enableCache){this.cache.set(kid,key)}return key}async getSecret(kid){const key=await this.get(kid);if(!key||!isSecretKeyData(key))return null;return key}async getAsymmetric(kid){const key=await this.get(kid);if(!key||!isAsymmetricKeyData(key))return null;return key}async set(key){const validation=validateKeyData(key);if(!validation.valid){throw new Error(`Invalid key data: ${validation.error}`)}await this.storage.set(key.kid,JSON.stringify(key,null,2));if(this.enableCache){this.cache.set(key.kid,key)}}async delete(kid){this.cache.delete(kid);return this.storage.delete(kid)}async has(kid){if(this.enableCache&&this.cache.has(kid)){return true}return this.storage.exists(kid)}async list(){return this.storage.keys()}async getOrCreateSecret(kid,options){const existing=await this.getSecret(kid);if(existing){return existing}const bytes=options?.bytes??32;const secret={type:"secret",kid,secret:base64urlEncode(randomBytes(bytes)),bytes,createdAt:Date.now(),version:1};await this.set(secret);return secret}clearCache(){this.cache.clear()}clearCacheFor(kid){this.cache.delete(kid)}isCached(kid){return this.cache.has(kid)}getAdapter(){return this.storage}}}});var StorageError,StorageConnectionError,StorageOperationError,StorageNotSupportedError,StorageConfigError,StorageTTLError,StoragePatternError,StorageNotConnectedError,EncryptedStorageError;var init_errors=__esm({"libs/utils/src/storage/errors.ts"(){"use strict";StorageError=class extends Error{cause;constructor(message,cause){super(message);this.cause=cause;this.name="StorageError";Object.setPrototypeOf(this,new.target.prototype);if(Error.captureStackTrace){Error.captureStackTrace(this,this.constructor)}}};StorageConnectionError=class extends StorageError{constructor(message,cause,backend){const fullMessage=cause?`${message}: ${cause.message}`:message;super(fullMessage,cause);this.backend=backend;this.name="StorageConnectionError"}backend};StorageOperationError=class extends StorageError{constructor(operation,key,message,cause){super(`${operation} failed for key "${key}": ${message}`,cause);this.operation=operation;this.key=key;this.name="StorageOperationError"}operation;key};StorageNotSupportedError=class extends StorageError{constructor(operation,backend,suggestion){const msg=suggestion?`${operation} is not supported by ${backend}. ${suggestion}`:`${operation} is not supported by ${backend}`;super(msg);this.operation=operation;this.backend=backend;this.name="StorageNotSupportedError"}operation;backend};StorageConfigError=class extends StorageError{constructor(backend,message){super(`Invalid ${backend} configuration: ${message}`);this.backend=backend;this.name="StorageConfigError"}backend};StorageTTLError=class extends StorageError{constructor(ttl,message){super(message??`Invalid TTL value: ${ttl}. TTL must be a positive integer.`);this.ttl=ttl;this.name="StorageTTLError"}ttl};StoragePatternError=class extends StorageError{constructor(pattern,message){super(`Invalid pattern "${pattern}": ${message}`);this.pattern=pattern;this.name="StoragePatternError"}pattern};StorageNotConnectedError=class extends StorageError{constructor(backend){super(`Storage backend "${backend}" is not connected. Call connect() first.`);this.backend=backend;this.name="StorageNotConnectedError"}backend};EncryptedStorageError=class extends StorageError{constructor(message){super(message);this.name="EncryptedStorageError"}}}});function globToRegex(pattern){if(pattern.length>MAX_PATTERN_LENGTH){throw new StoragePatternError(pattern.substring(0,50)+"...",`Pattern exceeds maximum length of ${MAX_PATTERN_LENGTH} characters`)}const wildcardCount=(pattern.match(/[*?]/g)||[]).length;if(wildcardCount>MAX_WILDCARDS){throw new StoragePatternError(pattern,`Pattern has too many wildcards (max: ${MAX_WILDCARDS})`)}if(pattern===""||pattern==="*"){return/^.*$/}let regexStr="^";let prevChar="";for(let i=0;i<pattern.length;i++){const char=pattern[i];switch(char){case"*":if(prevChar!=="*"){regexStr+=".*"}break;case"?":regexStr+=".";break;default:regexStr+=char.replace(REGEX_SPECIAL_CHARS,"\\$&")}prevChar=char}regexStr+="$";try{return new RegExp(regexStr)}catch{throw new StoragePatternError(pattern,"Failed to compile pattern to regex")}}function matchesPattern(key,pattern){const regex=globToRegex(pattern);return regex.test(key)}function validatePattern(pattern){try{globToRegex(pattern);return{valid:true}}catch(e){return{valid:false,error:e instanceof Error?e.message:"Invalid pattern"}}}function escapeGlob(literal){return literal.replace(/[*?\\]/g,"\\$&")}var MAX_PATTERN_LENGTH,MAX_WILDCARDS,REGEX_SPECIAL_CHARS;var init_pattern=__esm({"libs/utils/src/storage/utils/pattern.ts"(){"use strict";init_errors();MAX_PATTERN_LENGTH=500;MAX_WILDCARDS=20;REGEX_SPECIAL_CHARS=/[.+^${}()|[\]\\]/g}});function validateTTL(ttlSeconds){if(typeof ttlSeconds!=="number"){throw new StorageTTLError(ttlSeconds,`TTL must be a number, got ${typeof ttlSeconds}`)}if(!Number.isFinite(ttlSeconds)){throw new StorageTTLError(ttlSeconds,"TTL must be a finite number")}if(!Number.isInteger(ttlSeconds)){throw new StorageTTLError(ttlSeconds,`TTL must be an integer, got ${ttlSeconds}`)}if(ttlSeconds<=0){throw new StorageTTLError(ttlSeconds,`TTL must be positive, got ${ttlSeconds}`)}if(ttlSeconds>MAX_TTL_SECONDS){throw new StorageTTLError(ttlSeconds,`TTL exceeds maximum of ${MAX_TTL_SECONDS} seconds`)}}function validateOptionalTTL(ttlSeconds){if(ttlSeconds!==void 0){validateTTL(ttlSeconds)}}function ttlToExpiresAt(ttlSeconds){return Date.now()+ttlSeconds*1e3}function expiresAtToTTL(expiresAt){const remaining=Math.ceil((expiresAt-Date.now())/1e3);return Math.max(0,remaining)}function isExpired(expiresAt){if(expiresAt===void 0)return false;return Date.now()>=expiresAt}function normalizeTTL(ttl,unit){return unit==="milliseconds"?Math.ceil(ttl/1e3):ttl}var MAX_TTL_SECONDS;var init_ttl=__esm({"libs/utils/src/storage/utils/ttl.ts"(){"use strict";init_errors();MAX_TTL_SECONDS=31536e5}});var BaseStorageAdapter;var init_base=__esm({"libs/utils/src/storage/adapters/base.ts"(){"use strict";init_errors();init_ttl();BaseStorageAdapter=class{connected=false;ensureConnected(){if(!this.connected){throw new StorageNotConnectedError(this.backendName)}}async set(key,value,options){this.ensureConnected();this.validateSetOptions(options);return this.doSet(key,value,options)}async mget(keys){this.ensureConnected();return Promise.all(keys.map(k=>this.get(k)))}async mset(entries){this.ensureConnected();for(const entry of entries){this.validateSetOptions(entry.options)}await Promise.all(entries.map(e=>this.doSet(e.key,e.value,e.options)))}async mdelete(keys){this.ensureConnected();const results=await Promise.all(keys.map(k=>this.delete(k)));return results.filter(Boolean).length}async count(pattern="*"){const matchedKeys=await this.keys(pattern);return matchedKeys.length}async deleteIfEquals(_key,_expectedValue){throw new StorageNotSupportedError("deleteIfEquals",this.backendName,"Use the memory, Redis, Upstash, Vercel KV or SQLite adapter for an atomic compare-and-delete.")}async expireIfEquals(_key,_expectedValue,_ttlSeconds){throw new StorageNotSupportedError("expireIfEquals",this.backendName,"Use the memory, Redis, Upstash, Vercel KV or SQLite adapter for an atomic compare-and-expire.")}async setIfEquals(_key,_expectedValue,_value){throw new StorageNotSupportedError("setIfEquals",this.backendName,"Use the memory, Redis or SQLite adapter for an atomic compare-and-set.")}supportsPubSub(){return false}async publish(_channel,_message){throw new StorageNotSupportedError("publish",this.backendName,this.getPubSubSuggestion())}async subscribe(_channel,_handler){throw new StorageNotSupportedError("subscribe",this.backendName,this.getPubSubSuggestion())}getPubSubSuggestion(){return"Use Redis or Upstash adapter for pub/sub support."}validateSetOptions(options){if(!options)return;validateOptionalTTL(options.ttlSeconds);if(options.ifNotExists&&options.ifExists){throw new Error("ifNotExists and ifExists are mutually exclusive")}}}}});var import_event_emitter,DEFAULT_SWEEP_INTERVAL_SECONDS,MAX_TIMEOUT_MS,MemoryStorageAdapter;var init_memory=__esm({"libs/utils/src/storage/adapters/memory.ts"(){"use strict";import_event_emitter=require("#event-emitter");init_errors();init_pattern();init_ttl();init_base();DEFAULT_SWEEP_INTERVAL_SECONDS=60;MAX_TIMEOUT_MS=2147483647;MemoryStorageAdapter=class extends BaseStorageAdapter{backendName="memory";store=new Map;emitter=new import_event_emitter.EventEmitter;sweepInterval;options;accessOrder=[];constructor(options={}){super();this.options={enableSweeper:options.enableSweeper??true,sweepIntervalSeconds:options.sweepIntervalSeconds??DEFAULT_SWEEP_INTERVAL_SECONDS,maxEntries:options.maxEntries??0};this.emitter.setMaxListeners(1e3)}async connect(){if(this.connected)return;this.connected=true;if(this.options.enableSweeper&&this.options.sweepIntervalSeconds>0){this.startSweeper()}}async disconnect(){if(!this.connected)return;this.stopSweeper();this.clearAllTimeouts();this.store.clear();this.accessOrder=[];this.emitter.removeAllListeners();this.connected=false}async ping(){return this.connected}async get(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return null;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return null}this.touchLRU(key);return entry.value}async doSet(key,value,options){const existingEntry=this.store.get(key);const exists=existingEntry!==void 0&&!isExpired(existingEntry.expiresAt);if(options?.ifNotExists&&exists){return}if(options?.ifExists&&!exists){return}this.clearEntryTimeout(key);const entry={value};if(options?.ttlSeconds){entry.expiresAt=ttlToExpiresAt(options.ttlSeconds);const ttlMs=options.ttlSeconds*1e3;if(ttlMs<MAX_TIMEOUT_MS){entry.timeout=setTimeout(()=>{this.deleteEntry(key)},ttlMs);if(entry.timeout.unref){entry.timeout.unref()}}}if(this.options.maxEntries>0&&!this.store.has(key)){while(this.store.size>=this.options.maxEntries){this.evictOldest()}}this.store.set(key,entry);this.touchLRU(key)}async delete(key){this.ensureConnected();return this.deleteEntry(key)}async deleteIfEquals(key,expectedValue){this.ensureConnected();const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)||entry.value!==expectedValue)return false;return this.deleteEntry(key)}async expireIfEquals(key,expectedValue,ttlSeconds){this.ensureConnected();const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)||entry.value!==expectedValue)return false;return this.expire(key,ttlSeconds)}async setIfEquals(key,expectedValue,value){this.ensureConnected();const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)||entry.value!==expectedValue)return false;await this.doSet(key,value);return true}async exists(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return false;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return false}return true}async expire(key,ttlSeconds){this.ensureConnected();validateTTL(ttlSeconds);const entry=this.store.get(key);if(!entry||isExpired(entry.expiresAt)){return false}this.clearEntryTimeout(key);entry.expiresAt=ttlToExpiresAt(ttlSeconds);const ttlMs=ttlSeconds*1e3;if(ttlMs<MAX_TIMEOUT_MS){entry.timeout=setTimeout(()=>{this.deleteEntry(key)},ttlMs);if(entry.timeout.unref){entry.timeout.unref()}}return true}async ttl(key){this.ensureConnected();const entry=this.store.get(key);if(!entry)return null;if(isExpired(entry.expiresAt)){this.deleteEntry(key);return null}if(entry.expiresAt===void 0){return-1}return expiresAtToTTL(entry.expiresAt)}async keys(pattern="*"){this.ensureConnected();const regex=globToRegex(pattern);const result=[];for(const[key,entry]of this.store){if(isExpired(entry.expiresAt)){this.deleteEntry(key);continue}if(regex.test(key)){result.push(key)}}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const entry=this.store.get(key);let currentValue=0;if(entry&&!isExpired(entry.expiresAt)){const parsed=parseInt(entry.value,10);if(isNaN(parsed)){throw new StorageOperationError("incrBy",key,"Value is not an integer")}currentValue=parsed}const newValue=currentValue+amount;const newEntry={value:String(newValue)};if(entry?.expiresAt&&!isExpired(entry.expiresAt)){newEntry.expiresAt=entry.expiresAt;const remainingMs=entry.expiresAt-Date.now();if(remainingMs>0&&remainingMs<MAX_TIMEOUT_MS){this.clearEntryTimeout(key);newEntry.timeout=setTimeout(()=>{this.deleteEntry(key)},remainingMs);if(newEntry.timeout.unref){newEntry.timeout.unref()}}}this.store.set(key,newEntry);this.touchLRU(key);return newValue}supportsPubSub(){return true}async publish(channel,message){this.ensureConnected();return this.emitter.listenerCount(channel)>0?(this.emitter.emit(channel,message,channel),this.emitter.listenerCount(channel)):0}async subscribe(channel,handler){this.ensureConnected();const wrappedHandler=(message,ch)=>{handler(message,ch)};this.emitter.on(channel,wrappedHandler);return async()=>{this.emitter.off(channel,wrappedHandler)}}deleteEntry(key){const entry=this.store.get(key);if(!entry)return false;this.clearEntryTimeout(key);this.store.delete(key);this.removeLRU(key);return true}clearEntryTimeout(key){const entry=this.store.get(key);if(entry?.timeout){clearTimeout(entry.timeout);entry.timeout=void 0}}clearAllTimeouts(){for(const[key]of this.store){this.clearEntryTimeout(key)}}touchLRU(key){if(this.options.maxEntries<=0)return;const idx=this.accessOrder.indexOf(key);if(idx!==-1){this.accessOrder.splice(idx,1)}this.accessOrder.push(key)}removeLRU(key){if(this.options.maxEntries<=0)return;const idx=this.accessOrder.indexOf(key);if(idx!==-1){this.accessOrder.splice(idx,1)}}evictOldest(){if(this.accessOrder.length===0)return;const oldestKey=this.accessOrder.shift();if(oldestKey){this.deleteEntry(oldestKey)}}startSweeper(){this.sweepInterval=setInterval(()=>{this.sweep()},this.options.sweepIntervalSeconds*1e3);if(this.sweepInterval.unref){this.sweepInterval.unref()}}stopSweeper(){if(this.sweepInterval){clearInterval(this.sweepInterval);this.sweepInterval=void 0}}sweep(){const now=Date.now();for(const[key,entry]of this.store){if(entry.expiresAt&&now>=entry.expiresAt){this.deleteEntry(key)}}}getStats(){return{size:this.store.size,maxEntries:this.options.maxEntries,sweeperActive:this.sweepInterval!==void 0}}}}});var filesystem_exports={};__export(filesystem_exports,{FileSystemStorageAdapter:()=>FileSystemStorageAdapter});var FileSystemStorageAdapter;var init_filesystem=__esm({"libs/utils/src/storage/adapters/filesystem.ts"(){"use strict";init_base();init_errors();init_pattern();init_fs2();init_crypto();FileSystemStorageAdapter=class extends BaseStorageAdapter{backendName="filesystem";baseDir;extension;dirMode;fileMode;constructor(options){super();this.baseDir=options.baseDir;this.extension=options.extension??".json";this.dirMode=options.dirMode??448;this.fileMode=options.fileMode??384}async connect(){if(this.connected)return;await ensureDir(this.baseDir);try{await mkdir(this.baseDir,{recursive:true,mode:this.dirMode})}catch{}this.connected=true}async disconnect(){if(!this.connected)return;this.connected=false}async ping(){if(!this.connected)return false;try{return await fileExists(this.baseDir)}catch{return false}}async get(key){this.ensureConnected();const filePath=this.keyToPath(key);try{const entry=await readJSON(filePath);if(!entry)return null;if(entry.expiresAt&&Date.now()>=entry.expiresAt){await this.deleteFile(filePath);return null}return entry.value}catch(e){const error=e;if(error.code==="ENOENT"){return null}throw e}}async doSet(key,value,options){const filePath=this.keyToPath(key);const existingEntry=await this.readEntry(filePath);const exists=existingEntry!==null&&!this.isExpired(existingEntry);if(options?.ifNotExists&&exists){return}if(options?.ifExists&&!exists){return}const entry={value};if(options?.ttlSeconds){entry.expiresAt=Date.now()+options.ttlSeconds*1e3}await this.atomicWrite(filePath,entry)}async delete(key){this.ensureConnected();const filePath=this.keyToPath(key);return this.deleteFile(filePath)}async exists(key){this.ensureConnected();const filePath=this.keyToPath(key);try{const entry=await this.readEntry(filePath);if(!entry)return false;if(this.isExpired(entry)){await this.deleteFile(filePath);return false}return true}catch{return false}}async expire(key,ttlSeconds){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(!entry||this.isExpired(entry)){return false}entry.expiresAt=Date.now()+ttlSeconds*1e3;await this.atomicWrite(filePath,entry);return true}async ttl(key){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(!entry)return null;if(this.isExpired(entry)){await this.deleteFile(filePath);return null}if(entry.expiresAt===void 0){return-1}return Math.max(0,Math.ceil((entry.expiresAt-Date.now())/1e3))}async keys(pattern="*"){this.ensureConnected();const regex=globToRegex(pattern);const result=[];try{const files=await readdir(this.baseDir);for(const file of files){if(!file.endsWith(this.extension))continue;const key=this.pathToKey(file);if(!regex.test(key))continue;const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);if(entry&&!this.isExpired(entry)){result.push(key)}else if(entry&&this.isExpired(entry)){await this.deleteFile(filePath)}}}catch(e){const error=e;if(error.code==="ENOENT"){return[]}throw e}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const filePath=this.keyToPath(key);const entry=await this.readEntry(filePath);let currentValue=0;if(entry&&!this.isExpired(entry)){const parsed=parseInt(entry.value,10);if(isNaN(parsed)){throw new StorageOperationError("incrBy",key,"Value is not an integer")}currentValue=parsed}const newValue=currentValue+amount;const newEntry={value:String(newValue)};if(entry?.expiresAt&&!this.isExpired(entry)){newEntry.expiresAt=entry.expiresAt}await this.atomicWrite(filePath,newEntry);return newValue}keyToPath(key){const safeKey=this.encodeKey(key);return`${this.baseDir}/${safeKey}${this.extension}`}pathToKey(filename){const safeKey=filename.slice(0,-this.extension.length);return this.decodeKey(safeKey)}encodeKey(key){return encodeURIComponent(key).replace(/\./g,"%2E")}decodeKey(encoded){return decodeURIComponent(encoded)}async readEntry(filePath){try{return await readJSON(filePath)}catch{return null}}isExpired(entry){return entry.expiresAt!==void 0&&Date.now()>=entry.expiresAt}async deleteFile(filePath){try{await unlink(filePath);return true}catch(e){const error=e;if(error.code==="ENOENT"){return false}throw e}}async atomicWrite(filePath,entry){const tempSuffix=bytesToHex(randomBytes(8));const tempPath=`${filePath}.${tempSuffix}.tmp`;try{const content=JSON.stringify(entry,null,2);await writeFile(tempPath,content,{mode:this.fileMode});await rename(tempPath,filePath)}catch(e){try{await unlink(tempPath)}catch{}throw e}}getPubSubSuggestion(){return"FileSystem adapter does not support pub/sub. Use Redis or Memory adapter for pub/sub support."}}}});var indexeddb_exports={};__export(indexeddb_exports,{IndexedDBStorageAdapter:()=>IndexedDBStorageAdapter});var IndexedDBStorageAdapter;var init_indexeddb=__esm({"libs/utils/src/storage/adapters/indexeddb.ts"(){"use strict";init_base();init_pattern();IndexedDBStorageAdapter=class extends BaseStorageAdapter{backendName="indexeddb";dbName;storeName;prefix;db=null;constructor(options){super();this.dbName=options?.dbName??"frontmcp";this.storeName=options?.storeName??"kv";this.prefix=options?.prefix??"frontmcp:"}assertAvailable(){if(typeof indexedDB==="undefined"){throw new Error("IndexedDB is not available in this environment")}}key(k){return`${this.prefix}${k}`}stripPrefix(fullKey){return fullKey.slice(this.prefix.length)}async connect(){this.assertAvailable();if(this.db){this.connected=true;return}this.db=await new Promise((resolve2,reject)=>{const request=indexedDB.open(this.dbName,1);request.onupgradeneeded=()=>{const db=request.result;if(!db.objectStoreNames.contains(this.storeName)){db.createObjectStore(this.storeName,{keyPath:"k"})}};request.onsuccess=()=>resolve2(request.result);request.onerror=()=>reject(request.error)});this.connected=true}async disconnect(){if(this.db){this.db.close();this.db=null}this.connected=false}async ping(){return this.db!==null&&this.connected}getStore(mode){if(!this.db){throw new Error("IndexedDB adapter is not connected. Call connect() first.")}const tx=this.db.transaction(this.storeName,mode);return tx.objectStore(this.storeName)}idbRequest(request){return new Promise((resolve2,reject)=>{request.onsuccess=()=>resolve2(request.result);request.onerror=()=>reject(request.error)})}idbTransaction(store){return new Promise((resolve2,reject)=>{const tx=store.transaction;tx.oncomplete=()=>resolve2();tx.onerror=()=>reject(tx.error)})}async get(key){this.ensureConnected();const store=this.getStore("readonly");const entry=await this.idbRequest(store.get(this.key(key)));if(!entry)return null;if(entry.e&&entry.e<Date.now()){const writeStore=this.getStore("readwrite");writeStore.delete(this.key(key));return null}return entry.v}async doSet(key,value,options){if(options?.ifNotExists){const existing=await this.get(key);if(existing!==null)return}if(options?.ifExists){const existing=await this.get(key);if(existing===null)return}const entry={k:this.key(key),v:value};if(options?.ttlSeconds){entry.e=Date.now()+options.ttlSeconds*1e3}const store=this.getStore("readwrite");await this.idbRequest(store.put(entry))}async delete(key){this.ensureConnected();const existing=await this.get(key);if(existing===null)return false;const store=this.getStore("readwrite");await this.idbRequest(store.delete(this.key(key)));return true}async exists(key){return await this.get(key)!==null}async expire(key,ttlSeconds){this.ensureConnected();const value=await this.get(key);if(value===null)return false;await this.doSet(key,value,{ttlSeconds});return true}async ttl(key){this.ensureConnected();const store=this.getStore("readonly");const entry=await this.idbRequest(store.get(this.key(key)));if(!entry)return null;if(entry.e){const remaining=Math.ceil((entry.e-Date.now())/1e3);return remaining>0?remaining:null}return-1}async keys(pattern){this.ensureConnected();const store=this.getStore("readonly");const allKeys=await this.idbRequest(store.getAllKeys());const now=Date.now();const result=[];for(const fullKey of allKeys){const keyStr=String(fullKey);if(!keyStr.startsWith(this.prefix))continue;const key=this.stripPrefix(keyStr);if(pattern&&pattern!=="*"&&!this.matchPattern(key,pattern))continue;const entry=await this.idbRequest(store.get(keyStr));if(entry&&(!entry.e||entry.e>=now)){result.push(key)}}return result}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){this.ensureConnected();const current=await this.get(key);const value=current!==null?parseInt(current,10)+amount:amount;if(Number.isNaN(value)){throw new Error(`Value at "${key}" is not an integer`)}await this.doSet(key,String(value));return value}matchPattern(key,pattern){return matchesPattern(key,pattern)}}}});var localstorage_exports={};__export(localstorage_exports,{LocalStorageAdapter:()=>LocalStorageAdapter});var LocalStorageAdapter;var init_localstorage=__esm({"libs/utils/src/storage/adapters/localstorage.ts"(){"use strict";init_base();init_crypto();init_pattern();LocalStorageAdapter=class extends BaseStorageAdapter{backendName="localstorage";prefix;encryptionKey;allowPlaintext;encoder=new TextEncoder;decoder=new TextDecoder;constructor(options){super();this.prefix=options?.prefix??"frontmcp:";this.allowPlaintext=options?.allowPlaintext??true;if(options?.encryptionKey){if(options.encryptionKey.length!==32){throw new Error(`encryptionKey must be exactly 32 bytes, got ${options.encryptionKey.length}`)}this.encryptionKey=options.encryptionKey}}assertAvailable(){if(typeof localStorage==="undefined"){throw new Error("localStorage is not available in this environment")}}key(k){return`${this.prefix}${k}`}stripPrefix(fullKey){return fullKey.slice(this.prefix.length)}async connect(){this.assertAvailable();const probeKey=this.key("__probe__");try{localStorage.setItem(probeKey,"1");const read=localStorage.getItem(probeKey);if(read!=="1"){throw new Error("localStorage probe: read-back mismatch")}}catch(err){throw new Error(`localStorage is not writable: ${err instanceof Error?err.message:String(err)}`)}finally{try{localStorage.removeItem(probeKey)}catch{}}this.connected=true}async disconnect(){this.connected=false}async ping(){const probeKey=this.key("__probe__");try{this.assertAvailable();localStorage.setItem(probeKey,"1");return localStorage.getItem(probeKey)==="1"}catch{return false}finally{try{localStorage.removeItem(probeKey)}catch{}}}async get(key){const raw=localStorage.getItem(this.key(key));if(raw===null)return null;try{const entry=JSON.parse(raw);if(entry.e&&entry.e<Date.now()){localStorage.removeItem(this.key(key));return null}if(entry._enc){if(!this.encryptionKey)return null;const iv=base64urlDecode(entry._enc.iv);const tag=base64urlDecode(entry._enc.tag);const ciphertext=base64urlDecode(entry._enc.data);const plainBytes=decryptAesGcm(this.encryptionKey,ciphertext,iv,tag);return this.decoder.decode(plainBytes)}return entry.v}catch{return null}}async set(key,value,options){if(options?.ifNotExists){const existing=await this.get(key);if(existing!==null)return}if(options?.ifExists){const existing=await this.get(key);if(existing===null)return}await this.doSet(key,value,options)}async doSet(key,value,options){const entry={v:""};if(options?.ttlSeconds){entry.e=Date.now()+options.ttlSeconds*1e3}if(this.encryptionKey){const iv=randomBytes(12);const plainBytes=this.encoder.encode(value);const{ciphertext,tag}=encryptAesGcm(this.encryptionKey,plainBytes,iv);entry._enc={alg:"A256GCM",iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}else{if(!this.allowPlaintext){throw new Error("Plaintext storage is disabled. Provide an encryptionKey or set allowPlaintext: true.")}entry.v=value}localStorage.setItem(this.key(key),JSON.stringify(entry))}async delete(key){const existed=await this.get(key)!==null;localStorage.removeItem(this.key(key));return existed}async exists(key){return await this.get(key)!==null}async mget(keys){return Promise.all(keys.map(k=>this.get(k)))}async mset(entries){for(const entry of entries){await this.set(entry.key,entry.value,entry.options)}}async mdelete(keys){let count=0;for(const key of keys){if(await this.delete(key))count++}return count}async expire(key,ttlSeconds){const value=await this.get(key);if(value===null)return false;await this.set(key,value,{ttlSeconds});return true}async ttl(key){const raw=localStorage.getItem(this.key(key));if(raw===null)return null;try{const entry=JSON.parse(raw);if(!entry.e)return-1;const remaining=Math.ceil((entry.e-Date.now())/1e3);return remaining>0?remaining:null}catch{return null}}async keys(pattern){const result=[];const candidates=[];for(let i=0;i<localStorage.length;i++){const fullKey=localStorage.key(i);if(fullKey&&fullKey.startsWith(this.prefix)){candidates.push(this.stripPrefix(fullKey))}}for(const key of candidates){if(!pattern||pattern==="*"||this.matchPattern(key,pattern)){if(await this.get(key)!==null){result.push(key)}}}return result}async count(pattern){return(await this.keys(pattern)).length}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(key,amount){if(!Number.isInteger(amount)){throw new Error(`amount must be an integer, got ${amount}`)}const current=await this.get(key);if(current!==null&&!/^-?\d+$/.test(current)){throw new Error(`Value at "${key}" is not an integer`)}const value=current!==null?parseInt(current,10)+amount:amount;await this.set(key,String(value));return value}async publish(){throw new Error("LocalStorage adapter does not support pub/sub")}async subscribe(_channel,_handler){throw new Error("LocalStorage adapter does not support pub/sub")}supportsPubSub(){return false}matchPattern(key,pattern){return matchesPattern(key,pattern)}}}});function getOrCreateInstallationSalt(){if(typeof localStorage==="undefined"){throw new Error("localStorage unavailable: cannot derive installation salt")}const existing=localStorage.getItem(INSTALL_SALT_KEY);if(existing){try{return base64urlDecode(existing)}catch{}}const legacy=localStorage.getItem(LEGACY_SALT_KEY);if(legacy){try{const salt2=base64urlDecode(legacy);localStorage.setItem(INSTALL_SALT_KEY,base64urlEncode(salt2));localStorage.removeItem(LEGACY_SALT_KEY);return salt2}catch{localStorage.removeItem(LEGACY_SALT_KEY)}}const salt=randomBytes(32);localStorage.setItem(INSTALL_SALT_KEY,base64urlEncode(salt));return salt}function deriveLocalStorageKey(userKey){if(userKey)return userKey;const salt=getOrCreateInstallationSalt();const origin=typeof location!=="undefined"?location.origin:"unknown";const info=new TextEncoder().encode(origin);return import_crypto_provider.cryptoProvider.hkdfSha256(LS_HKDF_IKM,salt,info,32)}async function createKeyPersistence(options){const type=options?.type??"auto";const baseDir=options?.baseDir??DEFAULT_BASE_DIR;let adapter;if(type==="memory"){adapter=new MemoryStorageAdapter}else if(type==="filesystem"){const{FileSystemStorageAdapter:FileSystemStorageAdapter2}=await Promise.resolve().then(()=>(init_filesystem(),filesystem_exports));adapter=new FileSystemStorageAdapter2({baseDir})}else if(type==="indexeddb"){const{IndexedDBStorageAdapter:IndexedDBStorageAdapter2}=await Promise.resolve().then(()=>(init_indexeddb(),indexeddb_exports));adapter=new IndexedDBStorageAdapter2({prefix:"frontmcp:keys:"})}else if(type==="localstorage"){const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)})}else{let connected=false;if(isNode()){try{const{FileSystemStorageAdapter:FileSystemStorageAdapter2}=await Promise.resolve().then(()=>(init_filesystem(),filesystem_exports));adapter=new FileSystemStorageAdapter2({baseDir});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else if(isBrowser()&&typeof indexedDB!=="undefined"){try{const{IndexedDBStorageAdapter:IndexedDBStorageAdapter2}=await Promise.resolve().then(()=>(init_indexeddb(),indexeddb_exports));adapter=new IndexedDBStorageAdapter2({prefix:"frontmcp:keys:"});await adapter.connect();connected=true}catch{if(typeof localStorage!=="undefined"){try{const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else{adapter=new MemoryStorageAdapter}}}else if(isBrowser()&&typeof localStorage!=="undefined"){try{const{LocalStorageAdapter:LocalStorageAdapter2}=await Promise.resolve().then(()=>(init_localstorage(),localstorage_exports));adapter=new LocalStorageAdapter2({prefix:"frontmcp:keys:",encryptionKey:deriveLocalStorageKey(options?.encryptionKey)});await adapter.connect();connected=true}catch{adapter=new MemoryStorageAdapter}}else{adapter=new MemoryStorageAdapter}if(!connected){await adapter.connect()}}if(type!=="auto"){await adapter.connect()}return new KeyPersistence({storage:adapter,throwOnInvalid:options?.throwOnInvalid??false,enableCache:options?.enableCache??true})}function createKeyPersistenceWithStorage(storage,options){return new KeyPersistence({storage,throwOnInvalid:options?.throwOnInvalid??false,enableCache:options?.enableCache??true})}var import_crypto_provider,DEFAULT_BASE_DIR,LS_HKDF_IKM,INSTALL_SALT_KEY,LEGACY_SALT_KEY;var init_factory=__esm({"libs/utils/src/crypto/key-persistence/factory.ts"(){"use strict";init_runtime();import_crypto_provider=require("#crypto-provider");init_memory();init_key_persistence();init_crypto();DEFAULT_BASE_DIR=".frontmcp/keys";LS_HKDF_IKM=new TextEncoder().encode("frontmcp:localstorage:v1");INSTALL_SALT_KEY="__frontmcp_internal__:install_salt";LEGACY_SALT_KEY="frontmcp:_install_salt"}});var init_key_persistence2=__esm({"libs/utils/src/crypto/key-persistence/index.ts"(){"use strict";init_schemas();init_key_persistence();init_factory()}});function getCrypto(){return platformCrypto.cryptoProvider}function rsaVerify2(jwtAlg,data,publicJwk,signature){if(isNode()){return Promise.resolve(platformCrypto.rsaVerify(jwtAlg,data,publicJwk,signature))}return rsaVerifyBrowser(jwtAlg,data,publicJwk,signature)}function rsaSignBase64Url2(jwtAlg,data,privateJwk){if(!isNode()){throw new Error("rsaSignBase64Url is only available in Node.js runtimes")}return platformCrypto.rsaSignBase64Url(jwtAlg,data,privateJwk)}function rsaVerifySync2(jwtAlg,data,publicJwk,signature){if(!isNode()){throw new Error("rsaVerifySync is only available in Node.js runtimes; use the async rsaVerify in browsers")}return platformCrypto.rsaVerifySync(jwtAlg,data,publicJwk,signature)}function pemToPublicJwk2(pem){if(!isNode()){throw new Error("pemToPublicJwk is only available in Node.js runtimes")}return platformCrypto.pemToPublicJwk(pem)}function generateRsaKeyPair2(modulusLength,alg){if(!isNode()){throw new Error("generateRsaKeyPair is only available in Node.js runtimes")}return platformCrypto.generateRsaKeyPair(modulusLength,alg)}function randomUUID(){return getCrypto().randomUUID()}function randomBytes(length){if(!Number.isInteger(length)||length<=0){throw new Error(`randomBytes length must be a positive integer, got ${length}`)}return getCrypto().randomBytes(length)}function sha256(data){return getCrypto().sha256(data)}function sha256Hex(data){return getCrypto().sha256Hex(data)}function hmacSha256(key,data){return getCrypto().hmacSha256(key,data)}function hkdfSha256(ikm,salt,info,length){if(!Number.isInteger(length)||length<=0){throw new Error(`HKDF length must be a positive integer, got ${length}`)}if(length>HKDF_SHA256_MAX_LENGTH){throw new Error(`HKDF-SHA256 length cannot exceed ${HKDF_SHA256_MAX_LENGTH} bytes, got ${length}`)}return getCrypto().hkdfSha256(ikm,salt,info,length)}function encryptAesGcm(key,plaintext,iv){if(key.length!==32){throw new Error(`AES-256-GCM requires a 32-byte key, got ${key.length} bytes`)}if(iv.length!==12){throw new Error(`AES-GCM requires a 12-byte IV, got ${iv.length} bytes`)}return getCrypto().encryptAesGcm(key,plaintext,iv)}function decryptAesGcm(key,ciphertext,iv,tag){if(key.length!==32){throw new Error(`AES-256-GCM requires a 32-byte key, got ${key.length} bytes`)}if(iv.length!==12){throw new Error(`AES-GCM requires a 12-byte IV, got ${iv.length} bytes`)}if(tag.length!==16){throw new Error(`AES-GCM requires a 16-byte authentication tag, got ${tag.length} bytes`)}return getCrypto().decryptAesGcm(key,ciphertext,iv,tag)}function timingSafeEqual(a,b){if(a.length!==b.length){throw new Error(`timingSafeEqual requires equal-length arrays, got ${a.length} and ${b.length} bytes`)}return getCrypto().timingSafeEqual(a,b)}function bytesToHex(data){return Array.from(data).map(b=>b.toString(16).padStart(2,"0")).join("")}function base64urlEncode(data){let base64;if(typeof Buffer!=="undefined"){base64=Buffer.from(data).toString("base64")}else{const binString=Array.from(data,byte=>String.fromCodePoint(byte)).join("");base64=btoa(binString)}const result=base64.replace(/\+/g,"-").replace(/\//g,"_");let end=result.length;while(end>0&&result[end-1]==="="){end--}return result.slice(0,end)}function base64urlDecode(data){let base64=data.replace(/-/g,"+").replace(/_/g,"/");const pad=base64.length%4;if(pad){base64+="=".repeat(4-pad)}if(typeof Buffer!=="undefined"){return new Uint8Array(Buffer.from(base64,"base64"))}else{const binString=atob(base64);return Uint8Array.from(binString,c=>c.codePointAt(0)??0)}}function base64Encode(data){if(typeof Buffer!=="undefined"){return Buffer.from(data).toString("base64")}else{const binString=Array.from(data,byte=>String.fromCodePoint(byte)).join("");return btoa(binString)}}function base64Decode(data){if(typeof Buffer!=="undefined"){return new Uint8Array(Buffer.from(data,"base64"))}else{const binString=atob(data);return Uint8Array.from(binString,c=>c.codePointAt(0)??0)}}function sha256Base64url(data){return base64urlEncode(sha256(data))}var platformCrypto,HKDF_SHA256_MAX_LENGTH;var init_crypto=__esm({"libs/utils/src/crypto/index.ts"(){"use strict";platformCrypto=__toESM(require("#crypto-provider"));init_runtime();init_web_rsa();init_jwt_alg();init_runtime();init_encrypted_blob();init_pkce2();init_secret_persistence();init_hmac_signing();init_key_persistence2();HKDF_SHA256_MAX_LENGTH=255*32}});function attachRedisErrorListener(client,options={}){const label=options.label??"redis";const intervalMs=options.intervalMs??DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;let lastLoggedAt=0;let suppressed=0;const listener=error=>{const now=Date.now();if(lastLoggedAt!==0&&now-lastLoggedAt<intervalMs){suppressed++;return}const extra=suppressed>0?` (${suppressed} similar error(s) suppressed)`:"";suppressed=0;lastLoggedAt=now;const message=`[${label}] Redis connection error: ${error?.message??String(error)}${extra}`;if(options.logger){options.logger.warn(message)}else{console.warn(message)}};client.on("error",listener);return()=>{client.removeListener("error",listener)}}var DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS;var init_redis_error_listener=__esm({"libs/utils/src/storage/redis-error-listener.ts"(){"use strict";DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS=3e4}});function decodeOrRaw(encoded){try{return decodeURIComponent(encoded)}catch{return encoded}}function integerOrUndefined(text){const value=Number.parseInt(text??"",10);return Number.isNaN(value)?void 0:value}function readRedisUrl(rawUrl){let url;try{url=new URL(rawUrl)}catch{return void 0}if(url.protocol!=="redis:"&&url.protocol!=="rediss:")return void 0;const query=Object.fromEntries(url.searchParams);const{host,port,username,password,db,...otherOptions}=query;const queryOptions={};for(const[name,value=""]of Object.entries(otherOptions)){queryOptions[name]=name==="family"?integerOrUndefined(value)??value:value}return{host:url.hostname.replace(/^\[(.*)\]$/,"$1")||host,port:integerOrUndefined(url.port||port),username:decodeOrRaw(url.username)||username||void 0,password:decodeOrRaw(url.password)||password||void 0,db:integerOrUndefined(url.pathname.replace(/^\/+/,"")||db),tls:url.protocol==="rediss:",queryOptions}}function mergeRedisUrlFields(rawUrl,fields){const connection=readRedisUrl(rawUrl);if(!connection)return void 0;const fillIns={};const conflicts=[];if(fields.host!==void 0&&fields.host!==connection.host)conflicts.push("host");if(fields.port!==void 0){if(connection.port===void 0)fillIns.port=fields.port;else if(fields.port!==connection.port)conflicts.push("port")}if(fields.password!==void 0){if(connection.password===void 0)fillIns.password=fields.password;else if(fields.password!==connection.password)conflicts.push("password")}if(fields.db!==void 0){if(connection.db===void 0)fillIns.db=fields.db;else if(fields.db!==connection.db)conflicts.push("db")}if(fields.tls===true&&!connection.tls)fillIns.tls=true;if(fields.tls===false&&connection.tls)conflicts.push("tls");return{connection,fillIns,conflicts}}function describeRedisUrlConflicts(conflicts){return`redis ${conflicts.join(", ")} contradict${conflicts.length===1?"s":""} redis.url. Fields beside a url only fill in what the URL leaves out (port, password, db, tls); put the value in the URL or drop the field.`}var init_redis_url=__esm({"libs/utils/src/storage/redis-url.ts"(){"use strict"}});var init_utils=__esm({"libs/utils/src/storage/utils/index.ts"(){"use strict";init_ttl()}});var COMPARE_AND_DELETE_SCRIPT,COMPARE_AND_EXPIRE_SCRIPT,COMPARE_AND_SET_SCRIPT;var init_compare_and_delete=__esm({"libs/utils/src/storage/utils/compare-and-delete.ts"(){"use strict";COMPARE_AND_DELETE_SCRIPT=`if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end return 0`;COMPARE_AND_EXPIRE_SCRIPT=`if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('EXPIRE', KEYS[1], ARGV[2]) end return 0`;COMPARE_AND_SET_SCRIPT=`if redis.call('GET', KEYS[1]) == ARGV[1] then redis.call('SET', KEYS[1], ARGV[2]) return 1 end return 0`}});var redis_exports={};__export(redis_exports,{RedisStorageAdapter:()=>RedisStorageAdapter,createRedisClient:()=>createRedisClient});function getRedisClass(){try{return require("ioredis").default||require("ioredis")}catch(error){const msg=error instanceof Error?error.message:String(error);if(msg.includes("Dynamic require")||msg.includes("require is not defined")){throw new Error(`Failed to load ioredis: ${msg}. This typically happens with ESM bundlers (esbuild, Vite). Ensure your bundler externalizes ioredis or use CJS mode.`,{cause:error})}throw new Error("ioredis is required for Redis storage adapter. Install it with: npm install ioredis",{cause:error})}}function resolveUrlOptions(connectionUrl,options){const{url:configUrl,...siblingFields}={url:void 0,...options.config};if(options.url&&configUrl&&configUrl!==options.url){throw new StorageConfigError("redis","redis.url and redis.config.url name different servers; set one of them.")}return urlConnectionOptions(connectionUrl,siblingFields)}function urlConnectionOptions(url,fields){const merge=mergeRedisUrlFields(url,fields);if(!merge)return void 0;if(merge.conflicts.length>0){throw new StorageConfigError("redis",describeRedisUrlConflicts(merge.conflicts))}const{queryOptions,tls,...stated}=merge.connection;return{...queryOptions,...stated,...toFillInOptions(merge.fillIns),...tls?{tls:{}}:{}}}function toFillInOptions({port,password,db,tls}){return{...port!==void 0?{port}:{},...password!==void 0?{password}:{},...db!==void 0?{db}:{},...tls?{tls:{}}:{}}}function createRedisClient(options){const urlOptions=options.url?urlConnectionOptions(options.url,options):void 0;const RedisClass=getRedisClass();const baseOptions={lazyConnect:false,maxRetriesPerRequest:3};let client;if(urlOptions){client=new RedisClass({...baseOptions,...urlOptions})}else if(options.url){client=new RedisClass(options.url,baseOptions)}else{client=new RedisClass({...baseOptions,host:options.host??"localhost",port:options.port??6379,password:options.password,db:options.db??0,tls:options.tls?{}:void 0})}attachRedisErrorListener(client,{label:options.label??"redis",logger:options.logger});return client}var RedisStorageAdapter;var init_redis=__esm({"libs/utils/src/storage/adapters/redis.ts"(){"use strict";init_errors();init_redis_error_listener();init_redis_url();init_utils();init_compare_and_delete();init_base();RedisStorageAdapter=class extends BaseStorageAdapter{backendName="redis";client;subscriber;options;ownsClient;detachErrorListener;connecting;keyPrefix;subscriptionHandlers=new Map;reconnectListeners=new Set;connectionUrl;urlOptions;constructor(options={}){super();const hasClient=options.client!==void 0;const hasConfig=options.config!==void 0||options.url!==void 0;if(hasClient&&hasConfig){throw new StorageConfigError("redis",'Cannot specify both "client" and "config"/"url". Use one or the other.')}if(!hasClient&&!hasConfig){const envUrl=process.env["REDIS_URL"]||process.env["REDIS_HOST"];if(envUrl){options={...options,url:envUrl}}else{throw new StorageConfigError("redis",'Either "client", "config", "url", or REDIS_URL environment variable must be provided.')}}this.options=options;this.ownsClient=!hasClient;this.keyPrefix=options.keyPrefix??"";const configUrl=options.config?.url;this.connectionUrl=options.url??(typeof configUrl==="string"?configUrl:void 0);this.urlOptions=this.connectionUrl?resolveUrlOptions(this.connectionUrl,options):void 0}async connect(){if(this.connected)return;this.connecting??=this.openConnection().finally(()=>{this.connecting=void 0});return this.connecting}async openConnection(){let socketError;const recordSocketError=error=>{socketError=error};let client;try{if(this.options.client){client=this.options.client}else{client=this.newClient();client.on("error",recordSocketError)}await client.ping();this.client=client;this.connected=true;if(this.ownsClient){client.removeListener("error",recordSocketError);this.detachErrorListener=attachRedisErrorListener(client,{label:"RedisStorage"})}}catch(e){if(this.ownsClient&&client){try{client.disconnect()}catch{}}const cause=socketError??(e instanceof Error?e:void 0);throw new StorageConnectionError("Failed to connect to Redis",cause,"redis")}}async disconnect(){if(!this.connected)return;if(this.subscriber){await this.subscriber.quit();this.subscriber=void 0}if(this.ownsClient&&this.client){await this.client.quit()}this.detachErrorListener?.();this.detachErrorListener=void 0;this.client=void 0;this.connected=false;this.subscriptionHandlers.clear()}async ping(){if(!this.client)return false;try{const result=await this.client.ping();return result==="PONG"}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Redis client not connected",void 0,"redis")}return this.client}getConnectedSubscriber(){if(!this.subscriber){throw new StorageConnectionError("Redis subscriber not created",void 0,"redis")}return this.subscriber}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);if(options?.ttlSeconds){if(options.ifNotExists){await client.set(prefixedKey,value,"EX",options.ttlSeconds,"NX")}else if(options.ifExists){await client.set(prefixedKey,value,"EX",options.ttlSeconds,"XX")}else{await client.set(prefixedKey,value,"EX",options.ttlSeconds)}}else if(options?.ifNotExists){await client.set(prefixedKey,value,"NX")}else if(options?.ifExists){await client.set(prefixedKey,value,"XX")}else{await client.set(prefixedKey,value)}}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,1,this.prefixKey(key),expectedValue);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,1,this.prefixKey(key),expectedValue,String(ttlSeconds));return extended===1}async setIfEquals(key,expectedValue,value){const stored=await this.getConnectedClient().eval(COMPARE_AND_SET_SCRIPT,1,this.prefixKey(key),expectedValue,value);return stored===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mset(entries){if(entries.length===0)return;for(const entry of entries){this.validateSetOptions(entry.options)}const pipeline=this.getConnectedClient().pipeline();for(const entry of entries){const prefixedKey=this.prefixKey(entry.key);if(entry.options?.ttlSeconds){if(entry.options.ifNotExists){pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds,"NX")}else if(entry.options.ifExists){pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds,"XX")}else{pipeline.set(prefixedKey,entry.value,"EX",entry.options.ttlSeconds)}}else if(entry.options?.ifNotExists){pipeline.set(prefixedKey,entry.value,"NX")}else if(entry.options?.ifExists){pipeline.set(prefixedKey,entry.value,"XX")}else{pipeline.set(prefixedKey,entry.value)}}await pipeline.exec()}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);const result=[];let cursor="0";do{const[nextCursor,keys]=await client.scan(cursor,"MATCH",prefixedPattern,"COUNT",100);cursor=nextCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!=="0");return result}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return true}async publish(channel,message){const prefixedChannel=this.prefixKey(channel);return this.getConnectedClient().publish(prefixedChannel,message)}async subscribe(channel,handler){this.ensureConnected();const prefixedChannel=this.prefixKey(channel);if(!this.subscriber){await this.createSubscriber()}const subscriber=this.getConnectedSubscriber();if(!this.subscriptionHandlers.has(prefixedChannel)){this.subscriptionHandlers.set(prefixedChannel,new Set);await subscriber.subscribe(prefixedChannel)}const handlers=this.subscriptionHandlers.get(prefixedChannel);if(handlers){handlers.add(handler)}return async()=>{const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){handlers2.delete(handler);if(handlers2.size===0){this.subscriptionHandlers.delete(prefixedChannel);await this.subscriber?.unsubscribe(prefixedChannel)}}}}onPubSubReconnect(listener){this.reconnectListeners.add(listener);return()=>{this.reconnectListeners.delete(listener)}}buildRedisOptions(){if(this.connectionUrl){return{lazyConnect:false,maxRetriesPerRequest:3,...this.urlOptions}}const config=this.options.config;if(!config||typeof config.url==="string"||config.host===void 0){throw new StorageConfigError("redis","Redis config is required when URL is not provided")}return{host:config.host,port:config.port??6379,password:config.password,db:config.db??0,tls:config.tls?{}:void 0,lazyConnect:false,maxRetriesPerRequest:3}}newClient(){const RedisClass=getRedisClass();if(this.connectionUrl&&!this.urlOptions){return new RedisClass(this.connectionUrl,this.buildRedisOptions())}return new RedisClass(this.buildRedisOptions())}async createSubscriber(){let subscriber;if(this.connectionUrl||this.options.config){subscriber=this.newClient()}else if(this.options.client){subscriber=this.options.client.duplicate()}else{throw new StorageConfigError("redis","Cannot create subscriber without url, config, or client")}attachRedisErrorListener(subscriber,{label:"RedisStorage:subscriber"});subscriber.on("message",(channel,message)=>{const handlers=this.subscriptionHandlers.get(channel);if(handlers){const unprefixedChannel=this.unprefixKey(channel);for(const handler of handlers){try{handler(message,unprefixedChannel)}catch{}}}});let readyBefore=false;subscriber.on("ready",()=>{if(readyBefore){for(const listener of[...this.reconnectListeners]){try{listener()}catch{}}}readyBefore=true});this.subscriber=subscriber}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}getClient(){return this.client}}}});var vercel_kv_exports={};__export(vercel_kv_exports,{VercelKvStorageAdapter:()=>VercelKvStorageAdapter,createVercelKvClient:()=>createVercelKvClient});async function loadVercelKv(){try{const mod=await import("@vercel/kv");const resolved=typeof mod.createClient==="function"?mod:mod.default;if(!resolved||typeof resolved.createClient!=="function")throw new Error("createClient missing");return resolved}catch{throw new Error("@vercel/kv is required for Vercel KV storage adapter. Install it with: npm install @vercel/kv")}}async function createVercelKvClient(connection={}){const url=connection.url??process.env["KV_REST_API_URL"];const token=connection.token??process.env["KV_REST_API_TOKEN"];if(!url||!token){throw new StorageConfigError("vercel-kv","Pass url and token, or set KV_REST_API_URL and KV_REST_API_TOKEN.")}const{createClient}=await loadVercelKv();return createClient({url,token,cache:void 0,automaticDeserialization:false})}var VercelKvStorageAdapter;var init_vercel_kv=__esm({"libs/utils/src/storage/adapters/vercel-kv.ts"(){"use strict";init_errors();init_compare_and_delete();init_ttl();init_base();VercelKvStorageAdapter=class extends BaseStorageAdapter{backendName="vercel-kv";client;options;keyPrefix;constructor(options={}){super();const url=options.url??process.env["KV_REST_API_URL"];const token=options.token??process.env["KV_REST_API_TOKEN"];if(!url||!token){throw new StorageConfigError("vercel-kv","KV_REST_API_URL and KV_REST_API_TOKEN must be provided via options or environment variables.")}this.options={...options,url,token};this.keyPrefix=options.keyPrefix??""}async connect(){if(this.connected)return;try{this.client=await createVercelKvClient({url:this.options.url,token:this.options.token});await this.client.exists("__healthcheck__");this.connected=true}catch(e){throw new StorageConnectionError("Failed to connect to Vercel KV",e instanceof Error?e:void 0,"vercel-kv")}}async disconnect(){this.client=void 0;this.connected=false}async ping(){if(!this.client)return false;try{await this.client.exists("__healthcheck__");return true}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Vercel KV client not connected",void 0,"vercel-kv")}return this.client}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);const setOptions={};if(options?.ttlSeconds){setOptions.ex=options.ttlSeconds}if(options?.ifNotExists){setOptions.nx=true}else if(options?.ifExists){setOptions.xx=true}await client.set(prefixedKey,value,Object.keys(setOptions).length>0?setOptions:void 0)}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,[this.prefixKey(key)],[expectedValue]);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,[this.prefixKey(key)],[expectedValue,String(ttlSeconds)]);return extended===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);try{const result=[];let cursor=0;do{const[nextCursor,keys]=await client.scan(cursor,{match:prefixedPattern,count:100});const parsedCursor=typeof nextCursor==="string"?parseInt(nextCursor,10):nextCursor;cursor=Number.isNaN(parsedCursor)?0:parsedCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!==0);return result}catch{const allKeys=await client.keys(prefixedPattern);return allKeys.map(k=>this.unprefixKey(k))}}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return false}getPubSubSuggestion(){return"Vercel KV is REST-based and does not support pub/sub. Use Upstash adapter for pub/sub support."}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}}}});var upstash_exports={};__export(upstash_exports,{UpstashStorageAdapter:()=>UpstashStorageAdapter});async function loadUpstashRedis(){try{const mod=await import("@upstash/redis");const resolved=typeof mod.Redis==="function"?mod:mod.default;if(!resolved||typeof resolved.Redis!=="function")throw new Error("Redis missing");return resolved}catch{throw new Error("@upstash/redis is required for Upstash storage adapter. Install it with: npm install @upstash/redis")}}var PUBSUB_POLL_INTERVAL_MS,UpstashStorageAdapter;var init_upstash=__esm({"libs/utils/src/storage/adapters/upstash.ts"(){"use strict";init_errors();init_compare_and_delete();init_ttl();init_base();PUBSUB_POLL_INTERVAL_MS=100;UpstashStorageAdapter=class extends BaseStorageAdapter{backendName="upstash";client;options;keyPrefix;pubSubEnabled;subscriptionHandlers=new Map;pollingIntervals=new Map;constructor(options={}){super();const url=options.url??process.env["UPSTASH_REDIS_REST_URL"];const token=options.token??process.env["UPSTASH_REDIS_REST_TOKEN"];if(!url||!token){throw new StorageConfigError("upstash","UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN must be provided via options or environment variables.")}this.options={...options,url,token};this.keyPrefix=options.keyPrefix??"";this.pubSubEnabled=options.enablePubSub??false}async connect(){if(this.connected)return;try{const{Redis}=await loadUpstashRedis();const url=this.options.url;const token=this.options.token;if(!url||!token){throw new StorageConfigError("upstash","URL and token are required")}this.client=new Redis({url,token,automaticDeserialization:false});await this.client.exists("__healthcheck__");this.connected=true}catch(e){throw new StorageConnectionError("Failed to connect to Upstash Redis",e instanceof Error?e:void 0,"upstash")}}async disconnect(){if(!this.connected)return;for(const interval of this.pollingIntervals.values()){clearInterval(interval)}this.pollingIntervals.clear();this.subscriptionHandlers.clear();this.client=void 0;this.connected=false}async ping(){if(!this.client)return false;try{await this.client.exists("__healthcheck__");return true}catch{return false}}getConnectedClient(){this.ensureConnected();if(!this.client){throw new StorageConnectionError("Upstash client not connected",void 0,"upstash")}return this.client}async get(key){return this.getConnectedClient().get(this.prefixKey(key))}async doSet(key,value,options){const client=this.getConnectedClient();const prefixedKey=this.prefixKey(key);const setOptions={};if(options?.ttlSeconds){setOptions.ex=options.ttlSeconds}if(options?.ifNotExists){setOptions.nx=true}else if(options?.ifExists){setOptions.xx=true}await client.set(prefixedKey,value,Object.keys(setOptions).length>0?setOptions:void 0)}async delete(key){const result=await this.getConnectedClient().del(this.prefixKey(key));return result>0}async deleteIfEquals(key,expectedValue){const deleted=await this.getConnectedClient().eval(COMPARE_AND_DELETE_SCRIPT,[this.prefixKey(key)],[expectedValue]);return deleted===1}async expireIfEquals(key,expectedValue,ttlSeconds){validateTTL(ttlSeconds);const extended=await this.getConnectedClient().eval(COMPARE_AND_EXPIRE_SCRIPT,[this.prefixKey(key)],[expectedValue,String(ttlSeconds)]);return extended===1}async exists(key){const result=await this.getConnectedClient().exists(this.prefixKey(key));return result>0}async mget(keys){if(keys.length===0)return[];const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().mget(...prefixedKeys)}async mdelete(keys){if(keys.length===0)return 0;const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.getConnectedClient().del(...prefixedKeys)}async expire(key,ttlSeconds){validateTTL(ttlSeconds);const result=await this.getConnectedClient().expire(this.prefixKey(key),ttlSeconds);return result===1}async ttl(key){const result=await this.getConnectedClient().ttl(this.prefixKey(key));if(result===-2)return null;return result}async keys(pattern="*"){const client=this.getConnectedClient();const prefixedPattern=this.prefixKey(pattern);const result=[];let cursor=0;do{const[nextCursor,keys]=await client.scan(cursor,{match:prefixedPattern,count:100});const parsedCursor=typeof nextCursor==="string"?parseInt(nextCursor,10):nextCursor;cursor=Number.isNaN(parsedCursor)?0:parsedCursor;for(const key of keys){result.push(this.unprefixKey(key))}}while(cursor!==0);return result}async incr(key){return this.getConnectedClient().incr(this.prefixKey(key))}async decr(key){return this.getConnectedClient().decr(this.prefixKey(key))}async incrBy(key,amount){return this.getConnectedClient().incrby(this.prefixKey(key),amount)}supportsPubSub(){return this.pubSubEnabled}async publish(channel,message){if(!this.pubSubEnabled){return super.publish(channel,message)}const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);const listKey=`${prefixedChannel}:queue`;await this.getConnectedClient().lpush(listKey,message);return 1}async subscribe(channel,handler){const client=this.getConnectedClient();if(!this.pubSubEnabled){return super.subscribe(channel,handler)}const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);if(!this.subscriptionHandlers.has(prefixedChannel)){this.subscriptionHandlers.set(prefixedChannel,new Set);const listKey=`${prefixedChannel}:queue`;const interval=setInterval(async()=>{try{const message=await client.rpop(listKey);if(message){const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){for(const h of handlers2){try{h(message,channel)}catch{}}}}}catch{}},PUBSUB_POLL_INTERVAL_MS);if(interval.unref){interval.unref()}this.pollingIntervals.set(prefixedChannel,interval)}const handlers=this.subscriptionHandlers.get(prefixedChannel);if(handlers){handlers.add(handler)}return async()=>{const handlers2=this.subscriptionHandlers.get(prefixedChannel);if(handlers2){handlers2.delete(handler);if(handlers2.size===0){this.subscriptionHandlers.delete(prefixedChannel);const interval=this.pollingIntervals.get(prefixedChannel);if(interval){clearInterval(interval);this.pollingIntervals.delete(prefixedChannel)}}}}}async publishToQueue(channel,message){const prefixedChannel=this.prefixKey(`__pubsub__:${channel}`);const listKey=`${prefixedChannel}:queue`;await this.getConnectedClient().lpush(listKey,message)}getPubSubSuggestion(){return"Enable pub/sub by setting enablePubSub: true in the adapter options."}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){if(this.keyPrefix&&key.startsWith(this.keyPrefix)){return key.slice(this.keyPrefix.length)}return key}}}});var cloudflare_kv_exports={};__export(cloudflare_kv_exports,{CloudflareKvStorageAdapter:()=>CloudflareKvStorageAdapter});function literalPrefix(pattern){const star=pattern.indexOf("*");const q=pattern.indexOf("?");const idx=star===-1?q:q===-1?star:Math.min(star,q);return idx===-1?pattern:pattern.slice(0,idx)}var CF_KV_MIN_TTL_SECONDS,CloudflareKvStorageAdapter;var init_cloudflare_kv=__esm({"libs/utils/src/storage/adapters/cloudflare-kv.ts"(){"use strict";init_errors();init_pattern();init_ttl();init_base();CF_KV_MIN_TTL_SECONDS=60;CloudflareKvStorageAdapter=class extends BaseStorageAdapter{backendName="cloudflare-kv";kv;keyPrefix;constructor(options){super();if(!options?.namespace){throw new Error("CloudflareKvStorageAdapter: a bound KV `namespace` is required (resolve it from the Worker `env`).")}this.kv=options.namespace;this.keyPrefix=options.keyPrefix??""}async connect(){this.connected=true}async disconnect(){this.connected=false}async ping(){if(!this.connected)return false;try{await this.kv.list({limit:1});return true}catch{return false}}async get(key){this.ensureConnected();return this.kv.get(this.prefixKey(key),"text")}async doSet(key,value,options){if(options?.ifNotExists||options?.ifExists){throw new StorageNotSupportedError("conditional set (ifNotExists/ifExists)",this.backendName,"Cloudflare KV has no compare-and-set; use a Durable Object for atomic conditional writes.")}const putOptions=options?.ttlSeconds!==void 0?{expirationTtl:this.toExpirationTtl(options.ttlSeconds,key)}:void 0;await this.kv.put(this.prefixKey(key),value,putOptions)}async delete(key){this.ensureConnected();const existed=await this.exists(key);await this.kv.delete(this.prefixKey(key));return existed}async exists(key){this.ensureConnected();return await this.kv.get(this.prefixKey(key),"text")!==null}async expire(key,ttlSeconds){this.ensureConnected();const ttl=this.toExpirationTtl(ttlSeconds,key);const value=await this.kv.get(this.prefixKey(key),"text");if(value===null)return false;await this.kv.put(this.prefixKey(key),value,{expirationTtl:ttl});return true}async ttl(_key){throw new StorageNotSupportedError("ttl",this.backendName,"Cloudflare KV does not expose a key's remaining TTL. Track expiry alongside the value if you need it.")}async keys(pattern="*"){this.ensureConnected();const prefixedPattern=this.prefixKey(pattern);const listPrefix=literalPrefix(prefixedPattern);const out=[];let cursor;do{const page=await this.kv.list({prefix:listPrefix||void 0,cursor});for(const{name}of page.keys){if(matchesPattern(name,prefixedPattern))out.push(this.unprefixKey(name))}cursor=page.list_complete?void 0:page.cursor}while(cursor);return out}async incr(key){return this.incrBy(key,1)}async decr(key){return this.incrBy(key,-1)}async incrBy(_key,_amount){throw new StorageNotSupportedError("incr/decr/incrBy",this.backendName,"Cloudflare KV has no atomic increment (a get+put is racy under eventual consistency). Use a Durable Object for atomic counters.")}async deleteIfEquals(_key,_expectedValue){throw new StorageNotSupportedError("deleteIfEquals",this.backendName,"Cloudflare KV has no compare-and-set; use a Durable Object for an atomic compare-and-delete.")}getPubSubSuggestion(){return"Cloudflare KV does not support pub/sub. Use a Durable Object (or Queues) for fan-out."}toExpirationTtl(ttlSeconds,key){validateTTL(ttlSeconds);if(ttlSeconds<CF_KV_MIN_TTL_SECONDS){throw new StorageOperationError("set",key,`cloudflare-kv: expirationTtl must be >= ${CF_KV_MIN_TTL_SECONDS}s (Cloudflare KV minimum); got ${ttlSeconds}s.`)}return ttlSeconds}prefixKey(key){return this.keyPrefix+key}unprefixKey(key){return this.keyPrefix&&key.startsWith(this.keyPrefix)?key.slice(this.keyPrefix.length):key}}}});var index_exports={};__export(index_exports,{AsyncContextOverlapError:()=>import_async_context.AsyncContextOverlapError,AsyncLocalStorage:()=>import_async_context.AsyncLocalStorage,BaseStorageAdapter:()=>BaseStorageAdapter,DEFAULT_CHANGE_FEED_COALESCE_MS:()=>DEFAULT_CHANGE_FEED_COALESCE_MS,DEFAULT_CHANGE_FEED_POLL_INTERVAL_MS:()=>DEFAULT_CHANGE_FEED_POLL_INTERVAL_MS,DEFAULT_CODE_VERIFIER_LENGTH:()=>DEFAULT_CODE_VERIFIER_LENGTH,DEFAULT_MAX_INPUT_LENGTH:()=>DEFAULT_MAX_INPUT_LENGTH,DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS:()=>DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS,DEV_BUFFER_FULL:()=>DEV_BUFFER_FULL,DEV_ERROR_MESSAGE:()=>DEV_ERROR_MESSAGE,DEV_RELOAD_DEADLINE:()=>DEV_RELOAD_DEADLINE,DEV_SERVER_UNREACHABLE:()=>DEV_SERVER_UNREACHABLE,EncryptedBlobError:()=>EncryptedBlobError,EncryptedStorageError:()=>EncryptedStorageError,EncryptedTypedStorage:()=>EncryptedTypedStorage,EventEmitter:()=>import_event_emitter2.EventEmitter,FileSystemStorageAdapter:()=>FileSystemStorageAdapter,KeyPersistence:()=>KeyPersistence,MAX_CODE_VERIFIER_LENGTH:()=>MAX_CODE_VERIFIER_LENGTH,MAX_TTL_SECONDS:()=>MAX_TTL_SECONDS,MIN_CODE_VERIFIER_LENGTH:()=>MIN_CODE_VERIFIER_LENGTH,MemoryStorageAdapter:()=>MemoryStorageAdapter,NAMESPACE_SEPARATOR:()=>NAMESPACE_SEPARATOR,NamespacedStorageImpl:()=>NamespacedStorageImpl,OwnedProcessError:()=>OwnedProcessError,PkceError:()=>PkceError,REDOS_THRESHOLDS:()=>import_redos.REDOS_THRESHOLDS,RedisStorageAdapter:()=>RedisStorageAdapter,StorageConfigError:()=>StorageConfigError,StorageConnectionError:()=>StorageConnectionError,StorageError:()=>StorageError,StorageNotConnectedError:()=>StorageNotConnectedError,StorageNotSupportedError:()=>StorageNotSupportedError,StorageOperationError:()=>StorageOperationError,StoragePatternError:()=>StoragePatternError,StorageTTLError:()=>StorageTTLError,TypedStorage:()=>TypedStorage,UpstashStorageAdapter:()=>UpstashStorageAdapter,VercelKvStorageAdapter:()=>VercelKvStorageAdapter,access:()=>access,analyzePattern:()=>analyzePattern,anyKeyDataSchema:()=>anyKeyDataSchema,appendFile:()=>appendFile,assertNode:()=>assertNode,asymmetricAlgSchema:()=>asymmetricAlgSchema,asymmetricKeyDataSchema:()=>asymmetricKeyDataSchema,attachRedisErrorListener:()=>attachRedisErrorListener,awaitOutsideRequest:()=>import_async_context.awaitOutsideRequest,base64Decode:()=>base64Decode,base64Encode:()=>base64Encode,base64urlDecode:()=>base64urlDecode,base64urlEncode:()=>base64urlEncode,basename:()=>import_path2.basename,brandClass:()=>brandClass,buildPrefix:()=>buildPrefix,buildSetCookie:()=>buildSetCookie,bytesToHex:()=>bytesToHex,checkEntryAvailability:()=>import_runtime_context.checkEntryAvailability,chmod:()=>chmod,classifyIpAddress:()=>classifyIpAddress,clearCachedSecret:()=>clearCachedSecret,collapseChar:()=>collapseChar,collapseWhitespace:()=>collapseWhitespace,copyFile:()=>copyFile,cp:()=>cp,createBridgeStateMachine:()=>createBridgeStateMachine,createChangeFeed:()=>createChangeFeed,createHttpUpstream:()=>createHttpUpstream,createKeyPersistence:()=>createKeyPersistence,createKeyPersistenceWithStorage:()=>createKeyPersistenceWithStorage,createMemoryStorage:()=>createMemoryStorage,createNamespacedStorage:()=>createNamespacedStorage,createPipeUpstream:()=>createPipeUpstream,createRedisClient:()=>createRedisClient,createRootStorage:()=>createRootStorage,createSafeRegExp:()=>createSafeRegExp,createSecretData:()=>createSecretData,createStdioFramer:()=>createStdioFramer,createStorage:()=>createStorage,createVercelKvClient:()=>createVercelKvClient,decryptAesGcm:()=>decryptAesGcm,decryptValue:()=>decryptValue,deleteSecret:()=>deleteSecret,describeRedisUrlConflicts:()=>describeRedisUrlConflicts,deserializeAndDecrypt:()=>deserializeAndDecrypt,deserializeBlob:()=>deserializeBlob,detectRuntimeContext:()=>import_runtime_context.detectRuntimeContext,dirname:()=>import_path2.dirname,encryptAesGcm:()=>encryptAesGcm,encryptAndSerialize:()=>encryptAndSerialize,encryptValue:()=>encryptValue,ensureDir:()=>ensureDir,ensureDirSync:()=>ensureDirSync,ensureMaxLen:()=>ensureMaxLen,entryAvailabilitySchema:()=>import_runtime_context.entryAvailabilitySchema,escapeGlob:()=>escapeGlob,escapeHtml:()=>escapeHtml,escapeHtmlAttr:()=>escapeHtmlAttr,escapeJsString:()=>escapeJsString,escapeScriptClose:()=>escapeScriptClose,expandIpv6:()=>expandIpv6,expandTemplate:()=>expandTemplate,expandUriTemplate:()=>expandUriTemplate,expiresAtToTTL:()=>expiresAtToTTL,extname:()=>import_path2.extname,extractBracedParams:()=>extractBracedParams,extractEmbeddedIpv4:()=>extractEmbeddedIpv4,extractTemplateParams:()=>extractTemplateParams,extractUriScheme:()=>extractUriScheme,fileExists:()=>fileExists,fileExistsSync:()=>fileExistsSync,findDroppedKeys:()=>findDroppedKeys,findNonFiniteNumber:()=>findNonFiniteNumber,generateCodeChallenge:()=>generateCodeChallenge,generateCodeVerifier:()=>generateCodeVerifier,generatePkcePair:()=>generatePkcePair,generateRsaKeyPair:()=>generateRsaKeyPair2,generateSecret:()=>generateSecret,getAsyncContextMode:()=>import_async_context.getAsyncContextMode,getCookie:()=>getCookie,getCrypto:()=>getCrypto,getCwd:()=>import_env2.getCwd,getDetectedStorageType:()=>getDetectedStorageType,getEnv:()=>import_env2.getEnv,getEnvFlag:()=>import_env2.getEnvFlag,getHostname:()=>getHostname,getMachineId:()=>getMachineId,getNodeEnv:()=>import_env2.getNodeEnv,getOrCreateSecret:()=>getOrCreateSecret,getRuntimeContext:()=>import_runtime_context.getRuntimeContext,getSpawnFn:()=>getSpawnFn,globToRegex:()=>globToRegex,hasTemplatePlaceholders:()=>hasTemplatePlaceholders,hkdfSha256:()=>hkdfSha256,hmacSha256:()=>hmacSha256,idFromString:()=>idFromString,inferMimeType:()=>inferMimeType,isAbsolute:()=>import_path2.isAbsolute,isAsymmetricKeyData:()=>isAsymmetricKeyData,isBrandedInstance:()=>isBrandedInstance,isBrowser:()=>isBrowser,isDebug:()=>import_env2.isDebug,isDevelopment:()=>import_env2.isDevelopment,isDirEmpty:()=>isDirEmpty,isEdgeRuntime:()=>import_env2.isEdgeRuntime,isEntryAvailable:()=>import_runtime_context.isEntryAvailable,isExpired:()=>isExpired,isInputLengthSafe:()=>isInputLengthSafe,isLocalhost:()=>isLocalhost,isNode:()=>isNode,isPatternSafe:()=>isPatternSafe,isProcessTreeAlive:()=>isProcessTreeAlive,isProduction:()=>import_env2.isProduction,isRedirectResponse:()=>isRedirectResponse,isRsaPssAlg:()=>isRsaPssAlg,isSecretCached:()=>isSecretCached,isSecretKeyData:()=>isSecretKeyData,isSecretPersistenceEnabled:()=>isSecretPersistenceEnabled,isSecureRequest:()=>isSecureRequest,isServerless:()=>import_env2.isServerless,isSignedData:()=>isSignedData,isUriTemplate:()=>isUriTemplate,isValidCodeChallenge:()=>isValidCodeChallenge,isValidCodeVerifier:()=>isValidCodeVerifier,isValidEncryptedBlob:()=>isValidEncryptedBlob,isValidMcpUri:()=>isValidMcpUri,isValidMcpUriTemplate:()=>isValidMcpUriTemplate,joinPath:()=>joinPath,jwtAlgToNodeAlg:()=>jwtAlgToNodeAlg,listChangedNotifications:()=>listChangedNotifications,loadSecret:()=>loadSecret,lstat:()=>lstat,makeDevError:()=>makeDevError,matchUriTemplate:()=>matchUriTemplate,matchesPattern:()=>matchesPattern,mergeRedisUrlFields:()=>mergeRedisUrlFields,mkdir:()=>mkdir,mkdtemp:()=>mkdtemp,normalizeTTL:()=>normalizeTTL,parseCookies:()=>parseCookies,parseIpv4:()=>parseIpv4,parseKeyData:()=>parseKeyData,parseSecretData:()=>parseSecretData,parseUriTemplate:()=>parseUriTemplate,pathJoin:()=>import_path2.join,pathResolve:()=>import_path2.resolve,pathToFileURL:()=>import_path2.pathToFileURL,pemToPublicJwk:()=>pemToPublicJwk2,processPlatformToolCalls:()=>processPlatformToolCalls,processTreeSpawnOptions:()=>processTreeSpawnOptions,randomBytes:()=>randomBytes,randomUUID:()=>randomUUID,readFile:()=>readFile,readFileBuffer:()=>readFileBuffer,readFileSync:()=>readFileSync,readJSON:()=>readJSON,readdir:()=>readdir,readdirSync:()=>readdirSync,realpath:()=>realpath,reapOrphans:()=>reapOrphans,redactFields:()=>redactFields,redactJson:()=>redactJson,rename:()=>rename,resetRuntimeContext:()=>import_runtime_context.resetRuntimeContext,resolveSecretPath:()=>resolveSecretPath,rm:()=>rm,rsaSignBase64Url:()=>rsaSignBase64Url2,rsaVerify:()=>rsaVerify2,rsaVerifySync:()=>rsaVerifySync2,runCmd:()=>runCmd,runRequestExclusive:()=>import_async_context.runRequestExclusive,safeExec:()=>safeExec,safeJsonForScript:()=>safeJsonForScript,safeMatch:()=>safeMatch,safeReplace:()=>safeReplace,safeStringify:()=>safeStringify,safeTest:()=>safeTest,sanitizeToJson:()=>sanitizeToJson,saveSecret:()=>saveSecret,secretDataSchema:()=>secretDataSchema,secretKeyDataSchema:()=>secretKeyDataSchema,sep:()=>import_path2.sep,sepFor:()=>sepFor,serializeBlob:()=>serializeBlob,setEnv:()=>import_env2.setEnv,setMachineIdOverride:()=>setMachineIdOverride,sha256:()=>sha256,sha256Base64url:()=>sha256Base64url,sha256Hex:()=>sha256Hex,shortHash:()=>shortHash,signData:()=>signData,signalProcessTree:()=>signalProcessTree,spawnOwned:()=>spawnOwned,splitWords:()=>splitWords,stat:()=>stat,stopProcessTree:()=>stopProcessTree,supportsAnsi:()=>import_env2.supportsAnsi,symlink:()=>symlink,timingSafeEqual:()=>timingSafeEqual,toCase:()=>toCase,trimBoth:()=>trimBoth,trimChars:()=>trimChars,trimLeading:()=>trimLeading,trimSlashes:()=>trimSlashes,trimTrailing:()=>trimTrailing,tryDecryptValue:()=>tryDecryptValue,tryDeserializeAndDecrypt:()=>tryDeserializeAndDecrypt,tryDeserializeBlob:()=>tryDeserializeBlob,ttlToExpiresAt:()=>ttlToExpiresAt,unlink:()=>unlink,validateBaseUrl:()=>validateBaseUrl,validateKeyData:()=>validateKeyData,validateOptionalTTL:()=>validateOptionalTTL,validatePattern:()=>validatePattern,validateSecretData:()=>validateSecretData,validateTTL:()=>validateTTL,verifyCodeChallenge:()=>verifyCodeChallenge,verifyData:()=>verifyData,verifyOrParseData:()=>verifyOrParseData,watchFile:()=>watchFile,watchParent:()=>watchParent,watchPath:()=>watchPath,writeFile:()=>writeFile,writeJSON:()=>writeJSON});module.exports=__toCommonJS(index_exports);var import_redos=require("@enclave-vm/ast/redos");var DEFAULT_MAX_INPUT_LENGTH=5e4;function analyzePattern(pattern,level="polynomial"){const patternStr=typeof pattern==="string"?pattern:pattern.source;try{new RegExp(patternStr)}catch{return{safe:false,score:100,vulnerabilityType:"invalid_syntax",explanation:"Pattern has invalid regex syntax"}}try{const result=(0,import_redos.analyzeForReDoS)(patternStr,level);return{safe:!result.vulnerable,score:result.score,vulnerabilityType:result.vulnerabilityType,explanation:result.explanation}}catch{return{safe:false,score:100,vulnerabilityType:"analysis_failed",explanation:"Pattern analysis failed - treating as potentially unsafe"}}}function isPatternSafe(pattern,level="polynomial"){return analyzePattern(pattern,level).safe}function createSafeRegExp(pattern,flags,options={}){const{level="polynomial",throwOnVulnerable=false}=options;const analysis=analyzePattern(pattern,level);if(!analysis.safe){if(throwOnVulnerable){throw new Error(`Vulnerable regex pattern detected: ${analysis.explanation||analysis.vulnerabilityType}`)}return null}try{return new RegExp(pattern,flags)}catch{return null}}function safeTest(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return pattern.test(input)}function safeMatch(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return input.match(pattern)}function safeReplace(input,pattern,replacement,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return input}return input.replace(pattern,replacement)}function safeExec(pattern,input,options={}){const{maxInputLength=DEFAULT_MAX_INPUT_LENGTH}=options;if(input.length>maxInputLength){return null}return pattern.exec(input)}function isInputLengthSafe(input,maxLength=DEFAULT_MAX_INPUT_LENGTH){return input.length<=maxLength}function trimLeading(input,char){if(!input||char.length!==1){return input??""}let start=0;while(start<input.length&&input[start]===char){start++}return start===0?input:input.slice(start)}function trimTrailing(input,char){if(!input||char.length!==1){return input??""}let end=input.length;while(end>0&&input[end-1]===char){end--}return end===input.length?input:input.slice(0,end)}function trimBoth(input,char){return trimTrailing(trimLeading(input,char),char)}function trimChars(input,chars){if(!input||chars.size===0){return input??""}let start=0;while(start<input.length&&chars.has(input[start])){start++}let end=input.length;while(end>start&&chars.has(input[end-1])){end--}return input.slice(start,end)}function extractBracedParams(template,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!template||template.length>maxLength){return[]}const params=[];let i=0;while(i<template.length){const openBrace=template.indexOf("{",i);if(openBrace===-1){break}const closeBrace=template.indexOf("}",openBrace+1);if(closeBrace===-1){break}const nestedOpen=template.indexOf("{",openBrace+1);if(nestedOpen!==-1&&nestedOpen<closeBrace){i=nestedOpen+1;continue}const paramName=template.slice(openBrace+1,closeBrace).trim();if(paramName&&!paramName.includes("{")&&!paramName.includes("}")){params.push(paramName)}i=closeBrace+1}return params}function expandTemplate(template,values,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!template||template.length>maxLength){return template??""}let result="";let i=0;while(i<template.length){const openBrace=template.indexOf("{",i);if(openBrace===-1){result+=template.slice(i);break}result+=template.slice(i,openBrace);const closeBrace=template.indexOf("}",openBrace+1);if(closeBrace===-1){result+=template.slice(openBrace);break}const nestedOpen=template.indexOf("{",openBrace+1);if(nestedOpen!==-1&&nestedOpen<closeBrace){result+="{";i=openBrace+1;continue}const paramName=template.slice(openBrace+1,closeBrace).trim();if(paramName in values){result+=values[paramName]}else{result+=template.slice(openBrace,closeBrace+1)}i=closeBrace+1}return result}function hasTemplatePlaceholders(str,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!str||str.length>maxLength){return false}const openBrace=str.indexOf("{");if(openBrace===-1){return false}const closeBrace=str.indexOf("}",openBrace+1);return closeBrace>openBrace+1}function collapseChar(input,char){if(!input||char.length!==1){return input??""}let result="";let lastWasChar=false;for(let i=0;i<input.length;i++){const c=input[i];if(c===char){if(!lastWasChar){result+=c;lastWasChar=true}}else{result+=c;lastWasChar=false}}return result}function collapseWhitespace(input,maxLength=DEFAULT_MAX_INPUT_LENGTH){if(!input){return""}if(input.length>maxLength){return input}let result="";let lastWasWhitespace=false;for(let i=0;i<input.length;i++){const c=input[i];const isWhitespace=c===" "||c===" "||c==="\n"||c==="\r"||c==="\f"||c==="\v";if(isWhitespace){if(!lastWasWhitespace){result+=" ";lastWasWhitespace=true}}else{result+=c;lastWasWhitespace=false}}return result}function splitWords(input){const parts=[];let buff="";for(let i=0;i<input.length;i++){const ch=input[i];const isAlphaNum=/[A-Za-z0-9]/.test(ch);if(!isAlphaNum){if(buff){parts.push(buff);buff=""}continue}if(buff&&/[a-z]/.test(buff[buff.length-1])&&/[A-Z]/.test(ch)){parts.push(buff);buff=ch}else{buff+=ch}}if(buff)parts.push(buff);return parts}function toCase(words,kind){const safe=words.filter(Boolean);switch(kind){case"snake":return safe.map(w=>w.toLowerCase()).join("_");case"kebab":return safe.map(w=>w.toLowerCase()).join("-");case"dot":return safe.map(w=>w.toLowerCase()).join(".");case"camel":if(safe.length===0)return"";return safe[0].toLowerCase()+safe.slice(1).map(w=>w.charAt(0).toUpperCase()+w.slice(1).toLowerCase()).join("")}}function sepFor(kind){return kind==="snake"?"_":kind==="kebab"?"-":kind==="dot"?".":""}function shortHash(s){let h=5381;for(let i=0;i<s.length;i++)h=(h<<5)+h+s.charCodeAt(i);return(h>>>0).toString(16).slice(-6).padStart(6,"0")}function ensureMaxLen(name,max){if(name.length<=max)return name;const hash=shortHash(name);const lastSep=Math.max(name.lastIndexOf("_"),name.lastIndexOf("-"),name.lastIndexOf("."),name.lastIndexOf("/"));const tail=lastSep>0?name.slice(lastSep+1):name.slice(-Math.max(3,Math.min(16,Math.floor(max/4))));const budget=Math.max(1,max-(1+hash.length+1+tail.length));const prefix=name.slice(0,budget);return`${prefix}-${hash}-${tail}`.slice(0,max)}function idFromString(name){const cleaned=name.replace(/[^A-Za-z0-9_-]+/g,"-");return trimBoth(cleaned,"-").slice(0,64)}var RFC_3986_SCHEME_PATTERN=/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//;var SCHEME_EXTRACT_PATTERN=/^([a-zA-Z][a-zA-Z0-9+.-]*):/;function isValidMcpUri(uri){return RFC_3986_SCHEME_PATTERN.test(uri)}function extractUriScheme(uri){const match=uri.match(SCHEME_EXTRACT_PATTERN);return match?match[1].toLowerCase():null}function isValidMcpUriTemplate(uriTemplate){return RFC_3986_SCHEME_PATTERN.test(uriTemplate)}function parseUriTemplate(template){if(template.length>1e3){throw new Error("URI template too long (max 1000 characters)")}const paramCount=(template.match(/\{[^{}]+\}/g)||[]).length;if(paramCount>50){throw new Error("URI template has too many parameters (max 50)")}const paramNames=[];const placeholder=/\{([^{}]+)\}/g;let regexStr="";let lastIndex=0;for(let m=placeholder.exec(template);m!==null;m=placeholder.exec(template)){regexStr+=escapeRegex(template.slice(lastIndex,m.index));const raw=m[1];const reserved=raw.startsWith("+");paramNames.push(reserved?raw.slice(1):raw);regexStr+=reserved?"(.+?)":"([^/]+)";lastIndex=m.index+m[0].length}regexStr+=escapeRegex(template.slice(lastIndex));return{pattern:new RegExp(`^${regexStr}$`),paramNames}}function escapeRegex(literal){return literal.replace(/[.*+?^${}()|[\]\\]/g,c=>`\\${c}`)}function matchUriTemplate(template,uri){const{pattern,paramNames}=parseUriTemplate(template);const match=uri.match(pattern);if(!match)return null;const params={};paramNames.forEach((name,index)=>{params[name]=decodeURIComponent(match[index+1])});return params}function expandUriTemplate(template,params){return template.replace(/\{([^{}]+)\}/g,(_,raw)=>{const reserved=raw.startsWith("+");const paramName=reserved?raw.slice(1):raw;const value=params[paramName];if(value===void 0){throw new Error(`Missing parameter '${paramName}' for URI template '${template}'`)}return reserved?encodeReserved(value):encodeURIComponent(value)})}function encodeReserved(value){const decoded=safeDecode(value);return decoded.replace(/[^A-Za-z0-9\-._~:/?#[\]@!$&'()*+,;=]/g,c=>encodeURIComponent(c))}function safeDecode(value){try{return decodeURIComponent(value)}catch{return value.replace(/%[0-9A-Fa-f]{2}/g,triplet=>{try{return decodeURIComponent(triplet)}catch{return triplet}})}}function extractTemplateParams(template){const params=[];template.replace(/\{([^{}]+)\}/g,(_,raw)=>{params.push(raw.startsWith("+")?raw.slice(1):raw);return""});return params}function isUriTemplate(uri){return/\{[^{}]+\}/.test(uri)}function trimSlashes(s){return trimBoth(s??"","/")}function joinPath(...parts){const cleaned=parts.map(p=>trimSlashes(p)).filter(Boolean);return cleaned.length?`/${cleaned.join("/")}`:""}var import_path2=require("#path");function sanitizeToJson(value){const ancestors=new WeakSet;function withinAncestors(container,build){if(ancestors.has(container)){return void 0}ancestors.add(container);try{return build()}finally{ancestors.delete(container)}}function sanitize(val){if(typeof val==="function"||typeof val==="symbol"){return void 0}if(typeof val==="bigint"){return val.toString()}if(val instanceof Date){return val.toISOString()}if(val instanceof Error){return{name:val.name,message:val.message,stack:val.stack}}if(val instanceof Map){return withinAncestors(val,()=>{const obj={};for(const[k,v]of val.entries()){obj[String(k)]=sanitize(v)}return obj})}if(val instanceof Set){return withinAncestors(val,()=>Array.from(val).map(sanitize))}if(Array.isArray(val)){return withinAncestors(val,()=>val.map(sanitize))}if(val&&typeof val==="object"){return withinAncestors(val,()=>{const sanitized={};for(const[key,value2]of Object.entries(val)){const clean=sanitize(value2);if(clean!==void 0){sanitized[key]=clean}}return sanitized})}return val}return sanitize(value)}function findNonFiniteNumber(value){const seen=new WeakSet;function walk(val,path){if(typeof val==="number"&&!Number.isFinite(val)){return{path,value:val}}if(val&&typeof val==="object"){if(seen.has(val))return void 0;seen.add(val);if(Array.isArray(val)){for(let i=0;i<val.length;i++){const found=walk(val[i],`${path}[${i}]`);if(found)return found}return void 0}for(const[k,v]of Object.entries(val)){const found=walk(v,path?`${path}.${k}`:k);if(found)return found}}return void 0}return walk(value,"")}function findDroppedKeys(original,parsed){const droppedPaths=new Set;function walk(source,target,path){if(source===target)return;if(Array.isArray(source)){source.forEach((item,index)=>walk(item,Array.isArray(target)?target[index]:void 0,`${path}[]`));return}if(!isPlainRecord(source))return;const targetRecord=isPlainRecord(target)?target:{};for(const[key,value]of Object.entries(source)){if(value===void 0)continue;const keyPath=path?`${path}.${key}`:key;if(Object.prototype.hasOwnProperty.call(targetRecord,key))walk(value,targetRecord[key],keyPath);else droppedPaths.add(keyPath)}}walk(original,parsed,"");return[...droppedPaths].sort()}function isPlainRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}var MIME_TYPES={json:"application/json",xml:"application/xml",html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",ts:"application/typescript",txt:"text/plain",md:"text/markdown",yaml:"application/yaml",yml:"application/yaml",csv:"text/csv",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",pdf:"application/pdf"};function inferMimeType(uri,content){const ext=uri.split(".").pop()?.toLowerCase();if(ext&&MIME_TYPES[ext]){return MIME_TYPES[ext]}if(typeof content==="string"){if(content.trim().startsWith("{")||content.trim().startsWith("[")){return"application/json"}if(content.trim().startsWith("<")){return content.includes("<!DOCTYPE html")||content.includes("<html")?"text/html":"application/xml"}}return"text/plain"}function validateBaseUrl(url){try{const parsed=new URL(url);if(!["http:","https:"].includes(parsed.protocol)){throw new Error(`Unsupported protocol: ${parsed.protocol}. Only http: and https: are supported.`)}return parsed}catch(err){if(err instanceof Error&&err.message.includes("Unsupported protocol")){throw err}throw new Error(`Invalid base URL: ${url}`)}}init_runtime();var LOCALHOST_PATTERNS=new Set(["localhost","127.0.0.1","::1","0.0.0.0"]);function isLocalhost(host){if(!host)return false;if(host.startsWith("[")){const closeBracket=host.indexOf("]");if(closeBracket>0){return LOCALHOST_PATTERNS.has(host.slice(1,closeBracket))}}if(LOCALHOST_PATTERNS.has(host))return true;const lastColon=host.lastIndexOf(":");if(lastColon>0){const hostname=host.slice(0,lastColon);return LOCALHOST_PATTERNS.has(hostname)}return false}function isSecureRequest(req){if(!req)return false;if(req.protocol==="https")return true;const forwarded=req.headers?.["x-forwarded-proto"];const forwardedStr=(Array.isArray(forwarded)?forwarded[0]:forwarded)?.split(",")[0]?.trim()?.toLowerCase();if(forwardedStr==="https")return true;if(req.socket?.encrypted)return true;return false}function buildSetCookie(options,req){if(!isNode())return null;const{name,value,path="/",maxAge=86400,httpOnly=true,sameSite="Strict",domain}=options;let secure;if(options.secure!==void 0){secure=options.secure}else{const host=req?.headers?.["host"];const hostStr=Array.isArray(host)?host[0]:host;if(isLocalhost(hostStr)){secure=false}else if(req){secure=isSecureRequest(req)}else{secure=process.env["NODE_ENV"]==="production"}}if(sameSite==="None"&&!secure){secure=true}const parts=[`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];parts.push(`Path=${path}`);parts.push(`Max-Age=${maxAge}`);if(httpOnly)parts.push("HttpOnly");if(secure)parts.push("Secure");parts.push(`SameSite=${sameSite}`);if(domain)parts.push(`Domain=${domain}`);return parts.join("; ")}function parseCookies(cookieHeader){const cookies={};if(!cookieHeader)return cookies;const pairs=cookieHeader.split(";");for(const pair of pairs){const eqIdx=pair.indexOf("=");if(eqIdx<0)continue;try{const name=decodeURIComponent(pair.slice(0,eqIdx).trim());const value=decodeURIComponent(pair.slice(eqIdx+1).trim());if(name)cookies[name]=value}catch{continue}}return cookies}function getCookie(cookieHeader,name){if(!cookieHeader)return void 0;return parseCookies(cookieHeader)[name]}var IPV4_OCTET_PATTERN=/^(0|[1-9]\d{0,2})$/;var IPV6_GROUP_PATTERN=/^[0-9a-f]{1,4}$/;var IPV4_BLOCKS=compileBlocks([["0.0.0.0/8","this-network"],["10.0.0.0/8","private"],["100.64.0.0/10","carrier-grade-nat"],["127.0.0.0/8","loopback"],["169.254.0.0/16","link-local"],["172.16.0.0/12","private"],["192.0.0.0/24","ietf-protocol"],["192.168.0.0/16","private"],["198.18.0.0/15","benchmarking"],["224.0.0.0/4","multicast"],["255.255.255.255/32","reserved"],["240.0.0.0/4","reserved"]],parseIpv4);var IPV6_BLOCKS=compileBlocks([["::/128","unspecified"],["::1/128","loopback"],["fd00:ec2::254/128","cloud-metadata"],["fc00::/7","private"],["fe80::/10","link-local"],["fec0::/10","site-local"],["64:ff9b:1::/48","local-use-nat64"],["ff00::/8","multicast"]],expandIpv6);var IPV4_EMBEDDINGS=compileBlocks([["::ffff:0:0/96",6],["::ffff:0:0:0/96",6],["::/96",6],["64:ff9b::/96",6],["2002::/16",1]],expandIpv6);function parseIpv4(address){const parts=address.split(".");if(parts.length!==4||!parts.every(part=>IPV4_OCTET_PATTERN.test(part)))return void 0;const octets=parts.map(Number);return octets.every(octet=>octet<=255)?octets:void 0}function expandIpv6(address){const zoneIndex=address.indexOf("%");let text=(zoneIndex===-1?address:address.slice(0,zoneIndex)).toLowerCase();const lastColonIndex=text.lastIndexOf(":");const trailingSegment=text.slice(lastColonIndex+1);if(lastColonIndex!==-1&&trailingSegment.includes(".")){const octets=parseIpv4(trailingSegment);if(!octets)return void 0;const highGroup=(octets[0]<<8|octets[1]).toString(16);const lowGroup=(octets[2]<<8|octets[3]).toString(16);text=`${text.slice(0,lastColonIndex+1)}${highGroup}:${lowGroup}`}const halves=text.split("::");if(halves.length>2)return void 0;const head=parseIpv6Groups(halves[0]);if(!head)return void 0;if(halves.length===1)return head.length===8?head:void 0;const tail=parseIpv6Groups(halves[1]);if(!tail||head.length+tail.length>7)return void 0;return[...head,...new Array(8-head.length-tail.length).fill(0),...tail]}function extractEmbeddedIpv4(groups){const octets=findEmbeddedIpv4Octets(groups);return octets?octets.join("."):void 0}function classifyIpAddress(address){const isBracketed=address.startsWith("[")&&address.endsWith("]");const octets=isBracketed?void 0:parseIpv4(address);if(octets)return classifyIpv4(octets);const groups=expandIpv6(isBracketed?address.slice(1,-1):address);if(!groups)return void 0;const block=IPV6_BLOCKS.find(candidate=>matchesBlock(groups,candidate,16));if(block)return{family:6,range:block.value,cidr:block.cidr};const embeddedOctets=findEmbeddedIpv4Octets(groups);if(!embeddedOctets)return{family:6,range:"public"};return{...classifyIpv4(embeddedOctets),family:6,embeddedIpv4:embeddedOctets.join(".")}}function classifyIpv4(octets){const block=IPV4_BLOCKS.find(candidate=>matchesBlock(octets,candidate,8));return block?{family:4,range:block.value,cidr:block.cidr}:{family:4,range:"public"}}function findEmbeddedIpv4Octets(groups){const embedding=IPV4_EMBEDDINGS.find(block=>matchesBlock(groups,block,16));if(!embedding)return void 0;const highGroup=groups[embedding.value];const lowGroup=groups[embedding.value+1];return[highGroup>>8,highGroup&255,lowGroup>>8,lowGroup&255]}function parseIpv6Groups(part){if(part==="")return[];const groups=part.split(":");if(!groups.every(group=>IPV6_GROUP_PATTERN.test(group)))return void 0;return groups.map(group=>parseInt(group,16))}function matchesBlock(words,block,bitsPerWord){let remainingBits=block.prefixLength;for(let index=0;remainingBits>0;index++){const comparedBits=Math.min(bitsPerWord,remainingBits);const ignoredBits=bitsPerWord-comparedBits;if(words[index]>>ignoredBits!==block.network[index]>>ignoredBits)return false;remainingBits-=comparedBits}return true}function compileBlocks(entries,parseNetwork){return entries.map(([cidr,value])=>{const[networkText,prefixText]=cidr.split("/");const network=parseNetwork(networkText);if(!network)throw new Error(`Invalid network in address block "${cidr}"`);return{cidr,network,prefixLength:Number(prefixText),value}})}function isRedirectResponse(response){return response.type==="opaqueredirect"||response.status>=300&&response.status<400}init_fs2();init_runtime();var childProcess=null;function getChildProcess(){if(!childProcess){assertNode("Process operations");childProcess=require("child_process")}return childProcess}function runTaskkill(pid,force){const result=getChildProcess().spawnSync("taskkill",["/pid",String(pid),"/T",...force?["/F"]:[]],{stdio:"ignore",windowsHide:true});return!result.error&&result.status===0}function queryChildPids(pid){if(!Number.isInteger(pid)||pid<=0)return[];const result=getChildProcess().spawnSync("powershell.exe",["-NoProfile","-NonInteractive","-Command",`Get-CimInstance Win32_Process -Filter 'ParentProcessId=${pid}' | ForEach-Object { $_.ProcessId }`],{encoding:"utf8",windowsHide:true,timeout:15e3});if(result.error||result.status!==0)return[];return parsePidList(String(result.stdout??""))}function parsePidList(output){return output.split(/\r?\n/).map(line=>line.trim()).filter(line=>/^\d+$/.test(line)).map(Number).filter(pid=>pid>0)}function sleep(ms){return new Promise(resolve2=>setTimeout(resolve2,ms))}function withDefaults(deps){return{platform:process.platform,kill:(pid,signal)=>process.kill(pid,signal),taskkill:runTaskkill,childPids:queryChildPids,sleep,...deps}}function processTreeSpawnOptions(platform=process.platform){return platform==="win32"?{}:{detached:true}}function hasExited(child){return child.exitCode!==null||child.signalCode!==null}function isPidRunning(pid,d){try{d.kill(pid,0);return true}catch(err){return err.code==="EPERM"}}function windowsOrphans(pid,d){if(isPidRunning(pid,d))return[];return d.childPids(pid)}function taskkillTree(child,pid,force,d){const roots=hasExited(child)?windowsOrphans(pid,d):[pid];let delivered=false;for(const root of roots){if(d.taskkill(root,force))delivered=true}return delivered}function signalProcessTree(child,signal,deps){const d=withDefaults(deps);const pid=child?.pid;if(!child||pid===void 0)return false;if(d.platform==="win32")return taskkillTree(child,pid,signal==="SIGKILL",d);try{d.kill(-pid,signal);return true}catch{}if(hasExited(child))return false;try{return child.kill(signal)}catch{return false}}function isProcessTreeAlive(child,deps){const d=withDefaults(deps);const pid=child?.pid;if(!child||pid===void 0)return false;if(d.platform==="win32")return!hasExited(child)||windowsOrphans(pid,d).length>0;try{d.kill(-pid,0);return true}catch(err){return err.code==="EPERM"}}async function stopProcessTree(child,signal,graceMs,deps){const d=withDefaults(deps);if(!child)return true;if(d.platform==="win32")return stopWindowsTree(child,signal,graceMs,d);signalProcessTree(child,signal,d);if(await waitForProcessTreeExit(child,graceMs,d))return true;signalProcessTree(child,"SIGKILL",d);return waitForProcessTreeExit(child,1e3,d)}async function waitForProcessTreeExit(child,timeoutMs,d){const deadline=Date.now()+timeoutMs;while(isProcessTreeAlive(child,d)){if(Date.now()>=deadline)return false;await d.sleep(50)}return true}async function stopWindowsTree(child,signal,graceMs,d){const pid=child.pid;if(pid===void 0)return true;if(hasExited(child)&&windowsOrphans(pid,d).length===0)return true;if(signal!=="SIGKILL"){const asked=taskkillTree(child,pid,false,d);if(asked&&await waitForWindowsTreeExit(child,pid,graceMs,d))return true}const rootWasRunning=!hasExited(child);const forced=taskkillTree(child,pid,true,d);return waitForWindowsTreeExit(child,pid,1e3,d,!(forced&&rootWasRunning))}async function waitForWindowsTreeExit(child,pid,timeoutMs,d,checkOrphans=true){const deadline=Date.now()+timeoutMs;while(!hasExited(child)){if(Date.now()>=deadline)return false;await d.sleep(50)}if(!checkOrphans)return true;for(;;){if(windowsOrphans(pid,d).length===0)return true;if(Date.now()>=deadline)return false;await d.sleep(250)}}var OWNER_ENV_VAR="FRONTMCP_OWNER";var OWNER_ARG_PREFIX="--frontmcp-owner=";var MARKER_PATTERN=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;var DEFAULT_REAP_GRACE_MS=2e3;var KILL_WAIT_MS=1e3;var OwnedProcessError=class extends Error{constructor(message){super(message);this.name="OwnedProcessError"}};function assertMarker(marker){if(!MARKER_PATTERN.test(marker)){throw new OwnedProcessError(`Invalid process marker "${marker}": use up to 64 letters, digits, ".", "_" and "-", starting with a letter or digit`)}}function spawnOwned(command,args,options){const{marker,...spawnOptions}=options;assertMarker(marker);const owner=`${marker}:${process.pid}`;const child=getChildProcess().spawn(command,[...args,`${OWNER_ARG_PREFIX}${owner}`],{...spawnOptions,env:{...spawnOptions.env??process.env,[OWNER_ENV_VAR]:owner}});const stopsTree=spawnOptions.detached===true||process.platform==="win32";return{child,stop:(signal="SIGTERM",graceMs=5e3)=>stopsTree?stopProcessTree(child,signal,graceMs):stopChild(child,signal,graceMs)}}function exitsWithin(child,timeoutMs){if(child.exitCode!==null||child.signalCode!==null)return Promise.resolve(true);return new Promise(resolve2=>{const onExit=()=>{clearTimeout(timer);resolve2(true)};const timer=setTimeout(()=>{child.removeListener("exit",onExit);resolve2(false)},timeoutMs);child.once("exit",onExit)})}async function stopChild(child,signal,graceMs){if(child.pid===void 0)return true;child.kill(signal);if(await exitsWithin(child,graceMs))return true;child.kill("SIGKILL");return exitsWithin(child,KILL_WAIT_MS)}function parseProcessList(output){const processes=[];for(const line of output.split("\n")){const match=/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)$/.exec(line);if(match){processes.push({pid:Number(match[1]),ppid:Number(match[2]),pgid:Number(match[3]),zombie:match[4].startsWith("Z"),command:match[5]})}}return processes}function listProcesses(){const result=getChildProcess().spawnSync("ps",["-A","-ww","-o","pid=,ppid=,pgid=,stat=,command="],{encoding:"utf8"});if(result.error||result.status!==0){const reason=result.error?.message??(String(result.stderr).trim()||`exit code ${result.status}`);throw new OwnedProcessError(`Could not list processes with ps: ${reason}`)}return parseProcessList(String(result.stdout))}function ownerPidOf(command,marker){const prefix=`${OWNER_ARG_PREFIX}${marker}:`;const tag=command.split(/\s+/).find(token=>token.startsWith(prefix));const pid=tag?.slice(prefix.length);return pid&&/^\d+$/.test(pid)?Number(pid):void 0}function ownLineage(processes){const byPid=new Map(processes.map(info=>[info.pid,info]));const lineage=new Set([process.pid]);const self=byPid.get(process.pid);let ancestor=self&&byPid.get(self.ppid);while(ancestor&&!lineage.has(ancestor.pid)){lineage.add(ancestor.pid);ancestor=byPid.get(ancestor.ppid)}if(self)lineage.add(self.pgid);return lineage}function treesOf(orphans,processes,spared){const members=new Set;const pending=orphans.map(orphan=>orphan.pid);for(const orphan of orphans){if(orphan.pgid===orphan.pid){for(const info of processes)if(info.pgid===orphan.pid)pending.push(info.pid)}}while(pending.length>0){const pid=pending.pop();if(members.has(pid)||spared.has(pid))continue;members.add(pid);for(const info of processes)if(info.ppid===pid)pending.push(info.pid)}return members}function signalEach(pids,signal,d){for(const pid of pids){try{d.kill(pid,signal)}catch{}}}function stillRunning(pids,d){const signalled=pids.filter(pid=>isPidRunning(pid,d));if(signalled.length===0)return signalled;const zombies=new Set(d.listProcesses().filter(info=>info.zombie).map(info=>info.pid));return signalled.filter(pid=>!zombies.has(pid))}async function waitForExit(pids,timeoutMs,d){const deadline=Date.now()+timeoutMs;let running=stillRunning(pids,d);while(running.length>0&&Date.now()<deadline){await d.sleep(50);running=stillRunning(running,d)}return running}async function reapOrphans(marker,options={},deps){assertMarker(marker);const d={platform:process.platform,kill:(pid,signal)=>process.kill(pid,signal),sleep,listProcesses,...deps};if(d.platform==="win32")return[];const processes=d.listProcesses();const lineage=ownLineage(processes);const orphans=processes.filter(info=>{const owner=ownerPidOf(info.command,marker);return owner!==void 0&&!lineage.has(info.pid)&&!isPidRunning(owner,d)});if(orphans.length===0)return[];const tree=[...treesOf(orphans,processes,lineage)];signalEach(tree,"SIGTERM",d);const survivors=await waitForExit(tree,options.graceMs??DEFAULT_REAP_GRACE_MS,d);if(survivors.length>0){signalEach(survivors,"SIGKILL",d);await waitForExit(survivors,KILL_WAIT_MS,d)}const orphanPids=orphans.map(orphan=>orphan.pid);const left=new Set(stillRunning(orphanPids,d));return orphanPids.filter(pid=>!left.has(pid))}init_fs();var DEFAULT_INTERVAL_MS=1e3;function watchParent(options,deps){const d={ppid:()=>process.ppid,kill:(pid,signal)=>process.kill(pid,signal),...deps};const parentPid=d.ppid();const stdin=options.stdin;let timer;let closed=false;const close=()=>{closed=true;clearInterval(timer);stdin?.removeListener("end",onStdinEnded);stdin?.removeListener("close",onStdinEnded)};const report=reason=>{if(closed)return;close();options.onGone(reason)};function onStdinEnded(){report("stdin-ended")}if(stdin?.readableEnded||stdin?.destroyed)queueMicrotask(onStdinEnded);stdin?.once("end",onStdinEnded);stdin?.once("close",onStdinEnded);if(parentPid>1){timer=setInterval(()=>{if(d.ppid()!==parentPid||!isPidRunning(parentPid,d))report("parent-exited")},options.intervalMs??DEFAULT_INTERVAL_MS);timer.unref()}return{close}}function watchPath(path,options){const timer=setInterval(()=>{if(!isMissingSync(path))return;clearInterval(timer);options.onGone()},options.intervalMs??DEFAULT_INTERVAL_MS);timer.unref();return{close:()=>clearInterval(timer)}}var DEV_SERVER_UNREACHABLE=-32099;var DEV_BUFFER_FULL=-32098;var DEV_RELOAD_DEADLINE=-32097;var DEV_ERROR_MESSAGE={[DEV_SERVER_UNREACHABLE]:"dev_server_unreachable",[DEV_BUFFER_FULL]:"dev_buffer_full",[DEV_RELOAD_DEADLINE]:"dev_reload_deadline"};function makeDevError(id,code,data){return{jsonrpc:"2.0",id,error:{code,message:DEV_ERROR_MESSAGE[code]??"dev_error",...data?{data}:{}}}}var LIST_CHANGED={tools:"notifications/tools/list_changed",resources:"notifications/resources/list_changed",prompts:"notifications/prompts/list_changed"};function listChangedNotifications(initializeResult){const capabilities=initializeResult?.["capabilities"];if(typeof capabilities!=="object"||capabilities===null)return[];const frames=[];for(const[capability,method]of Object.entries(LIST_CHANGED)){const entry=capabilities[capability];if(typeof entry==="object"&&entry!==null&&entry.listChanged===true){frames.push({jsonrpc:"2.0",method})}}return frames}function createBridgeStateMachine(options){const{log,bufferSize,reloadDeadlineMs,respond,forward}=options;let state="Idle";const buffer=[];const requeued=new WeakSet;const inflight=new Map;let reloadTimer;let degradedDetail;let readyGen=0;function transition(next,info){if(state===next)return;log.info("state-transition",{from:state,to:next,...info});state=next}function clearReloadTimer(){if(reloadTimer){clearTimeout(reloadTimer);reloadTimer=void 0}}async function flushBufferAsResponses(code,reason,data){while(buffer.length>0){const f=buffer.shift();if(!f)break;const id=f.id??null;if(id===null){log.warn("drop-notification",{method:f.method,reason});continue}await respond(makeDevError(id,code,{reason,...data}))}}async function failInflightAsResponses(reason,data){for(const[id,req]of inflight){const idVal=typeof id==="number"?id:id;await respond(makeDevError(idVal,DEV_SERVER_UNREACHABLE,{reason,...data,method:req.frame.method}))}inflight.clear()}const machine={get state(){return state},bufferDepth:()=>buffer.length,onBootStart(){transition("Booting")},onChildReady(){clearReloadTimer();degradedDetail=void 0;transition("Ready",{bufferDepth:buffer.length});const drain=[...buffer];buffer.length=0;const drainGen=readyGen;void(async()=>{for(const[index,f]of drain.entries()){if(readyGen!==drainGen){await keepUnsent(drain.slice(index));return}const requestId=typeof f.id==="string"||typeof f.id==="number"?f.id:null;if(requestId!==null){inflight.set(requestId,{frame:f,forwardedAt:Date.now()})}try{await forward(f)}catch(err){log.error("forward-failed",{error:err.message});if(requestId!==null&&inflight.delete(requestId)){await respond(makeDevError(requestId,DEV_SERVER_UNREACHABLE,{reason:"forward_failed"}))}}}})()},onChildExit(reason){log.warn("child-exit",{reason,state});if(state==="Stopping")return;if(state==="Ready"||state==="Booting"){readyGen++;transition("Reloading",{trigger:"child-exit",reason});void failInflightAsResponses("child_exit",{reason});scheduleReloadDeadline()}else if(state==="Reloading"){}},onUpstreamLost(reason){if(state!=="Ready"&&state!=="Booting")return;readyGen++;transition("Reloading",{trigger:"upstream-lost",reason});scheduleReloadDeadline()},async requeue(frame){if(frame.id!==void 0&&frame.id!==null)inflight.delete(frame.id);if(state==="Ready"){await machine.enqueue(frame);return}requeued.add(frame);buffer.unshift(frame);if(state==="Degraded"||state==="Stopping")await keepUnsent([])},onWatcherEvent(trigger){if(state==="Stopping"||state==="Degraded")return;log.reloadEvent("start",{trigger});readyGen++;transition("Reloading",{trigger});void failInflightAsResponses("reload",{trigger});scheduleReloadDeadline()},onReloadDeadline(detail){log.error("reload-deadline-elapsed",{bufferDepth:buffer.length});transition("Degraded",{reason:"reload_deadline"});degradedDetail=detail;void flushBufferAsResponses(DEV_RELOAD_DEADLINE,"deadline",{deadlineMs:reloadDeadlineMs,...detail})},async enqueue(frame){const isRequest=frame.id!==void 0&&frame.id!==null;if(state==="Ready"){if(isRequest){inflight.set(frame.id,{frame,forwardedAt:Date.now()})}try{await forward(frame)}catch(err){log.error("forward-failed",{error:err.message});if(isRequest&&inflight.delete(frame.id)){await respond(makeDevError(frame.id??null,DEV_SERVER_UNREACHABLE,{reason:"forward_failed"}))}}return}if(state==="Degraded"||state==="Stopping"){if(isRequest){await respond(makeDevError(frame.id??null,DEV_SERVER_UNREACHABLE,{reason:state==="Stopping"?"stopping":"degraded",...state==="Degraded"?degradedDetail:void 0}))}else{log.warn("drop-notification",{method:frame.method,reason:state==="Stopping"?"stopping":"degraded"})}return}if(buffer.length>=bufferSize){if(isRequest){await respond(makeDevError(frame.id??null,DEV_BUFFER_FULL,{capacity:bufferSize}))}else{log.warn("drop-notification",{method:frame.method,reason:"buffer_full"})}return}buffer.push(frame)},async relayUpstream(frame){if(frame.id!==void 0&&frame.id!==null&&(frame.result!==void 0||frame.error!==void 0)){inflight.delete(frame.id)}await respond(frame)},async stop(){readyGen++;transition("Stopping");clearReloadTimer();await failInflightAsResponses("stopping");await flushBufferAsResponses(DEV_SERVER_UNREACHABLE,"stopping")}};return machine;async function keepUnsent(frames){if(state==="Ready"){for(const frame of frames)await machine.enqueue(frame);return}let at=0;while(at<buffer.length&&requeued.has(buffer[at]))at++;buffer.splice(at,0,...frames);if(state==="Stopping")await flushBufferAsResponses(DEV_SERVER_UNREACHABLE,"stopping");if(state==="Degraded")await flushBufferAsResponses(DEV_RELOAD_DEADLINE,"deadline",degradedDetail)}function scheduleReloadDeadline(){clearReloadTimer();reloadTimer=setTimeout(()=>{if(state==="Reloading"||state==="Booting"){log.error("reload-deadline-fired");transition("Degraded",{reason:"reload_deadline"});void(async()=>{while(buffer.length>0){const f=buffer.shift();if(!f)break;const id=f.id??null;if(id===null){log.warn("drop-notification",{method:f.method,reason:"deadline"});continue}await respond(makeDevError(id,DEV_RELOAD_DEADLINE,{deadlineMs:reloadDeadlineMs}))}})()}},reloadDeadlineMs).unref()}}function createStdioFramer(options){const{input,output,log,onFrame,onClose}=options;let buffer="";let paused=false;let drainResolvers=[];function flushBuffer(){let nl;while((nl=buffer.indexOf("\n"))>=0){const raw=buffer.slice(0,nl).replace(/\r$/,"");buffer=buffer.slice(nl+1);if(raw.length===0)continue;let parsed;try{parsed=JSON.parse(raw)}catch(err){log.warn("parse-error",{raw:raw.slice(0,200),error:err.message});void write(makeDevError(null,-32700,{reason:"parse_error"}));continue}if(!parsed||typeof parsed!=="object"){log.warn("parse-error",{raw:raw.slice(0,200),reason:"not_object"});void write(makeDevError(null,-32700,{reason:"not_object"}));continue}void Promise.resolve(onFrame(parsed)).catch(err=>{log.error("on-frame-error",{error:err instanceof Error?err.message:String(err)})})}}let closed=false;function onInputClosed(){if(closed)return;closed=true;onClose?.()}function onData(chunk){buffer+=typeof chunk==="string"?chunk:chunk.toString("utf-8");flushBuffer()}function write(frame){return new Promise(resolve2=>{const line=JSON.stringify(frame)+"\n";const ok=output.write(line);if(ok)return resolve2();if(!paused){paused=true;input.pause?.()}drainResolvers.push(resolve2)})}function onDrain(){if(paused){paused=false;input.resume?.()}const resolvers=drainResolvers;drainResolvers=[];for(const r of resolvers)r()}return{start:()=>{input.setEncoding?.("utf-8");input.on("data",onData);input.on("end",onInputClosed);input.on("close",onInputClosed);output.on("drain",onDrain)},write,stop:()=>{input.off("data",onData);input.off("end",onInputClosed);input.off("close",onInputClosed);output.off("drain",onDrain);if(paused){paused=false;input.resume?.()}const resolvers=drainResolvers;drainResolvers=[];for(const r of resolvers)r()}}}var SESSION_HEADER="mcp-session-id";var END_SESSION_TIMEOUT_MS=2e3;var reinitCounter=0;function nextReinitId(){reinitCounter+=1;return`frontmcp-dev-bridge:reinitialize:${reinitCounter}`}function initializedNotification(){return{jsonrpc:"2.0",method:"notifications/initialized"}}function resultOf(frame,method){if(!frame)throw new Error(`no response to the replayed ${method}`);if(frame.error)throw new Error(`replayed ${method} failed: ${frame.error.message}`);return typeof frame.result==="object"&&frame.result!==null?frame.result:void 0}function createHttpUpstream(options){const{log,url,onFrame}=options;const abortControllers=new Set;let sessionId;async function post(frame,deliver){const abortController=new AbortController;abortControllers.add(abortController);const signal=abortController.signal;try{const headers={...options.headers,"content-type":"application/json",accept:"application/json, text/event-stream"};if(sessionId&&frame.method!=="initialize")headers[SESSION_HEADER]=sessionId;const res=await(options.fetch??fetch)(url,{method:"POST",redirect:"error",headers,body:JSON.stringify(frame),signal});if(!res.ok){log.warn("http-upstream-non-ok",{status:res.status,method:frame.method});throw new Error(`upstream returned ${res.status} for ${frame.method??"request"}`)}const issued=res.headers.get(SESSION_HEADER);if(issued&&frame.method==="initialize"){sessionId=issued;log.info("http-upstream-session")}const contentType=res.headers.get("content-type")??"";if(contentType.includes("text/event-stream")){const reader=res.body?.getReader();if(!reader)return;const decoder=new TextDecoder;let buffer="";while(true){const{done,value}=await reader.read();if(done)break;buffer+=decoder.decode(value,{stream:true});let nl;while((nl=buffer.indexOf("\n"))>=0){const line=buffer.slice(0,nl).trim();buffer=buffer.slice(nl+1);if(!line.startsWith("data:"))continue;const json=line.slice(5).trim();if(!json)continue;try{const parsed=JSON.parse(json);await deliver(parsed)}catch(err){log.warn("sse-parse-error",{error:err.message,raw:json.slice(0,200)})}}}}else if(contentType.includes("application/json")){const body=await res.json();await deliver(body)}}catch(err){if(err.name==="AbortError"){log.info("http-upstream-aborted",{method:frame.method})}else{log.error("http-upstream-error",{error:err.message,method:frame.method})}throw err}finally{abortControllers.delete(abortController)}}return{send:frame=>post(frame,onFrame),async reinitialize(initialize,initialized){const id=nextReinitId();let response;await post({...initialize,id},async frame=>{if(frame.id===id)response=frame;else await onFrame(frame)});const result=resultOf(response,"initialize");if(initialized)await post(initializedNotification(),onFrame);return result},async endSession(){const ending=sessionId;if(!ending)return;sessionId=void 0;try{const res=await(options.fetch??fetch)(url,{method:"DELETE",redirect:"error",headers:{...options.headers,[SESSION_HEADER]:ending},signal:AbortSignal.timeout(END_SESSION_TIMEOUT_MS)});await res.body?.cancel()}catch(err){log.warn("http-upstream-end-session-failed",{error:err.message})}},close:async()=>{for(const ac of abortControllers)ac.abort();abortControllers.clear()}}}function createPipeUpstream(options){const{log,child,onFrame,onDevEvents,reinitializeTimeoutMs=1e4}=options;const pending=new Map;function handleMessage(msg){if(!msg||typeof msg!=="object"){log.warn("pipe-upstream-non-object",{type:typeof msg});return}const control=msg;if(control.__frontmcp==="dev-events"&&Array.isArray(control.events))onDevEvents?.(control.events);if(control.__frontmcp!==void 0)return;const frame=msg;const waiter=typeof frame.id==="string"?pending.get(frame.id):void 0;if(waiter){waiter(frame);return}void onFrame(frame)}child.on("message",handleMessage);async function send(frame){if(!child.connected){log.warn("pipe-upstream-disconnected",{method:frame.method});throw new Error(`pipe upstream disconnected for ${frame.method??"request"}`)}await new Promise((resolve2,reject)=>{child.send(frame,err=>{if(err)reject(err);else resolve2()})}).catch(err=>{log.warn("pipe-upstream-send-error",{error:err.message,method:frame.method});throw err})}return{send,async reinitialize(initialize,initialized){const id=nextReinitId();let timer;const response=new Promise((resolve2,reject)=>{pending.set(id,resolve2);timer=setTimeout(()=>reject(new Error(`no response to the replayed initialize within ${reinitializeTimeoutMs}ms`)),reinitializeTimeoutMs)});try{await send({...initialize,id});const result=resultOf(await response,"initialize");if(initialized)await send(initializedNotification());return result}finally{if(timer)clearTimeout(timer);pending.delete(id)}},close:async()=>{child.off("message",handleMessage);pending.clear()}}}var REDACTED="[REDACTED]";function redactFields(obj,fields,maxDepth=5){if(typeof fields!=="function"&&fields.length===0)return obj;return redactRecord(obj,0,{isSensitive:sensitiveKeyTest(fields),maxDepth,jsonText:false})}function redactJson(value,fields){return redactValue(value,0,{isSensitive:sensitiveKeyTest(fields),maxDepth:Infinity,jsonText:true})}function sensitiveKeyTest(fields){if(typeof fields==="function")return fields;const names=new Set(fields.map(field=>field.toLowerCase()));return key=>names.has(key.toLowerCase())}function redactValue(value,depth,options){if(typeof value==="string")return options.jsonText?redactJsonText(value,depth,options):value;if(Array.isArray(value))return value.map(item=>redactValue(item,depth,options));if(isPlainObject(value))return redactRecord(value,depth,options);return value}function redactRecord(obj,depth,options){if(depth>=options.maxDepth)return obj;const result={};for(const[key,value]of Object.entries(obj)){result[key]=options.isSensitive(key)?REDACTED:redactValue(value,depth+1,options)}return result}var AUTH_SCHEME_CREDENTIAL=/\b(Bearer|Basic)([ \t]+)(?=[\w.~+/-]*[\d.~+/_-])[\w.~+/-]{8,}=*/gi;var JWT=/(?<![\w-])eyJ[\w-]+(?:\.[\w-]*){2,4}/g;var URL_CREDENTIALS=/(?<![a-z\d+.-])([a-z][a-z\d+.-]*:\/\/)[^\s/?#@]+@/gi;var VALUE_NAME=/(?:^|[?&#;,{("'\s])(["']?)([A-Za-z_][\w.-]*)\1[ \t]*[:=][ \t]*/g;var NAMED_VALUE=/"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|[^\s"'&#;?,)}]+/y;function redactNamedValues(text,isSensitive){let redacted="";let copiedUpTo=0;VALUE_NAME.lastIndex=0;for(let name=VALUE_NAME.exec(text);name;name=VALUE_NAME.exec(text)){if(!isSensitive(name[2]))continue;NAMED_VALUE.lastIndex=VALUE_NAME.lastIndex;const value=NAMED_VALUE.exec(text)?.[0];if(value===void 0)continue;const quote=value[0]==='"'||value[0]==="'"?value[0]:"";redacted+=`${text.slice(copiedUpTo,VALUE_NAME.lastIndex)}${quote}${REDACTED}${quote}`;copiedUpTo=VALUE_NAME.lastIndex+value.length;VALUE_NAME.lastIndex=copiedUpTo}return copiedUpTo===0?text:redacted+text.slice(copiedUpTo)}function redactCredentialText(text,isSensitive){const withoutCredentials=text.replace(AUTH_SCHEME_CREDENTIAL,`$1$2${REDACTED}`).replace(JWT,REDACTED).replace(URL_CREDENTIALS,`$1${REDACTED}@`);return redactNamedValues(withoutCredentials,isSensitive)}function redactJsonText(text,depth,options){const start=text.trimStart()[0];if(start!=="{"&&start!=="[")return redactCredentialText(text,options.isSensitive);let parsed;try{parsed=JSON.parse(text)}catch{return redactCredentialText(text,options.isSensitive)}const redacted=JSON.stringify(redactValue(parsed,depth,options));return redacted===JSON.stringify(parsed)?text:redacted}function isPlainObject(value){if(typeof value!=="object"||value===null)return false;const proto=Object.getPrototypeOf(value);return proto===Object.prototype||proto===null}function escapeHtml(str){if(str===null||str===void 0){return""}const s=String(str);return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function escapeHtmlAttr(str){return str.replace(/&/g,"&").replace(/"/g,""")}function escapeJsString(str){return str.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}function escapeScriptClose(jsonString){return jsonString.replace(/<\//g,"<\\/")}function safeJsonForScript(value){if(value===void 0){return"null"}try{const jsonString=JSON.stringify(value,(_key,val)=>{if(typeof val==="bigint"){return val.toString()}return val});if(jsonString===void 0){return"null"}return escapeScriptClose(jsonString)}catch{return'{"error":"Value could not be serialized"}'}}var CLASS_BRAND=Symbol.for("@frontmcp/class-brand");var ordinaryHasInstance=Function.prototype[Symbol.hasInstance];function ownBrandOf(klass){if(typeof klass!=="function"||!Object.prototype.hasOwnProperty.call(klass,CLASS_BRAND))return void 0;return klass[CLASS_BRAND]}function classOfPrototype(proto){return Object.getOwnPropertyDescriptor(proto,"constructor")?.value}function brandClass(klass,brand){Object.defineProperty(klass,CLASS_BRAND,{value:brand,enumerable:false,writable:false,configurable:false})}function isBrandedInstance(klass,value){if(ordinaryHasInstance.call(klass,value))return true;if(typeof value!=="object"||value===null)return false;const brand=ownBrandOf(klass);if(brand===void 0)return false;for(let proto=Object.getPrototypeOf(value);proto!==null;proto=Object.getPrototypeOf(proto)){if(ownBrandOf(classOfPrototype(proto))===brand)return true}return false}function safeStringify(value,space){const seen=new WeakSet;try{return JSON.stringify(value,(_key,val)=>{if(typeof val==="object"&&val!==null){if(seen.has(val))return"[Circular]";seen.add(val)}return val},space)}catch{return JSON.stringify({error:"Output could not be serialized"})}}init_crypto();var import_async_context=require("#async-context");var import_event_emitter2=require("#event-emitter");var import_env2=require("#env");var import_runtime_context=require("#runtime-context");var import_lazy_zod3=require("@frontmcp/lazy-zod");var import_env3=require("#env");var import_runtime_context2=require("#runtime-context");init_memory();init_errors();init_errors();var NAMESPACE_SEPARATOR=":";function buildPrefix(name,id){if(id){return`${name}${NAMESPACE_SEPARATOR}${id}${NAMESPACE_SEPARATOR}`}return`${name}${NAMESPACE_SEPARATOR}`}var NamespacedStorageImpl=class _NamespacedStorageImpl{constructor(adapter,prefix="",root=adapter){this.adapter=adapter;this.prefix=prefix;this.root=root}adapter;prefix;root;prefixKey(key){return this.prefix+key}unprefixKey(key){if(this.prefix&&key.startsWith(this.prefix)){return key.slice(this.prefix.length)}return key}prefixPattern(pattern){return this.prefix+pattern}prefixChannel(channel){return this.prefix+channel}namespace(name,id){const newPrefix=this.prefix+buildPrefix(name,id);return new _NamespacedStorageImpl(this.adapter,newPrefix,this.root)}async connect(){return this.adapter.connect()}async disconnect(){return this.adapter.disconnect()}async ping(){return this.adapter.ping()}async get(key){return this.adapter.get(this.prefixKey(key))}async set(key,value,options){return this.adapter.set(this.prefixKey(key),value,options)}async delete(key){return this.adapter.delete(this.prefixKey(key))}async exists(key){return this.adapter.exists(this.prefixKey(key))}async mget(keys){const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.adapter.mget(prefixedKeys)}async mset(entries){const prefixedEntries=entries.map(e=>({...e,key:this.prefixKey(e.key)}));return this.adapter.mset(prefixedEntries)}async mdelete(keys){const prefixedKeys=keys.map(k=>this.prefixKey(k));return this.adapter.mdelete(prefixedKeys)}async expire(key,ttlSeconds){return this.adapter.expire(this.prefixKey(key),ttlSeconds)}async ttl(key){return this.adapter.ttl(this.prefixKey(key))}async keys(pattern="*"){const prefixedPattern=this.prefixPattern(pattern);const keys=await this.adapter.keys(prefixedPattern);return keys.map(k=>this.unprefixKey(k))}async count(pattern="*"){const prefixedPattern=this.prefixPattern(pattern);return this.adapter.count(prefixedPattern)}async incr(key){return this.adapter.incr(this.prefixKey(key))}async decr(key){return this.adapter.decr(this.prefixKey(key))}async incrBy(key,amount){return this.adapter.incrBy(this.prefixKey(key),amount)}async deleteIfEquals(key,expectedValue){if(!this.adapter.deleteIfEquals){throw new StorageNotSupportedError("deleteIfEquals","this storage adapter")}return this.adapter.deleteIfEquals(this.prefixKey(key),expectedValue)}async expireIfEquals(key,expectedValue,ttlSeconds){if(!this.adapter.expireIfEquals){throw new StorageNotSupportedError("expireIfEquals","this storage adapter")}return this.adapter.expireIfEquals(this.prefixKey(key),expectedValue,ttlSeconds)}async setIfEquals(key,expectedValue,value){if(!this.adapter.setIfEquals){throw new StorageNotSupportedError("setIfEquals","this storage adapter")}return this.adapter.setIfEquals(this.prefixKey(key),expectedValue,value)}async publish(channel,message){return this.adapter.publish(this.prefixChannel(channel),message)}async subscribe(channel,handler){const prefixedChannel=this.prefixChannel(channel);const wrappedHandler=(message,ch)=>{const unprefixedChannel=ch.startsWith(this.prefix)?ch.slice(this.prefix.length):ch;handler(message,unprefixedChannel)};return this.adapter.subscribe(prefixedChannel,wrappedHandler)}onPubSubReconnect(listener){return this.adapter.onPubSubReconnect?.(listener)??(()=>void 0)}supportsPubSub(){return this.adapter.supportsPubSub()}};function createRootStorage(adapter){return new NamespacedStorageImpl(adapter,"",adapter)}function createNamespacedStorage(adapter,prefix){const normalizedPrefix=prefix&&!prefix.endsWith(NAMESPACE_SEPARATOR)?prefix+NAMESPACE_SEPARATOR:prefix;return new NamespacedStorageImpl(adapter,normalizedPrefix,adapter)}var SQLITE_STORAGE_PACKAGE="@frontmcp/storage-sqlite";var PATH_REQUIRED={error:"is required (the path of the database file)"};var sqliteAdapterOptionsSchema=import_lazy_zod3.z.object({path:import_lazy_zod3.z.string(PATH_REQUIRED).min(1,PATH_REQUIRED),walMode:import_lazy_zod3.z.boolean().optional(),busyTimeoutMs:import_lazy_zod3.z.number().int().nonnegative().optional(),ttlCleanupIntervalMs:import_lazy_zod3.z.number().int().nonnegative().optional(),encryption:import_lazy_zod3.z.object({secret:import_lazy_zod3.z.string().min(1)}).optional()});function parseSqliteOptions(options){const result=sqliteAdapterOptionsSchema.safeParse(options??{});if(result.success)return result.data;const problems=result.error.issues.map(issue=>`sqlite.${issue.path.join(".")}: ${issue.message}`);throw new StorageConfigError("sqlite",problems.join("; "))}function loadSqliteStorage(){try{return require(SQLITE_STORAGE_PACKAGE)}catch(error){const missing=error.code==="MODULE_NOT_FOUND";if(!missing||!String(error.message).includes(SQLITE_STORAGE_PACKAGE))throw error;throw new StorageConfigError("sqlite",`the sqlite type needs ${SQLITE_STORAGE_PACKAGE}. Install it with: npm install ${SQLITE_STORAGE_PACKAGE}`)}}var noDistributedStorageWarned=false;function warnNoDistributedStorage(){if(noDistributedStorageWarned||(0,import_runtime_context2.getRuntimeContext)().runtime==="browser")return;noDistributedStorageWarned=true;console.warn("[storage] Warning: No distributed storage backend detected in production. Using in-memory storage. Set REDIS_URL, UPSTASH_REDIS_REST_URL, or KV_REST_API_URL.")}function detectStorageType(){if((0,import_env3.getEnv)("UPSTASH_REDIS_REST_URL")&&(0,import_env3.getEnv)("UPSTASH_REDIS_REST_TOKEN")){return"upstash"}if((0,import_env3.getEnv)("KV_REST_API_URL")&&(0,import_env3.getEnv)("KV_REST_API_TOKEN")){return"vercel-kv"}if((0,import_env3.getEnv)("REDIS_URL")||(0,import_env3.getEnv)("REDIS_HOST")){return"redis"}return"memory"}async function createAdapter(type,config){switch(type){case"memory":{return new MemoryStorageAdapter(config.memory)}case"redis":{const{RedisStorageAdapter:RedisStorageAdapter2}=await Promise.resolve().then(()=>(init_redis(),redis_exports));return new RedisStorageAdapter2(config.redis)}case"vercel-kv":{const{VercelKvStorageAdapter:VercelKvStorageAdapter2}=await Promise.resolve().then(()=>(init_vercel_kv(),vercel_kv_exports));return new VercelKvStorageAdapter2(config.vercelKv)}case"upstash":{const{UpstashStorageAdapter:UpstashStorageAdapter2}=await Promise.resolve().then(()=>(init_upstash(),upstash_exports));return new UpstashStorageAdapter2(config.upstash)}case"sqlite":{const{SqliteStorageAdapter}=loadSqliteStorage();return new SqliteStorageAdapter(parseSqliteOptions(config.sqlite))}case"cloudflare-kv":{if(!config.cloudflareKv){throw new StorageConfigError("cloudflare-kv","cloudflare-kv requires `cloudflareKv: { namespace }` (the KV binding can't be auto-detected)")}const{CloudflareKvStorageAdapter:CloudflareKvStorageAdapter2}=await Promise.resolve().then(()=>(init_cloudflare_kv(),cloudflare_kv_exports));return new CloudflareKvStorageAdapter2(config.cloudflareKv)}case"auto":throw new StorageConfigError("auto","Auto type should be resolved before calling createAdapter");default:throw new StorageConfigError("unknown",`Unknown storage type: ${type}`)}}async function createStorage(config={}){let type=config.type??"auto";const fallback=config.fallback??((0,import_env3.isProduction)()?"error":"memory");if(type==="auto"){type=detectStorageType();if(type==="memory"&&(0,import_env3.isProduction)())warnNoDistributedStorage()}if(type==="sqlite")parseSqliteOptions(config.sqlite);let adapter;try{adapter=await createAdapter(type,config)}catch(e){if(fallback==="memory"&&type!=="memory"){console.warn(`[storage] Warning: Failed to create ${type} adapter, falling back to memory. Error: ${e instanceof Error?e.message:String(e)}`);adapter=new MemoryStorageAdapter(config.memory)}else{throw e}}try{await adapter.connect()}catch(e){if(fallback==="memory"&&type!=="memory"){console.warn(`[storage] Warning: Failed to connect to ${type}, falling back to memory. Error: ${e instanceof Error?e.message:String(e)}`);adapter=new MemoryStorageAdapter(config.memory);await adapter.connect()}else{throw e}}if(config.prefix){return createNamespacedStorage(adapter,config.prefix)}return createRootStorage(adapter)}function createMemoryStorage(config={}){const adapter=new MemoryStorageAdapter(config);if(config.prefix){return createNamespacedStorage(adapter,config.prefix)}return createRootStorage(adapter)}function getDetectedStorageType(){return detectStorageType()}var DEFAULT_CHANGE_FEED_POLL_INTERVAL_MS=250;var DEFAULT_CHANGE_FEED_COALESCE_MS=50;var TOPIC_PREFIX="feed:";var TopicFeed=class{constructor(options){this.options=options}options;closed=false;listeners=new Map;pending=new Map;subscribe(topic,listener){let topicListeners=this.listeners.get(topic);if(!topicListeners){topicListeners=new Set;this.listeners.set(topic,topicListeners);this.watch(topic)}const subscribed=topicListeners;subscribed.add(listener);return()=>{if(!subscribed.delete(listener)||subscribed.size>0||this.listeners.get(topic)!==subscribed)return;this.listeners.delete(topic);this.unwatch(topic)}}async close(){this.closed=true;for(const timer of this.pending.values())clearTimeout(timer);this.pending.clear();for(const topic of this.listeners.keys())this.unwatch(topic);this.listeners.clear()}changed(topic){if(this.closed||this.pending.has(topic)||!this.listeners.has(topic))return;const timer=setTimeout(()=>{this.pending.delete(topic);for(const listener of[...this.listeners.get(topic)??[]]){try{listener()}catch(error){this.options.onError?.(error)}}},this.options.coalesceMs??DEFAULT_CHANGE_FEED_COALESCE_MS);timer.unref?.();this.pending.set(topic,timer)}};var LocalChangeFeed=class extends TopicFeed{kind="local";async publish(topic){this.changed(topic)}watch(){return}unwatch(){return}};var PubSubChangeFeed=class extends TopicFeed{constructor(storage,options){super(options);this.storage=storage;this.stopReconnectListener=storage.onPubSubReconnect?.(()=>{for(const topic of this.channels.keys())this.changed(topic)})}storage;kind="pubsub";channels=new Map;stopReconnectListener;async close(){this.stopReconnectListener?.();await super.close()}async publish(topic){await this.storage.publish(TOPIC_PREFIX+topic,"")}watch(topic){const subscription=this.storage.subscribe(TOPIC_PREFIX+topic,()=>this.changed(topic)).catch(error=>{this.options.onError?.(error);return void 0});this.channels.set(topic,subscription)}unwatch(topic){const subscription=this.channels.get(topic);this.channels.delete(topic);void subscription?.then(unsubscribe=>unsubscribe?.()).catch(error=>this.options.onError?.(error))}};var pollingFeeds=new Set;var PollingChangeFeed=class extends TopicFeed{constructor(storage,options){super(options);this.storage=storage;pollingFeeds.add(this)}storage;kind="poll";seen=new Map;timer;polling=false;lastVersion;failing=false;async publish(topic){const count=String(await this.storage.incr(TOPIC_PREFIX+topic));if(this.seen.has(topic))this.seen.set(topic,count);const counterKey=this.storage.prefix+TOPIC_PREFIX+topic;for(const feed of pollingFeeds)feed.published(counterKey)}async close(){pollingFeeds.delete(this);await super.close();clearTimeout(this.timer);this.timer=void 0}published(counterKey){const ownPrefix=this.storage.prefix+TOPIC_PREFIX;if(!counterKey.startsWith(ownPrefix))return;const topic=counterKey.slice(ownPrefix.length);if(this.seen.has(topic))this.changed(topic)}watch(topic){this.seen.set(topic,void 0);void this.storage.get(TOPIC_PREFIX+topic).then(count=>{if(this.seen.has(topic)&&this.seen.get(topic)===void 0)this.seen.set(topic,count)},error=>this.options.onError?.(error));this.schedule()}unwatch(topic){this.seen.delete(topic);if(this.seen.size>0)return;clearTimeout(this.timer);this.timer=void 0}schedule(){if(this.timer||this.polling||this.closed||this.seen.size===0)return;this.timer=setTimeout(()=>{this.timer=void 0;void this.poll()},this.options.pollIntervalMs??DEFAULT_CHANGE_FEED_POLL_INTERVAL_MS);this.timer.unref?.()}async poll(){this.polling=true;try{const version=await this.storage.root.dataVersion?.();if(version!==this.lastVersion){const topics=[...this.seen.keys()];const counts=await this.storage.mget(topics.map(topic=>TOPIC_PREFIX+topic));this.lastVersion=version;topics.forEach((topic,index)=>this.compare(topic,counts[index]))}this.failing=false}catch(error){if(!this.failing&&!this.closed)this.options.onError?.(error);this.failing=true}finally{this.polling=false;this.schedule()}}compare(topic,count){if(!this.seen.has(topic))return;const before=this.seen.get(topic);this.seen.set(topic,count);if(before!==void 0&&before!==count)this.changed(topic)}};function createChangeFeed(storage,options={}){if(storage.supportsPubSub())return new PubSubChangeFeed(storage,options);if(storage.root.dataVersion)return new PollingChangeFeed(storage,options);return new LocalChangeFeed(options)}init_redis_error_listener();init_redis_url();init_errors();var TypedStorage=class{storage;serialize;deserialize;schema;throwOnInvalid;constructor(storage,options={}){this.storage=storage;this.serialize=options.serialize??JSON.stringify;this.deserialize=options.deserialize??JSON.parse;this.schema=options.schema;this.throwOnInvalid=options.throwOnInvalid??false}async get(key){const raw=await this.storage.get(key);if(raw===null){return null}return this.parseValue(raw,key)}async set(key,value,options){const serialized=this.serialize(value);await this.storage.set(key,serialized,options)}async delete(key){return this.storage.delete(key)}async exists(key){return this.storage.exists(key)}async mget(keys){if(keys.length===0){return[]}const rawValues=await this.storage.mget(keys);return rawValues.map((raw,index)=>{if(raw===null){return null}return this.parseValue(raw,keys[index])})}async mset(entries){if(entries.length===0){return}const rawEntries=entries.map(entry=>({key:entry.key,value:this.serialize(entry.value),options:entry.options}));await this.storage.mset(rawEntries)}async mdelete(keys){return this.storage.mdelete(keys)}async expire(key,ttlSeconds){return this.storage.expire(key,ttlSeconds)}async ttl(key){return this.storage.ttl(key)}async keys(pattern){return this.storage.keys(pattern)}async count(pattern){return this.storage.count(pattern)}get raw(){return this.storage}parseValue(raw,key){try{const parsed=this.deserialize(raw);if(this.schema){const result=this.schema.safeParse(parsed);if(!result.success){if(this.throwOnInvalid){throw new Error(`TypedStorage validation failed for key "${key}": ${result.error.message}`)}return null}return result.data}return parsed}catch(error){if(this.throwOnInvalid){throw error}return null}}};init_crypto();init_errors();var textEncoder2=new TextEncoder;var textDecoder2=new TextDecoder;var EncryptedTypedStorage=class{storage;activeKey;keyMap;schema;throwOnError;onKeyRotationNeeded;clientBinding;constructor(storage,options){if(!options.keys||options.keys.length===0){throw new EncryptedStorageError("At least one encryption key is required")}for(const k of options.keys){if(k.key.length!==32){throw new EncryptedStorageError(`Encryption key "${k.kid}" must be 32 bytes (AES-256), got ${k.key.length} bytes`)}}this.storage=storage;this.activeKey=options.keys[0];this.keyMap=new Map(options.keys.map(k=>[k.kid,k.key]));this.schema=options.schema;this.throwOnError=options.throwOnError??false;this.onKeyRotationNeeded=options.onKeyRotationNeeded;this.clientBinding=options.clientBinding}async get(key){const raw=await this.storage.get(key);if(raw===null){return null}return this.decryptAndParse(raw,key)}async set(key,value,options){const encrypted=this.encryptValue(value);const serialized=JSON.stringify(encrypted);await this.storage.set(key,serialized,options)}async delete(key){return this.storage.delete(key)}async exists(key){return this.storage.exists(key)}async mget(keys){if(keys.length===0){return[]}const rawValues=await this.storage.mget(keys);return rawValues.map((raw,index)=>{if(raw===null){return null}return this.decryptAndParse(raw,keys[index])})}async mset(entries){if(entries.length===0){return}const rawEntries=entries.map(entry=>({key:entry.key,value:JSON.stringify(this.encryptValue(entry.value)),options:entry.options}));await this.storage.mset(rawEntries)}async mdelete(keys){return this.storage.mdelete(keys)}async expire(key,ttlSeconds){return this.storage.expire(key,ttlSeconds)}async ttl(key){return this.storage.ttl(key)}async keys(pattern){return this.storage.keys(pattern)}async count(pattern){return this.storage.count(pattern)}async reencrypt(key,options){const value=await this.get(key);if(value===null){return false}await this.set(key,value,options);return true}rotateKey(newKey){if(newKey.key.length!==32){throw new EncryptedStorageError(`New encryption key must be 32 bytes (AES-256), got ${newKey.key.length} bytes`)}if(!this.keyMap.has(newKey.kid)){this.keyMap.set(newKey.kid,newKey.key)}this.activeKey=newKey}get activeKeyId(){return this.activeKey.kid}get keyIds(){return Array.from(this.keyMap.keys())}get raw(){return this.storage}get hasClientBinding(){return this.clientBinding!==void 0}deriveKey(serverKey){if(!this.clientBinding){return serverKey}const clientSecret=typeof this.clientBinding.secret==="string"?textEncoder2.encode(this.clientBinding.secret):this.clientBinding.secret;const ikm=new Uint8Array(serverKey.length+clientSecret.length);ikm.set(serverKey,0);ikm.set(clientSecret,serverKey.length);const salt=this.clientBinding.salt??new Uint8Array(0);const info=textEncoder2.encode(this.clientBinding.info??"frontmcp-client-bound-v1");return hkdfSha256(ikm,salt,info,32)}encryptValue(value){let jsonString;try{jsonString=JSON.stringify(value)}catch(error){throw new EncryptedStorageError(`Failed to serialize value: ${error.message}`)}const plaintext=textEncoder2.encode(jsonString);const iv=randomBytes(12);const encryptionKey=this.deriveKey(this.activeKey.key);const{ciphertext,tag}=encryptAesGcm(encryptionKey,plaintext,iv);return{alg:"A256GCM",kid:this.activeKey.kid,iv:base64urlEncode(iv),tag:base64urlEncode(tag),data:base64urlEncode(ciphertext)}}decryptAndParse(raw,storageKey){let blob;try{blob=JSON.parse(raw)}catch(_error){if(this.throwOnError){throw new EncryptedStorageError(`Failed to parse stored blob for key "${storageKey}"`)}return null}if(!this.isValidBlob(blob)){if(this.throwOnError){throw new EncryptedStorageError(`Invalid encrypted blob structure for key "${storageKey}"`)}return null}const serverKey=this.keyMap.get(blob.kid);if(!serverKey){if(this.throwOnError){throw new EncryptedStorageError(`Unknown encryption key "${blob.kid}" for key "${storageKey}". Known keys: ${Array.from(this.keyMap.keys()).join(", ")}`)}return null}const decryptionKey=this.deriveKey(serverKey);let decrypted;try{const iv=base64urlDecode(blob.iv);const tag=base64urlDecode(blob.tag);const ciphertext=base64urlDecode(blob.data);const plaintext=decryptAesGcm(decryptionKey,ciphertext,iv,tag);decrypted=JSON.parse(textDecoder2.decode(plaintext))}catch(error){if(this.throwOnError){throw new EncryptedStorageError(`Decryption failed for key "${storageKey}": ${error.message}`)}return null}if(this.schema){const result=this.schema.safeParse(decrypted);if(!result.success){if(this.throwOnError){throw new EncryptedStorageError(`Schema validation failed for key "${storageKey}": ${result.error.message}`)}return null}decrypted=result.data}if(blob.kid!==this.activeKey.kid&&this.onKeyRotationNeeded){this.onKeyRotationNeeded(storageKey,blob.kid,this.activeKey.kid)}return decrypted}isValidBlob(blob){return typeof blob==="object"&&blob!==null&&"alg"in blob&&"kid"in blob&&"iv"in blob&&"tag"in blob&&"data"in blob&&blob.alg==="A256GCM"&&typeof blob.kid==="string"&&typeof blob.iv==="string"&&typeof blob.tag==="string"&&typeof blob.data==="string"}};init_base();init_memory();init_redis();init_vercel_kv();init_upstash();init_filesystem();init_pattern();init_ttl();async function processPlatformToolCalls(platform,calls,callTool){switch(platform){case"openai":return processOpenAI(calls,callTool);case"claude":return processClaude(calls,callTool);case"vercel-ai":return processVercel(calls,callTool);default:throw new Error(`Unsupported platform: ${platform}`)}}async function processOpenAI(toolCalls,callTool){return Promise.all(toolCalls.map(async tc=>{let args;try{args=JSON.parse(tc.function.arguments)}catch{return{role:"tool",tool_call_id:tc.id,content:JSON.stringify({error:`Invalid JSON in tool call arguments for "${tc.function.name}"`})}}const result=await callTool(tc.function.name,args);return{role:"tool",tool_call_id:tc.id,content:typeof result==="string"?result:JSON.stringify(result)}}))}async function processClaude(toolUseBlocks,callTool){return Promise.all(toolUseBlocks.map(async block=>{const result=await callTool(block.name,block.input);const content=Array.isArray(result)?result.map(c=>c.text??"").join("\n"):typeof result==="string"?result:JSON.stringify(result);return{type:"tool_result",tool_use_id:block.id,content}}))}async function processVercel(info,callTool){const args=info.args!=null&&typeof info.args==="object"&&!Array.isArray(info.args)?info.args:void 0;return callTool(info.toolName,args)}init_crypto();init_runtime();function getEnvDirect(key){return typeof process!=="undefined"?process.env[key]:void 0}function isProductionDirect(){return getEnvDirect("NODE_ENV")==="production"}var DEFAULT_MACHINE_ID_PATH=".frontmcp/machine-id";function isDevPersistenceEnabled(){if(isBrowser())return false;return!isProductionDirect()}function resolveMachineIdPath(){if(isBrowser())return DEFAULT_MACHINE_ID_PATH;const path=require("path");const machineIdPath=getEnvDirect("MACHINE_ID_PATH")??DEFAULT_MACHINE_ID_PATH;const cwd=typeof process!=="undefined"?process.cwd():".";return path.isAbsolute(machineIdPath)?machineIdPath:path.resolve(cwd,machineIdPath)}function loadMachineIdSync(){if(!isDevPersistenceEnabled())return null;const machineIdPath=resolveMachineIdPath();try{const fs=require("fs");const content=fs.readFileSync(machineIdPath,"utf8").trim();if(/^[0-9a-f-]{32,36}$/i.test(content))return content;console.warn(`[MachineId] Invalid format at ${machineIdPath}, will regenerate`);return null}catch(error){if(error.code!=="ENOENT"){console.warn(`[MachineId] Failed to load from ${machineIdPath}: ${error.message}`)}return null}}function saveMachineIdAsync(machineId){if(!isDevPersistenceEnabled())return;const machineIdPath=resolveMachineIdPath();const path=require("path");const dir=path.dirname(machineIdPath);(async()=>{try{const fsp=require("fs").promises;await fsp.mkdir(dir,{recursive:true,mode:448});await fsp.writeFile(machineIdPath,machineId,{mode:384})}catch(error){console.warn(`[MachineId] Failed to save to ${machineIdPath}: ${error.message}`)}})()}function getHostname(){if(!isNode())return void 0;try{return require("os").hostname()}catch{return void 0}}function computeMachineId(){const envMachineId=getEnvDirect("MACHINE_ID");if(envMachineId)return envMachineId;const deploymentMode=getEnvDirect("FRONTMCP_DEPLOYMENT_MODE");if(deploymentMode==="distributed"){const hostname=getEnvDirect("HOSTNAME");if(hostname)return hostname;if(isNode()){const os=require("os");return os.hostname()}}if(deploymentMode==="serverless"){return randomUUID()}const loadedId=loadMachineIdSync();if(loadedId)return loadedId;const newId=randomUUID();saveMachineIdAsync(newId);return newId}var cachedMachineId;var machineIdOverride;function getMachineId(){if(machineIdOverride!==void 0)return machineIdOverride;if(cachedMachineId===void 0){cachedMachineId=computeMachineId()}return cachedMachineId}function setMachineIdOverride(id){machineIdOverride=id}0&&(module.exports={AsyncContextOverlapError,AsyncLocalStorage,BaseStorageAdapter,DEFAULT_CHANGE_FEED_COALESCE_MS,DEFAULT_CHANGE_FEED_POLL_INTERVAL_MS,DEFAULT_CODE_VERIFIER_LENGTH,DEFAULT_MAX_INPUT_LENGTH,DEFAULT_REDIS_ERROR_LOG_INTERVAL_MS,DEV_BUFFER_FULL,DEV_ERROR_MESSAGE,DEV_RELOAD_DEADLINE,DEV_SERVER_UNREACHABLE,EncryptedBlobError,EncryptedStorageError,EncryptedTypedStorage,EventEmitter,FileSystemStorageAdapter,KeyPersistence,MAX_CODE_VERIFIER_LENGTH,MAX_TTL_SECONDS,MIN_CODE_VERIFIER_LENGTH,MemoryStorageAdapter,NAMESPACE_SEPARATOR,NamespacedStorageImpl,OwnedProcessError,PkceError,REDOS_THRESHOLDS,RedisStorageAdapter,StorageConfigError,StorageConnectionError,StorageError,StorageNotConnectedError,StorageNotSupportedError,StorageOperationError,StoragePatternError,StorageTTLError,TypedStorage,UpstashStorageAdapter,VercelKvStorageAdapter,access,analyzePattern,anyKeyDataSchema,appendFile,assertNode,asymmetricAlgSchema,asymmetricKeyDataSchema,attachRedisErrorListener,awaitOutsideRequest,base64Decode,base64Encode,base64urlDecode,base64urlEncode,basename,brandClass,buildPrefix,buildSetCookie,bytesToHex,checkEntryAvailability,chmod,classifyIpAddress,clearCachedSecret,collapseChar,collapseWhitespace,copyFile,cp,createBridgeStateMachine,createChangeFeed,createHttpUpstream,createKeyPersistence,createKeyPersistenceWithStorage,createMemoryStorage,createNamespacedStorage,createPipeUpstream,createRedisClient,createRootStorage,createSafeRegExp,createSecretData,createStdioFramer,createStorage,createVercelKvClient,decryptAesGcm,decryptValue,deleteSecret,describeRedisUrlConflicts,deserializeAndDecrypt,deserializeBlob,detectRuntimeContext,dirname,encryptAesGcm,encryptAndSerialize,encryptValue,ensureDir,ensureDirSync,ensureMaxLen,entryAvailabilitySchema,escapeGlob,escapeHtml,escapeHtmlAttr,escapeJsString,escapeScriptClose,expandIpv6,expandTemplate,expandUriTemplate,expiresAtToTTL,extname,extractBracedParams,extractEmbeddedIpv4,extractTemplateParams,extractUriScheme,fileExists,fileExistsSync,findDroppedKeys,findNonFiniteNumber,generateCodeChallenge,generateCodeVerifier,generatePkcePair,generateRsaKeyPair,generateSecret,getAsyncContextMode,getCookie,getCrypto,getCwd,getDetectedStorageType,getEnv,getEnvFlag,getHostname,getMachineId,getNodeEnv,getOrCreateSecret,getRuntimeContext,getSpawnFn,globToRegex,hasTemplatePlaceholders,hkdfSha256,hmacSha256,idFromString,inferMimeType,isAbsolute,isAsymmetricKeyData,isBrandedInstance,isBrowser,isDebug,isDevelopment,isDirEmpty,isEdgeRuntime,isEntryAvailable,isExpired,isInputLengthSafe,isLocalhost,isNode,isPatternSafe,isProcessTreeAlive,isProduction,isRedirectResponse,isRsaPssAlg,isSecretCached,isSecretKeyData,isSecretPersistenceEnabled,isSecureRequest,isServerless,isSignedData,isUriTemplate,isValidCodeChallenge,isValidCodeVerifier,isValidEncryptedBlob,isValidMcpUri,isValidMcpUriTemplate,joinPath,jwtAlgToNodeAlg,listChangedNotifications,loadSecret,lstat,makeDevError,matchUriTemplate,matchesPattern,mergeRedisUrlFields,mkdir,mkdtemp,normalizeTTL,parseCookies,parseIpv4,parseKeyData,parseSecretData,parseUriTemplate,pathJoin,pathResolve,pathToFileURL,pemToPublicJwk,processPlatformToolCalls,processTreeSpawnOptions,randomBytes,randomUUID,readFile,readFileBuffer,readFileSync,readJSON,readdir,readdirSync,realpath,reapOrphans,redactFields,redactJson,rename,resetRuntimeContext,resolveSecretPath,rm,rsaSignBase64Url,rsaVerify,rsaVerifySync,runCmd,runRequestExclusive,safeExec,safeJsonForScript,safeMatch,safeReplace,safeStringify,safeTest,sanitizeToJson,saveSecret,secretDataSchema,secretKeyDataSchema,sep,sepFor,serializeBlob,setEnv,setMachineIdOverride,sha256,sha256Base64url,sha256Hex,shortHash,signData,signalProcessTree,spawnOwned,splitWords,stat,stopProcessTree,supportsAnsi,symlink,timingSafeEqual,toCase,trimBoth,trimChars,trimLeading,trimSlashes,trimTrailing,tryDecryptValue,tryDeserializeAndDecrypt,tryDeserializeBlob,ttlToExpiresAt,unlink,validateBaseUrl,validateKeyData,validateOptionalTTL,validatePattern,validateSecretData,validateTTL,verifyCodeChallenge,verifyData,verifyOrParseData,watchFile,watchParent,watchPath,writeFile,writeJSON});
|