diff --git a/src/auth/profile-registry.ts b/src/auth/profile-registry.ts index a0b944b2..35d17193 100644 --- a/src/auth/profile-registry.ts +++ b/src/auth/profile-registry.ts @@ -9,6 +9,9 @@ import { import type { AccountConfig } from '../config/unified-config-types'; import { getCcsDir } from '../utils/config-manager'; import { isValidContextGroupName, normalizeContextGroupName } from './account-context'; +import { createLogger } from '../services/logging'; + +const logger = createLogger('auth:profile-registry'); /** * Profile Registry (Simplified) @@ -182,6 +185,10 @@ export class ProfileRegistry { // Default always stays on implicit 'default' profile (uses ~/.claude/) this._write(data); + logger.stage('route', 'auth.profile.created', 'Profile created in registry', { + profile: name, + profileType: metadata.type || 'account', + }); } /** @@ -235,6 +242,9 @@ export class ProfileRegistry { } this._write(data); + logger.stage('cleanup', 'auth.profile.deleted', 'Profile deleted from registry', { + profile: name, + }); } /** diff --git a/src/cliproxy/auth/oauth-handler.ts b/src/cliproxy/auth/oauth-handler.ts index 78a3ea6a..3777e9a3 100644 --- a/src/cliproxy/auth/oauth-handler.ts +++ b/src/cliproxy/auth/oauth-handler.ts @@ -12,6 +12,7 @@ import * as fs from 'fs'; import { fail, info, warn, color, ok } from '../../utils/ui'; +import { createLogger } from '../../services/logging'; import { ensureCLIProxyBinary } from '../binary-manager'; import { generateConfig } from '../config/config-generator'; import { CLIProxyProvider } from '../types'; @@ -82,6 +83,8 @@ interface PasteCallbackStartData { const PASTE_CALLBACK_AUTH_URL_POLL_INTERVAL_MS = 3000; const POLLED_AUTH_LOCAL_TOKEN_GRACE_MS = 15 * 1000; +const logger = createLogger('cliproxy:auth:oauth'); + export async function requestPasteCallbackStart( provider: CLIProxyProvider, target: ProxyTarget, @@ -800,6 +803,12 @@ export async function triggerOAuth( ): Promise { const oauthConfig = getOAuthConfig(provider); warnOAuthBanRisk(provider); + const oauthStartedAt = Date.now(); + logger.stage('auth', 'cliproxy.oauth.start', 'Triggering OAuth flow', { + provider, + add: options.add === true, + fromUI: options.fromUI === true, + }); const { verbose = false, add = false, fromUI = false, noIncognito = true } = options; const acceptAgyRisk = options.acceptAgyRisk === true; const { nickname } = options; @@ -1055,6 +1064,24 @@ export async function triggerOAuth( } } + if (account) { + logger.stage( + 'auth', + 'cliproxy.oauth.success', + 'OAuth flow completed successfully', + { provider, accountId: account.id }, + { latencyMs: Date.now() - oauthStartedAt } + ); + } else { + logger.stage( + 'cleanup', + 'cliproxy.oauth.failed', + 'OAuth flow failed or was cancelled', + { provider }, + { level: 'warn', latencyMs: Date.now() - oauthStartedAt } + ); + } + return account; } @@ -1067,6 +1094,9 @@ export async function ensureAuth( options: { verbose?: boolean; headless?: boolean; account?: string } = {} ): Promise { if (isAuthenticated(provider)) { + logger.stage('auth', 'cliproxy.auth.cached', 'Provider already authenticated', { + provider, + }); if (options.verbose) { console.error(`[auth] ${provider} already authenticated`); } @@ -1077,6 +1107,10 @@ export async function ensureAuth( return true; } + logger.stage('auth', 'cliproxy.auth.required', 'Provider needs authentication', { + provider, + }); + const oauthConfig = getOAuthConfig(provider); console.log(info(`${oauthConfig.displayName} authentication required`)); diff --git a/src/commands/doctor-command.ts b/src/commands/doctor-command.ts index 5c4c9580..084f4cc1 100644 --- a/src/commands/doctor-command.ts +++ b/src/commands/doctor-command.ts @@ -5,6 +5,9 @@ */ import { initUI, header, dim, color, subheader } from '../utils/ui'; +import { createLogger } from '../services/logging'; + +const logger = createLogger('commands:doctor'); /** * Show help for doctor command @@ -68,15 +71,34 @@ export async function handleDoctorCommand(args: string[]): Promise { } const shouldFix = args.includes('--fix') || args.includes('-f'); + const startedAt = Date.now(); + logger.stage('intake', 'doctor.start', 'Doctor health check starting', { + fix: shouldFix, + }); const DoctorModule = await import('../management/doctor'); const Doctor = DoctorModule.default; const doctor = new Doctor(); await doctor.runAllChecks(); + logger.stage( + 'route', + 'doctor.checks_complete', + 'Doctor checks complete', + { healthy: doctor.isHealthy() }, + { latencyMs: Date.now() - startedAt } + ); if (shouldFix) { + logger.stage('dispatch', 'doctor.fix_start', 'Attempting auto-fix', {}); await doctor.fixIssues(); + logger.stage( + 'respond', + 'doctor.fix_complete', + 'Doctor auto-fix complete', + { healthy: doctor.isHealthy() }, + { latencyMs: Date.now() - startedAt } + ); } process.exit(doctor.isHealthy() ? 0 : 1);