{"version":3,"sources":["../src/index.ts","../src/logger.ts","../src/app.ts","../config/config-prod.ts","../src/api.ts","../src/manager.ts","../src/config/schemas.ts","../src/config/store.ts","../src/config/provider.ts","../src/auth/provider.ts","../src/auth/propel.ts","../src/auth/oauth.ts","../src/analytics/posthog.ts","../src/analytics/provider.ts","../src/config/secrets.ts","../src/auth/auth-store.ts","../src/user-provider-factory.ts","../src/multi-tenant-provider.ts"],"sourcesContent":["export * from \"./app.js\";\nexport * from \"./api.js\";\nexport * from \"./manager.js\";\nexport * from \"./analytics/provider.js\";\nexport * from \"./auth/provider.js\";\nexport * from \"./auth/auth-store.js\";\nexport * from \"./auth/propel.js\";\nexport * from \"./config/provider.js\";\nexport * from \"./config/secrets.js\";\nexport * from \"./config/store.js\";\nexport * from \"./config/schemas.js\";\nexport * from \"./user-provider-factory.js\";\nexport * from \"./multi-tenant-provider.js\";\n","import { getChildLogger } from \"@toolprint/sdk\";\n\nconst providersLogLevel = () => {\n  return (\n    process.env.ONEGREP_PROVIDERS_LOG_LEVEL ?? process.env.LOG_LEVEL ?? \"info\"\n  );\n};\n\n// The child logger for the CLI, which uses the env vars or defaults\nconst getLogger = () => {\n  return getChildLogger(\"providers\", providersLogLevel());\n};\n\nexport const logger = getLogger();\n","import { AppConfig } from \"./config/schemas.js\";\nimport { logger } from \"./logger.js\";\nimport { z } from \"zod\";\nimport { appConfig as prod } from \"../config/config-prod.js\";\n\n// NodeEnv is a commonly used env var BUT using it here can result in conflicts with\n// a lot of other libraries that use it.\n// TODO: Rename to AppEnv\nexport type AppEnv = \"test\" | \"development\" | \"production\";\nexport type DevMode = \"linked\" | \"source\";\n\nexport const appEnv = z.object({\n  APP_ENV: z\n    .any()\n    .transform((val) => {\n      return val?.toString().trim().toLowerCase();\n    })\n    .refine((val) => [\"test\", \"development\", \"production\"].includes(val), {\n      message: \"APP_ENV must be one of: test, development, production\",\n    })\n    .default(\"production\"),\n  DEV_MODE: z\n    .string()\n    .transform((val) => val?.trim().toLowerCase())\n    .pipe(z.enum([\"linked\", \"source\"]))\n    .optional(),\n  ONEGREP_APP_CONFIG: z.string().optional(),\n});\n\nexport function getEnv(): z.infer<typeof appEnv> {\n  const parsedEnv = appEnv.strip().parse(process.env);\n\n  if ([\"development\"].includes(parsedEnv.APP_ENV) && !parsedEnv.DEV_MODE) {\n    throw new Error(`DEV_MODE is required when APP_ENV is development`);\n  }\n  if (parsedEnv.APP_ENV === \"production\" && !!parsedEnv.DEV_MODE) {\n    throw new Error(`DEV_MODE is not allowed when APP_ENV is production`);\n  }\n  return parsedEnv;\n}\n\nexport const getAppConfig = async (): Promise<AppConfig> => {\n  const env = getEnv();\n  logger.debug(`App config loaded for ${env.APP_ENV} environment`);\n\n  // If we're in production, we use bundled prod config\n  if (env.APP_ENV === \"production\") {\n    return prod;\n  }\n\n  // If we're not in production, we dynamically import app config from a JSON file\n  if (!env.ONEGREP_APP_CONFIG) {\n    throw new Error(\"ONEGREP_APP_CONFIG is required if not in production\");\n  }\n\n  const fs = await import(\"fs\");\n\n  // ? config-{var}.ts under the ../config/ directory\n  const path = await import(\"path\");\n  const __dirname = path.dirname(new URL(import.meta.url).pathname);\n  const configDir = path.resolve(__dirname, \"..\", \"config\");\n\n  const appConfigFileName = `${env.ONEGREP_APP_CONFIG}.json`;\n  const appConfigPath = path.resolve(configDir, appConfigFileName);\n  logger.debug(`Loading app config from ${appConfigPath}`);\n\n  const appConfig = JSON.parse(fs.readFileSync(appConfigPath, \"utf8\"));\n  return appConfig;\n};\n","import { AppConfig } from \"../src/config/schemas.js\";\n\n/**\n * Bake in the production launch config here.\n * Prevents a majority of cases where the user\n * could override values.\n */\nexport const appConfig: AppConfig = {\n  propelAuth: {\n    url: \"https://auth.onegrep.dev\",\n  },\n  oidc: {\n    discoveryUrl: \"https://auth.onegrep.dev/.well-known/openid-configuration\",\n    clientId: \"9de8c8c4fd9cf1c63a9c95d079979a09\",\n  },\n  agent: {\n    agentType: \"blaxel\",\n    url: \"https://run.blaxel.ai/onegrep/agents/agent-demo-sandbox\",\n    apiKey: \"bl_216917beczu7cngzk2rrnuzx2vn766te\",\n  },\n  demoSandbox: {\n    api: {\n      url: \"https://demo.sandbox.onegrep.dev\",\n    },\n    invitationCode: \"SANDBOX\",\n  },\n  posthog: {\n    apiKey: \"phc_76OFLcbYe3zQ6QUcIUKl2tMwUveGOBwNBfG6H9Ed4rK\",\n  },\n};\n","import {\n  createApiClientFromParams,\n  createUnauthenticatedClient,\n  OneGrepApiClient,\n  OneGrepApiHighLevelClient,\n} from \"@toolprint/sdk\";\nimport { Config } from \"./config/schemas.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Validate an API URL by checking if the health check endpoint is reachable.\n * @param url The API URL to validate\n * @returns True if the API URL is valid, false otherwise\n */\nexport async function validateApiUrl(url: string): Promise<boolean> {\n  try {\n    const client = createUnauthenticatedClient(url);\n\n    // TODO: High level client health check seems broken.\n    const response = await client.get({\n      responseType: \"json\",\n      url: \"/health\",\n    });\n    if (response.status !== 200) {\n      logger.debug(\n        `Health check failed with status ${response.status} for API URL: ${url}`,\n      );\n      return false;\n    }\n\n    logger.debug(`Health check passed for API URL: ${url}`);\n    return true;\n  } catch (error) {\n    logger.debug(`Unable to validate API URL: ${url} ${JSON.stringify(error)}`);\n    return false;\n  }\n}\n\n/**\n * Create a raw API Client from a Config object.\n * @param config The config to use to create the client\n * @returns A an initialized OneGrepApiClient\n */\nexport function clientFromConfig(config: Config): OneGrepApiClient {\n  try {\n    // Check if API URL is set\n    if (!config.api.url) {\n      throw new Error(\n        \"API URL is not set. Please set an API URL using the account setup command.\",\n      );\n    }\n\n    const clientParams = {\n      baseUrl: config.api.url,\n      accessToken: config.credentials?.accessToken,\n      apiKey: config.credentials?.apiKey,\n    };\n\n    logger.debug(`Creating client pointing to ${clientParams.baseUrl}`);\n\n    return createApiClientFromParams(clientParams);\n  } catch (error) {\n    logger.debug(`Failed to create API client: ${error}`);\n    throw error;\n  }\n}\n\nexport function bearerAuthClientFromConfig(\n  config: Config,\n): OneGrepApiHighLevelClient {\n  return new OneGrepApiHighLevelClient(clientFromConfig(config));\n}\n\nexport async function apiKeyFromConfig(config: Config): Promise<string> {\n  // First check environment variable\n  if (!!process.env.ONEGREP_API_KEY) {\n    logger.debug(\"Using API key from environment variable\");\n    return process.env.ONEGREP_API_KEY;\n  }\n\n  // Check if API key is already in credentials (from X-API-KEY header)\n  if (config.credentials?.apiKey) {\n    logger.debug(\"Using API key from credentials\");\n    return config.credentials.apiKey;\n  }\n\n  // Otherwise, try to get API key from account information using bearer auth\n  logger.debug(\"Fetching API key from account information using bearer auth\", {\n    hasAccessToken: !!config.credentials?.accessToken,\n    apiUrl: config.api?.url,\n  });\n\n  // This should never happen - if we're trying to fetch API key via bearer auth without an access token\n  if (!config.credentials?.accessToken) {\n    logger.error(\n      \"Attempting to fetch API key via bearer auth without access token - this will fail\",\n    );\n    throw new Error(\n      \"Cannot fetch API key: no access token available for bearer authentication\",\n    );\n  }\n\n  const userClient = bearerAuthClientFromConfig(config);\n  const userAccount = await userClient.getAccountInformation();\n\n  if (!userAccount) {\n    throw new Error(\"No account information found\");\n  }\n  logger.debug(`Using API key for user: ${userAccount.account.id}`);\n\n  return userAccount.account.api_key;\n}\n\nexport async function isClientAuthenticated(\n  client: OneGrepApiClient,\n): Promise<boolean> {\n  const highLevelClient = new OneGrepApiHighLevelClient(client);\n  const response = await highLevelClient.authStatus();\n  return response.credentials_provided && response.is_authenticated;\n}\n\nexport async function apiKeyClientFromConfig(\n  config: Config,\n): Promise<OneGrepApiClient> {\n  const apiKey = await apiKeyFromConfig(config);\n\n  return createApiClientFromParams({\n    baseUrl: config.api.url,\n    apiKey: apiKey,\n  });\n}\n","import { Flags, FlagsProvider, FlagValue } from \"@toolprint/sdk\";\n\nimport { ConfigProvider } from \"./config/provider.js\";\nimport { AuthProvider } from \"./auth/provider.js\";\nimport {\n  AnalyticsProvider,\n  AnalyticsProviderImpl,\n  DummyAnalyticsProvider,\n} from \"./analytics/provider.js\";\n\nimport { getAppConfig } from \"./app.js\";\nimport { logger } from \"./logger.js\";\nimport { newSecretStorage } from \"./config/secrets.js\";\nimport { storedConfigSchema } from \"./config/schemas.js\";\n\nexport type {\n  ConfigProvider,\n  AuthProvider,\n  AnalyticsProvider,\n  DummyAnalyticsProvider,\n};\n\nexport interface Providers {\n  readonly configProvider: ConfigProvider;\n  readonly authProvider: AuthProvider;\n  readonly analyticsProvider: AnalyticsProviderImpl;\n  readonly flagsProvider: ValidatedFlagsProvider;\n}\n\n/**\n * The flags that are specific to the CLI.\n */\nconst CLI_FLAGS = [\"onegrep-cli-main-menu-settings-enabled\"];\n\nclass FlagConfigurationError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"FlagConfigurationError\";\n  }\n}\n\nclass ValidatedFlagsProvider {\n  private readonly configProvider: ConfigProvider;\n  private readonly authProvider: AuthProvider;\n\n  constructor(configProvider: ConfigProvider, authProvider: AuthProvider) {\n    this.configProvider = configProvider;\n    this.authProvider = authProvider;\n  }\n\n  /**\n   * Lazy-initializes the flags provider because we might not have\n   * authentication configured at the time of instantiation.\n   */\n  private async getProvider(): Promise<FlagsProvider> {\n    return new FlagsProvider(await this.authProvider.getApi());\n  }\n\n  private isValidFlagName(flagName: string): boolean {\n    return CLI_FLAGS.includes(flagName);\n  }\n\n  validateFlagName(flagName: string): void {\n    if (!this.isValidFlagName(flagName)) {\n      throw new FlagConfigurationError(\n        `Flag ${flagName} is not a valid CLI flag`,\n      );\n    }\n  }\n\n  async all(): Promise<Flags> {\n    const flags = await (await this.getProvider()).all();\n    // Filter flags to only include known CLI-specific flags\n    const cliFlags: Flags = {};\n    for (const flagName of CLI_FLAGS) {\n      if (this.isValidFlagName(flagName)) {\n        cliFlags[flagName] = flags[flagName];\n      }\n    }\n    return cliFlags;\n  }\n\n  async value(flagName: string): Promise<FlagValue | undefined> {\n    this.validateFlagName(flagName);\n    return (await this.getProvider()).value(flagName);\n  }\n}\n\nexport async function getProviders(): Promise<Providers> {\n  try {\n    const appConfig = await getAppConfig();\n\n    const configDirSecretStorage = await newSecretStorage(\n      storedConfigSchema,\n      \"config-dir\",\n    );\n    const configProvider = new ConfigProvider(\n      appConfig,\n      configDirSecretStorage,\n    );\n    await configProvider.init();\n\n    const authProvider = new AuthProvider({ configProvider });\n\n    let analyticsProvider: AnalyticsProviderImpl;\n    if (!!appConfig.posthog?.apiKey) {\n      analyticsProvider = new AnalyticsProvider({\n        appConfig,\n        configProvider,\n      });\n    } else {\n      logger.debug(\"No PostHog API key found, using DummyAnalyticsProvider\");\n      analyticsProvider = new DummyAnalyticsProvider({\n        appConfig,\n        configProvider,\n      });\n    }\n\n    return {\n      configProvider: configProvider,\n      authProvider: authProvider,\n      analyticsProvider: analyticsProvider,\n      flagsProvider: new ValidatedFlagsProvider(configProvider, authProvider),\n    };\n  } catch (error) {\n    logger.error(`Error getting providers: ${error}`);\n    throw error;\n  }\n}\n","import { z } from \"zod\";\n\nexport const propelAuthSchema = z.object({\n  url: z.string().url(),\n});\n\nexport const oidcSchema = z.object({\n  discoveryUrl: z.string().url(),\n  clientId: z.string(),\n  issuer: z.string().url().optional(),\n  redirectUrl: z.string().url().optional(),\n  jwtSecret: z.string().optional(),\n  jwtAudience: z.string().default(\"toolprint-mcp-server\"),\n});\n\nexport const posthogSchema = z.object({\n  apiKey: z.string(),\n});\n\nexport const apiSchema = z.object({\n  url: z.string().url(),\n});\n\nexport const demoSandboxSchema = z.object({\n  api: apiSchema,\n  invitationCode: z.string(),\n});\n\nexport const agentSchema = z.object({\n  agentType: z.enum([\"blaxel\", \"local\"]),\n  url: z\n    .string()\n    .url()\n    .transform((url?: string) => {\n      if (url !== undefined && url !== null) {\n        return url;\n      }\n\n      if (process.env.TOOLPRINT_AGENT_URL) {\n        return process.env.TOOLPRINT_AGENT_URL;\n      }\n\n      return \"http://localhost:1338\";\n    }),\n  apiKey: z.string().optional(), // only needed when calling an agent which requires this kind of AuthN (ex. Blaxel)\n});\n\nexport const appSchema = z.object({\n  propelAuth: propelAuthSchema,\n  oidc: oidcSchema,\n  demoSandbox: demoSandboxSchema,\n  agent: agentSchema,\n  posthog: posthogSchema.optional(),\n});\n\nexport const userPreferencesSchema = z.object({\n  loginMode: z.enum([\"callback\", \"mcp-gateway\"]).default(\"callback\"),\n  autoRefreshCredentials: z.boolean().default(true),\n});\n\nexport const userSchema = z.object({\n  id: z.string(),\n  email: z.string(),\n  preferences: userPreferencesSchema.default({\n    loginMode: \"callback\",\n    autoRefreshCredentials: true,\n  }),\n});\n\nexport const orgSchema = z.object({\n  id: z.string(),\n});\n\nexport const identitySchema = z.object({\n  user: userSchema,\n  org: orgSchema.optional(),\n});\n\nexport const credentialsSchema = z.object({\n  accessToken: z.string().optional(),\n  apiKey: z.string().optional(),\n});\n\nexport const storedConfigSchema = z.object({\n  api: apiSchema,\n  identity: identitySchema.optional(),\n  credentials: credentialsSchema.optional(),\n});\n\nexport const configSchema = storedConfigSchema.extend({\n  app: appSchema,\n});\n\nexport type OidcConfig = z.infer<typeof oidcSchema>;\nexport type PropelAuthConfig = z.infer<typeof propelAuthSchema>;\nexport type PosthogConfig = z.infer<typeof posthogSchema>;\nexport type ApiConfig = z.infer<typeof apiSchema>;\nexport type DemoSandboxConfig = z.infer<typeof demoSandboxSchema>;\nexport type AppConfig = z.infer<typeof appSchema>;\n\nexport type UserPreferencesConfig = z.infer<typeof userPreferencesSchema>;\nexport type IdentityConfig = z.infer<typeof identitySchema>;\nexport type CredentialsConfig = z.infer<typeof credentialsSchema>;\n\nexport type StoredConfig = z.infer<typeof storedConfigSchema>;\n\nexport type Config = z.infer<typeof configSchema>;\n\nfunction isSensitiveKey(key: string): boolean {\n  const sensitiveKeys = [\"apiKey\", \"accessToken\"].map((key) =>\n    key.toLowerCase().trim(),\n  );\n  const cleanedKey = key.toLowerCase().trim();\n  return sensitiveKeys.includes(cleanedKey);\n}\n\n// Custom serializer mode for JSON.stringify\nexport function maskSensitiveFieldsSerializer(key: string, value: any): any {\n  // Omit undefined values\n  if (value === undefined) {\n    return undefined;\n  }\n  // Mask sensitive fields\n  if (isSensitiveKey(key)) {\n    return value ? \"***********\" : value;\n  }\n  return value;\n}\n\nexport function masked(config: Config): string {\n  return JSON.stringify(config, maskSensitiveFieldsSerializer);\n}\n","import { SecretStorage } from \"./secrets.js\";\nimport { configSchema, Config, AppConfig, StoredConfig } from \"./schemas.js\";\nimport { Mutex } from \"async-mutex\";\nimport { logger } from \"../logger.js\";\n\nexport class ConfigStore {\n  private mutex = new Mutex();\n\n  constructor(\n    private readonly secretStore: SecretStorage<StoredConfig>,\n    private readonly currentAppConfig: AppConfig,\n    private readonly storageKey: string = \"secrets\",\n  ) {}\n\n  async init() {\n    const exists = await this.secretStore.exists(this.storageKey);\n    if (!exists) {\n      logger.info(\"No config found, setting defaults\");\n      await this.save({ api: this.currentAppConfig.demoSandbox.api });\n    }\n  }\n\n  async load(): Promise<Readonly<Config>> {\n    const storedConfig = await this.secretStore.get(this.storageKey);\n    if (!storedConfig) {\n      throw new Error(\"Invalid stored config found\");\n    }\n    const config = { ...storedConfig, app: this.currentAppConfig };\n    return configSchema.parse(config);\n  }\n\n  private async save(config: Config) {\n    // ! Never save the app config, it should be loaded via code\n    const { app, ...configWithoutApp } = config;\n    await this.secretStore.set(this.storageKey, configWithoutApp);\n  }\n\n  async update(config: Partial<Config>) {\n    try {\n      await this.mutex.runExclusive(async () => {\n        const currentConfig = await this.load();\n        await this.save({ ...currentConfig, ...config });\n      });\n    } catch (error) {\n      logger.error(\"Error updating config\", error);\n      throw error;\n    }\n  }\n\n  async clear() {\n    await this.mutex.runExclusive(async () => {\n      await this.secretStore.delete(this.storageKey);\n    });\n  }\n}\n","import { SecretStorage } from \"./secrets.js\";\nimport {\n  ApiConfig,\n  AppConfig,\n  Config,\n  CredentialsConfig,\n  IdentityConfig,\n  StoredConfig,\n} from \"./schemas.js\";\nimport { ConfigStore } from \"./store.js\";\n\n/** Responsible for providing the runtime configuration for the CLI that is comprised of\n * any locally cached data that is needed in order to interact with the user's resources.\n *\n * It is responsible for managing the lifecycle of the user's cached config data including items such as:\n * - API Keys\n * - Ephemeral JWTs\n * - User's profile data\n */\nexport class ConfigProvider {\n  private configStore: ConfigStore;\n\n  constructor(\n    private readonly appConfig: AppConfig,\n    private readonly secretStore: SecretStorage<StoredConfig>,\n  ) {\n    this.configStore = new ConfigStore(secretStore, appConfig);\n  }\n\n  /** Call this method to initialize the config provider. */\n  async init(): Promise<void> {\n    await this.configStore.init();\n  }\n\n  async reset() {\n    await this.configStore.clear();\n    await this.configStore.init();\n  }\n\n  /**\n   * Returns a read-only reference to the current config. The caller should only use\n   * explicit setters to update this.\n   */\n  async getConfig(): Promise<Readonly<Config>> {\n    // TODO: Merge in overrides\n    return await this.configStore.load();\n  }\n\n  async update(config: Partial<Config>) {\n    await this.configStore.update(config);\n  }\n\n  async updateApiUrl(apiUrl: string) {\n    await this.configStore.update({ api: { url: apiUrl } });\n  }\n\n  async updateIdentity(identity: IdentityConfig) {\n    await this.configStore.update({ identity });\n  }\n\n  async updateCredentials(credentials: CredentialsConfig) {\n    await this.configStore.update({ credentials });\n  }\n}\n","import open from \"open\";\n\nimport { OneGrepApiClient, OneGrepApiHighLevelClient } from \"@toolprint/sdk\";\nimport { ConfigProvider } from \"../config/provider.js\";\nimport {\n  apiKeyClientFromConfig,\n  apiKeyFromConfig,\n  bearerAuthClientFromConfig,\n} from \"../api.js\";\nimport { PropelAuthProvider, PropelAuthUserJwtClaims } from \"./propel.js\";\nimport { logger } from \"../logger.js\";\nimport { TokensResponse } from \"./oauth.js\";\n\n// ! TODO: Isolated API factory methods and rename better\nexport class AuthProvider {\n  private readonly configProvider: ConfigProvider;\n  private readonly propelAuthProvider: PropelAuthProvider;\n\n  constructor(params: { configProvider: ConfigProvider }) {\n    this.configProvider = params.configProvider;\n    this.propelAuthProvider = new PropelAuthProvider({\n      configProvider: this.configProvider,\n    });\n    logger.debug(\"AuthzProvider initialized\");\n  }\n\n  async getBearerAuthApi(): Promise<OneGrepApiHighLevelClient> {\n    const config = await this.configProvider.getConfig();\n    return bearerAuthClientFromConfig(config);\n  }\n\n  async getApiKey(): Promise<string> {\n    const config = await this.configProvider.getConfig();\n    return apiKeyFromConfig(config);\n  }\n\n  async getApiKeyClient(): Promise<OneGrepApiClient> {\n    const config = await this.configProvider.getConfig();\n    return apiKeyClientFromConfig(config);\n  }\n\n  async getApi(): Promise<OneGrepApiHighLevelClient> {\n    return new OneGrepApiHighLevelClient(await this.getApiKeyClient());\n  }\n\n  async isUserIdentified(): Promise<boolean> {\n    const currentConfig = await this.configProvider.getConfig();\n    return !!currentConfig.identity;\n  }\n\n  async isAuthenticated(): Promise<boolean> {\n    try {\n      const api = await this.getApi();\n      const response = await api.authStatus();\n      return response.credentials_provided && response.is_authenticated;\n    } catch (error) {\n      logger.error(`Error checking authentication status: ${error}`);\n      return false;\n    }\n  }\n\n  async signup(\n    invitationCode: string,\n    loginMode: \"callback\" | \"mcp-gateway\" = \"callback\",\n  ): Promise<void> {\n    await this.login(loginMode);\n    logger.debug(\"Sign-Up Login successful\");\n\n    const config = await this.configProvider.getConfig();\n    const userEmail = config.identity?.user?.email;\n    if (!userEmail) {\n      throw new Error(\"User email not found in config\");\n    }\n\n    const client = bearerAuthClientFromConfig(config);\n    logger.debug(`Connected to API endpoint: ${config.api?.url}`);\n\n    try {\n      const authStatus = await client.authStatus();\n      logger.info(`Auth status: ${JSON.stringify(authStatus)}`);\n      if (authStatus.user_id) {\n        logger.debug(\"User already joined organization\");\n        return;\n      }\n    } catch (error) {\n      logger.error(`Error checking if user is already joined: ${error}`);\n    }\n\n    // Create an account for this user in the domain that they're pointed at.\n    logger.debug(\n      `Creating account with email: ${userEmail} and invitation code: ${invitationCode}`,\n    );\n    try {\n      const accountInfo = await client.createAccountByInvitation(\n        invitationCode,\n        userEmail,\n      );\n      logger.debug(\n        `User account created and joined organization: ${accountInfo.organization.id}`,\n      );\n    } catch (error) {\n      logger.error(`Error creating account: ${error}`);\n      // TODO: Catch HTTP 409 errors and throw a more specific error message in that case.\n      throw new Error(\n        \"Failed to create account. Check if you already created an account with this email address.\",\n      );\n    }\n  }\n\n  async login(\n    loginMode: \"callback\" | \"mcp-gateway\" = \"callback\",\n    output: Console = console,\n  ): Promise<void> {\n    if (loginMode === \"callback\") {\n      const { tokens, userDetails } =\n        await this.propelAuthProvider.loginWithOAuthCallback(output);\n      logger.debug(\n        `PropelAuth login successful: ${JSON.stringify(userDetails)}`,\n      );\n\n      // Update the config store with the new account info.\n      await this.updateConfigStore(tokens, userDetails);\n    } else if (loginMode === \"mcp-gateway\") {\n      await this.openAccountPage();\n      // TODO: Wait for the user to login and then update the config store.\n    } else {\n      throw new Error(`Invalid login mode: ${loginMode}`);\n    }\n  }\n\n  /**\n   * Update the config store with the provided tokens and JWT claims.\n   */\n  private async updateConfigStore(\n    tokens: TokensResponse,\n    userDetails: PropelAuthUserJwtClaims,\n  ) {\n    await this.configProvider.update({\n      credentials: {\n        accessToken: tokens.access_token,\n      },\n      identity: {\n        user: {\n          id: userDetails.user_id,\n          email: userDetails.email,\n        },\n      },\n    });\n    logger.debug(`Config store identity and credentials updated.`);\n  }\n\n  /**\n   * Logout the user by removing the credentials and identity from the config store.\n   *\n   * TODO: Call propel auth logout endpoint?\n   */\n  async logout(): Promise<void> {\n    await this.propelAuthProvider.logout();\n    logger.debug(\"PropelAuth logout successful\");\n\n    await this.configProvider.update({\n      credentials: {\n        accessToken: undefined,\n      },\n      identity: undefined,\n    });\n    logger.debug(`Config store identity and credentials removed.`);\n  }\n\n  async openSignupPage(): Promise<void> {\n    const url = await this.propelAuthProvider.signupUrl();\n    await open(url.toString());\n  }\n\n  async openLoginPage(): Promise<void> {\n    const url = await this.propelAuthProvider.loginUrl();\n    await open(url.toString());\n  }\n\n  async openAccountPage(): Promise<void> {\n    const url = await this.propelAuthProvider.accountUrl();\n    await open(url.toString());\n  }\n}\n\nexport default AuthProvider;\n","import http from \"http\";\nimport open from \"open\";\n\nimport * as jose from \"jose\";\nimport {\n  AuthenticationInfo,\n  createClient,\n  IAuthClient,\n} from \"@propelauth/javascript\";\n\nimport { ConfigProvider } from \"../config/provider.js\";\nimport {\n  loginFlowWithTimeout,\n  TokensResponse,\n  UserJwtClaims,\n} from \"./oauth.js\";\nimport { logger } from \"../logger.js\";\n\nimport { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\n\n/**\n * Extra authentication data for PropelAuthInfo\n */\nexport interface PropelAuthExtra extends Record<string, unknown> {\n  userId?: string;\n  email?: string;\n  propelAccessToken?: string;\n  propelRefreshToken?: string;\n  apiKey?: string;\n  redditAccessToken?: string;\n  redditRefreshToken?: string;\n}\n\n/**\n * Extended authentication information with Propel-specific data.\n *\n * @remarks\n * This interface extends the base MCP AuthInfo type to include\n * Propel OAuth tokens and user information in the extra field.\n * The extra field is populated after successful OAuth authentication.\n *\n * @example\n * ```typescript\n * const authInfo: PropelAuthInfo = {\n *   clientId: \"mcp-client-123\",\n *   extra: {\n *     userId: \"reddit_username\",\n *     redditAccessToken: \"access_token_here\",\n *     redditRefreshToken: \"refresh_token_here\"\n *   }\n * };\n * ```\n */\nexport interface PropelAuthInfo extends AuthInfo {\n  /**\n   * Extra authentication data containing Propel-specific information.\n   * Populated after successful OAuth flow completion.\n   */\n  extra?: PropelAuthExtra;\n}\n\n// Additional PropelAuth fields\nexport interface PropelAuthUserJwtClaims extends UserJwtClaims {\n  user_id?: string;\n  org_id_to_org_member_info?: Record<string, unknown>; // ! TODO: Get shape of this.\n}\n\n/** Decodes claims from a provided JWT or uses the access token from the config\n * if no token is provided.\n */\nconst getUserDetailsFromJwt = async (\n  accessToken: string,\n): Promise<PropelAuthUserJwtClaims> => {\n  try {\n    // Decode the JWT without verifying the signature\n    const decoded = jose.decodeJwt(accessToken!);\n    return decoded as PropelAuthUserJwtClaims;\n  } catch (error) {\n    logger.error(`Failed to decode JWT: ${error}`);\n    throw new Error(\"Failed to extract user details from token\");\n  }\n};\n\nexport class PropelAuthProvider {\n  private readonly configProvider: ConfigProvider;\n\n  constructor(params: { configProvider: ConfigProvider }) {\n    this.configProvider = params.configProvider;\n  }\n\n  private async authClient(): Promise<IAuthClient> {\n    const config = await this.configProvider.getConfig();\n    const propelAuthUrl = config.app?.propelAuth?.url;\n    if (!propelAuthUrl) {\n      throw new Error(\"No PropelAuth URL found in config\");\n    }\n\n    const authClient = createClient({\n      // The base URL where your authentication pages are hosted.\n      // You can find this under the Frontend Integration section for your project.\n      authUrl: propelAuthUrl,\n\n      // If true, periodically refresh the access token in the background.\n      // This helps ensure you always have a valid token ready to go. Default true.\n      enableBackgroundTokenRefresh: false,\n    });\n\n    return authClient;\n  }\n\n  async signupUrl(): Promise<URL> {\n    const urlString = (await this.authClient()).getSignupPageUrl();\n    return new URL(urlString);\n  }\n\n  async loginUrl(): Promise<URL> {\n    const urlString = (await this.authClient()).getLoginPageUrl();\n    return new URL(urlString);\n  }\n\n  async accountUrl(): Promise<URL> {\n    const urlString = (await this.authClient()).getAccountPageUrl();\n    return new URL(urlString);\n  }\n\n  async getAuthInfo(): Promise<AuthenticationInfo | null> {\n    logger.debug(\"Getting auth info\");\n    const authClient = await this.authClient();\n    return await authClient.getAuthenticationInfoOrNull();\n  }\n\n  async isLoggedIn(): Promise<boolean> {\n    return (await this.getAuthInfo()) !== null;\n  }\n\n  async loginWithOAuthCallback(output: Console = console): Promise<{\n    tokens: TokensResponse;\n    userDetails: PropelAuthUserJwtClaims;\n  }> {\n    const config = await this.configProvider.getConfig();\n    const oidcConfig = config.app?.oidc;\n    if (!oidcConfig) {\n      throw new Error(\"No OIDC config found in config\");\n    }\n    const tokens = await loginFlowWithTimeout(oidcConfig, output);\n\n    const userDetails = await getUserDetailsFromJwt(tokens.access_token);\n    logger.debug(\n      `PropelAuth claims extracted successfully: ${JSON.stringify(userDetails)}`,\n    );\n    return {\n      tokens,\n      userDetails,\n    };\n  }\n\n  async logout(): Promise<void> {\n    const authClient = await this.authClient();\n    // TODO: Not sure if this is actually working.\n    await authClient.logout(false);\n  }\n}\n","import http from \"http\";\nimport open from \"open\";\n\nimport { OidcConfig } from \"../config/schemas.js\";\nimport { logger } from \"../logger.js\";\n\nimport {\n  authorizationCodeGrant,\n  discovery,\n  buildAuthorizationUrl,\n  TokenEndpointResponse,\n  TokenEndpointResponseHelpers,\n  randomState,\n  calculatePKCECodeChallenge,\n  randomPKCECodeVerifier,\n} from \"openid-client\";\n\n/**\n * Convenience type for the response from the token endpoint.\n *\n * This is a union of the TokenEndpointResponse and TokenEndpointResponseHelpers\n * from the openid-client library.\n */\nexport type TokensResponse = TokenEndpointResponse &\n  TokenEndpointResponseHelpers;\n\n// Define interface for JWT claims based on standard OpenID Connect claims\n// that match our requested scopes: 'openid profile email'\n/**\n * Interface for JWT claims that aligns with the OpenID Connect (OIDC) specification.\n *\n * These fields are defined in the OIDC Core specification:\n * https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims\n *\n * We request the scopes 'openid profile email' which provides access to these claims.\n * The actual claims returned will depend on the identity provider and user permissions.\n */\nexport interface UserJwtClaims {\n  // Required by OpenID Connect\n  sub: string;\n\n  // Email scope\n  email?: string;\n  email_verified?: boolean;\n\n  // Profile scope\n  name?: string;\n  given_name?: string;\n  family_name?: string;\n  middle_name?: string;\n  nickname?: string;\n  preferred_username?: string;\n  profile?: string;\n  picture?: string;\n  website?: string;\n  gender?: string;\n  birthdate?: string;\n  zoneinfo?: string;\n  locale?: string;\n  updated_at?: number;\n\n  // JWT standard fields\n  iat?: number;\n  exp?: number;\n  iss?: string;\n}\n\nclass OAuthCallbackServer {\n  private port: number;\n  private server: http.Server;\n\n  constructor(port: number) {\n    this.port = port;\n    this.server = http.createServer();\n  }\n\n  get redirectPort() {\n    return this.port;\n  }\n\n  get redirectUri() {\n    return `http://localhost:${this.redirectPort}/oauth/openid/callback`;\n  }\n\n  /**\n   * Starts the server and returns a promise that resolves with the callback URL.\n   */\n  start() {\n    // Start the server\n    this.server.listen(this.redirectPort, () => {\n      logger.debug(\n        `Local authentication server listening on port ${this.redirectPort}`,\n      );\n    });\n  }\n\n  waitForCallbackUrl() {\n    // Create a promise that will resolve with the callback URL\n    const codePromise = new Promise<URL>((resolve, reject) => {\n      // Set a timeout\n      const timeoutId = setTimeout(() => {\n        reject(new Error(\"Authentication timed out\"));\n        this.server?.close();\n      }, 120000); // 2 minute timeout\n\n      this.server?.on(\"request\", (req, res) => {\n        try {\n          if (!req.url) {\n            throw new Error(\"Request URL is undefined\");\n          }\n\n          // Parse the callback URL\n          const callbackUrl = new URL(req.url, `http://${req.headers.host}`);\n\n          // Parse the URL params and check for errors.\n          if (callbackUrl.searchParams.has(\"error\")) {\n            const error = callbackUrl.searchParams.get(\"error\");\n            const errorDescription =\n              callbackUrl.searchParams.get(\"error_description\") ||\n              \"Unknown error\";\n\n            // Send an error response\n            res.writeHead(400, { \"Content-Type\": \"text/html\" });\n            res.end(`\n                                      <html>\n                                          <body>\n                                              <h1>Authentication Failed</h1>\n                                              <p>Error: ${error}</p>\n                                              <p>${errorDescription}</p>\n                                              <p>Please close this window and try again.</p>\n                                          </body>\n                                      </html>\n                                  `);\n\n            reject(\n              new Error(`Authentication error: ${error} - ${errorDescription}`),\n            );\n          } else if (callbackUrl.searchParams.has(\"code\")) {\n            // Auth was successful, resolve the promise - ?code=...\n            clearTimeout(timeoutId);\n            resolve(callbackUrl);\n\n            // Send a success response\n            res.writeHead(200, { \"Content-Type\": \"text/html\" });\n            res.end(`\n                                      <html>\n                                          <body>\n                                              <h1>Authentication Successful</h1>\n                                              <p>You can close this window and return to the CLI.</p>\n                                              <script>setTimeout(function() { window.close(); }, 2000);</script>\n                                          </body>\n                                      </html>\n                                  `);\n          } else {\n            // No code parameter found\n            res.writeHead(400, { \"Content-Type\": \"text/html\" });\n            res.end(`\n                                      <html>\n                                          <body>\n                                              <h1>Authentication Failed</h1>\n                                              <p>No authorization code was received.</p>\n                                              <p>Please close this window and try again.</p>\n                                          </body>\n                                      </html>\n                                  `);\n\n            reject(new Error(\"No authorization code received\"));\n          }\n        } catch (err) {\n          const errorMessage = err instanceof Error ? err.message : String(err);\n\n          // Send an error response\n          res.writeHead(500, { \"Content-Type\": \"text/html\" });\n          res.end(`\n                                  <html>\n                                      <body>\n                                          <h1>Authentication Failed</h1>\n                                          <p>Error: ${errorMessage}</p>\n                                          <p>Please close this window and try again.</p>\n                                      </body>\n                                  </html>\n                              `);\n\n          reject(new Error(`Error processing callback: ${errorMessage}`));\n        }\n      });\n    });\n\n    return codePromise;\n  }\n\n  stop() {\n    this.server.close();\n  }\n}\n\nexport const loginFlow = async (\n  oidcConfig: OidcConfig,\n  output: Console = console,\n  redirectPort: number = 3080,\n): Promise<TokensResponse> => {\n  const server = new OAuthCallbackServer(redirectPort);\n  await server.start();\n\n  try {\n    // Discover OpenID configuration\n    logger.debug(\"Discovering OAuth provider...\");\n    const oidcDiscoveredConfig = await discovery(\n      new URL(oidcConfig.discoveryUrl ?? \"\"),\n      oidcConfig.clientId ?? \"\",\n    );\n\n    // Generate PKCE parameters\n    const code_verifier = randomPKCECodeVerifier();\n    const code_challenge = await calculatePKCECodeChallenge(code_verifier);\n\n    // Always generate a state parameter for CSRF protection\n    const state = randomState();\n\n    // Build the redirect URL with appropriate parameters\n    const parameters: Record<string, string> = {\n      redirect_uri: server.redirectUri,\n      scope: \"openid profile email\",\n      code_challenge,\n      code_challenge_method: \"S256\",\n      state, // Always include state parameter\n    };\n\n    // Build the authorization URL for login.\n    const redirectTo = buildAuthorizationUrl(oidcDiscoveredConfig, parameters);\n\n    // Open the browser for the user to authenticate\n\n    try {\n      await open(redirectTo.href);\n      logger.debug(\"Browser opened automatically.\");\n    } catch (error) {\n      logger.error(`Unable to open browser automatically: ${error}`);\n\n      output.info(\"\\n\"); // Add a new line so it comes after the spinner.\n      output.error(\"⚠️  Unable to open browser automatically.\");\n      output.info(\"\\n\");\n      output.info(\"Please open this URL in your browser:\");\n      output.info(\"\\n\");\n      output.info(redirectTo.href);\n      output.info(\"\\n\");\n    }\n\n    const callbackUrl = await server.waitForCallbackUrl();\n\n    // We don't need the server anymore.\n    await server.stop();\n\n    // Exchange the authorization code for tokens\n    logger.debug(\"Exchanging code for tokens...\");\n    const tokens = await authorizationCodeGrant(\n      oidcDiscoveredConfig,\n      callbackUrl,\n      {\n        pkceCodeVerifier: code_verifier,\n        expectedState: state, // Always verify the state parameter\n      },\n    );\n\n    if (!tokens.access_token) {\n      logger.error(\"Authentication failed. No access token received.\");\n      throw new Error(\"Authentication failed. No access token received.\");\n    }\n\n    logger.debug(\"Tokens generated successfully.\");\n\n    return tokens;\n  } catch (error) {\n    logger.error(\"Failed signup flow: \", error);\n    throw error;\n  } finally {\n    server.stop();\n  }\n};\n\nexport const loginFlowWithTimeout = async (\n  oidcConfig: OidcConfig,\n  output: Console = console,\n  redirectPort: number = 3080,\n  timeout: number = 5 * 60 * 1000, // Default to 5 minutes\n): Promise<TokensResponse> => {\n  const timeoutPromise = new Promise<never>((_, reject) => {\n    setTimeout(() => {\n      reject(new Error(`Authentication process timed out after ${timeout}ms`));\n    }, timeout);\n  });\n\n  return Promise.race([\n    loginFlow(oidcConfig, output, redirectPort),\n    timeoutPromise,\n  ]);\n};\n","import { PostHog } from \"posthog-node\";\n\nexport const getPostHogClient = (\n  apiKey: string,\n  host: string = \"https://us.i.posthog.com\",\n): PostHog => {\n  const posthog = new PostHog(apiKey, {\n    host,\n    enableExceptionAutocapture: true,\n  });\n\n  return posthog;\n};\n","import { PostHog } from \"posthog-node\";\nimport { getPostHogClient } from \"./posthog.js\";\nimport { ConfigProvider } from \"../config/provider.js\";\nimport { AppConfig } from \"../config/schemas.js\";\nimport { logger } from \"../logger.js\";\n\nexport interface AnalyticsProviderImpl {\n  capture(event: string, properties?: Record<string, any>): Promise<void>;\n  captureException(\n    error: unknown,\n    properties?: Record<string, any>,\n  ): Promise<void>;\n  close(): Promise<void>;\n}\n\nexport class AnalyticsProvider implements AnalyticsProviderImpl {\n  private configProvider: ConfigProvider;\n  private posthog: PostHog;\n\n  constructor(params: {\n    appConfig: AppConfig;\n    configProvider: ConfigProvider;\n  }) {\n    this.configProvider = params.configProvider;\n    this.posthog = getPostHogClient(params.appConfig.posthog.apiKey);\n    logger.debug(\"AnalyticsProvider initialized\");\n  }\n\n  private async getUserId() {\n    return (await this.configProvider.getConfig()).identity?.user.id;\n  }\n\n  private async getApiUrl() {\n    return (await this.configProvider.getConfig()).api.url;\n  }\n\n  private async extendProperties(properties?: Record<string, any>) {\n    return {\n      ...properties,\n      // version: getPackageVersion(), // TODO: Add this back in\n      // \"sdk-version\": getSDKVersion(), // TODO: Add this back in\n      \"api-url\": await this.getApiUrl(),\n    };\n  }\n\n  async capture(event: string, properties?: Record<string, any>) {\n    const userId = await this.getUserId();\n    if (!userId) {\n      logger.warn(\n        `No User ID found, skipping analytics capture for event: ${event}`,\n      );\n      return;\n    }\n\n    this.posthog.capture({\n      distinctId: userId,\n      event: event,\n      properties: this.extendProperties(properties),\n    });\n    logger.debug(`Captured event: ${event} for user: ${userId}`);\n  }\n\n  async captureException(error: unknown, properties?: Record<string, any>) {\n    const userId = await this.getUserId();\n    if (!userId) {\n      logger.warn(\n        `No User ID found, skipping analytics capture for exception: ${error}`,\n      );\n      return;\n    }\n\n    this.posthog.captureException(\n      error,\n      userId,\n      this.extendProperties(properties),\n    );\n    logger.debug(`Captured exception: ${error}`);\n  }\n\n  async close() {\n    await this.posthog.shutdown();\n    logger.debug(\"AnalyticsProvider closed\");\n  }\n}\n\n/**\n * A dummy analytics provider that does nothing.\n * This is used when the user is in local mode.\n */\nexport class DummyAnalyticsProvider implements AnalyticsProviderImpl {\n  private configProvider: ConfigProvider;\n\n  constructor(params: {\n    appConfig: AppConfig;\n    configProvider: ConfigProvider;\n  }) {\n    this.configProvider = params.configProvider;\n  }\n\n  private async getUserId() {\n    return (await this.configProvider.getConfig()).identity?.user.id;\n  }\n\n  async capture(event: string, _?: Record<string, any>) {\n    logger.debug(\n      `DummyAnalyticsProvider: Captured event: ${event} for user: ${await this.getUserId()}`,\n    );\n  }\n\n  async captureException(error: unknown, _?: Record<string, any>) {\n    logger.debug(`DummyAnalyticsProvider: Captured exception: ${error}`);\n  }\n\n  async close() {\n    logger.debug(\"DummyAnalyticsProvider closed\");\n  }\n}\n","import { getConfigDir } from \"@toolprint/sdk\";\nimport { z } from \"zod\";\nimport { logger } from \"../logger.js\";\n\nexport interface SecretStorage<T> {\n  exists(key: string): Promise<boolean>;\n  get(key: string): Promise<T | undefined>;\n  set(key: string, value: T): Promise<void>;\n  delete(key: string): Promise<void>;\n}\n\nexport const newSecretStorage = async <T>(\n  schema: z.ZodSchema<T>,\n  location: \"config-dir\" | \"keyring\" | \"in-memory\" = \"in-memory\",\n): Promise<SecretStorage<T>> => {\n  logger.info(\"Using secret storage for\", location);\n  if (location === \"keyring\") {\n    return await newKeyringStorage<T>(schema);\n  } else if (location === \"config-dir\") {\n    return await newConfigDirStorage<T>(schema);\n  }\n  return await newInMemoryStorage<T>(schema);\n};\n\nasync function newConfigDirStorage<T>(schema: z.ZodType<T, z.ZodTypeDef, T>) {\n  const path = await import(\"path\");\n  const fs = await import(\"fs/promises\");\n  const configDir = await getConfigDir();\n\n  class SchemaValidatedConfigDirSecretStorage implements SecretStorage<T> {\n    constructor(private schema: z.ZodSchema<T>) {\n      this.schema = schema;\n    }\n\n    private filePathForKey(key: string) {\n      // Ensure the key is a valid filename by replacing any non-alphanumeric characters with underscores\n      const sanitizedKey = key.replace(/[^a-zA-Z0-9]/g, \"_\");\n      return path.join(configDir, sanitizedKey + \".json\");\n    }\n\n    async exists(key: string): Promise<boolean> {\n      const filePath = this.filePathForKey(key);\n      logger.info(\"Checking if secret exists\", filePath);\n      return this.get(key).then((value) => value !== undefined);\n    }\n\n    async get(key: string): Promise<T | undefined> {\n      logger.info(\"Getting secret\", key);\n      const filePath = this.filePathForKey(key);\n      if (\n        !(await fs\n          .access(filePath)\n          .then(() => true)\n          .catch(() => false))\n      ) {\n        logger.info(\"Secret does not exist\", filePath);\n        return undefined;\n      }\n\n      logger.info(\"Reading secret from\", filePath);\n      const fileContent = await fs.readFile(filePath, \"utf8\");\n      const validated = this.schema.safeParse(JSON.parse(fileContent));\n      if (validated) {\n        return validated.data;\n      }\n      return undefined;\n    }\n\n    async set(key: string, value: T): Promise<void> {\n      logger.info(\"Setting secret\", key);\n      const filePath = this.filePathForKey(key);\n      logger.info(\"Writing secret to\", filePath);\n      const jsonString = JSON.stringify(value, null, 2);\n      await fs.writeFile(filePath, jsonString);\n    }\n\n    async delete(key: string): Promise<void> {\n      logger.info(\"Deleting secret\", key);\n      const filePath = this.filePathForKey(key);\n      logger.info(\"Deleting secret from\", filePath);\n      await fs.rm(filePath);\n    }\n  }\n\n  return new SchemaValidatedConfigDirSecretStorage(schema);\n}\n\nasync function newKeyringStorage<T>(schema: z.ZodType<T, z.ZodTypeDef, T>) {\n  const { Entry } = await import(\"@napi-rs/keyring\");\n\n  class SchemaValidatedKeyringSecretStorage implements SecretStorage<T> {\n    constructor(private schema: z.ZodSchema<T>) {\n      this.schema = schema;\n    }\n\n    private entryForKey(key: string) {\n      return new Entry(\"toolprint\", key);\n    }\n\n    async exists(key: string): Promise<boolean> {\n      const entry = this.entryForKey(key);\n      return this.get(key).then((value) => value !== undefined);\n    }\n\n    async get(key: string): Promise<T | undefined> {\n      logger.info(\"Getting secret\", key);\n      const entry = this.entryForKey(key);\n      try {\n        const value = await entry.getPassword();\n        if (value) {\n          const validated = this.schema.safeParse(JSON.parse(value));\n          if (validated) {\n            return validated.data;\n          }\n        }\n      } catch (error) {\n        logger.error(\"Error getting secret\", key, error);\n      }\n      return undefined;\n    }\n\n    async set(key: string, value: T): Promise<void> {\n      logger.info(\"Setting secret\", key);\n      const entry = this.entryForKey(key);\n      const jsonString = JSON.stringify(value);\n      entry.setPassword(jsonString);\n    }\n\n    async delete(key: string): Promise<void> {\n      logger.info(\"Deleting secret\", key);\n      const entry = this.entryForKey(key);\n      await entry.deletePassword();\n    }\n  }\n\n  return new SchemaValidatedKeyringSecretStorage(schema);\n}\n\nasync function newInMemoryStorage<T>(schema: z.ZodType<T, z.ZodTypeDef, T>) {\n  class SchemaValidatedInMemorySecretStorage implements SecretStorage<T> {\n    private storage: Map<string, T> = new Map();\n\n    constructor(private schema: z.ZodSchema<T>) {\n      this.schema = schema;\n    }\n\n    async exists(key: string): Promise<boolean> {\n      logger.debug(`Checking if in-memory secret exists: ${key}`);\n      return this.storage.has(key);\n    }\n\n    async get(key: string): Promise<T | undefined> {\n      logger.debug(`Getting in-memory secret: ${key}`);\n      const value = this.storage.get(key);\n\n      if (value === undefined) {\n        logger.debug(`In-memory secret not found: ${key}`);\n        return undefined;\n      }\n\n      // Validate the stored value against the schema\n      const validated = this.schema.safeParse(value);\n      if (validated.success) {\n        return validated.data;\n      } else {\n        logger.error(\n          `Invalid in-memory secret format for key: ${key}`,\n          validated.error,\n        );\n        return undefined;\n      }\n    }\n\n    async set(key: string, value: T): Promise<void> {\n      logger.debug(`Setting in-memory secret: ${key}`);\n\n      // Validate the value before storing\n      const validated = this.schema.safeParse(value);\n      if (!validated.success) {\n        throw new Error(\n          `Invalid value for secret ${key}: ${validated.error.message}`,\n        );\n      }\n\n      this.storage.set(key, validated.data);\n    }\n\n    async delete(key: string): Promise<void> {\n      logger.debug(`Deleting in-memory secret: ${key}`);\n      this.storage.delete(key);\n    }\n\n    /**\n     * Clear all stored secrets. Useful for cleanup.\n     */\n    async clear(): Promise<void> {\n      logger.debug(\"Clearing all in-memory secrets\");\n      this.storage.clear();\n    }\n  }\n\n  return new SchemaValidatedInMemorySecretStorage(schema);\n}\n","/**\n * @file Generic auth store for session management\n * @module auth/auth-store\n *\n * @remarks\n * This module provides a generic store for authentication information that can be accessed\n * by handlers that need authentication context. It supports any type of auth info\n * and provides session-based storage with optional TTL support.\n */\n\nimport { logger } from \"../logger.js\";\n\n/**\n * Generic authentication store interface\n */\nexport interface IAuthStore<T> {\n  /**\n   * Store auth info for a session\n   */\n  set(sessionId: string, authInfo: T): void;\n\n  /**\n   * Get auth info for a session\n   */\n  get(sessionId: string): T | undefined;\n\n  /**\n   * Remove auth info for a session\n   */\n  remove(sessionId: string): void;\n\n  /**\n   * Clear all auth info\n   */\n  clear(): void;\n\n  /**\n   * Get all session IDs\n   */\n  keys(): string[];\n\n  /**\n   * Get the number of stored sessions\n   */\n  size(): number;\n\n  /**\n   * Check if a session exists\n   */\n  has(sessionId: string): boolean;\n}\n\n/**\n * Session entry with optional metadata\n */\ninterface SessionEntry<T> {\n  authInfo: T;\n  createdAt: Date;\n  lastAccessed: Date;\n  expiresAt?: Date;\n}\n\n/**\n * Options for creating an auth store\n */\nexport interface AuthStoreOptions {\n  /**\n   * Time-to-live for sessions in milliseconds\n   * If not specified, sessions don't expire\n   */\n  ttl?: number;\n\n  /**\n   * Interval for cleaning up expired sessions in milliseconds\n   * Default: 5 minutes\n   */\n  cleanupInterval?: number;\n\n  /**\n   * Maximum number of sessions to store\n   * If exceeded, oldest sessions are evicted\n   */\n  maxSessions?: number;\n}\n\n/**\n * Generic in-memory auth store implementation\n */\nexport class AuthStore<T> implements IAuthStore<T> {\n  private readonly store = new Map<string, SessionEntry<T>>();\n  private readonly options: AuthStoreOptions;\n  private cleanupTimer?: NodeJS.Timeout;\n\n  constructor(options: AuthStoreOptions = {}) {\n    this.options = {\n      cleanupInterval: 5 * 60 * 1000, // 5 minutes default\n      ...options,\n    };\n\n    // Start cleanup timer if TTL is specified\n    if (this.options.ttl && this.options.cleanupInterval) {\n      this.startCleanupTimer();\n    }\n  }\n\n  /**\n   * Store auth info for a session\n   */\n  set(sessionId: string, authInfo: T): void {\n    const now = new Date();\n    const entry: SessionEntry<T> = {\n      authInfo,\n      createdAt: now,\n      lastAccessed: now,\n      expiresAt: this.options.ttl\n        ? new Date(now.getTime() + this.options.ttl)\n        : undefined,\n    };\n\n    // Check max sessions limit\n    if (\n      this.options.maxSessions &&\n      this.store.size >= this.options.maxSessions\n    ) {\n      this.evictOldestSession();\n    }\n\n    this.store.set(sessionId, entry);\n    logger.debug(`Stored auth info for session: ${sessionId}`);\n  }\n\n  /**\n   * Get auth info for a session\n   */\n  get(sessionId: string): T | undefined {\n    const entry = this.store.get(sessionId);\n\n    if (!entry) {\n      return undefined;\n    }\n\n    // Check if expired\n    if (entry.expiresAt && entry.expiresAt < new Date()) {\n      this.remove(sessionId);\n      logger.debug(`Session expired and removed: ${sessionId}`);\n      return undefined;\n    }\n\n    // Update last accessed time\n    entry.lastAccessed = new Date();\n\n    return entry.authInfo;\n  }\n\n  /**\n   * Remove auth info for a session\n   */\n  remove(sessionId: string): void {\n    if (this.store.delete(sessionId)) {\n      logger.debug(`Removed auth info for session: ${sessionId}`);\n    }\n  }\n\n  /**\n   * Clear all auth info\n   */\n  clear(): void {\n    const count = this.store.size;\n    this.store.clear();\n    logger.debug(`Cleared all ${count} auth sessions`);\n  }\n\n  /**\n   * Get all session IDs\n   */\n  keys(): string[] {\n    return Array.from(this.store.keys());\n  }\n\n  /**\n   * Get the number of stored sessions\n   */\n  size(): number {\n    return this.store.size;\n  }\n\n  /**\n   * Check if a session exists\n   */\n  has(sessionId: string): boolean {\n    const entry = this.store.get(sessionId);\n\n    if (!entry) {\n      return false;\n    }\n\n    // Check if expired\n    if (entry.expiresAt && entry.expiresAt < new Date()) {\n      this.remove(sessionId);\n      return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Get all valid (non-expired) sessions\n   */\n  getAll(): Map<string, T> {\n    const result = new Map<string, T>();\n    const now = new Date();\n\n    for (const [sessionId, entry] of this.store) {\n      if (!entry.expiresAt || entry.expiresAt > now) {\n        result.set(sessionId, entry.authInfo);\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Clean up expired sessions\n   */\n  cleanup(): void {\n    const now = new Date();\n    let removed = 0;\n\n    for (const [sessionId, entry] of this.store) {\n      if (entry.expiresAt && entry.expiresAt < now) {\n        this.store.delete(sessionId);\n        removed++;\n      }\n    }\n\n    if (removed > 0) {\n      logger.debug(`Cleaned up ${removed} expired sessions`);\n    }\n  }\n\n  /**\n   * Evict the oldest session (based on last accessed time)\n   */\n  private evictOldestSession(): void {\n    let oldestSessionId: string | null = null;\n    let oldestTime = new Date();\n\n    for (const [sessionId, entry] of this.store) {\n      if (entry.lastAccessed < oldestTime) {\n        oldestTime = entry.lastAccessed;\n        oldestSessionId = sessionId;\n      }\n    }\n\n    if (oldestSessionId) {\n      this.remove(oldestSessionId);\n      logger.debug(`Evicted oldest session: ${oldestSessionId}`);\n    }\n  }\n\n  /**\n   * Start the cleanup timer\n   */\n  private startCleanupTimer(): void {\n    this.cleanupTimer = setInterval(() => {\n      this.cleanup();\n    }, this.options.cleanupInterval!);\n  }\n\n  /**\n   * Stop the cleanup timer\n   */\n  destroy(): void {\n    if (this.cleanupTimer) {\n      clearInterval(this.cleanupTimer);\n      this.cleanupTimer = undefined;\n    }\n    this.clear();\n  }\n}\n\n/**\n * Create a simple auth store with default options\n */\nexport function createAuthStore<T>(options?: AuthStoreOptions): IAuthStore<T> {\n  return new AuthStore<T>(options);\n}\n\n/**\n * Create an auth store specifically for PropelAuthInfo\n * This is a convenience function for the common use case\n */\nexport function createPropelAuthStore(options?: AuthStoreOptions) {\n  // Import type dynamically to avoid circular dependency\n  type PropelAuthInfo = import(\"./propel.js\").PropelAuthInfo;\n  return createAuthStore<PropelAuthInfo>(options);\n}\n","import { Providers } from \"./manager.js\";\nimport { ConfigProvider } from \"./config/provider.js\";\nimport { newSecretStorage } from \"./config/secrets.js\";\nimport { storedConfigSchema } from \"./config/schemas.js\";\nimport { AuthProvider } from \"./auth/provider.js\";\nimport { DummyAnalyticsProvider } from \"./analytics/provider.js\";\nimport { getAppConfig } from \"./app.js\";\nimport { logger } from \"./logger.js\";\nimport { Config, CredentialsConfig } from \"./config/schemas.js\";\n\n/**\n * Session authentication information for creating user-specific providers\n */\nexport interface UserSessionAuth {\n  accessToken?: string;\n  refreshToken?: string;\n  apiKey?: string;\n  username: string;\n  isApiKeyAuth: boolean;\n}\n\n/**\n * Creates a complete set of isolated providers for a specific user session.\n * This ensures each user has their own configuration without file persistence\n * or cross-contamination between users.\n *\n * @deprecated Use MultiTenantProviderManager instead for better lifecycle management\n * @param sessionAuth - The user's authentication information\n * @param baseConfig - Optional base configuration to use (defaults to app config)\n * @returns Complete set of providers for the user\n */\nexport async function createUserProviders(\n  sessionAuth: UserSessionAuth,\n  baseConfig?: Config,\n): Promise<Providers> {\n  logger.info(\"Creating user-specific providers\", {\n    username: sessionAuth.username,\n    isApiKeyAuth: sessionAuth.isApiKeyAuth,\n    hasBaseConfig: !!baseConfig,\n  });\n\n  // Get app configuration\n  const appConfig = await getAppConfig();\n\n  // Determine initial configuration\n  const initialConfig = baseConfig || {\n    app: appConfig,\n    api: appConfig.demoSandbox.api,\n  };\n\n  // Create credentials based on auth type\n  const credentials: CredentialsConfig =\n    sessionAuth.isApiKeyAuth && sessionAuth.apiKey\n      ? {\n          accessToken: \"\", // Empty for API key auth\n          apiKey: sessionAuth.apiKey,\n        }\n      : {\n          accessToken: sessionAuth.accessToken || \"\",\n        };\n\n  // Create in-memory secret storage\n  const secretStorage = await newSecretStorage(storedConfigSchema, \"in-memory\");\n\n  // Create config provider with in-memory storage\n  const configProvider = new ConfigProvider(appConfig, secretStorage);\n\n  // Initialize the config provider with user-specific values\n  await configProvider.update({\n    api: initialConfig.api,\n    credentials,\n    identity: {\n      user: {\n        id: sessionAuth.username,\n        email: `${sessionAuth.username}@toolprint.local`, // Placeholder email\n      },\n    },\n  });\n\n  // Create auth provider with the user-specific config\n  const authProvider = new AuthProvider({ configProvider });\n\n  // Create analytics provider (using dummy for user sessions)\n  const analyticsProvider = new DummyAnalyticsProvider({\n    appConfig,\n    configProvider,\n  });\n\n  // Create a minimal flags provider that doesn't require authentication\n  // for user-specific sessions (flags are typically app-wide)\n  const flagsProvider = {\n    validateFlagName: (flagName: string) => {\n      // No-op for user sessions\n    },\n    all: async () => ({}),\n    value: async (flagName: string) => undefined,\n  } as any; // Type assertion needed due to private class\n\n  logger.debug(\"User providers created successfully\", {\n    username: sessionAuth.username,\n  });\n\n  return {\n    configProvider,\n    authProvider,\n    analyticsProvider,\n    flagsProvider,\n  };\n}\n\n/**\n * Creates user providers from an existing base provider set.\n * This is useful when you want to derive user-specific providers from\n * a global provider configuration.\n *\n * @deprecated Use MultiTenantProviderManager instead for better lifecycle management\n * @param baseProviders - The base providers to derive from\n * @param sessionAuth - The user's authentication information\n * @returns Complete set of providers for the user\n */\nexport async function createUserProvidersFromBase(\n  baseProviders: Providers,\n  sessionAuth: UserSessionAuth,\n): Promise<Providers> {\n  // Get the base configuration\n  const baseConfig = await baseProviders.configProvider.getConfig();\n\n  // Create new providers with the base configuration\n  return createUserProviders(sessionAuth, baseConfig);\n}\n","/**\n * @file Multi-tenant provider management system\n * @module multi-tenant-provider\n *\n * @remarks\n * This module provides a centralized manager for user-specific providers\n * in a multi-tenant environment. It ensures proper isolation between users\n * while efficiently sharing common resources like app configuration.\n */\n\nimport { Providers } from \"./manager.js\";\nimport { ConfigProvider } from \"./config/provider.js\";\nimport { newSecretStorage } from \"./config/secrets.js\";\nimport {\n  storedConfigSchema,\n  AppConfig,\n  Config,\n  CredentialsConfig,\n} from \"./config/schemas.js\";\nimport { AuthProvider } from \"./auth/provider.js\";\nimport { DummyAnalyticsProvider } from \"./analytics/provider.js\";\nimport { logger } from \"./logger.js\";\nimport { IAuthStore } from \"./auth/auth-store.js\";\nimport { PropelAuthInfo } from \"./auth/propel.js\";\nimport { apiKeyFromConfig } from \"./api.js\";\n\n/**\n * Options for configuring the multi-tenant provider manager\n */\nexport interface MultiTenantProviderOptions {\n  /**\n   * Maximum number of concurrent user providers to maintain\n   * If exceeded, least recently used providers are evicted\n   */\n  maxUsers?: number;\n\n  /**\n   * Time-to-live for idle providers in milliseconds\n   * Providers not accessed within this time are eligible for cleanup\n   */\n  providerTTL?: number;\n\n  /**\n   * Interval for running cleanup operations in milliseconds\n   * Default: 5 minutes\n   */\n  cleanupInterval?: number;\n\n  /**\n   * Base API configuration to use for all users\n   * If not provided, uses app's demo sandbox config\n   */\n  baseApiConfig?: Config[\"api\"];\n}\n\n/**\n * Interface for multi-tenant provider management\n */\nexport interface IMultiTenantProviderManager {\n  /**\n   * Get or create providers for a specific user\n   * @param userId - The unique identifier for the user\n   * @returns Complete set of providers for the user\n   */\n  getProviders(userId: string): Promise<Providers>;\n\n  /**\n   * Update authentication information for a user\n   * @param userId - The unique identifier for the user\n   * @param authInfo - The authentication information to update\n   */\n  updateAuth(userId: string, authInfo: PropelAuthInfo): Promise<void>;\n\n  /**\n   * Remove all providers for a specific user\n   * @param userId - The unique identifier for the user\n   */\n  removeUser(userId: string): void;\n\n  /**\n   * Check if a user has active providers\n   * @param userId - The unique identifier for the user\n   * @returns true if the user has providers\n   */\n  hasUser(userId: string): boolean;\n\n  /**\n   * Get all active user IDs\n   * @returns Array of user IDs with active providers\n   */\n  getAllUsers(): string[];\n\n  /**\n   * Clean up expired providers\n   */\n  cleanup(): void;\n\n  /**\n   * Destroy the manager and clean up all resources\n   */\n  destroy(): void;\n}\n\n/**\n * Provider cache entry with metadata\n */\ninterface ProviderCacheEntry {\n  providers: Providers;\n  createdAt: Date;\n  lastAccessed: Date;\n}\n\n/**\n * Multi-tenant provider manager implementation\n *\n * @remarks\n * This class manages provider instances for multiple users in a server environment.\n * It ensures each user has isolated configuration and credentials while sharing\n * common resources like application configuration.\n *\n * @example\n * ```typescript\n * const authStore = createAuthStore<PropelAuthInfo>({ ttl: 3600000 });\n * const manager = new MultiTenantProviderManager(appConfig, authStore);\n *\n * // Get providers for a user\n * const providers = await manager.getProviders(\"user123\");\n *\n * // Update user's auth\n * await manager.updateAuth(\"user123\", newAuthInfo);\n * ```\n */\nexport class MultiTenantProviderManager implements IMultiTenantProviderManager {\n  private readonly appConfig: AppConfig;\n  private readonly authStore: IAuthStore<PropelAuthInfo>;\n  private readonly providersCache = new Map<string, ProviderCacheEntry>();\n  private readonly options: Required<MultiTenantProviderOptions>;\n  private cleanupTimer?: NodeJS.Timeout;\n\n  constructor(\n    appConfig: AppConfig,\n    authStore: IAuthStore<PropelAuthInfo>,\n    options: MultiTenantProviderOptions = {},\n  ) {\n    this.appConfig = appConfig;\n    this.authStore = authStore;\n    this.options = {\n      maxUsers: options.maxUsers ?? 1000,\n      providerTTL: options.providerTTL ?? 3600000, // 1 hour default\n      cleanupInterval: options.cleanupInterval ?? 300000, // 5 minutes default\n      baseApiConfig: options.baseApiConfig ?? appConfig.demoSandbox.api,\n    };\n\n    // Start cleanup timer if TTL is configured\n    if (this.options.providerTTL > 0) {\n      this.startCleanupTimer();\n    }\n\n    logger.info(\"MultiTenantProviderManager initialized\", {\n      maxUsers: this.options.maxUsers,\n      providerTTL: this.options.providerTTL,\n      cleanupInterval: this.options.cleanupInterval,\n    });\n  }\n\n  /**\n   * Get or create providers for a specific user\n   */\n  async getProviders(userId: string): Promise<Providers> {\n    // Check cache first\n    const cached = this.providersCache.get(userId);\n    if (cached) {\n      cached.lastAccessed = new Date();\n      logger.debug(\"Returning cached providers\", { userId });\n      return cached.providers;\n    }\n\n    // Get auth info from store\n    const authInfo = this.authStore.get(userId);\n    if (!authInfo) {\n      throw new Error(`No authentication found for user: ${userId}`);\n    }\n\n    // Check cache size limit\n    if (this.providersCache.size >= this.options.maxUsers) {\n      this.evictOldestProvider();\n    }\n\n    // Create new providers for the user\n    const providers = await this.createUserProviders(userId, authInfo);\n\n    // Cache the providers\n    const entry: ProviderCacheEntry = {\n      providers,\n      createdAt: new Date(),\n      lastAccessed: new Date(),\n    };\n    this.providersCache.set(userId, entry);\n\n    logger.info(\"Created new providers for user\", { userId });\n    return providers;\n  }\n\n  /**\n   * Update authentication information for a user\n   */\n  async updateAuth(userId: string, authInfo: PropelAuthInfo): Promise<void> {\n    // Update auth in store\n    this.authStore.set(userId, authInfo);\n\n    // Update existing providers if cached\n    const cached = this.providersCache.get(userId);\n    if (cached) {\n      const { providers } = cached;\n\n      // Extract credentials from auth info\n      const credentials = this.extractCredentials(authInfo);\n\n      // Update the config provider with new credentials\n      await providers.configProvider.update({\n        credentials,\n        identity: {\n          user: {\n            id: userId,\n            email: authInfo.extra?.email || `${userId}@toolprint.local`,\n          },\n        },\n      });\n\n      cached.lastAccessed = new Date();\n      logger.debug(\"Updated auth for existing providers\", { userId });\n    }\n  }\n\n  /**\n   * Remove all providers for a specific user\n   */\n  removeUser(userId: string): void {\n    // Remove from auth store\n    this.authStore.remove(userId);\n\n    // Remove from cache\n    if (this.providersCache.delete(userId)) {\n      logger.info(\"Removed providers for user\", { userId });\n    }\n  }\n\n  /**\n   * Check if a user has active providers\n   */\n  hasUser(userId: string): boolean {\n    return this.providersCache.has(userId) || this.authStore.has(userId);\n  }\n\n  /**\n   * Get all active user IDs\n   */\n  getAllUsers(): string[] {\n    // Combine users from cache and auth store\n    const users = new Set<string>();\n\n    // Add cached users\n    for (const userId of this.providersCache.keys()) {\n      users.add(userId);\n    }\n\n    // Add users with auth but no cached providers\n    for (const userId of this.authStore.keys()) {\n      users.add(userId);\n    }\n\n    return Array.from(users);\n  }\n\n  /**\n   * Clean up expired providers\n   */\n  cleanup(): void {\n    const now = new Date();\n    const ttl = this.options.providerTTL;\n    let removed = 0;\n\n    for (const [userId, entry] of this.providersCache) {\n      const age = now.getTime() - entry.lastAccessed.getTime();\n      if (age > ttl) {\n        this.providersCache.delete(userId);\n        removed++;\n      }\n    }\n\n    if (removed > 0) {\n      logger.info(`Cleaned up ${removed} expired provider entries`);\n    }\n  }\n\n  /**\n   * Destroy the manager and clean up all resources\n   */\n  destroy(): void {\n    // Stop cleanup timer\n    if (this.cleanupTimer) {\n      clearInterval(this.cleanupTimer);\n      this.cleanupTimer = undefined;\n    }\n\n    // Clear all caches\n    this.providersCache.clear();\n\n    logger.info(\"MultiTenantProviderManager destroyed\");\n  }\n\n  /**\n   * Create providers for a specific user\n   */\n  private async createUserProviders(\n    userId: string,\n    authInfo: PropelAuthInfo,\n  ): Promise<Providers> {\n    // Create in-memory secret storage\n    const secretStorage = await newSecretStorage(\n      storedConfigSchema,\n      \"in-memory\",\n    );\n\n    // Create config provider with in-memory storage\n    const configProvider = new ConfigProvider(this.appConfig, secretStorage);\n\n    // Initialize the config provider first to set up defaults\n    await configProvider.init();\n\n    // Extract credentials from auth info\n    let credentials = this.extractCredentials(authInfo);\n\n    // First, set up the initial config with credentials\n    await configProvider.update({\n      api: this.options.baseApiConfig,\n      credentials,\n      identity: {\n        user: {\n          id: userId,\n          email: authInfo.extra?.email || `${userId}@toolprint.local`,\n        },\n      },\n    });\n\n    // If OAuth user (no API key), fetch the API key using the access token\n    if (!authInfo.extra?.apiKey && authInfo.extra?.propelAccessToken) {\n      try {\n        // Fetch API key using the OAuth token\n        const config = await configProvider.getConfig();\n        const apiKey = await apiKeyFromConfig(config);\n\n        // Update credentials to include the API key\n        credentials = {\n          accessToken: String(authInfo.extra.propelAccessToken),\n          apiKey: apiKey,\n        };\n\n        // Update the config with the API key\n        await configProvider.update({ credentials });\n\n        // Update auth info with the fetched API key for future use\n        authInfo.extra.apiKey = apiKey;\n        this.authStore.set(userId, authInfo);\n\n        logger.info(\"Fetched and stored API key for OAuth user\", { userId });\n      } catch (error) {\n        logger.error(\"Failed to fetch API key for OAuth user\", {\n          userId,\n          error: error instanceof Error ? error.message : String(error),\n        });\n        // Continue without API key - will use OAuth token\n      }\n    }\n\n    // Config has already been updated above\n\n    // Create auth provider with the user-specific config\n    const authProvider = new AuthProvider({ configProvider });\n\n    // Create analytics provider (using dummy for user sessions)\n    const analyticsProvider = new DummyAnalyticsProvider({\n      appConfig: this.appConfig,\n      configProvider,\n    });\n\n    // Create a minimal flags provider for user sessions\n    const flagsProvider = {\n      validateFlagName: (flagName: string) => {\n        // No-op for user sessions\n      },\n      all: async () => ({}),\n      value: async (flagName: string) => undefined,\n    } as any; // Type assertion needed due to private class\n\n    return {\n      configProvider,\n      authProvider,\n      analyticsProvider,\n      flagsProvider,\n    };\n  }\n\n  /**\n   * Extract credentials from PropelAuthInfo\n   */\n  private extractCredentials(authInfo: PropelAuthInfo): CredentialsConfig {\n    // Check if this is API key auth\n    if (authInfo.extra?.apiKey) {\n      return {\n        accessToken: \"\", // Empty for API key auth\n        apiKey: String(authInfo.extra.apiKey),\n      };\n    }\n\n    // OAuth credentials\n    return {\n      accessToken: String(authInfo.extra?.propelAccessToken || \"\"),\n    };\n  }\n\n  /**\n   * Evict the oldest provider based on last accessed time\n   */\n  private evictOldestProvider(): void {\n    let oldestUserId: string | null = null;\n    let oldestTime = new Date();\n\n    for (const [userId, entry] of this.providersCache) {\n      if (entry.lastAccessed < oldestTime) {\n        oldestTime = entry.lastAccessed;\n        oldestUserId = userId;\n      }\n    }\n\n    if (oldestUserId) {\n      this.providersCache.delete(oldestUserId);\n      logger.debug(`Evicted oldest provider entry: ${oldestUserId}`);\n    }\n  }\n\n  /**\n   * Start the cleanup timer\n   */\n  private startCleanupTimer(): void {\n    this.cleanupTimer = setInterval(() => {\n      this.cleanup();\n    }, this.options.cleanupInterval);\n  }\n}\n\n/**\n * Create a multi-tenant provider manager with default options\n */\nexport function createMultiTenantProviderManager(\n  appConfig: AppConfig,\n  authStore: IAuthStore<PropelAuthInfo>,\n  options?: MultiTenantProviderOptions,\n): IMultiTenantProviderManager {\n  return new MultiTenantProviderManager(appConfig, authStore, options);\n}\n"],"mappings":"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","names":["index_exports","__export","AnalyticsProvider","AuthProvider","AuthStore","ConfigProvider","ConfigStore","DummyAnalyticsProvider","MultiTenantProviderManager","PropelAuthProvider","agentSchema","apiKeyClientFromConfig","apiKeyFromConfig","apiSchema","appEnv","appSchema","bearerAuthClientFromConfig","clientFromConfig","configSchema","createAuthStore","createMultiTenantProviderManager","createPropelAuthStore","createUserProviders","createUserProvidersFromBase","credentialsSchema","demoSandboxSchema","getAppConfig","getEnv","getProviders","identitySchema","isClientAuthenticated","maskSensitiveFieldsSerializer","masked","newSecretStorage","oidcSchema","orgSchema","posthogSchema","propelAuthSchema","storedConfigSchema","userPreferencesSchema","userSchema","validateApiUrl","__toCommonJS","import_sdk","providersLogLevel","getLogger","logger","import_zod","appConfig","import_meta","appEnv","val","getEnv","parsedEnv","getAppConfig","env","logger","appConfig","fs","path","__dirname","configDir","appConfigFileName","appConfigPath","import_sdk","validateApiUrl","url","response","logger","error","clientFromConfig","config","clientParams","bearerAuthClientFromConfig","apiKeyFromConfig","userAccount","isClientAuthenticated","client","apiKeyClientFromConfig","apiKey","import_sdk","import_zod","propelAuthSchema","oidcSchema","posthogSchema","apiSchema","demoSandboxSchema","agentSchema","url","appSchema","userPreferencesSchema","userSchema","orgSchema","identitySchema","credentialsSchema","storedConfigSchema","configSchema","isSensitiveKey","key","sensitiveKeys","cleanedKey","maskSensitiveFieldsSerializer","value","masked","config","import_async_mutex","ConfigStore","secretStore","currentAppConfig","storageKey","logger","storedConfig","config","configSchema","app","configWithoutApp","currentConfig","error","ConfigProvider","appConfig","secretStore","ConfigStore","config","apiUrl","identity","credentials","import_open","import_sdk","jose","import_javascript","import_http","import_open","import_openid_client","OAuthCallbackServer","port","http","logger","resolve","reject","timeoutId","req","res","callbackUrl","error","errorDescription","err","errorMessage","loginFlow","oidcConfig","output","redirectPort","server","oidcDiscoveredConfig","code_verifier","code_challenge","state","parameters","redirectTo","open","tokens","loginFlowWithTimeout","timeout","timeoutPromise","_","getUserDetailsFromJwt","accessToken","error","logger","PropelAuthProvider","params","propelAuthUrl","urlString","output","oidcConfig","tokens","loginFlowWithTimeout","userDetails","AuthProvider","params","PropelAuthProvider","logger","config","bearerAuthClientFromConfig","apiKeyFromConfig","apiKeyClientFromConfig","response","error","invitationCode","loginMode","userEmail","client","authStatus","accountInfo","output","tokens","userDetails","url","open","import_posthog_node","getPostHogClient","apiKey","host","AnalyticsProvider","params","getPostHogClient","logger","properties","event","userId","error","DummyAnalyticsProvider","_","import_sdk","newSecretStorage","schema","location","logger","newKeyringStorage","newConfigDirStorage","newInMemoryStorage","path","fs","configDir","SchemaValidatedConfigDirSecretStorage","key","sanitizedKey","filePath","value","fileContent","validated","jsonString","Entry","SchemaValidatedKeyringSecretStorage","entry","error","SchemaValidatedInMemorySecretStorage","CLI_FLAGS","FlagConfigurationError","message","ValidatedFlagsProvider","configProvider","authProvider","flagName","flags","cliFlags","getProviders","appConfig","getAppConfig","configDirSecretStorage","newSecretStorage","storedConfigSchema","ConfigProvider","AuthProvider","analyticsProvider","AnalyticsProvider","logger","DummyAnalyticsProvider","error","AuthStore","options","sessionId","authInfo","now","entry","logger","count","result","removed","oldestSessionId","oldestTime","createAuthStore","createPropelAuthStore","createUserProviders","sessionAuth","baseConfig","logger","appConfig","getAppConfig","initialConfig","credentials","secretStorage","newSecretStorage","storedConfigSchema","configProvider","ConfigProvider","authProvider","AuthProvider","analyticsProvider","DummyAnalyticsProvider","flagsProvider","flagName","createUserProvidersFromBase","baseProviders","MultiTenantProviderManager","appConfig","authStore","options","logger","userId","cached","authInfo","providers","entry","credentials","users","now","ttl","removed","secretStorage","newSecretStorage","storedConfigSchema","configProvider","ConfigProvider","config","apiKey","apiKeyFromConfig","error","authProvider","AuthProvider","analyticsProvider","DummyAnalyticsProvider","flagName","oldestUserId","oldestTime","createMultiTenantProviderManager"]}