aemeathcli 1.0.4 → 1.0.6

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.
@@ -121,7 +121,7 @@ var ProviderRegistry = class {
121
121
  };
122
122
  async function createDefaultRegistry() {
123
123
  const registry = new ProviderRegistry();
124
- const { SessionManager } = await import('./session-manager-ECEEACGY.js');
124
+ const { SessionManager } = await import('./session-manager-ZMRJN33X.js');
125
125
  const session = new SessionManager();
126
126
  const { execa } = await import('execa');
127
127
  const preferSdk = process.env["AEMEATHCLI_PREFER_SDK"] === "1";
@@ -242,5 +242,5 @@ async function createDefaultRegistry() {
242
242
  }
243
243
 
244
244
  export { ProviderRegistry, createDefaultRegistry };
245
- //# sourceMappingURL=chunk-O3ZF22SW.js.map
246
- //# sourceMappingURL=chunk-O3ZF22SW.js.map
245
+ //# sourceMappingURL=chunk-LJ6K3FYY.js.map
246
+ //# sourceMappingURL=chunk-LJ6K3FYY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/providers/registry.ts"],"names":["provider"],"mappings":"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","file":"chunk-O3ZF22SW.js","sourcesContent":["/**\n * Provider registry per PRD section 7.1\n * Central registry for provider adapters — register, resolve, list.\n */\n\nimport { logger } from \"../utils/logger.js\";\nimport { ModelNotFoundError } from \"../types/errors.js\";\nimport { SUPPORTED_MODELS } from \"../types/model.js\";\nimport type { IModelInfo } from \"../types/model.js\";\nimport type { IModelProvider } from \"./types.js\";\n\n/**\n * Singleton registry that maps provider names and model IDs to provider adapters.\n */\nexport class ProviderRegistry {\n private readonly providers = new Map<string, IModelProvider>();\n private readonly modelToProvider = new Map<string, string>();\n\n /**\n * Register a provider adapter.\n * Automatically indexes all supported models to this provider.\n */\n register(provider: IModelProvider): void {\n this.providers.set(provider.name, provider);\n\n for (const modelId of provider.supportedModels) {\n this.modelToProvider.set(modelId, provider.name);\n }\n\n logger.debug(\n { provider: provider.name, models: provider.supportedModels },\n \"Provider registered\",\n );\n }\n\n /**\n * Get a provider adapter by its name (e.g. \"anthropic\", \"openai\").\n */\n getByName(name: string): IModelProvider | undefined {\n return this.providers.get(name);\n }\n\n /**\n * Get the provider adapter that supports a given model ID.\n * @throws ModelNotFoundError if no provider serves this model.\n */\n getForModel(modelId: string): IModelProvider {\n const providerName = this.modelToProvider.get(modelId);\n if (providerName === undefined) {\n throw new ModelNotFoundError(modelId);\n }\n\n const provider = this.providers.get(providerName);\n if (provider === undefined) {\n throw new ModelNotFoundError(modelId);\n }\n\n return provider;\n }\n\n /**\n * Resolve a model string to its provider.\n * Supports both model IDs (\"claude-sonnet-4-6\") and provider-prefixed\n * forms (\"anthropic:claude-sonnet-4-6\").\n */\n resolve(modelString: string): { provider: IModelProvider; modelId: string } {\n const colonIndex = modelString.indexOf(\":\");\n if (colonIndex !== -1) {\n const providerName = modelString.slice(0, colonIndex);\n const modelId = modelString.slice(colonIndex + 1);\n const provider = this.providers.get(providerName);\n if (provider === undefined) {\n throw new ModelNotFoundError(modelString);\n }\n return { provider, modelId };\n }\n\n const provider = this.getForModel(modelString);\n return { provider, modelId: modelString };\n }\n\n /**\n * List all registered model IDs across all providers.\n */\n listModels(): readonly IModelInfo[] {\n const models: IModelInfo[] = [];\n\n for (const provider of this.providers.values()) {\n for (const modelId of provider.supportedModels) {\n const info = SUPPORTED_MODELS[modelId];\n if (info !== undefined) {\n models.push(info);\n }\n }\n }\n\n return models;\n }\n\n /**\n * List all registered provider names.\n */\n listProviders(): readonly string[] {\n return [...this.providers.keys()];\n }\n\n /**\n * Check if a model ID is supported by any registered provider.\n */\n hasModel(modelId: string): boolean {\n return this.modelToProvider.has(modelId);\n }\n\n /**\n * Check if a provider is registered.\n */\n hasProvider(name: string): boolean {\n return this.providers.has(name);\n }\n\n /**\n * List available models from all providers.\n * Uses dynamic API listing where supported, falls back to static models.\n */\n async listAllAvailableModels(): Promise<Map<string, readonly string[]>> {\n const entries = [...this.providers.entries()];\n const fetched = await Promise.all(\n entries.map(async ([name, provider]): Promise<[string, readonly string[]]> => {\n if (typeof provider.listAvailableModels === \"function\") {\n try {\n return [name, await provider.listAvailableModels()];\n } catch {\n return [name, [...provider.supportedModels]];\n }\n }\n return [name, [...provider.supportedModels]];\n }),\n );\n\n const result = new Map<string, readonly string[]>();\n fetched.sort(([a], [b]) => a.localeCompare(b));\n for (const [name, models] of fetched) {\n result.set(name, models);\n }\n\n return result;\n }\n}\n\n/**\n * Create a pre-populated registry with all available providers.\n * Resolves credentials via SessionManager (CLI delegation, API keys, env vars).\n */\nexport async function createDefaultRegistry(): Promise<ProviderRegistry> {\n const registry = new ProviderRegistry();\n\n const { SessionManager } = await import(\"../auth/session-manager.js\");\n const session = new SessionManager();\n const { execa } = await import(\"execa\");\n\n // When AEMEATHCLI_PREFER_SDK=1 (set for agent child processes), prefer\n // SDK-based adapters over native CLI adapters. Native CLI adapters shell\n // out to external binaries whose raw JSON output can interfere with IPC\n // streaming. Falls back to native only when no API key is available.\n const preferSdk = process.env[\"AEMEATHCLI_PREFER_SDK\"] === \"1\";\n\n const cliAvailability = new Map<string, boolean>();\n const hasCli = async (command: string): Promise<boolean> => {\n const cached = cliAvailability.get(command);\n if (cached !== undefined) {\n return cached;\n }\n\n try {\n await execa(\"which\", [command], { timeout: 3000 });\n cliAvailability.set(command, true);\n return true;\n } catch {\n cliAvailability.set(command, false);\n return false;\n }\n };\n\n /** Determine whether to use a native CLI adapter for a provider. */\n const shouldUseNative = async (\n credential: { method: string; token?: string | undefined } | undefined,\n cliCommand: string,\n envKeyName: string,\n ): Promise<boolean> => {\n // Native login credentials (OAuth sessions) must always use the native CLI\n // adapter. The stored token is an OAuth session token, NOT an API key — SDK\n // adapters will reject it with \"invalid x-api-key\" / \"API key not valid\".\n if (credential?.method === \"native_login\") {\n return await hasCli(cliCommand);\n }\n\n // When preferSdk is set, only use native if SDK has no way to authenticate.\n if (preferSdk) {\n const hasApiKey =\n credential?.token !== undefined ||\n process.env[envKeyName] !== undefined;\n if (hasApiKey) {\n return false;\n }\n // No API key available — fall back to native if CLI exists.\n return await hasCli(cliCommand);\n }\n\n // Default behavior: prefer native when CLI is available and no explicit credential.\n return credential === undefined && await hasCli(cliCommand);\n };\n\n const providerLoaders: ReadonlyArray<{\n name: string;\n load: () => Promise<IModelProvider>;\n }> = [\n {\n name: \"anthropic\",\n load: async () => {\n const { ClaudeAdapter } = await import(\"./claude-adapter.js\");\n const credential = await session.getActiveCredential(\"anthropic\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"claude\", \"ANTHROPIC_API_KEY\");\n\n if (useNative) {\n const { ClaudeNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"anthropic\");\n return new ClaudeNativeCLIAdapter();\n }\n\n return new ClaudeAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"openai\",\n load: async () => {\n const { OpenAIAdapter } = await import(\"./openai-adapter.js\");\n const credential = await session.getActiveCredential(\"openai\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"codex\", \"OPENAI_API_KEY\");\n\n if (useNative) {\n const { CodexNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"openai\");\n return new CodexNativeCLIAdapter();\n }\n\n return new OpenAIAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"google\",\n load: async () => {\n const { GeminiAdapter } = await import(\"./gemini-adapter.js\");\n const credential = await session.getActiveCredential(\"google\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"gemini\", \"GOOGLE_API_KEY\");\n\n if (useNative) {\n const { GeminiNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"google\");\n return new GeminiNativeCLIAdapter();\n }\n\n return new GeminiAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"kimi\",\n load: async () => {\n const { KimiAdapter } = await import(\"./kimi-adapter.js\");\n const credential = await session.getActiveCredential(\"kimi\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"kimi\", \"MOONSHOT_API_KEY\");\n\n if (useNative) {\n const { KimiNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"kimi\");\n return new KimiNativeCLIAdapter();\n }\n\n return new KimiAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n ];\n\n // Initialize all providers in parallel (including Ollama)\n const ollamaTask = (async () => {\n try {\n const { OllamaAdapter } = await import(\"./ollama-adapter.js\");\n const ollama = new OllamaAdapter();\n await ollama.refreshModels();\n registry.register(ollama);\n } catch {\n // Ollama not available\n }\n })();\n\n await Promise.all([\n ...providerLoaders.map(async (config) => {\n try {\n const adapter = await config.load();\n registry.register(adapter);\n } catch {\n // Skip provider if adapter fails to initialize\n }\n }),\n ollamaTask,\n ]);\n\n return registry;\n}\n"]}
1
+ {"version":3,"sources":["../src/providers/registry.ts"],"names":["provider"],"mappings":"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","file":"chunk-LJ6K3FYY.js","sourcesContent":["/**\n * Provider registry per PRD section 7.1\n * Central registry for provider adapters — register, resolve, list.\n */\n\nimport { logger } from \"../utils/logger.js\";\nimport { ModelNotFoundError } from \"../types/errors.js\";\nimport { SUPPORTED_MODELS } from \"../types/model.js\";\nimport type { IModelInfo } from \"../types/model.js\";\nimport type { IModelProvider } from \"./types.js\";\n\n/**\n * Singleton registry that maps provider names and model IDs to provider adapters.\n */\nexport class ProviderRegistry {\n private readonly providers = new Map<string, IModelProvider>();\n private readonly modelToProvider = new Map<string, string>();\n\n /**\n * Register a provider adapter.\n * Automatically indexes all supported models to this provider.\n */\n register(provider: IModelProvider): void {\n this.providers.set(provider.name, provider);\n\n for (const modelId of provider.supportedModels) {\n this.modelToProvider.set(modelId, provider.name);\n }\n\n logger.debug(\n { provider: provider.name, models: provider.supportedModels },\n \"Provider registered\",\n );\n }\n\n /**\n * Get a provider adapter by its name (e.g. \"anthropic\", \"openai\").\n */\n getByName(name: string): IModelProvider | undefined {\n return this.providers.get(name);\n }\n\n /**\n * Get the provider adapter that supports a given model ID.\n * @throws ModelNotFoundError if no provider serves this model.\n */\n getForModel(modelId: string): IModelProvider {\n const providerName = this.modelToProvider.get(modelId);\n if (providerName === undefined) {\n throw new ModelNotFoundError(modelId);\n }\n\n const provider = this.providers.get(providerName);\n if (provider === undefined) {\n throw new ModelNotFoundError(modelId);\n }\n\n return provider;\n }\n\n /**\n * Resolve a model string to its provider.\n * Supports both model IDs (\"claude-sonnet-4-6\") and provider-prefixed\n * forms (\"anthropic:claude-sonnet-4-6\").\n */\n resolve(modelString: string): { provider: IModelProvider; modelId: string } {\n const colonIndex = modelString.indexOf(\":\");\n if (colonIndex !== -1) {\n const providerName = modelString.slice(0, colonIndex);\n const modelId = modelString.slice(colonIndex + 1);\n const provider = this.providers.get(providerName);\n if (provider === undefined) {\n throw new ModelNotFoundError(modelString);\n }\n return { provider, modelId };\n }\n\n const provider = this.getForModel(modelString);\n return { provider, modelId: modelString };\n }\n\n /**\n * List all registered model IDs across all providers.\n */\n listModels(): readonly IModelInfo[] {\n const models: IModelInfo[] = [];\n\n for (const provider of this.providers.values()) {\n for (const modelId of provider.supportedModels) {\n const info = SUPPORTED_MODELS[modelId];\n if (info !== undefined) {\n models.push(info);\n }\n }\n }\n\n return models;\n }\n\n /**\n * List all registered provider names.\n */\n listProviders(): readonly string[] {\n return [...this.providers.keys()];\n }\n\n /**\n * Check if a model ID is supported by any registered provider.\n */\n hasModel(modelId: string): boolean {\n return this.modelToProvider.has(modelId);\n }\n\n /**\n * Check if a provider is registered.\n */\n hasProvider(name: string): boolean {\n return this.providers.has(name);\n }\n\n /**\n * List available models from all providers.\n * Uses dynamic API listing where supported, falls back to static models.\n */\n async listAllAvailableModels(): Promise<Map<string, readonly string[]>> {\n const entries = [...this.providers.entries()];\n const fetched = await Promise.all(\n entries.map(async ([name, provider]): Promise<[string, readonly string[]]> => {\n if (typeof provider.listAvailableModels === \"function\") {\n try {\n return [name, await provider.listAvailableModels()];\n } catch {\n return [name, [...provider.supportedModels]];\n }\n }\n return [name, [...provider.supportedModels]];\n }),\n );\n\n const result = new Map<string, readonly string[]>();\n fetched.sort(([a], [b]) => a.localeCompare(b));\n for (const [name, models] of fetched) {\n result.set(name, models);\n }\n\n return result;\n }\n}\n\n/**\n * Create a pre-populated registry with all available providers.\n * Resolves credentials via SessionManager (CLI delegation, API keys, env vars).\n */\nexport async function createDefaultRegistry(): Promise<ProviderRegistry> {\n const registry = new ProviderRegistry();\n\n const { SessionManager } = await import(\"../auth/session-manager.js\");\n const session = new SessionManager();\n const { execa } = await import(\"execa\");\n\n // When AEMEATHCLI_PREFER_SDK=1 (set for agent child processes), prefer\n // SDK-based adapters over native CLI adapters. Native CLI adapters shell\n // out to external binaries whose raw JSON output can interfere with IPC\n // streaming. Falls back to native only when no API key is available.\n const preferSdk = process.env[\"AEMEATHCLI_PREFER_SDK\"] === \"1\";\n\n const cliAvailability = new Map<string, boolean>();\n const hasCli = async (command: string): Promise<boolean> => {\n const cached = cliAvailability.get(command);\n if (cached !== undefined) {\n return cached;\n }\n\n try {\n await execa(\"which\", [command], { timeout: 3000 });\n cliAvailability.set(command, true);\n return true;\n } catch {\n cliAvailability.set(command, false);\n return false;\n }\n };\n\n /** Determine whether to use a native CLI adapter for a provider. */\n const shouldUseNative = async (\n credential: { method: string; token?: string | undefined } | undefined,\n cliCommand: string,\n envKeyName: string,\n ): Promise<boolean> => {\n // Native login credentials (OAuth sessions) must always use the native CLI\n // adapter. The stored token is an OAuth session token, NOT an API key — SDK\n // adapters will reject it with \"invalid x-api-key\" / \"API key not valid\".\n if (credential?.method === \"native_login\") {\n return await hasCli(cliCommand);\n }\n\n // When preferSdk is set, only use native if SDK has no way to authenticate.\n if (preferSdk) {\n const hasApiKey =\n credential?.token !== undefined ||\n process.env[envKeyName] !== undefined;\n if (hasApiKey) {\n return false;\n }\n // No API key available — fall back to native if CLI exists.\n return await hasCli(cliCommand);\n }\n\n // Default behavior: prefer native when CLI is available and no explicit credential.\n return credential === undefined && await hasCli(cliCommand);\n };\n\n const providerLoaders: ReadonlyArray<{\n name: string;\n load: () => Promise<IModelProvider>;\n }> = [\n {\n name: \"anthropic\",\n load: async () => {\n const { ClaudeAdapter } = await import(\"./claude-adapter.js\");\n const credential = await session.getActiveCredential(\"anthropic\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"claude\", \"ANTHROPIC_API_KEY\");\n\n if (useNative) {\n const { ClaudeNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"anthropic\");\n return new ClaudeNativeCLIAdapter();\n }\n\n return new ClaudeAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"openai\",\n load: async () => {\n const { OpenAIAdapter } = await import(\"./openai-adapter.js\");\n const credential = await session.getActiveCredential(\"openai\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"codex\", \"OPENAI_API_KEY\");\n\n if (useNative) {\n const { CodexNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"openai\");\n return new CodexNativeCLIAdapter();\n }\n\n return new OpenAIAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"google\",\n load: async () => {\n const { GeminiAdapter } = await import(\"./gemini-adapter.js\");\n const credential = await session.getActiveCredential(\"google\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"gemini\", \"GOOGLE_API_KEY\");\n\n if (useNative) {\n const { GeminiNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"google\");\n return new GeminiNativeCLIAdapter();\n }\n\n return new GeminiAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n {\n name: \"kimi\",\n load: async () => {\n const { KimiAdapter } = await import(\"./kimi-adapter.js\");\n const credential = await session.getActiveCredential(\"kimi\").catch(() => undefined);\n const useNative = await shouldUseNative(credential, \"kimi\", \"MOONSHOT_API_KEY\");\n\n if (useNative) {\n const { KimiNativeCLIAdapter, logNativeAdapterSelection } = await import(\n \"./native-cli-adapters.js\"\n );\n logNativeAdapterSelection(\"kimi\");\n return new KimiNativeCLIAdapter();\n }\n\n return new KimiAdapter(\n credential?.token !== undefined ? { apiKey: credential.token } : undefined,\n );\n },\n },\n ];\n\n // Initialize all providers in parallel (including Ollama)\n const ollamaTask = (async () => {\n try {\n const { OllamaAdapter } = await import(\"./ollama-adapter.js\");\n const ollama = new OllamaAdapter();\n await ollama.refreshModels();\n registry.register(ollama);\n } catch {\n // Ollama not available\n }\n })();\n\n await Promise.all([\n ...providerLoaders.map(async (config) => {\n try {\n const adapter = await config.load();\n registry.register(adapter);\n } catch {\n // Skip provider if adapter fails to initialize\n }\n }),\n ollamaTask,\n ]);\n\n return registry;\n}\n"]}
@@ -128,15 +128,15 @@ var SessionManager = class {
128
128
  return new mod.ClaudeLogin(this.credentialStore);
129
129
  }
130
130
  case "openai": {
131
- const mod = await import('./codex-login-7HHLJHBF.js');
131
+ const mod = await import('./codex-login-PQ6A6T5P.js');
132
132
  return new mod.CodexLogin(this.credentialStore);
133
133
  }
134
134
  case "google": {
135
- const mod = await import('./gemini-login-ZZLYC3J6.js');
135
+ const mod = await import('./gemini-login-WVBX7642.js');
136
136
  return new mod.GeminiLogin(this.credentialStore);
137
137
  }
138
138
  case "kimi": {
139
- const mod = await import('./kimi-login-CZPS63NK.js');
139
+ const mod = await import('./kimi-login-RQIEP7TO.js');
140
140
  return new mod.KimiLogin(this.credentialStore);
141
141
  }
142
142
  default:
@@ -177,5 +177,5 @@ var SessionManager = class {
177
177
  };
178
178
 
179
179
  export { SessionManager };
180
- //# sourceMappingURL=chunk-SUSJPZU2.js.map
181
- //# sourceMappingURL=chunk-SUSJPZU2.js.map
180
+ //# sourceMappingURL=chunk-YVJL75JT.js.map
181
+ //# sourceMappingURL=chunk-YVJL75JT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/session-manager.ts"],"names":[],"mappings":"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","file":"chunk-SUSJPZU2.js","sourcesContent":["/**\n * Multi-provider session lifecycle per PRD section 13.5\n * Resolution priority: native login (CLI delegation) > API key > env variable > credential helper\n *\n * Credentials are obtained by delegating to official CLI tools:\n * - Claude Code CLI → macOS Keychain\n * - Codex CLI → ~/.codex/auth.json\n * - Gemini CLI → ~/.gemini/oauth_creds.json\n * - Kimi CLI → ~/.kimi/credentials/kimi-code.json\n */\n\nimport type { ProviderName, ICredential, AuthMethod } from \"../types/index.js\";\nimport { AuthenticationError } from \"../types/index.js\";\nimport { CredentialStore } from \"./credential-store.js\";\nimport { ApiKeyFallback } from \"./api-key-fallback.js\";\nimport { logger } from \"../utils/index.js\";\n\nexport class SessionManager {\n private readonly credentialStore: CredentialStore;\n private readonly apiKeyFallback: ApiKeyFallback;\n\n constructor(store?: CredentialStore) {\n this.credentialStore = store ?? new CredentialStore();\n this.apiKeyFallback = new ApiKeyFallback(this.credentialStore);\n }\n\n /**\n * Get the best available credential for a provider.\n * Follows resolution priority from PRD section 13.5.\n */\n async getActiveCredential(provider: ProviderName): Promise<ICredential> {\n // 1. Native account session (delegated CLI login — stored in our credential store)\n const nativeCredential = await this.credentialStore.get(provider);\n if (nativeCredential && nativeCredential.method === \"native_login\" && !this.isExpired(nativeCredential)) {\n return nativeCredential;\n }\n\n // 1b. If expired, try re-reading from the official CLI's cached tokens\n if (nativeCredential && nativeCredential.method === \"native_login\" && this.isExpired(nativeCredential)) {\n const refreshed = await this.refreshFromCliCache(provider);\n if (refreshed) {\n return refreshed;\n }\n }\n\n // 1c. Even if no native credential stored, check CLI caches directly\n if (!nativeCredential || nativeCredential.method !== \"native_login\") {\n const fromCli = await this.refreshFromCliCache(provider);\n if (fromCli) {\n return fromCli;\n }\n }\n\n // 2. API key set via auth set-key\n const apiKeyCredential = await this.apiKeyFallback.getCredential(provider);\n if (apiKeyCredential) {\n return apiKeyCredential;\n }\n\n // 3. Environment variable\n const envCredential = this.getFromEnvironment(provider);\n if (envCredential) {\n return envCredential;\n }\n\n throw new AuthenticationError(provider, `No credentials found for ${provider}`);\n }\n\n /**\n * Check if a provider has any available credential.\n */\n async isAuthenticated(provider: ProviderName): Promise<boolean> {\n try {\n await this.getActiveCredential(provider);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get status info for a provider.\n */\n async getStatus(provider: ProviderName): Promise<{\n loggedIn: boolean;\n method?: AuthMethod | undefined;\n email?: string | undefined;\n plan?: string | undefined;\n }> {\n try {\n const credential = await this.getActiveCredential(provider);\n return {\n loggedIn: true,\n method: credential.method,\n ...(credential.email !== undefined ? { email: credential.email } : {}),\n ...(credential.plan !== undefined ? { plan: credential.plan } : {}),\n };\n } catch {\n return { loggedIn: false };\n }\n }\n\n /**\n * Get the API key or token string for a provider.\n */\n async getToken(provider: ProviderName): Promise<string> {\n const credential = await this.getActiveCredential(provider);\n if (!credential.token) {\n throw new AuthenticationError(provider, \"Credential has no token\");\n }\n return credential.token;\n }\n\n /**\n * Re-read tokens from the official CLI's cached storage.\n * This is the \"refresh\" mechanism — instead of doing HTTP refresh ourselves,\n * we re-read from the CLI tool's cache which may have been refreshed by the CLI.\n */\n private async refreshFromCliCache(provider: ProviderName): Promise<ICredential | undefined> {\n try {\n const loginModule = await this.loadLoginModule(provider);\n if (!loginModule) {\n return undefined;\n }\n\n // Prefer direct cached credential extraction from the provider login module.\n if (typeof loginModule.getCachedCredential === \"function\") {\n const cached = await loginModule.getCachedCredential();\n if (cached) {\n await this.credentialStore.set(provider, cached);\n if (!this.isExpired(cached) || cached.refreshToken !== undefined) {\n logger.info({ provider }, \"Loaded credentials from provider CLI cache\");\n return cached;\n }\n }\n }\n\n const status = await loginModule.getStatus();\n if (!status.loggedIn) {\n return undefined;\n }\n\n // The login module reads from the CLI's cache, check if we can get a fresh credential\n const isStillLoggedIn = await loginModule.isLoggedIn();\n if (!isStillLoggedIn) {\n return undefined;\n }\n\n // Re-read by checking the stored credential in our store\n // The login modules update the credential store when they find valid tokens\n const credential = await this.credentialStore.get(provider);\n if (credential && !this.isExpired(credential)) {\n logger.info({ provider }, \"Refreshed credentials from CLI cache\");\n return credential;\n }\n\n return undefined;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.debug({ provider, error: msg }, \"Failed to refresh from CLI cache\");\n return undefined;\n }\n }\n\n private async loadLoginModule(provider: ProviderName): Promise<{\n getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }>;\n isLoggedIn(): Promise<boolean>;\n getCachedCredential?(): Promise<ICredential | undefined>;\n } | undefined> {\n try {\n switch (provider) {\n case \"anthropic\": {\n const mod = await import(\"./providers/claude-login.js\");\n return new mod.ClaudeLogin(this.credentialStore);\n }\n case \"openai\": {\n const mod = await import(\"./providers/codex-login.js\");\n return new mod.CodexLogin(this.credentialStore);\n }\n case \"google\": {\n const mod = await import(\"./providers/gemini-login.js\");\n return new mod.GeminiLogin(this.credentialStore);\n }\n case \"kimi\": {\n const mod = await import(\"./providers/kimi-login.js\");\n return new mod.KimiLogin(this.credentialStore);\n }\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n }\n\n private isExpired(credential: ICredential): boolean {\n if (!credential.expiresAt) {\n return false;\n }\n return new Date() > credential.expiresAt;\n }\n\n private getFromEnvironment(provider: ProviderName): ICredential | undefined {\n const envMap: Record<ProviderName, string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n google: \"GOOGLE_API_KEY\",\n kimi: \"MOONSHOT_API_KEY\",\n ollama: \"\",\n };\n\n const envKey = envMap[provider];\n if (!envKey) {\n return undefined;\n }\n\n const token = process.env[envKey];\n if (!token) {\n return undefined;\n }\n\n return {\n provider,\n method: \"env_variable\",\n token,\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/auth/session-manager.ts"],"names":[],"mappings":"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","file":"chunk-YVJL75JT.js","sourcesContent":["/**\n * Multi-provider session lifecycle per PRD section 13.5\n * Resolution priority: native login (CLI delegation) > API key > env variable > credential helper\n *\n * Credentials are obtained by delegating to official CLI tools:\n * - Claude Code CLI → macOS Keychain\n * - Codex CLI → ~/.codex/auth.json\n * - Gemini CLI → ~/.gemini/oauth_creds.json\n * - Kimi CLI → ~/.kimi/credentials/kimi-code.json\n */\n\nimport type { ProviderName, ICredential, AuthMethod } from \"../types/index.js\";\nimport { AuthenticationError } from \"../types/index.js\";\nimport { CredentialStore } from \"./credential-store.js\";\nimport { ApiKeyFallback } from \"./api-key-fallback.js\";\nimport { logger } from \"../utils/index.js\";\n\nexport class SessionManager {\n private readonly credentialStore: CredentialStore;\n private readonly apiKeyFallback: ApiKeyFallback;\n\n constructor(store?: CredentialStore) {\n this.credentialStore = store ?? new CredentialStore();\n this.apiKeyFallback = new ApiKeyFallback(this.credentialStore);\n }\n\n /**\n * Get the best available credential for a provider.\n * Follows resolution priority from PRD section 13.5.\n */\n async getActiveCredential(provider: ProviderName): Promise<ICredential> {\n // 1. Native account session (delegated CLI login — stored in our credential store)\n const nativeCredential = await this.credentialStore.get(provider);\n if (nativeCredential && nativeCredential.method === \"native_login\" && !this.isExpired(nativeCredential)) {\n return nativeCredential;\n }\n\n // 1b. If expired, try re-reading from the official CLI's cached tokens\n if (nativeCredential && nativeCredential.method === \"native_login\" && this.isExpired(nativeCredential)) {\n const refreshed = await this.refreshFromCliCache(provider);\n if (refreshed) {\n return refreshed;\n }\n }\n\n // 1c. Even if no native credential stored, check CLI caches directly\n if (!nativeCredential || nativeCredential.method !== \"native_login\") {\n const fromCli = await this.refreshFromCliCache(provider);\n if (fromCli) {\n return fromCli;\n }\n }\n\n // 2. API key set via auth set-key\n const apiKeyCredential = await this.apiKeyFallback.getCredential(provider);\n if (apiKeyCredential) {\n return apiKeyCredential;\n }\n\n // 3. Environment variable\n const envCredential = this.getFromEnvironment(provider);\n if (envCredential) {\n return envCredential;\n }\n\n throw new AuthenticationError(provider, `No credentials found for ${provider}`);\n }\n\n /**\n * Check if a provider has any available credential.\n */\n async isAuthenticated(provider: ProviderName): Promise<boolean> {\n try {\n await this.getActiveCredential(provider);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get status info for a provider.\n */\n async getStatus(provider: ProviderName): Promise<{\n loggedIn: boolean;\n method?: AuthMethod | undefined;\n email?: string | undefined;\n plan?: string | undefined;\n }> {\n try {\n const credential = await this.getActiveCredential(provider);\n return {\n loggedIn: true,\n method: credential.method,\n ...(credential.email !== undefined ? { email: credential.email } : {}),\n ...(credential.plan !== undefined ? { plan: credential.plan } : {}),\n };\n } catch {\n return { loggedIn: false };\n }\n }\n\n /**\n * Get the API key or token string for a provider.\n */\n async getToken(provider: ProviderName): Promise<string> {\n const credential = await this.getActiveCredential(provider);\n if (!credential.token) {\n throw new AuthenticationError(provider, \"Credential has no token\");\n }\n return credential.token;\n }\n\n /**\n * Re-read tokens from the official CLI's cached storage.\n * This is the \"refresh\" mechanism — instead of doing HTTP refresh ourselves,\n * we re-read from the CLI tool's cache which may have been refreshed by the CLI.\n */\n private async refreshFromCliCache(provider: ProviderName): Promise<ICredential | undefined> {\n try {\n const loginModule = await this.loadLoginModule(provider);\n if (!loginModule) {\n return undefined;\n }\n\n // Prefer direct cached credential extraction from the provider login module.\n if (typeof loginModule.getCachedCredential === \"function\") {\n const cached = await loginModule.getCachedCredential();\n if (cached) {\n await this.credentialStore.set(provider, cached);\n if (!this.isExpired(cached) || cached.refreshToken !== undefined) {\n logger.info({ provider }, \"Loaded credentials from provider CLI cache\");\n return cached;\n }\n }\n }\n\n const status = await loginModule.getStatus();\n if (!status.loggedIn) {\n return undefined;\n }\n\n // The login module reads from the CLI's cache, check if we can get a fresh credential\n const isStillLoggedIn = await loginModule.isLoggedIn();\n if (!isStillLoggedIn) {\n return undefined;\n }\n\n // Re-read by checking the stored credential in our store\n // The login modules update the credential store when they find valid tokens\n const credential = await this.credentialStore.get(provider);\n if (credential && !this.isExpired(credential)) {\n logger.info({ provider }, \"Refreshed credentials from CLI cache\");\n return credential;\n }\n\n return undefined;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n logger.debug({ provider, error: msg }, \"Failed to refresh from CLI cache\");\n return undefined;\n }\n }\n\n private async loadLoginModule(provider: ProviderName): Promise<{\n getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }>;\n isLoggedIn(): Promise<boolean>;\n getCachedCredential?(): Promise<ICredential | undefined>;\n } | undefined> {\n try {\n switch (provider) {\n case \"anthropic\": {\n const mod = await import(\"./providers/claude-login.js\");\n return new mod.ClaudeLogin(this.credentialStore);\n }\n case \"openai\": {\n const mod = await import(\"./providers/codex-login.js\");\n return new mod.CodexLogin(this.credentialStore);\n }\n case \"google\": {\n const mod = await import(\"./providers/gemini-login.js\");\n return new mod.GeminiLogin(this.credentialStore);\n }\n case \"kimi\": {\n const mod = await import(\"./providers/kimi-login.js\");\n return new mod.KimiLogin(this.credentialStore);\n }\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n }\n\n private isExpired(credential: ICredential): boolean {\n if (!credential.expiresAt) {\n return false;\n }\n return new Date() > credential.expiresAt;\n }\n\n private getFromEnvironment(provider: ProviderName): ICredential | undefined {\n const envMap: Record<ProviderName, string> = {\n anthropic: \"ANTHROPIC_API_KEY\",\n openai: \"OPENAI_API_KEY\",\n google: \"GOOGLE_API_KEY\",\n kimi: \"MOONSHOT_API_KEY\",\n ollama: \"\",\n };\n\n const envKey = envMap[provider];\n if (!envKey) {\n return undefined;\n }\n\n const token = process.env[envKey];\n if (!token) {\n return undefined;\n }\n\n return {\n provider,\n method: \"env_variable\",\n token,\n };\n }\n}\n"]}
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import { select } from '@inquirer/prompts';
14
14
  function createChatCommand() {
15
15
  const chat = new Command("chat").description("Start interactive chat mode (default)").argument("[message...]", "Initial message to send").option("-m, --model <model>", "Override model for this session").option("-r, --role <role>", "Set the task role (planning, coding, review, testing, bugfix)").option("--system <prompt>", "Custom system prompt").option("--no-stream", "Disable streaming output").action(async (messageParts, options) => {
16
16
  const message = messageParts.join(" ");
17
- const { startChatSession } = await import('./App-APN34QBQ.js');
17
+ const { startChatSession } = await import('./App-RTXQQKXN.js');
18
18
  const model = options["model"];
19
19
  const role = options["role"];
20
20
  const systemPrompt = options["system"];
@@ -32,7 +32,7 @@ function createChatCommand() {
32
32
  function createPlanCommand() {
33
33
  const plan = new Command("plan").description("Enter planning mode with a high-reasoning model").argument("[message...]", "Planning prompt").option("-m, --model <model>", "Override model (default: planning role)").action(async (messageParts, options) => {
34
34
  const message = messageParts.join(" ");
35
- const { startChatSession } = await import('./App-APN34QBQ.js');
35
+ const { startChatSession } = await import('./App-RTXQQKXN.js');
36
36
  const model = options["model"];
37
37
  const initialMessage = message || void 0;
38
38
  await startChatSession({
@@ -47,7 +47,7 @@ function createPlanCommand() {
47
47
  function createReviewCommand() {
48
48
  const review = new Command("review").description("Code review mode with a thorough model").argument("[files...]", "Files to review").option("-m, --model <model>", "Override model (default: review role)").action(async (files, options) => {
49
49
  const message = files.length > 0 ? `Review these files: ${files.join(", ")}` : "Review the recent changes";
50
- const { startChatSession } = await import('./App-APN34QBQ.js');
50
+ const { startChatSession } = await import('./App-RTXQQKXN.js');
51
51
  const model = options["model"];
52
52
  await startChatSession({
53
53
  initialMessage: message,
@@ -61,7 +61,7 @@ function createReviewCommand() {
61
61
  function createTestCommand() {
62
62
  const test = new Command("test").description("Testing mode with a cost-efficient model").argument("[message...]", "Testing prompt").option("-m, --model <model>", "Override model (default: testing role)").action(async (messageParts, options) => {
63
63
  const message = messageParts.join(" ");
64
- const { startChatSession } = await import('./App-APN34QBQ.js');
64
+ const { startChatSession } = await import('./App-RTXQQKXN.js');
65
65
  const model = options["model"];
66
66
  await startChatSession({
67
67
  initialMessage: message || "Generate tests for the recent changes",
@@ -123,7 +123,7 @@ function createConfigCommand() {
123
123
  });
124
124
  config.command("init").description("Initialize configuration with interactive setup").action(async () => {
125
125
  try {
126
- const { runFirstRunSetup } = await import('./App-APN34QBQ.js');
126
+ const { runFirstRunSetup } = await import('./App-RTXQQKXN.js');
127
127
  await runFirstRunSetup();
128
128
  } catch (error) {
129
129
  const message = error instanceof Error ? error.message : String(error);
@@ -381,15 +381,15 @@ async function loadLoginModule(provider) {
381
381
  return new mod.ClaudeLogin();
382
382
  }
383
383
  case "codex": {
384
- const mod = await import('./codex-login-7HHLJHBF.js');
384
+ const mod = await import('./codex-login-PQ6A6T5P.js');
385
385
  return new mod.CodexLogin();
386
386
  }
387
387
  case "gemini": {
388
- const mod = await import('./gemini-login-ZZLYC3J6.js');
388
+ const mod = await import('./gemini-login-WVBX7642.js');
389
389
  return new mod.GeminiLogin();
390
390
  }
391
391
  case "kimi": {
392
- const mod = await import('./kimi-login-CZPS63NK.js');
392
+ const mod = await import('./kimi-login-RQIEP7TO.js');
393
393
  return new mod.KimiLogin();
394
394
  }
395
395
  }
@@ -434,7 +434,7 @@ async function maybeRunAgentMode(args) {
434
434
  let registryPromise;
435
435
  function getRegistry() {
436
436
  if (!registryPromise) {
437
- registryPromise = import('./registry-4KD24ZC3.js').then(
437
+ registryPromise = import('./registry-H6ZI4OFW.js').then(
438
438
  ({ createDefaultRegistry }) => createDefaultRegistry()
439
439
  );
440
440
  }
@@ -700,7 +700,7 @@ async function main() {
700
700
  }
701
701
  }
702
702
  }
703
- const { startChatSession } = await import('./App-APN34QBQ.js');
703
+ const { startChatSession } = await import('./App-RTXQQKXN.js');
704
704
  const model = options["model"];
705
705
  const role = options["role"];
706
706
  await startChatSession({
@@ -62,7 +62,7 @@ var CodexLogin = class {
62
62
  if (!cliAvailable) {
63
63
  throw new AuthenticationError(
64
64
  "openai",
65
- "Codex CLI not found. Install it first: npm install -g @openai/codex\nOr set an API key: aemeathcli auth set-key codex <key>"
65
+ "Codex CLI not found. Install it first:\n npm install -g @openai/codex\nOr set an API key: aemeathcli auth set-key codex <key>"
66
66
  );
67
67
  }
68
68
  logger.info("Spawning codex login (browser will open automatically)");
@@ -151,7 +151,8 @@ var CodexLogin = class {
151
151
  }
152
152
  async isCliAvailable() {
153
153
  try {
154
- await execFileAsync("which", [CLI_COMMAND], { timeout: 3e3 });
154
+ const cmd = process.platform === "win32" ? "where" : "which";
155
+ await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3e3 });
155
156
  return true;
156
157
  } catch {
157
158
  return false;
@@ -160,5 +161,5 @@ var CodexLogin = class {
160
161
  };
161
162
 
162
163
  export { CodexLogin };
163
- //# sourceMappingURL=codex-login-7HHLJHBF.js.map
164
- //# sourceMappingURL=codex-login-7HHLJHBF.js.map
164
+ //# sourceMappingURL=codex-login-PQ6A6T5P.js.map
165
+ //# sourceMappingURL=codex-login-PQ6A6T5P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth/providers/codex-login.ts"],"names":[],"mappings":"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","file":"codex-login-PQ6A6T5P.js","sourcesContent":["/**\n * Codex (OpenAI) delegated authentication\n * Spawns `codex login` which opens the browser automatically for ChatGPT login.\n * After login, reads cached tokens from ~/.codex/auth.json.\n */\n\nimport { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ICredential } from \"../../types/index.js\";\nimport { AuthenticationError } from \"../../types/index.js\";\nimport { CredentialStore } from \"../credential-store.js\";\nimport { logger } from \"../../utils/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ── Codex CLI Token Paths ───────────────────────────────────────────────\n\nconst CLI_COMMAND = \"codex\";\n\nfunction getCodexHome(): string {\n return process.env[\"CODEX_HOME\"] ?? join(homedir(), \".codex\");\n}\n\nfunction getAuthJsonPath(): string {\n return join(getCodexHome(), \"auth.json\");\n}\n\n// ── auth.json Schema ────────────────────────────────────────────────────\n\ninterface ICodexAuthJson {\n readonly OPENAI_API_KEY?: string | null;\n readonly tokens?: {\n readonly id_token?: string;\n readonly access_token?: string;\n readonly refresh_token?: string;\n readonly account_id?: string;\n };\n readonly last_refresh?: string;\n}\n\nfunction readCodexAuthJson(): ICodexAuthJson | undefined {\n const authPath = getAuthJsonPath();\n if (!existsSync(authPath)) {\n return undefined;\n }\n\n try {\n const raw = readFileSync(authPath, \"utf-8\");\n return JSON.parse(raw) as ICodexAuthJson;\n } catch {\n return undefined;\n }\n}\n\nfunction extractEmailFromIdToken(idToken: string): string | undefined {\n try {\n const payload = idToken.split(\".\")[1];\n if (!payload) return undefined;\n const decoded = JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as {\n email?: string;\n };\n return decoded.email;\n } catch {\n return undefined;\n }\n}\n\n// ── CodexLogin Class ────────────────────────────────────────────────────\n\nexport class CodexLogin {\n private readonly credentialStore: CredentialStore;\n\n constructor(store?: CredentialStore) {\n this.credentialStore = store ?? new CredentialStore();\n }\n\n /**\n * Spawn `codex login` which opens the browser automatically for ChatGPT login,\n * then read the cached tokens from ~/.codex/auth.json.\n */\n async login(): Promise<ICredential> {\n // Check if already logged in via cached tokens\n const existing = this.readCachedCredentials();\n if (existing) {\n logger.info(\"Found existing Codex credentials in ~/.codex/auth.json\");\n await this.credentialStore.set(\"openai\", existing);\n return existing;\n }\n\n // Check if the CLI is available\n const cliAvailable = await this.isCliAvailable();\n if (!cliAvailable) {\n throw new AuthenticationError(\n \"openai\",\n \"Codex CLI not found. Install it first:\\n\" +\n \" npm install -g @openai/codex\\n\" +\n \"Or set an API key: aemeathcli auth set-key codex <key>\",\n );\n }\n\n // Spawn `codex login` — browser opens automatically\n logger.info(\"Spawning codex login (browser will open automatically)\");\n try {\n await this.spawnInteractive(CLI_COMMAND, [\"login\"]);\n } catch (error: unknown) {\n // Try device auth as fallback for headless environments\n try {\n await this.spawnInteractive(CLI_COMMAND, [\"login\", \"--device-auth\"]);\n } catch {\n const msg = error instanceof Error ? error.message : String(error);\n throw new AuthenticationError(\"openai\", `Codex login failed: ${msg}`);\n }\n }\n\n // Read the freshly cached credentials\n const credential = this.readCachedCredentials();\n if (!credential) {\n throw new AuthenticationError(\n \"openai\",\n \"No credentials found after Codex login. Please try again or set an API key: aemeathcli auth set-key codex <key>\",\n );\n }\n\n await this.credentialStore.set(\"openai\", credential);\n logger.info(\"Codex credentials imported successfully\");\n return credential;\n }\n\n async logout(): Promise<void> {\n await this.credentialStore.delete(\"openai\");\n logger.info(\"OpenAI session revoked from AemeathCLI\");\n }\n\n async isLoggedIn(): Promise<boolean> {\n const credential = this.readCachedCredentials();\n if (!credential) {\n return false;\n }\n\n await this.credentialStore.set(\"openai\", credential);\n return true;\n }\n\n async getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }> {\n const loggedIn = await this.isLoggedIn();\n if (!loggedIn) return { loggedIn: false };\n\n const credential = await this.credentialStore.get(\"openai\");\n if (!credential) return { loggedIn: false };\n\n return {\n loggedIn: true,\n ...(credential.email !== undefined ? { email: credential.email } : {}),\n };\n }\n\n async getCachedCredential(): Promise<ICredential | undefined> {\n const credential = this.readCachedCredentials();\n if (credential) {\n await this.credentialStore.set(\"openai\", credential);\n }\n return credential;\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n private readCachedCredentials(): ICredential | undefined {\n const authData = readCodexAuthJson();\n if (!authData) return undefined;\n\n if (authData.tokens?.access_token) {\n const email = authData.tokens.id_token\n ? extractEmailFromIdToken(authData.tokens.id_token)\n : undefined;\n\n return {\n provider: \"openai\",\n method: \"native_login\",\n token: authData.tokens.access_token,\n ...(authData.tokens.refresh_token !== undefined ? { refreshToken: authData.tokens.refresh_token } : {}),\n ...(email !== undefined ? { email } : {}),\n };\n }\n\n if (authData.OPENAI_API_KEY && typeof authData.OPENAI_API_KEY === \"string\") {\n return {\n provider: \"openai\",\n method: \"api_key\",\n token: authData.OPENAI_API_KEY,\n };\n }\n\n return undefined;\n }\n\n private spawnInteractive(command: string, args: readonly string[]): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, [...args], { stdio: \"inherit\", timeout: 300_000 });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else reject(new Error(`Process exited with code ${String(code)}`));\n });\n child.on(\"error\", reject);\n });\n }\n\n private async isCliAvailable(): Promise<boolean> {\n try {\n const cmd = process.platform === \"win32\" ? \"where\" : \"which\";\n await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3000 });\n return true;\n } catch {\n return false;\n }\n }\n}\n"]}
@@ -0,0 +1,174 @@
1
+ import { CredentialStore } from './chunk-4IJD72YB.js';
2
+ import './chunk-CGEV3ARR.js';
3
+ import './chunk-CYQNBB25.js';
4
+ import './chunk-NBR3GHMT.js';
5
+ import './chunk-CS5X3BWX.js';
6
+ import './chunk-HCIHOHLX.js';
7
+ import { AuthenticationError } from './chunk-ZGOHARPV.js';
8
+ import { logger } from './chunk-JAXXTYID.js';
9
+ import { execFile, spawn } from 'child_process';
10
+ import { promisify } from 'util';
11
+ import { existsSync, readFileSync } from 'fs';
12
+ import { join } from 'path';
13
+ import { homedir } from 'os';
14
+
15
+ var execFileAsync = promisify(execFile);
16
+ var CLI_COMMAND = "gemini";
17
+ function getGeminiHome() {
18
+ return process.env["GEMINI_HOME"] ?? join(homedir(), ".gemini");
19
+ }
20
+ function getOAuthCredsPath() {
21
+ return join(getGeminiHome(), "oauth_creds.json");
22
+ }
23
+ function getGoogleAccountsPath() {
24
+ return join(getGeminiHome(), "google_accounts.json");
25
+ }
26
+ function readOAuthCreds() {
27
+ const credsPath = getOAuthCredsPath();
28
+ if (!existsSync(credsPath)) return void 0;
29
+ try {
30
+ return JSON.parse(readFileSync(credsPath, "utf-8"));
31
+ } catch {
32
+ return void 0;
33
+ }
34
+ }
35
+ function readGoogleAccounts() {
36
+ const accountsPath = getGoogleAccountsPath();
37
+ if (!existsSync(accountsPath)) return void 0;
38
+ try {
39
+ return JSON.parse(readFileSync(accountsPath, "utf-8"));
40
+ } catch {
41
+ return void 0;
42
+ }
43
+ }
44
+ function extractEmailFromIdToken(idToken) {
45
+ try {
46
+ const payload = idToken.split(".")[1];
47
+ if (!payload) return void 0;
48
+ const decoded = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
49
+ return decoded.email;
50
+ } catch {
51
+ return void 0;
52
+ }
53
+ }
54
+ var GeminiLogin = class {
55
+ credentialStore;
56
+ constructor(store) {
57
+ this.credentialStore = store ?? new CredentialStore();
58
+ }
59
+ /**
60
+ * Spawn `gemini login` which opens the browser automatically for Google login,
61
+ * then read the cached tokens from ~/.gemini/oauth_creds.json.
62
+ */
63
+ async login() {
64
+ const existing = this.readCachedCredential();
65
+ if (existing) {
66
+ const isExpired = existing.expiresAt ? /* @__PURE__ */ new Date() > existing.expiresAt : false;
67
+ if (!isExpired) {
68
+ logger.info("Found existing Gemini CLI credentials in ~/.gemini/oauth_creds.json");
69
+ await this.credentialStore.set("google", existing);
70
+ return existing;
71
+ }
72
+ }
73
+ const cliAvailable = await this.isCliAvailable();
74
+ if (!cliAvailable) {
75
+ throw new AuthenticationError(
76
+ "google",
77
+ "Gemini CLI not found. Install it first:\n npm install -g @google/gemini-cli\nOr set an API key: aemeathcli auth set-key gemini <key>"
78
+ );
79
+ }
80
+ logger.info("Spawning gemini login (browser will open automatically)");
81
+ try {
82
+ await this.spawnInteractive(CLI_COMMAND, ["login"]);
83
+ } catch (error) {
84
+ const msg = error instanceof Error ? error.message : String(error);
85
+ throw new AuthenticationError("google", `Gemini login failed: ${msg}`);
86
+ }
87
+ const credential = this.readCachedCredential();
88
+ if (!credential) {
89
+ throw new AuthenticationError(
90
+ "google",
91
+ "No credentials found after Gemini login. Please try again or set an API key: aemeathcli auth set-key gemini <key>"
92
+ );
93
+ }
94
+ await this.credentialStore.set("google", credential);
95
+ logger.info("Gemini credentials imported successfully");
96
+ return credential;
97
+ }
98
+ async logout() {
99
+ await this.credentialStore.delete("google");
100
+ logger.info("Google session revoked from AemeathCLI");
101
+ }
102
+ async isLoggedIn() {
103
+ const credential = this.readCachedCredential();
104
+ if (!credential) return false;
105
+ if (credential.expiresAt && /* @__PURE__ */ new Date() > credential.expiresAt && credential.refreshToken === void 0) {
106
+ return false;
107
+ }
108
+ await this.credentialStore.set("google", credential);
109
+ return true;
110
+ }
111
+ async getStatus() {
112
+ const loggedIn = await this.isLoggedIn();
113
+ if (!loggedIn) return { loggedIn: false };
114
+ const credential = await this.credentialStore.get("google");
115
+ if (!credential) return { loggedIn: false };
116
+ return {
117
+ loggedIn: true,
118
+ ...credential.email !== void 0 ? { email: credential.email } : {},
119
+ plan: "Google AI"
120
+ };
121
+ }
122
+ async getCachedCredential() {
123
+ const credential = this.readCachedCredential();
124
+ if (credential) {
125
+ await this.credentialStore.set("google", credential);
126
+ }
127
+ return credential;
128
+ }
129
+ // ── Internal ──────────────────────────────────────────────────────────
130
+ readCachedCredential() {
131
+ const oauthCreds = readOAuthCreds();
132
+ if (!oauthCreds?.access_token) return void 0;
133
+ let email;
134
+ const accounts = readGoogleAccounts();
135
+ if (accounts?.active) {
136
+ email = accounts.active;
137
+ } else if (oauthCreds.id_token) {
138
+ email = extractEmailFromIdToken(oauthCreds.id_token);
139
+ }
140
+ const expiresAt = oauthCreds.expiry_date ? new Date(oauthCreds.expiry_date) : void 0;
141
+ return {
142
+ provider: "google",
143
+ method: "native_login",
144
+ token: oauthCreds.access_token,
145
+ ...oauthCreds.refresh_token !== void 0 ? { refreshToken: oauthCreds.refresh_token } : {},
146
+ ...expiresAt !== void 0 ? { expiresAt } : {},
147
+ ...email !== void 0 ? { email } : {},
148
+ plan: "Google AI"
149
+ };
150
+ }
151
+ spawnInteractive(command, args) {
152
+ return new Promise((resolve, reject) => {
153
+ const child = spawn(command, [...args], { stdio: "inherit", timeout: 3e5 });
154
+ child.on("close", (code) => {
155
+ if (code === 0) resolve();
156
+ else reject(new Error(`Process exited with code ${String(code)}`));
157
+ });
158
+ child.on("error", reject);
159
+ });
160
+ }
161
+ async isCliAvailable() {
162
+ try {
163
+ const cmd = process.platform === "win32" ? "where" : "which";
164
+ await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3e3 });
165
+ return true;
166
+ } catch {
167
+ return false;
168
+ }
169
+ }
170
+ };
171
+
172
+ export { GeminiLogin };
173
+ //# sourceMappingURL=gemini-login-WVBX7642.js.map
174
+ //# sourceMappingURL=gemini-login-WVBX7642.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth/providers/gemini-login.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAgBA,IAAM,aAAA,GAAgB,UAAU,QAAQ,CAAA;AAIxC,IAAM,WAAA,GAAc,QAAA;AAEpB,SAAS,aAAA,GAAwB;AAC/B,EAAA,OAAO,QAAQ,GAAA,CAAI,aAAa,KAAK,IAAA,CAAK,OAAA,IAAW,SAAS,CAAA;AAChE;AAEA,SAAS,iBAAA,GAA4B;AACnC,EAAA,OAAO,IAAA,CAAK,aAAA,EAAc,EAAG,kBAAkB,CAAA;AACjD;AAEA,SAAS,qBAAA,GAAgC;AACvC,EAAA,OAAO,IAAA,CAAK,aAAA,EAAc,EAAG,sBAAsB,CAAA;AACrD;AAiBA,SAAS,cAAA,GAAgD;AACvD,EAAA,MAAM,YAAY,iBAAA,EAAkB;AACpC,EAAA,IAAI,CAAC,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,MAAA;AACnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAA,EAAW,OAAO,CAAC,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAA,GAAkD;AACzD,EAAA,MAAM,eAAe,qBAAA,EAAsB;AAC3C,EAAA,IAAI,CAAC,UAAA,CAAW,YAAY,CAAA,EAAG,OAAO,MAAA;AACtC,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,YAAA,EAAc,OAAO,CAAC,CAAA;AAAA,EACvD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,wBAAwB,OAAA,EAAqC;AACpE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AACpC,IAAA,IAAI,CAAC,SAAS,OAAO,KAAA,CAAA;AACrB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,SAAS,WAAW,CAAA,CAAE,QAAA,CAAS,MAAM,CAAC,CAAA;AAC7E,IAAA,OAAO,OAAA,CAAQ,KAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAIO,IAAM,cAAN,MAAkB;AAAA,EACN,eAAA;AAAA,EAEjB,YAAY,KAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA,IAAS,IAAI,eAAA,EAAgB;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,GAA8B;AAElC,IAAA,MAAM,QAAA,GAAW,KAAK,oBAAA,EAAqB;AAC3C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,YAAY,QAAA,CAAS,SAAA,uBAAgB,IAAA,EAAK,GAAI,SAAS,SAAA,GAAY,KAAA;AACzE,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAA,CAAO,KAAK,qEAAqE,CAAA;AACjF,QAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,QAAA,EAAU,QAAQ,CAAA;AACjD,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,cAAA,EAAe;AAC/C,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,QAAA;AAAA,QACA;AAAA,OAGF;AAAA,IACF;AAGA,IAAA,MAAA,CAAO,KAAK,yDAAyD,CAAA;AACrE,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAC,OAAO,CAAC,CAAA;AAAA,IACpD,SAAS,KAAA,EAAgB;AACvB,MAAA,MAAM,MAAM,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AACjE,MAAA,MAAM,IAAI,mBAAA,CAAoB,QAAA,EAAU,CAAA,qBAAA,EAAwB,GAAG,CAAA,CAAE,CAAA;AAAA,IACvE;AAGA,IAAA,MAAM,UAAA,GAAa,KAAK,oBAAA,EAAqB;AAC7C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,QAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,QAAA,EAAU,UAAU,CAAA;AACnD,IAAA,MAAA,CAAO,KAAK,0CAA0C,CAAA;AACtD,IAAA,OAAO,UAAA;AAAA,EACT;AAAA,EAEA,MAAM,MAAA,GAAwB;AAC5B,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAO,QAAQ,CAAA;AAC1C,IAAA,MAAA,CAAO,KAAK,wCAAwC,CAAA;AAAA,EACtD;AAAA,EAEA,MAAM,UAAA,GAA+B;AACnC,IAAA,MAAM,UAAA,GAAa,KAAK,oBAAA,EAAqB;AAC7C,IAAA,IAAI,CAAC,YAAY,OAAO,KAAA;AACxB,IAAA,IAAI,UAAA,CAAW,6BAAa,IAAI,IAAA,KAAS,UAAA,CAAW,SAAA,IAAa,UAAA,CAAW,YAAA,KAAiB,MAAA,EAAW;AACtG,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,QAAA,EAAU,UAAU,CAAA;AACnD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,SAAA,GAAmG;AACvG,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,EAAW;AACvC,IAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAE,UAAU,KAAA,EAAM;AAExC,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,eAAA,CAAgB,IAAI,QAAQ,CAAA;AAC1D,IAAA,IAAI,CAAC,UAAA,EAAY,OAAO,EAAE,UAAU,KAAA,EAAM;AAE1C,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,IAAA;AAAA,MACV,GAAI,WAAW,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,UAAA,CAAW,KAAA,EAAM,GAAI,EAAC;AAAA,MACpE,IAAA,EAAM;AAAA,KACR;AAAA,EACF;AAAA,EAEA,MAAM,mBAAA,GAAwD;AAC5D,IAAA,MAAM,UAAA,GAAa,KAAK,oBAAA,EAAqB;AAC7C,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,QAAA,EAAU,UAAU,CAAA;AAAA,IACrD;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA,EAIQ,oBAAA,GAAgD;AACtD,IAAA,MAAM,aAAa,cAAA,EAAe;AAClC,IAAA,IAAI,CAAC,UAAA,EAAY,YAAA,EAAc,OAAO,MAAA;AAEtC,IAAA,IAAI,KAAA;AACJ,IAAA,MAAM,WAAW,kBAAA,EAAmB;AACpC,IAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,MAAA,KAAA,GAAQ,QAAA,CAAS,MAAA;AAAA,IACnB,CAAA,MAAA,IAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,KAAA,GAAQ,uBAAA,CAAwB,WAAW,QAAQ,CAAA;AAAA,IACrD;AAEA,IAAA,MAAM,YAAY,UAAA,CAAW,WAAA,GAAc,IAAI,IAAA,CAAK,UAAA,CAAW,WAAW,CAAA,GAAI,MAAA;AAE9E,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,cAAA;AAAA,MACR,OAAO,UAAA,CAAW,YAAA;AAAA,MAClB,GAAI,WAAW,aAAA,KAAkB,MAAA,GAAY,EAAE,YAAA,EAAc,UAAA,CAAW,aAAA,EAAc,GAAI,EAAC;AAAA,MAC3F,GAAI,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,KAAc,EAAC;AAAA,MAC/C,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU,EAAC;AAAA,MACvC,IAAA,EAAM;AAAA,KACR;AAAA,EACF;AAAA,EAEQ,gBAAA,CAAiB,SAAiB,IAAA,EAAwC;AAChF,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,EAAS,CAAC,GAAG,IAAI,CAAA,EAAG,EAAE,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,GAAA,EAAS,CAAA;AAC9E,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,QAAA,IAAI,IAAA,KAAS,GAAG,OAAA,EAAQ;AAAA,aACnB,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,OAAO,IAAI,CAAC,EAAE,CAAC,CAAA;AAAA,MACnE,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM,CAAA;AAAA,IAC1B,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,cAAA,GAAmC;AAC/C,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,QAAA,KAAa,OAAA,GAAU,OAAA,GAAU,OAAA;AACrD,MAAA,MAAM,aAAA,CAAc,KAAK,CAAC,WAAW,GAAG,EAAE,OAAA,EAAS,KAAM,CAAA;AACzD,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACF","file":"gemini-login-WVBX7642.js","sourcesContent":["/**\n * Gemini (Google) delegated authentication\n * Spawns `gemini login` which opens the browser automatically for Google login.\n * After login, reads cached tokens from ~/.gemini/oauth_creds.json.\n */\n\nimport { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ICredential } from \"../../types/index.js\";\nimport { AuthenticationError } from \"../../types/index.js\";\nimport { CredentialStore } from \"../credential-store.js\";\nimport { logger } from \"../../utils/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ── Gemini CLI Token Paths ──────────────────────────────────────────────\n\nconst CLI_COMMAND = \"gemini\";\n\nfunction getGeminiHome(): string {\n return process.env[\"GEMINI_HOME\"] ?? join(homedir(), \".gemini\");\n}\n\nfunction getOAuthCredsPath(): string {\n return join(getGeminiHome(), \"oauth_creds.json\");\n}\n\nfunction getGoogleAccountsPath(): string {\n return join(getGeminiHome(), \"google_accounts.json\");\n}\n\n// ── Read existing tokens from Gemini CLI cache ──────────────────────────\n\ninterface IGeminiOAuthCreds {\n readonly access_token?: string;\n readonly scope?: string;\n readonly token_type?: string;\n readonly id_token?: string;\n readonly expiry_date?: number;\n readonly refresh_token?: string;\n}\n\ninterface IGoogleAccounts {\n readonly active?: string;\n}\n\nfunction readOAuthCreds(): IGeminiOAuthCreds | undefined {\n const credsPath = getOAuthCredsPath();\n if (!existsSync(credsPath)) return undefined;\n try {\n return JSON.parse(readFileSync(credsPath, \"utf-8\")) as IGeminiOAuthCreds;\n } catch {\n return undefined;\n }\n}\n\nfunction readGoogleAccounts(): IGoogleAccounts | undefined {\n const accountsPath = getGoogleAccountsPath();\n if (!existsSync(accountsPath)) return undefined;\n try {\n return JSON.parse(readFileSync(accountsPath, \"utf-8\")) as IGoogleAccounts;\n } catch {\n return undefined;\n }\n}\n\nfunction extractEmailFromIdToken(idToken: string): string | undefined {\n try {\n const payload = idToken.split(\".\")[1];\n if (!payload) return undefined;\n const decoded = JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as { email?: string };\n return decoded.email;\n } catch {\n return undefined;\n }\n}\n\n// ── GeminiLogin Class ───────────────────────────────────────────────────\n\nexport class GeminiLogin {\n private readonly credentialStore: CredentialStore;\n\n constructor(store?: CredentialStore) {\n this.credentialStore = store ?? new CredentialStore();\n }\n\n /**\n * Spawn `gemini login` which opens the browser automatically for Google login,\n * then read the cached tokens from ~/.gemini/oauth_creds.json.\n */\n async login(): Promise<ICredential> {\n // Check if already logged in via cached tokens\n const existing = this.readCachedCredential();\n if (existing) {\n const isExpired = existing.expiresAt ? new Date() > existing.expiresAt : false;\n if (!isExpired) {\n logger.info(\"Found existing Gemini CLI credentials in ~/.gemini/oauth_creds.json\");\n await this.credentialStore.set(\"google\", existing);\n return existing;\n }\n }\n\n // Check if the CLI is available\n const cliAvailable = await this.isCliAvailable();\n if (!cliAvailable) {\n throw new AuthenticationError(\n \"google\",\n \"Gemini CLI not found. Install it first:\\n\" +\n \" npm install -g @google/gemini-cli\\n\" +\n \"Or set an API key: aemeathcli auth set-key gemini <key>\",\n );\n }\n\n // Spawn `gemini login` — browser opens automatically\n logger.info(\"Spawning gemini login (browser will open automatically)\");\n try {\n await this.spawnInteractive(CLI_COMMAND, [\"login\"]);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n throw new AuthenticationError(\"google\", `Gemini login failed: ${msg}`);\n }\n\n // Read the freshly cached credentials\n const credential = this.readCachedCredential();\n if (!credential) {\n throw new AuthenticationError(\n \"google\",\n \"No credentials found after Gemini login. Please try again or set an API key: aemeathcli auth set-key gemini <key>\",\n );\n }\n\n await this.credentialStore.set(\"google\", credential);\n logger.info(\"Gemini credentials imported successfully\");\n return credential;\n }\n\n async logout(): Promise<void> {\n await this.credentialStore.delete(\"google\");\n logger.info(\"Google session revoked from AemeathCLI\");\n }\n\n async isLoggedIn(): Promise<boolean> {\n const credential = this.readCachedCredential();\n if (!credential) return false;\n if (credential.expiresAt && new Date() > credential.expiresAt && credential.refreshToken === undefined) {\n return false;\n }\n\n await this.credentialStore.set(\"google\", credential);\n return true;\n }\n\n async getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }> {\n const loggedIn = await this.isLoggedIn();\n if (!loggedIn) return { loggedIn: false };\n\n const credential = await this.credentialStore.get(\"google\");\n if (!credential) return { loggedIn: false };\n\n return {\n loggedIn: true,\n ...(credential.email !== undefined ? { email: credential.email } : {}),\n plan: \"Google AI\",\n };\n }\n\n async getCachedCredential(): Promise<ICredential | undefined> {\n const credential = this.readCachedCredential();\n if (credential) {\n await this.credentialStore.set(\"google\", credential);\n }\n return credential;\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n private readCachedCredential(): ICredential | undefined {\n const oauthCreds = readOAuthCreds();\n if (!oauthCreds?.access_token) return undefined;\n\n let email: string | undefined;\n const accounts = readGoogleAccounts();\n if (accounts?.active) {\n email = accounts.active;\n } else if (oauthCreds.id_token) {\n email = extractEmailFromIdToken(oauthCreds.id_token);\n }\n\n const expiresAt = oauthCreds.expiry_date ? new Date(oauthCreds.expiry_date) : undefined;\n\n return {\n provider: \"google\",\n method: \"native_login\",\n token: oauthCreds.access_token,\n ...(oauthCreds.refresh_token !== undefined ? { refreshToken: oauthCreds.refresh_token } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n ...(email !== undefined ? { email } : {}),\n plan: \"Google AI\",\n };\n }\n\n private spawnInteractive(command: string, args: readonly string[]): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, [...args], { stdio: \"inherit\", timeout: 300_000 });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else reject(new Error(`Process exited with code ${String(code)}`));\n });\n child.on(\"error\", reject);\n });\n }\n\n private async isCliAvailable(): Promise<boolean> {\n try {\n const cmd = process.platform === \"win32\" ? \"where\" : \"which\";\n await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3000 });\n return true;\n } catch {\n return false;\n }\n }\n}\n"]}
package/dist/index.js CHANGED
@@ -11,11 +11,11 @@ export { OpenAIAdapter } from './chunk-WPP3PEDE.js';
11
11
  export { GeminiAdapter } from './chunk-UY2SYSEZ.js';
12
12
  export { KimiAdapter } from './chunk-MXZSI3AY.js';
13
13
  export { OllamaAdapter } from './chunk-H66O5Z2V.js';
14
- export { ProviderRegistry } from './chunk-O3ZF22SW.js';
14
+ export { ProviderRegistry } from './chunk-LJ6K3FYY.js';
15
15
  export { LayoutEngine, TmuxManager } from './chunk-CARHU3DO.js';
16
16
  import { getEventBus } from './chunk-YL5XFHR3.js';
17
17
  export { getEventBus } from './chunk-YL5XFHR3.js';
18
- export { SessionManager } from './chunk-SUSJPZU2.js';
18
+ export { SessionManager } from './chunk-YVJL75JT.js';
19
19
  import './chunk-I5PZ4JTS.js';
20
20
  export { CredentialStore } from './chunk-4IJD72YB.js';
21
21
  import { withRetry, sleep } from './chunk-CGEV3ARR.js';
@@ -50,7 +50,7 @@ var KimiLogin = class {
50
50
  if (!cliAvailable) {
51
51
  throw new AuthenticationError(
52
52
  "kimi",
53
- "Kimi CLI not found. Install it first: npm install -g @anthropic-ai/kimi-cli\nOr set an API key: aemeathcli auth set-key kimi <key>"
53
+ "Kimi CLI not found. Install it first:\n" + (process.platform === "win32" ? " irm https://code.kimi.com/install.ps1 | iex\n" : " curl -L code.kimi.com/install.sh | bash\n") + "Or set an API key: aemeathcli auth set-key kimi <key>"
54
54
  );
55
55
  }
56
56
  logger.info("Spawning Kimi CLI for login (browser will open automatically)");
@@ -136,7 +136,8 @@ var KimiLogin = class {
136
136
  }
137
137
  async isCliAvailable() {
138
138
  try {
139
- await execFileAsync("which", [CLI_COMMAND], { timeout: 3e3 });
139
+ const cmd = process.platform === "win32" ? "where" : "which";
140
+ await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3e3 });
140
141
  return true;
141
142
  } catch {
142
143
  return false;
@@ -145,5 +146,5 @@ var KimiLogin = class {
145
146
  };
146
147
 
147
148
  export { KimiLogin };
148
- //# sourceMappingURL=kimi-login-CZPS63NK.js.map
149
- //# sourceMappingURL=kimi-login-CZPS63NK.js.map
149
+ //# sourceMappingURL=kimi-login-RQIEP7TO.js.map
150
+ //# sourceMappingURL=kimi-login-RQIEP7TO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth/providers/kimi-login.ts"],"names":["expiresAt"],"mappings":";;;;;;;;;;;;;;AAiBA,IAAM,aAAA,GAAgB,UAAU,QAAQ,CAAA;AAIxC,IAAM,WAAA,GAAc,MAAA;AAEpB,SAAS,WAAA,GAAsB;AAC7B,EAAA,OAAO,QAAQ,GAAA,CAAI,WAAW,KAAK,IAAA,CAAK,OAAA,IAAW,OAAO,CAAA;AAC5D;AAEA,SAAS,kBAAA,GAA6B;AACpC,EAAA,OAAO,IAAA,CAAK,WAAA,EAAY,EAAG,aAAA,EAAe,gBAAgB,CAAA;AAC5D;AAYA,SAAS,mBAAA,GAAoD;AAC3D,EAAA,MAAM,YAAY,kBAAA,EAAmB;AACrC,EAAA,IAAI,CAAC,UAAA,CAAW,SAAS,CAAA,EAAG,OAAO,MAAA;AACnC,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAA,EAAW,OAAO,CAAC,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAIO,IAAM,YAAN,MAAgB;AAAA,EACJ,eAAA;AAAA,EAEjB,YAAY,KAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA,IAAS,IAAI,eAAA,EAAgB;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAA,GAA8B;AAElC,IAAA,MAAM,QAAA,GAAW,KAAK,qBAAA,EAAsB;AAC5C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA;AACjD,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,QAAQ,CAAA;AAC/C,MAAA,OAAO,QAAA;AAAA,IACT;AAGA,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,cAAA,EAAe;AAC/C,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,MAAA;AAAA,QACA,yCAAA,IACC,OAAA,CAAQ,QAAA,KAAa,OAAA,GAClB,oDACA,6CAAA,CAAA,GACJ;AAAA,OACF;AAAA,IACF;AAGA,IAAA,MAAA,CAAO,KAAK,+DAA+D,CAAA;AAC3E,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAC,OAAO,CAAC,CAAA;AAAA,IACpD,CAAA,CAAA,MAAQ;AAEN,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,EAAE,CAAA;AAAA,MAC7C,SAAS,MAAA,EAAiB;AACxB,QAAA,MAAM,MAAM,MAAA,YAAkB,KAAA,GAAQ,MAAA,CAAO,OAAA,GAAU,OAAO,MAAM,CAAA;AACpE,QAAA,MAAM,IAAI,mBAAA,CAAoB,MAAA,EAAQ,CAAA,mBAAA,EAAsB,GAAG,CAAA,CAAE,CAAA;AAAA,MACnE;AAAA,IACF;AAGA,IAAA,MAAM,UAAA,GAAa,KAAK,qBAAA,EAAsB;AAC9C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,MAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,UAAU,CAAA;AACjD,IAAA,MAAA,CAAO,KAAK,wCAAwC,CAAA;AACpD,IAAA,OAAO,UAAA;AAAA,EACT;AAAA,EAEA,MAAM,MAAA,GAAwB;AAC5B,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAO,MAAM,CAAA;AACxC,IAAA,MAAA,CAAO,KAAK,sCAAsC,CAAA;AAAA,EACpD;AAAA,EAEA,MAAM,UAAA,GAA+B;AACnC,IAAA,MAAM,UAAA,GAAa,KAAK,qBAAA,EAAsB;AAC9C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,UAAU,CAAA;AACjD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,SAAA,GAAmG;AACvG,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,UAAA,EAAW;AACvC,IAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAE,UAAU,KAAA,EAAM;AAExC,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,eAAA,CAAgB,IAAI,MAAM,CAAA;AACxD,IAAA,IAAI,CAAC,UAAA,EAAY,OAAO,EAAE,UAAU,KAAA,EAAM;AAE1C,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,IAAA;AAAA,MACV,GAAI,WAAW,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,UAAA,CAAW,KAAA,EAAM,GAAI;AAAC,KACtE;AAAA,EACF;AAAA,EAEA,MAAM,mBAAA,GAAwD;AAC5D,IAAA,MAAM,UAAA,GAAa,KAAK,qBAAA,EAAsB;AAC9C,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,UAAU,CAAA;AAAA,IACnD;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAAA;AAAA,EAIQ,qBAAA,GAAiD;AACvD,IAAA,MAAM,YAAY,mBAAA,EAAoB;AACtC,IAAA,IAAI,CAAC,SAAA,EAAW,YAAA,EAAc,OAAO,MAAA;AAGrC,IAAA,IAAI,UAAU,UAAA,EAAY;AACxB,MAAA,MAAMA,UAAAA,GAAY,IAAI,IAAA,CAAK,SAAA,CAAU,aAAa,GAAI,CAAA;AACtD,MAAA,wBAAQ,IAAA,EAAK,GAAIA,UAAAA,IAAa,CAAC,UAAU,aAAA,EAAe;AACtD,QAAA,MAAA,CAAO,MAAM,8CAA8C,CAAA;AAC3D,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,UAAU,UAAA,GACxB,IAAI,KAAK,SAAA,CAAU,UAAA,GAAa,GAAI,CAAA,GACpC,MAAA;AAEJ,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,MAAA;AAAA,MACV,MAAA,EAAQ,cAAA;AAAA,MACR,OAAO,SAAA,CAAU,YAAA;AAAA,MACjB,GAAI,UAAU,aAAA,KAAkB,MAAA,GAAY,EAAE,YAAA,EAAc,SAAA,CAAU,aAAA,EAAc,GAAI,EAAC;AAAA,MACzF,GAAI,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,KAAc;AAAC,KACjD;AAAA,EACF;AAAA,EAEQ,gBAAA,CAAiB,SAAiB,IAAA,EAAwC;AAChF,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,EAAS,CAAC,GAAG,IAAI,CAAA,EAAG,EAAE,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,GAAA,EAAS,CAAA;AAC9E,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,QAAA,IAAI,IAAA,KAAS,GAAG,OAAA,EAAQ;AAAA,aACnB,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,OAAO,IAAI,CAAC,EAAE,CAAC,CAAA;AAAA,MACnE,CAAC,CAAA;AACD,MAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM,CAAA;AAAA,IAC1B,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,cAAA,GAAmC;AAC/C,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,QAAA,KAAa,OAAA,GAAU,OAAA,GAAU,OAAA;AACrD,MAAA,MAAM,aAAA,CAAc,KAAK,CAAC,WAAW,GAAG,EAAE,OAAA,EAAS,KAAM,CAAA;AACzD,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACF","file":"kimi-login-RQIEP7TO.js","sourcesContent":["/**\n * Kimi (Moonshot) delegated authentication\n * Reads cached credentials from Kimi CLI's ~/.kimi/credentials/kimi-code.json.\n * If not found, spawns `kimi` CLI for interactive login.\n * Kimi's login opens a browser automatically from its interactive session.\n */\n\nimport { execFile, spawn } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ICredential } from \"../../types/index.js\";\nimport { AuthenticationError } from \"../../types/index.js\";\nimport { CredentialStore } from \"../credential-store.js\";\nimport { logger } from \"../../utils/index.js\";\n\nconst execFileAsync = promisify(execFile);\n\n// ── Kimi CLI Token Paths ────────────────────────────────────────────────\n\nconst CLI_COMMAND = \"kimi\";\n\nfunction getKimiHome(): string {\n return process.env[\"KIMI_HOME\"] ?? join(homedir(), \".kimi\");\n}\n\nfunction getCredentialsPath(): string {\n return join(getKimiHome(), \"credentials\", \"kimi-code.json\");\n}\n\n// ── kimi-code.json Schema ───────────────────────────────────────────────\n\ninterface IKimiCredentials {\n readonly access_token?: string;\n readonly refresh_token?: string;\n readonly expires_at?: number;\n readonly scope?: string;\n readonly token_type?: string;\n}\n\nfunction readKimiCredentials(): IKimiCredentials | undefined {\n const credsPath = getCredentialsPath();\n if (!existsSync(credsPath)) return undefined;\n try {\n return JSON.parse(readFileSync(credsPath, \"utf-8\")) as IKimiCredentials;\n } catch {\n return undefined;\n }\n}\n\n// ── KimiLogin Class ─────────────────────────────────────────────────────\n\nexport class KimiLogin {\n private readonly credentialStore: CredentialStore;\n\n constructor(store?: CredentialStore) {\n this.credentialStore = store ?? new CredentialStore();\n }\n\n /**\n * Login via the Kimi CLI.\n * First checks for cached credentials. If not found, spawns the Kimi CLI\n * interactive session which handles browser-based login automatically.\n */\n async login(): Promise<ICredential> {\n // Check if already logged in via cached tokens\n const existing = this.readCachedCredentials();\n if (existing) {\n logger.info(\"Found existing Kimi CLI credentials\");\n await this.credentialStore.set(\"kimi\", existing);\n return existing;\n }\n\n // Check if the CLI is available\n const cliAvailable = await this.isCliAvailable();\n if (!cliAvailable) {\n throw new AuthenticationError(\n \"kimi\",\n \"Kimi CLI not found. Install it first:\\n\" +\n (process.platform === \"win32\"\n ? \" irm https://code.kimi.com/install.ps1 | iex\\n\"\n : \" curl -L code.kimi.com/install.sh | bash\\n\") +\n \"Or set an API key: aemeathcli auth set-key kimi <key>\",\n );\n }\n\n // Spawn kimi CLI — it handles login with browser automatically\n logger.info(\"Spawning Kimi CLI for login (browser will open automatically)\");\n try {\n await this.spawnInteractive(CLI_COMMAND, [\"login\"]);\n } catch {\n // Some versions may not have `kimi login` — try spawning interactive session\n try {\n await this.spawnInteractive(CLI_COMMAND, []);\n } catch (error2: unknown) {\n const msg = error2 instanceof Error ? error2.message : String(error2);\n throw new AuthenticationError(\"kimi\", `Kimi login failed: ${msg}`);\n }\n }\n\n // Read the freshly cached credentials\n const credential = this.readCachedCredentials();\n if (!credential) {\n throw new AuthenticationError(\n \"kimi\",\n \"No Kimi credentials found after login. Please try again or set an API key: aemeathcli auth set-key kimi <key>\",\n );\n }\n\n await this.credentialStore.set(\"kimi\", credential);\n logger.info(\"Kimi credentials imported successfully\");\n return credential;\n }\n\n async logout(): Promise<void> {\n await this.credentialStore.delete(\"kimi\");\n logger.info(\"Kimi session revoked from AemeathCLI\");\n }\n\n async isLoggedIn(): Promise<boolean> {\n const credential = this.readCachedCredentials();\n if (!credential) {\n return false;\n }\n\n await this.credentialStore.set(\"kimi\", credential);\n return true;\n }\n\n async getStatus(): Promise<{ loggedIn: boolean; email?: string | undefined; plan?: string | undefined }> {\n const loggedIn = await this.isLoggedIn();\n if (!loggedIn) return { loggedIn: false };\n\n const credential = await this.credentialStore.get(\"kimi\");\n if (!credential) return { loggedIn: false };\n\n return {\n loggedIn: true,\n ...(credential.email !== undefined ? { email: credential.email } : {}),\n };\n }\n\n async getCachedCredential(): Promise<ICredential | undefined> {\n const credential = this.readCachedCredentials();\n if (credential) {\n await this.credentialStore.set(\"kimi\", credential);\n }\n return credential;\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n private readCachedCredentials(): ICredential | undefined {\n const kimiCreds = readKimiCredentials();\n if (!kimiCreds?.access_token) return undefined;\n\n // Check expiry (expires_at is seconds since epoch)\n if (kimiCreds.expires_at) {\n const expiresAt = new Date(kimiCreds.expires_at * 1000);\n if (new Date() > expiresAt && !kimiCreds.refresh_token) {\n logger.debug(\"Kimi CLI token expired with no refresh token\");\n return undefined;\n }\n }\n\n const expiresAt = kimiCreds.expires_at\n ? new Date(kimiCreds.expires_at * 1000)\n : undefined;\n\n return {\n provider: \"kimi\",\n method: \"native_login\",\n token: kimiCreds.access_token,\n ...(kimiCreds.refresh_token !== undefined ? { refreshToken: kimiCreds.refresh_token } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n };\n }\n\n private spawnInteractive(command: string, args: readonly string[]): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, [...args], { stdio: \"inherit\", timeout: 300_000 });\n child.on(\"close\", (code) => {\n if (code === 0) resolve();\n else reject(new Error(`Process exited with code ${String(code)}`));\n });\n child.on(\"error\", reject);\n });\n }\n\n private async isCliAvailable(): Promise<boolean> {\n try {\n const cmd = process.platform === \"win32\" ? \"where\" : \"which\";\n await execFileAsync(cmd, [CLI_COMMAND], { timeout: 3000 });\n return true;\n } catch {\n return false;\n }\n }\n}\n"]}